-
Notifications
You must be signed in to change notification settings - Fork 0
/
wifimanager.py
597 lines (558 loc) · 22.8 KB
/
wifimanager.py
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
## IMPORTS ##
import sys
import subprocess
import threading
import copy
from time import sleep
## MODULES ##
import jjcommon
import settings
import logpipe
import jjlogger
logger = jjlogger.getLogger(__name__)
## MODULE GLOBALS ##
_wifimanagerlock = threading.Lock() # locks the wpa_cli resources so they're only used one at a time - if you call while this is being used by another thread, it will block until the lock is freed
_currentwifimode = "unknown" # global storage of current wifi mode
_targetwifimode = "unknown" # set for when we run the change routine in the background
wifidetailschangedevent = threading.Event()
_changethread = None
# dummy values for when we're testing in windows
_dummynetworks = [{"id":0,"ssid":"dummynetwork_a","connected":True},{"id":1,"ssid":"dummynetwork_b","connected":False}]
_dummyscanresult = [{"bssid":"00:00:00:00","freq":2412,"channel":1,"rssi":-60,"flags":["WPA"],"ssid":"scannetwork_a","id":0},
{"bssid":"00:00:00:00","freq":2437,"channel":6,"rssi":-58,"flags":["WPA"],"ssid":"scannetwork_b","id":1}]
_hostapdconfdefault = { "interface":jjcommon.iface,
"ssid":jjcommon.ap_ssid,
"hw_mode":"g",
"channel":"6",
"macaddr_acl":"0",
"auth_algs":"1",
"ignore_broadcast_ssid":"0",
"wpa":"2",
"wpa_passphrase":jjcommon.ap_pass,
"wpa_key_mgmt":"WPA-PSK",
"wpa_pairwise":"TKIP",
"rsn_pairwise":"CCMP", }
def _makeconftext(dict):
"""Convert dictionary into config file text."""
t = ""
for k, v in dict.items():
t += "{0}={1}\n".format(k,v)
return t
def _parseconftext(t):
r"""Split config file into dictionary."""
conf = {}
t = ""
for l in t.splitlines():
if "=" in l:
kv = l.split("=")
conf[kv[0]] = kv[1]
return conf
#def updateDhcpdConf(iface, wifimode):
# # read from source
# logger.debug("writing dhcpd.conf for iface={0} mode={1}".format(iface,wifimode))
# if "linux" in sys.platform:
# if wifimode in ["ap", "client"]:
# with open("dhcpcd-"+wifimode+".conf", "r") as f:
# dhcpcdconf = f.readlines()
# for l in dhcpcdconf:
# if l.startswith("interface"):
# l = "interface " + iface
# with open("/tmp/dhcpcd.conf", "w") as f:
# f.writelines(dhcpcdconf)
# try:
# subprocess.run(["sudo", "cp", "/tmp/dhcpcd.conf", "/etc/dhcpcd.conf"], check=True)
# except subprocess.CalledProcessError:
# logger.error("could not copy dhcpcd.conf")
# else:
# logger.warning("bad wifi mode specified: " + wifimode)
# else:
# logger.warning("no dhcpcd.conf on this platform")
def readHostapd():
"""Read hostapd.conf file, ensure it's complete (fill with defaults if not) and return dict."""
conf = {}
if "linux" in sys.platform:
try:
# using cat, because python file read has trouble with file permissions
hostapdtext = subprocess.run(["cat", "/etc/hostapd/hostapd.conf"], capture_output=True, text=True, check=True)
conf = _parseconftext(hostapdtext)
except subprocess.CalledProcessError:
logger.error("could not read hostapd.conf - using default")
conf = copy.deepcopy(_hostapdconfdefault)
else:
# dummy - return global memory version without reading anything
logger.warning("no hostapd.conf - returning internal copy only")
conf = copy.deepcopy(_hostapdconfdefault)
# ensure whatever is read is complete (fill with defaults)
changed = False
for dk, dv in _hostapdconfdefault.items():
if not dk in conf:
conf[dk] = dv
changed = True
if changed:
writeHostapd(conf)
logger.debug("read hostapdconf: " + str(conf))
return conf
def writeHostapd(conf=None):
"""Write hostapd.conf file."""
needtochange = False
if conf:
global _wifimanagerlock
with _wifimanagerlock:
global _currentwifimode
if "linux" in sys.platform:
logger.debug("writing hostapdconf: " + str(conf))
with open("/tmp/hostapd.conf", "w") as f:
f.write(_makeconftext(conf))
try:
subprocess.run(["sudo", "cp", "/tmp/hostapd.conf", "/etc/hostapd/hostapd.conf"], check=True)
except subprocess.CalledProcessError:
logger.error("could not copy hostapd.conf")
if _currentwifimode == "ap":
# restart ap mode
needtochange = True
else:
# dummy - return global memory version without reading anything
logger.warning("no hostapd.conf - will not write")
if needtochange:
wifidetailschangedevent.set()
_doAPMode()
def updateHostapd(apssid, appass):
"""Update ssid and password settings in hostapd (no effect if unchanged)."""
modified = False
apssid = str(apssid)
appass = str(appass)
global _wifimanagerlock
conf = readHostapd()
with _wifimanagerlock:
if not apssid == conf["ssid"]:
conf["ssid"] = apssid
modified = True
if not appass == conf["wpa_passphrase"]:
conf["wpa_passphrase"] = appass
modified = True
if modified:
writeHostapd(conf)
else:
logger.debug("no need to update hostapd; details not changed")
def getChannel(freq):
"""Convert wifi frequency to channel number."""
if 2412 <= freq <= 2472:
return int((freq - 2412)/5)+1
elif freq == 2484:
return 14
elif 4915 <= freq <= 4980:
return int((freq-4915)/5)+183
elif 5035 <= freq <= 5885:
return int((freq - 5035)/5)+7
else:
return 0
## MODULE FUNCTIONS ##
def getNetworks():
"""Get current wifi client list."""
networks = []
iface = settings.getSettingValue("netiface")
if "linux" in sys.platform:
# get list of network indices & ssids
cp = subprocess.run(["wpa_cli", "-i", iface, "list_networks"], capture_output=True, text=True)
if "FAIL" in cp.stdout:
logger.error("could not list networks")
else:
lines = cp.stdout.splitlines()
for l in lines:
if not l.startswith("network id"):
lsplit = l.split()
network = {"id":int(lsplit[0]), "ssid":lsplit[1]}
networks.append(network)
cp = subprocess.run(["wpa_cli", "-i", iface, "status"], capture_output=True, text=True)
if not "FAIL" in cp.stdout:
lines = cp.stdout.strip().split("\n")
for l in lines:
parts = l.strip().split("=")
if len(parts)==2 and parts[0]=="id":
connectedid = int(parts[1])
for n in networks:
n["connected"] = bool(n["id"] == connectedid)
break
else:
for n in networks:
n["connected"] = False
logger.error("could not get wifi status")
else:
logger.error("cannot access wifi config")
global _dummynetworks
networks = _dummynetworks
return networks
def scanNetworks():
"""Scan for wifi networks."""
scannetworks = []
iface = settings.getSettingValue("netiface")
global _wifimanagerlock
with _wifimanagerlock:
if "linux" in sys.platform:
cp = subprocess.run(["wpa_cli", "-i", iface, "scan"], capture_output=True, text=True)
if "OK" in cp.stdout:
cp2 = subprocess.run(["wpa_cli", "-i", iface, "scan_results"], capture_output=True, text=True)
if cp2.returncode == 0:
lines = cp2.stdout.strip().split("\n")
i = 0
for l in lines:
if len(l) > 0 and not l.startswith("bssid"):
parts = l.split(None,4)
flags = parts[3].strip("[]").split("][")
if len(parts)==5: # has SSID (4-part entries have blank SSID)
network = {"bssid":parts[0],"freq":int(parts[1]),"rssi":int(parts[2]),"flags":flags,"ssid":parts[4],"id":i}
network["channel"] = getChannel(network["freq"])
scannetworks.append(network)
i = i + 1
else:
logger.error("could not retrieve scanned networks")
else:
logger.error("could not scan wifi networks")
else:
logger.error("cannot access wifi config")
global _dummyscanresult
scannetworks = _dummyscanresult
return scannetworks
def removeNetwork(netindex):
"""Remove network from the wifi client list."""
global _wifimanagerlock
iface = settings.getSettingValue("netiface")
with _wifimanagerlock:
# remove network and save config
if "linux" in sys.platform:
cp = subprocess.run(["wpa_cli", "-i", iface, "remove_network", str(netindex)], capture_output=True, text=True)
if not "OK" in cp.stdout:
logger.error("could not delete network " + str(netindex))
cp = subprocess.run(["wpa_cli", "-i", iface, "save_config"], capture_output=True, text=True)
if not "OK" in cp.stdout:
logger.error("error saving wifi config")
else:
logger.error("cannot access wifi config")
global _dummynetworks
for n in _dummynetworks:
if n["id"] == netindex:
_dummynetworks.remove(n)
def addNetwork(ssid, psk=None):
"""Add a network to the wifi client list."""
netindex = -1
if not ssid or ssid=="":
return netindex
iface = settings.getSettingValue("netiface")
global _wifimanagerlock
with _wifimanagerlock:
# add network
if "linux" in sys.platform:
cp = subprocess.run(["wpa_cli", "-i", iface, "add_network"], capture_output=True, text=True)
if cp.returncode == 0:
netindex = int(cp.stdout.strip())
logger.debug("netindex={0}".format(netindex))
allok = True
cp2 = subprocess.run(["wpa_cli", "-i", iface, "set_network", str(netindex), "ssid", "\""+str(ssid)+"\""], capture_output=True, text=True)
if "FAIL" in cp2.stdout:
allok = False
logger.debug("set ssid fail: " + cp2.stdout)
if psk:
cp2 = subprocess.run(["wpa_cli", "-i", iface, "set_network", str(netindex), "psk", "\""+str(psk)+"\""], capture_output=True, text=True)
if "FAIL" in cp2.stdout:
allok = False
logger.debug("set psk fail: " + cp2.stdout)
else:
logger.debug("no psk specified; making this an open network")
cp2 = subprocess.run(["wpa_cli", "-i", iface, "set_network", str(netindex), "key_mgmt", "NONE"], capture_output=True, text=True)
if "FAIL" in cp2.stdout:
allok = False
logger.debug("set key_mgmt fail: " + cp2.stdout)
cp2 = subprocess.run(["wpa_cli", "-i", iface, "set_network", str(netindex), "ssid", "\""+str(ssid)+"\""], capture_output=True, text=True)
if "FAIL" in cp2.stdout:
allok = False
logger.debug("set ssid fail: " + cp2.stdout)
cp2 = subprocess.run(["wpa_cli", "-i", iface, "enable_network", str(netindex)], capture_output=True, text=True)
if "FAIL" in cp2.stdout:
allok = False
logger.debug("enable network fail: " + cp2.stdout)
if allok:
cp = subprocess.run(["wpa_cli", "-i", iface, "save_config"], capture_output=True, text=True)
if not "OK" in cp.stdout:
logger.error("error saving wifi config")
else:
logger.error("error setting ssid/psk for wifi")
else:
logger.error("error adding wifi network")
else:
logger.error("cannot access wifi config")
indexused = []
global _dummynetworks
for n in _dummynetworks:
indexused.append(n["id"])
for i in range(0,20):
if not i in indexused:
netindex = i
_dummynetworks.append({"id":i, "ssid":ssid, "connected":False})
break
return netindex
def _doAPMode():
"""Change to AP mode - call this in a thread, takes a while."""
newmode = "unknown"
iface = settings.getSettingValue("netiface")
global _wifimanagerlock
with _wifimanagerlock:
if "linux" in sys.platform:
lp = logpipe.LogPipe(jjlogger.DEBUG, logger)
badcalls = []
#cp = subprocess.run(["sudo", "dhclient", iface, "-x"], check=False, stderr=lp, stdout=lp)
#if not cp.returncode == 0:
# badcalls.append("dhclient -x")
cp = subprocess.run(["wpa_cli", "-i", iface, "disconnect"], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("wpa_cli")
cp = subprocess.run(["sudo", "ip", "link", "set", "dev", iface, "down"], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("ip link set")
cp = subprocess.run(["sudo", "ip", "addr", "add", jjcommon.ap_addr+"/25", "dev", iface], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("ip addr add")
#updateDhcpdConf(iface, "ap")
cp = subprocess.run(["sudo", "systemctl", "daemon-reload"], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("daemon-reload")
#cp = subprocess.run(["sudo", "systemctl", "restart", "dhcpcd.service"], check=True, stderr=lp, stdout=lp)
#if not cp.returncode == 0:
# badcalls.append("restart dhcpcd")
cp = subprocess.run(["sudo", "systemctl", "restart", "dnsmasq.service"], check=True, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("restart dnsmasq")
cp = subprocess.run(["sudo", "systemctl", "restart", "hostapd.service"], check=True, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("restart hostapd")
if len(badcalls) == 0:
newmode = "ap"
logger.debug("wifi mode succesfully set to ap")
else:
logger.error("error when changing to ap mode: " + str(badcalls))
newmode = "unknown"
lp.close()
else:
logger.warning("cannot change wifi mode")
global _currentwifimode
_currentwifimode = newmode
def _doClientMode():
"""Change to client mode - call this in a thread; takes a while."""
newmode = "unknown"
iface = settings.getSettingValue("netiface")
global _wifimanagerlock
with _wifimanagerlock:
if "linux" in sys.platform:
lp = logpipe.LogPipe(jjlogger.DEBUG, logger)
badcalls = []
cp = subprocess.run(["sudo", "systemctl", "stop", "hostapd.service"], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("stop hostapd")
cp = subprocess.run(["sudo", "systemctl", "stop", "dnsmasq.service"], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("stop dnsmasq")
cp = subprocess.run(["sudo", "ip", "link", "set", "dev", iface, "down"], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("ip link down")
cp = subprocess.run(["sudo", "ip", "addr", "flush", "dev", iface], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("ip addr flush")
cp = subprocess.run(["wpa_cli", "-i", iface, "reconfigure"], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("wpa_cli reconfigure")
cp = subprocess.run(["sudo", "systemctl", "daemon-reload"], check=False, stderr=lp, stdout=lp)
#updateDhcpdConf(iface, "ap")
if not cp.returncode == 0:
badcalls.append("daemon-reload")
cp = subprocess.run(["sudo", "systemctl", "restart", "dhcpcd.service"], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("restart dhcpcd")
#cp = subprocess.run(["sudo", "dhclient", iface, "-x"], check=False, stderr=lp, stdout=lp)
#if not cp.returncode == 0:
# badcalls.append("dhclient -x")
cp = subprocess.run(["sudo", "dhcpcd", "-N", iface], check=False, stderr=lp, stdout=lp)
if not cp.returncode == 0:
badcalls.append("dhcpd renew")
if len(badcalls) == 0:
newmode = "client"
logger.debug("wifi mode succesfully set to client")
else:
newmode = "unknown"
logger.error("unsuccessful changing to client mode")
wifidetailschangedevent.set()
lp.close()
else:
logger.warning("cannot change wifi mode")
global _currentwifimode
_currentwifimode = newmode
def reconfigureWifi():
"""Asks wpa_cli to reconfigure wifi interface (i.e. reconnect)."""
if "linux" in sys.platform:
iface = settings.getSettingValue("netiface")
global _wifimanagerlock, _currentwifimode
with _wifimanagerlock:
if _currentwifimode == "client":
try:
subprocess.run(["wpa_cli", "-i", iface, "reconfigure"], check=True)
except subprocess.CalledProcessError:
logger.error("unsuccessful reconfiguring wifi")
else:
wifidetailschangedevent.set()
else:
logger.warning("cannot reconfigure wifi; in AP mode")
else:
logger.error("cannot reconfigure wifi")
_modechangefuncs = {"ap":_doAPMode, "client":_doClientMode}
def setWifiMode(newwifimode):
"""Set wifi mode to "ap" or "client"."""
global _wifimanagerlock, _changethread, _targetwifimode, _modechangefuncs, _currentwifimode
if _changethread and _changethread.is_alive():
logger.warning("mode change currently in progress. will ignore request to change to " + newwifimode)
else:
if _currentwifimode == "changing":
logger.warning("wifi mode currently changing; request ignored")
elif (newwifimode == _currentwifimode):
logger.info("wifi mode unchanged")
elif newwifimode == "ap" or newwifimode == "client":
logger.info("wifi mode changing to " + newwifimode)
with _wifimanagerlock:
_targetwifimode = newwifimode
_currentwifimode = "changing"
_changethread = threading.Thread(target=_modechangefuncs[newwifimode], daemon=True)
_changethread.start()
else:
logger.info("invalid wifi mode, no change")
def getWifiMode():
"""Get current wifi mode, "ap or "client"."""
global _currentwifimode
thewifimode = _currentwifimode
return thewifimode
def checkIfInClientMode():
"""Check wpa_cli and update mode if in client mode (for boot without reconfiguring)."""
if "linux" in sys.platform:
global _currentwifimode
if not _currentwifimode in ["client", "ap"]:
wifistatus = getWifiStatus()
if wifistatus["wpa_state"] == "COMPLETED":
logger.debug("Assuming wifi in client mode.")
with _wifimanagerlock:
_currentwifimode = "client"
else:
logger.warning("cannot check if in client mode on this platform")
def getDHCPDStatus():
"""Get DHCPCD dump"""
# get dhcpcd dump
dhcpdstatus = {}
if "linux" in sys.platform:
iface = settings.getSettingValue("netiface")
cp = subprocess.run(["dhcpcd", "-U", iface], capture_output=True, text=True)
if not "FAIL" in cp.stdout:
lines = cp.stdout.strip().split("\n")
for l in lines:
parts = l.strip().split("=")
if len(parts)==2:
dhcpdstatus[parts[0]] = parts[1]
else:
logger.warning("cannot retrieve dhcpd status on this platform")
logger.debug("dhcpdstatus = " + str(dhcpdstatus))
return dhcpdstatus
def getWifiStatus():
"""Get wifi status using wpa_cli, plus rdns lookup name."""
wifistatus = {}
if "linux" in sys.platform:
iface = settings.getSettingValue("netiface")
cp = subprocess.run(["wpa_cli", "-i", iface, "status"], capture_output=True, text=True)
if not "FAIL" in cp.stdout:
lines = cp.stdout.strip().split("\n")
for l in lines:
parts = l.strip().split("=")
if len(parts)==2:
wifistatus[parts[0]] = parts[1]
# rdns lookup for domain name - gets the authoritative domain name for the device
if "ip_address" in wifistatus:
cp = subprocess.run(["hostname", "-A"], capture_output=True, text=True)
if cp.returncode == 0:
wifistatus["dnsname"] = cp.stdout.strip()
else:
logger.warning("cannot retrieve IP address on this platform")
logger.debug("wifistatus = " + str(wifistatus))
return wifistatus
_wifistatusmonitorthread = None
_wifistatusmonitorquit = threading.Event()
def startWifiStatusMonitor():
"""Start monitoring change of wpa_cli status, trigger event on change."""
global _wifistatusmonitorthread, _wifistatusmonitorquit
if not (_wifistatusmonitorthread and _wifistatusmonitorthread.is_alive()):
_wifistatusmonitorquit.clear()
_wifistatusmonitorthread = threading.Thread(target=_runWifiStatusMonitor, daemon=True)
_wifistatusmonitorthread.start()
def stopWifiStatusMonitor():
"""Stop monitoring change of wpa_cli status."""
global _wifistatusmonitorthread, _wifistatusmonitorquit
if _wifistatusmonitorthread and _wifistatusmonitorthread.is_alive():
_wifistatusmonitorquit.set()
_wifistatusmonitorthread.join()
def _runWifiStatusMonitor():
logger.debug("wifi status monitor started")
oldwifistatus = {}
while not _wifistatusmonitorquit.is_set():
newwifistatus = getWifiStatus()
for k,v in newwifistatus.items():
if not (k in oldwifistatus):
logger.info("{0}={1} added".format(k,v))
wifidetailschangedevent.set() # something added or changed, send signal
break # look nae further
elif not (oldwifistatus[k] == v):
logger.info("{0} changed from {1} to {2}".format(k,oldwifistatus[k],v))
wifidetailschangedevent.set() # something added or changed, send signal
break # look nae further
oldwifistatus = copy.copy(newwifistatus)
sleep(2)
logger.debug("wifi status monitor stopped")
def getWifiInterfaces():
"""Get list of wifi interfaces available using wpa_cli."""
ifaces = []
if "linux" in sys.platform:
cp = subprocess.run(["wpa_cli", "interface"], capture_output=True, text=True)
if cp.returncode == 0:
lines = cp.stdout.splitlines()
if len(lines) > 2:
for i in range(2,len(lines)):
ifaces.append(lines[i])
else:
logger.warning("Unable to fetch interfaces on this platform.")
logger.debug("ifaces found: " + str(ifaces))
return ifaces
def getHostname():
"""Get device hostname."""
hostname = None
if "linux" in sys.platform:
cp = subprocess.run(["hostname"], capture_output=True, text=True)
if cp.returncode == 0:
hostname = cp.stdout.strip()
logger.debug("hostname: " + hostname)
else:
logger.warning("Unable to fetch hostname on this platform")
return hostname
def setHostname(hostname):
"""Set device hostname."""
if hostname:
if "linux" in sys.platform:
hostname = str(hostname)
currenthostname = getHostname()
if hostname == currenthostname:
logger.debug("hostname already {0}. not changing".format(hostname))
else:
logger.debug("setting hostname to: " + hostname)
global _wifimanagerlock
with _wifimanagerlock:
lp = logpipe.LogPipe(jjlogger.DEBUG, logger)
try:
#sudo raspi-config nonint do_hostname
subprocess.run(["sudo", "raspi-config", "nonint", "do_hostname", hostname], check=True, stderr=lp, stdout=lp)
except subprocess.CalledProcessError:
logger.error("unsuccessful changing hostname")
else:
wifidetailschangedevent.set()
lp.close()
else:
logger.warning("cannot change hostname on this platform")