Skip to content

Commit 381dc13

Browse files
committed
Merge remote-tracking branch 'origin/master' into py3
2 parents ebec6da + 3a3f26d commit 381dc13

File tree

6 files changed

+163
-39
lines changed

6 files changed

+163
-39
lines changed

INSTALL.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
**INSTALLATION**
2+
3+
* Create a Python 3 venv - the included service unit expects the venv to be in /usr/local/netconnectd/venv and activate it.
4+
* Install `wifi` from `https://github.com/ManuelMcLure/wifi.git` branch `master`
5+
* Install `netconnectd_mrbeam` from `https://github.com/ManuelMcLure/netconnectd_mrbeam.git` branch `master`.
6+
* Copy `netconnectd.yaml` from `extras` to the `/etc/netconnectd.conf.d/` directory.
7+
* Copy `netconnectd.service` from `extras` to the `/etc/systemd/system/` directory
8+
* Enable the netconnectd systemd unit with
9+
```
10+
systemctl enable netconnectd.service
11+
```
12+
* Disable the `dnsmasq` and `wpa_supplicant` services:
13+
```
14+
systemctl disable dnsmasq.service
15+
systemctl disable wpa_supplicant
16+
```
17+
* Copy `eth0` from `extras` to the `/etc/network/interfaces.d/` directory.
18+
* Start the daemon with
19+
```
20+
systemctl start netconnectd.service
21+
```
22+
* Install into your OctoPrint venv the version of `OctoPrint-Netconectd` from `https://github.com/ManuelMcLure/OctoPrint-Netconnectd.git` branch `master`.

extras/eth0

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
iface eth0 inet dhcp

extras/netconnectd.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ interfaces:
1717
# # interval between link checks
1818
# interval: 10
1919

20+
# Configure how the list of available WiFi access points appeard
21+
ap_list:
22+
# Don't show access points with hidden SSID
23+
filter_hidden_ssid: True
2024

2125
# access point configuration
2226
ap:
@@ -57,6 +61,12 @@ ap:
5761
# whether to create a true AP forwarding to the wired interface, defaults
5862
# to false
5963
#forwarding_to_wired: false
64+
65+
# whether to create the AP even if wired connectivity is available
66+
enable_if_wired: true
67+
68+
# should this redirect all DNS requests to the AP address?
69+
captive_portal: true
6070

6171
# wifi configuration
6272
wifi:
@@ -74,6 +84,9 @@ wifi:
7484
# Recommended, but depends on the rfkill command to be available
7585
kill: true
7686

87+
# default country setting
88+
default_country: DE
89+
7790
# various paths of tools used
7891
paths:
7992
# path to hostapd executable

netconnectd/server.py

Lines changed: 88 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -59,26 +59,12 @@ def get_country_list(cls):
5959
except Exception as e:
6060
print(e)
6161
country_list = [
62-
{"code": "US", "country": "United States"},
6362
{"code": "DE", "country": "Germany"},
63+
{"code": "US", "country": "United States"},
6464
]
65+
country_list.sort(key=lambda k: k["country"])
6566
return country_list
6667

67-
@classmethod
68-
def convert_cells(cls, cells):
69-
result = []
70-
for cell in cells:
71-
result.append(
72-
dict(
73-
ssid=cell.ssid,
74-
channel=cell.channel,
75-
address=cell.address,
76-
encrypted=cell.encrypted,
77-
signal=cell.signal if hasattr(cell, "signal") else None,
78-
)
79-
)
80-
return result
81-
8268
def __init__(
8369
self,
8470
server_address=None,
@@ -97,15 +83,18 @@ def __init__(
9783
ap_range=("10.250.250.100", "10.250.250.200"),
9884
ap_forwarding=False,
9985
ap_domain=None,
86+
ap_enable_if_wired=False,
10087
wifi_name="netconnect_wifi",
10188
wifi_free=False,
10289
wifi_kill=False,
90+
wifi_default_country="DE",
10391
path_hostapd="/usr/sbin/hostapd",
10492
path_hostapd_conf="/etc/hostapd/conf.d",
10593
path_dnsmasq="/usr/sbin/dnsmasq",
10694
path_dnsmasq_conf="/etc/dnsmasq.conf.d",
10795
path_interfaces="/etc/network/interfaces",
10896
path_interfaces_d="/etc/network/interfaces.d",
97+
filter_hidden_ssid=False,
10998
):
11099

111100
self.logger = logging.getLogger(__name__)
@@ -131,6 +120,9 @@ def exception_logger(exc_type, exc_value, exc_tb):
131120
self.ap_name = ap_name
132121
self.wifi_if = wifi_if
133122
self.wifi_name = wifi_name
123+
self.wifi_default_country = wifi_default_country
124+
self.filter_hidden_ssid = filter_hidden_ssid
125+
self.ap_enable_if_wired = ap_enable_if_wired
134126

135127
self.wifi_if_present = True
136128
try:
@@ -188,6 +180,7 @@ def exception_logger(exc_type, exc_value, exc_tb):
188180
self.server_address = server_address
189181

190182
# prepare access point configuration
183+
self.ap_ssid = ap_ssid
191184
self.logger.debug("Creating access point object and resetting configuration")
192185
self.access_point = self.AccessPoint.for_arguments(
193186
self.wifi_if,
@@ -242,20 +235,38 @@ def exception_logger(exc_type, exc_value, exc_tb):
242235
self.country_list = self.__class__.get_country_list()
243236

244237
def _link_monitor(self, interval=10, callback=None):
245-
former_link, reachable_devs = has_link()
238+
former_link, reachable_devs = has_link(self.logger)
246239

247240
self.logger.info("Starting up link monitor with interval %ds" % interval)
248241

249242
while True:
250243
try:
251244
with self.mutex:
252-
current_link, reachable_devs = has_link()
245+
current_link, reachable_devs = has_link(self.logger)
253246
callback(former_link, current_link, reachable_devs)
254247
time.sleep(interval)
255248
former_link = current_link
256249
except:
257250
self.logger.exception("Something went wrong inside the link monitor")
258251

252+
def convert_cells(self, cells):
253+
result = []
254+
for cell in cells:
255+
if (
256+
(not cell.ssid) or cell.ssid == None or cell.ssid == ""
257+
) and self.filter_hidden_ssid:
258+
continue
259+
result.append(
260+
dict(
261+
ssid=cell.ssid,
262+
channel=cell.channel,
263+
address=cell.address,
264+
encrypted=cell.encrypted,
265+
signal=cell.signal if hasattr(cell, "signal") else None,
266+
)
267+
)
268+
return result
269+
259270
def _socket_monitor(self, server_address, callbacks=None):
260271
if not callbacks:
261272
callbacks = dict()
@@ -287,7 +298,7 @@ def _socket_monitor(self, server_address, callbacks=None):
287298
while True:
288299
chunk = connection.recv(16)
289300
if chunk:
290-
self.logger.info("Recv: %r" % chunk)
301+
self.logger.debug("Recv: %r" % chunk)
291302
buffer.append(chunk)
292303
if chunk.endswith(b"\x00"):
293304
break
@@ -311,7 +322,7 @@ def _socket_monitor(self, server_address, callbacks=None):
311322
else:
312323
response = ErrorResponse(result)
313324

314-
self.logger.info("Send: %s" % str(response))
325+
self.logger.debug("Send: %s" % str(response))
315326
connection.sendall(str(response).encode("utf-8") + b"\x00")
316327

317328
except:
@@ -496,7 +507,7 @@ def wifi_scan(self):
496507
self.cells = wifi.Cell.all(self.wifi_if)
497508

498509
self.logger.debug("Converting result of scan")
499-
return self.__class__.convert_cells(self.cells)
510+
return self.convert_cells(self.cells)
500511

501512
def find_cell(self, ssid, force=False):
502513
if not self.cells:
@@ -538,6 +549,16 @@ def start_wifi(self, enable_restart=True):
538549
try:
539550
self.wifi_connection.activate()
540551
self.logger.info("Connected to wifi %s" % self.wifi_connection_ssid)
552+
if self.logger.getEffectiveLevel() == logging.DEBUG:
553+
try:
554+
self.logger.debug("ifconfig {}".format(self.wifi_if))
555+
output = subprocess.check_output(["ifconfig",
556+
self.wifi_if]).decode("utf-8")
557+
lines = output.split("\n")
558+
for line in lines:
559+
self.logger.debug(line)
560+
except:
561+
pass
541562
return True
542563

543564
except wifi.scheme.WifiError as e:
@@ -636,7 +657,7 @@ def on_list_wifi_message(self, message):
636657

637658
if self.access_point.is_running():
638659
if self.cells:
639-
return True, self.__class__.convert_cells(self.cells)
660+
return True, self.convert_cells(self.cells)
640661
elif not message.force:
641662
return (
642663
False,
@@ -650,7 +671,7 @@ def on_list_wifi_message(self, message):
650671
# we have to refresh it manually
651672
self.wifi_scan()
652673

653-
return True, self.__class__.convert_cells(self.cells)
674+
return True, self.convert_cells(self.cells)
654675

655676
def on_configure_wifi_message(self, message):
656677
if not self.wifi_if_present:
@@ -705,6 +726,7 @@ def on_reset_message(self, message):
705726
def on_status_message(self, message):
706727
current_ssid, current_address = self.current_wifi
707728

729+
708730
wifi = wired = ap = False
709731
if (
710732
self.wifi_if_present
@@ -718,6 +740,9 @@ def on_status_message(self, message):
718740
if self.wired_if in self.last_reachable_devs:
719741
wired = True
720742

743+
if current_ssid == None and ap:
744+
current_ssid=self.ap_ssid
745+
721746
return True, dict(
722747
link=self.last_link,
723748
devs=self.last_reachable_devs,
@@ -737,26 +762,31 @@ def on_status_message(self, message):
737762
def on_link_change(self, former_link, current_link, current_devs):
738763
self.last_link = current_link
739764
self.last_reachable_devs = tuple(current_devs)
765+
wifi_link = self.wifi_if in current_devs
740766

741767
access_point_running = self.access_point.is_running()
742768
if current_link or access_point_running:
743769
if current_link and not former_link and not access_point_running:
744770
self.logger.debug("Link restored!")
745771
self.link_down_count = 0
746-
return
747-
748-
if self.link_down_count < self.linkmon_maxdown:
772+
elif self.link_down_count < self.linkmon_maxdown:
749773
self.logger.debug("Link down since %d retries" % self.link_down_count)
750774
self.link_down_count += 1
751775
return
752-
753-
if self.wifi_connection is not None:
776+
elif self.wifi_connection is not None:
754777
self.logger.info("Link down, got a configured wifi connection, trying that")
755778
if self.start_wifi(enable_restart=False):
756779
return
757780

758-
self.logger.info("Link still down, starting access point")
759-
self.start_ap()
781+
# Enable AP if we have no link OR if we have just wired and we want
782+
# the AP even in this case
783+
if not access_point_running:
784+
if not current_link:
785+
self.logger.info("Link still down, starting access point")
786+
self.start_ap()
787+
elif self.ap_enable_if_wired and not wifi_link:
788+
self.logger.info("Only wired link active, starting access point")
789+
self.start_ap()
760790

761791
def on_country_list_message(self, message):
762792
country = None
@@ -767,6 +797,8 @@ def on_country_list_message(self, message):
767797
if line.startswith("country="):
768798
country = line.split("=", 1)[1]
769799
break
800+
else:
801+
country = self.wifi_default_country
770802
except:
771803
pass
772804
return True, {
@@ -843,14 +875,17 @@ def start_server(config):
843875
ap_range=config["ap"]["range"],
844876
ap_forwarding=config["ap"]["forwarding_to_wired"],
845877
ap_domain=config["ap"]["domain"],
878+
ap_enable_if_wired=config["ap"]["enable_if_wired"],
846879
wifi_name=config["wifi"]["name"],
847880
wifi_free=config["wifi"]["free"],
848881
wifi_kill=config["wifi"]["kill"],
882+
wifi_default_country=config["wifi"]["default_country"],
849883
path_hostapd=config["paths"]["hostapd"],
850884
path_hostapd_conf=config["paths"]["hostapd_conf"],
851885
path_dnsmasq=config["paths"]["dnsmasq"],
852886
path_dnsmasq_conf=config["paths"]["dnsmasq_conf"],
853887
path_interfaces=config["paths"]["interfaces"],
888+
filter_hidden_ssid=config["ap_list"]["filter_hidden_ssid"],
854889
)
855890
s = Server(**kwargs)
856891
s.start()
@@ -977,6 +1012,11 @@ def dhcp_range(arg):
9771012
action="store_true",
9781013
help="Enable forwarding from AP to wired connection, disabled by default",
9791014
)
1015+
parser.add_argument(
1016+
"--ap-enable-if-wired",
1017+
action="store_true",
1018+
help="Enable AP even if we have a working wired connection",
1019+
)
9801020
parser.add_argument(
9811021
"--wifi-name",
9821022
help="Internal name to assign to Wifi config, defaults to 'netconnectd_wifi', you mostly won't have to set this",
@@ -991,6 +1031,10 @@ def dhcp_range(arg):
9911031
action="store_true",
9921032
help="Whether the wifi interface has to be killed before every configuration attmept, defaults to false",
9931033
)
1034+
parser.add_argument(
1035+
"--wifi-default-country",
1036+
help="What country to set in wpa_supplicant.conf by default",
1037+
)
9941038
parser.add_argument(
9951039
"--path-hostapd",
9961040
help="Path to hostapd executable, defaults to /usr/sbin/hostapd",
@@ -1011,11 +1055,20 @@ def dhcp_range(arg):
10111055
"--path-interfaces",
10121056
help="Path to interfaces configuration file, defaults to /etc/network/interfaces",
10131057
)
1058+
parser.add_argument(
1059+
"--path-interfaces-d",
1060+
help="Path to interfaces.d configuration folder, defaults to /etc/network/interfaces.d",
1061+
)
10141062
parser.add_argument(
10151063
"--daemon",
10161064
choices=["stop", "status"],
10171065
help="Control the netconnectd daemon, supported arguments are 'stop' and 'status'.",
10181066
)
1067+
parser.add_argument(
1068+
"--filter-hidden-ssid",
1069+
action="store_true",
1070+
help="Don't display access points with hidden SSIDs.",
1071+
)
10191072

10201073
args = parser.parse_args()
10211074

@@ -1114,6 +1167,8 @@ def dhcp_range(arg):
11141167
config["ap"]["domain"] = args.ap_domain
11151168
if args.ap_forwarding:
11161169
config["ap"]["forward_to_wired"] = True
1170+
if args.ap_enable_if_wired:
1171+
config["ap"]["enable_if_wired"] = True
11171172

11181173
if args.wifi_name:
11191174
config["wifi"]["name"] = args.wifi_name
@@ -1122,6 +1177,9 @@ def dhcp_range(arg):
11221177
if args.wifi_kill:
11231178
config["wifi"]["kill"] = True
11241179

1180+
if args.filter_hidden_ssid:
1181+
config["ap_list"]["filter_hidden_ssid"] = True
1182+
11251183
if args.path_hostapd:
11261184
config["paths"]["hostapd"] = args.path_hostapd
11271185
if args.path_hostapd_conf:

0 commit comments

Comments
 (0)