Skip to content

Commit c7463c9

Browse files
committed
Add LED indicator
1 parent 3deda35 commit c7463c9

File tree

7 files changed

+55
-8
lines changed

7 files changed

+55
-8
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ Users will then be unable to access the API `http://your-device:9090/v1/connect`
3232

3333
Alternatively, if you would rather have your backend use specified ports instead of the host network, you can change the `PWC_HOST` environment variable to `172.17.0.1` and access the API from `http://172.17.0.1:9090/v1/connect`.
3434

35+
## LED Indicator
36+
Some devices - such as the Raspberry Pi series - have an LED that can be controlled. When your device is connected to Wi-Fi, Python Wi-Fi Connect turns the LED on. When disconnected or in Hotspot mode, it turns the LED off.
37+
38+
If you need to disable this feature to allow the LED to be used for other purposes, change the environment variable in the docker-compose.yml file to: `PWC_LED: "OFF"`.
39+
3540

3641
## Endpoints
3742
### http://your-device:9090/v1/connect

docker-compose.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ services:
1414
## Try to automatically set up a Wi-Fi network on first boot ##
1515
#PWC_SSID: "network-name" # Compulsory for this feature
1616
#USERNAME: "username" # Optional
17-
#PWC_PASSWORD: "your-password" # Optional. Must be 8 characters or more.
17+
#PWC_PASSWORD: "your-password" # Optional. Must be 8 characters or more.
18+
19+
## Enable/Disable LED interaction ##
20+
PWC_LED: "ON"
1821

1922
## Required System Variables ##
2023
DBUS_SYSTEM_BUS_ADDRESS: "unix:path=/host/run/dbus/system_bus_socket"
@@ -27,3 +30,4 @@ services:
2730
io.balena.features.dbus: '1'
2831
cap_add:
2932
- NET_ADMIN
33+
privileged: true # This can be removed if you do not need the LED indicator (see the docs for more info).

src/common/errors.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import logging
33

44
# Create custom logger
5-
logger = logging.getLogger('syslog')
65
syslog = logging.StreamHandler()
6+
logger = logging.getLogger('syslog')
77
logger.addHandler(syslog)
88

99
# When in development mode provide details in log of each line of code
@@ -19,6 +19,7 @@
1919
logger.setLevel(logging.INFO)
2020

2121
syslog.setFormatter(formatter)
22+
logger.propagate = False
2223

2324

2425
# Error classes for Flask-Restful

src/common/system.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import config
2+
import os
23
import subprocess
34
from common.errors import logger
45

@@ -20,3 +21,16 @@ def dnsmasq():
2021
subprocess.Popen(args)
2122
except Exception:
2223
logger.exception('Failed to start dnsmasq.')
24+
25+
26+
def led(mode):
27+
# Activate LED on compatible devices
28+
# 1 = on
29+
# 0 = off
30+
if "PWC_LED" in os.environ and os.environ['PWC_LED'].lower() == 'on':
31+
try:
32+
with open('/sys/class/leds/led0/brightness', 'w+') as f:
33+
f.write(str(mode))
34+
except Exception:
35+
# This is not possible on some devices.
36+
pass

src/common/wifi.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from common.errors import WifiNetworkManagerError
1010
from common.errors import WifiNoSuitableDevice
1111
from common.nm_dicts import get_nm_dict
12+
from common.system import led
1213

1314

1415
# Import DBus mainloop for NetworkManager use
@@ -108,7 +109,7 @@ def connect(conn_type=config.type_hotspot,
108109

109110
try:
110111
NetworkManager.Settings.AddConnection(conn_dict)
111-
logger.debug(f"Added connection of type {conn_type}")
112+
logger.info(f"Adding connection of type {conn_type}")
112113

113114
# Find this connection and its device
114115
connections = \
@@ -129,8 +130,11 @@ def connect(conn_type=config.type_hotspot,
129130
# Connect
130131
NetworkManager.NetworkManager.ActivateConnection(conn, dev, "/")
131132

133+
# If not a hotspot, log the connection SSID being attempted
134+
if conn_type != config.type_hotspot:
135+
logger.info(f"Attempting connection to {ssid}")
136+
132137
# Wait for ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
133-
logger.info("Waiting for connection to become active...")
134138
loop_count = 0
135139
while dev.State != NetworkManager.NM_DEVICE_STATE_ACTIVATED:
136140
time.sleep(1)
@@ -139,7 +143,14 @@ def connect(conn_type=config.type_hotspot,
139143
break
140144

141145
if dev.State == NetworkManager.NM_DEVICE_STATE_ACTIVATED:
142-
logger.info("Active.")
146+
logger.info("Connection active.")
147+
148+
# Activate the LED to indicate device is connected.
149+
if conn_type is not config.type_hotspot:
150+
led(1)
151+
else:
152+
led(0)
153+
143154
return True
144155
# If the current attempt is not already a hotspot attempt
145156
elif conn_type != config.type_hotspot:
@@ -179,6 +190,10 @@ def forget(create_new_hotspot=False, all_networks=False):
179190
connection_ids[config.ap_name].Delete()
180191
logger.debug(f"Deleted connection: {config.ap_name}")
181192

193+
# Disable LED indicating Wi-Fi is not active.
194+
led(0)
195+
196+
# If requested, create new Hotspot
182197
if create_new_hotspot:
183198
refresh_networks()
184199
connect()
@@ -196,6 +211,8 @@ def list_access_points():
196211
# button will be disabled.
197212
iw_status = refresh_networks(retries=1)
198213

214+
logger.debug('Fetching Wi-Fi networks.')
215+
199216
try:
200217
# Fetch dictionary of devices
201218
devices = dict([(x.DeviceType, x)
@@ -228,6 +245,8 @@ def list_access_points():
228245
ssids.append(item)
229246
tmp.append(item['ssid'])
230247

248+
logger.debug('Finished fetching Wi-Fi networks.')
249+
231250
# Return a list of available SSIDs and their security type,
232251
# or [] for none available.
233252
return ssids, iw_status

src/resources/wifi_routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import threading
2+
from common.errors import logger
23
from common.wifi import check_internet_status
34
from common.wifi import check_wifi_status
45
from common.wifi import connect
@@ -64,6 +65,7 @@ def post(self):
6465
request.get_json()
6566
['all_networks']})
6667

68+
logger.info('Removing connetion...')
6769
wifi_forget_thread.start()
6870

6971
return {'message': 'accepted'}, 202

src/run.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@
33
from common.errors import errors
44
from common.errors import logger
55
from common.system import dnsmasq
6+
from common.system import led
67
from common.wifi import auto_connect
78
from common.wifi import check_wifi_status
89
from common.wifi import connect
910
from common.wifi import refresh_networks
1011
from config import host
1112
from config import port
13+
from flask import Flask
14+
from flask_restful import Api
1215
from resources.system_routes import system_health_check
1316
from resources.wifi_routes import wifi_connect
1417
from resources.wifi_routes import wifi_connection_status
1518
from resources.wifi_routes import wifi_forget
1619
from resources.wifi_routes import wifi_list_access_points
17-
from flask import Flask
18-
from flask_restful import Api
1920
from waitress import serve
2021

2122

@@ -46,15 +47,16 @@
4647

4748
# If the Wi-Fi connection is not already active, start a hotspot
4849
if check_wifi_status():
50+
led(1)
4951
logger.info('Wi-Fi connection already established.')
5052
logger.info('Ready...')
5153
else:
54+
led(0)
5255
refresh_networks(retries=1)
5356
if config.auto_connect_kargs:
5457
logger.info('Attempting auto-connect...')
5558
auto_connect(**config.auto_connect_kargs)
5659
else:
57-
logger.info('Starting hotspot...')
5860
connect()
5961

6062
serve(app, host=host, port=port)

0 commit comments

Comments
 (0)