A Swift command-line tool to programmatically manage bandwidth rules on Grandstream WiFi access points. Perfect for home automation, parental controls, or dynamic network management.
- List bandwidth rules - View all configured rules with their settings
- Add/Update rules - Create new rules or modify existing ones
- Delete rules - Remove rules by name or MAC address
- Aliases support - Use friendly names instead of MAC addresses
- Cross-platform - Works on macOS and Linux
I want to throttle the bandwidth of specific wifi devices using my home automation system. Therefore I need a cli tool to change bandwidth rules programmatically. Grandstream supports schedules, but I need to (un)throttle things on demand.
Why would anyone do that? Well, think of the Apple TV. It still works, but cannot stream movies at 96kb/s. Also iPads, smartphones etc. It works somehow, but YouTube, TikTok etc. become unusable at low bandwidths. Did you say 'bad parenting'? Well, I call it a challenge for my kids to learn some things about networking 😬
- macOS: macOS 13+ with Swift 6.2+ (Xcode 16+)
- Linux: Swift 6.2+ with FoundationNetworking
- Access Point: Grandstream GWN series AP
swift buildFor release build:
swift build -c release# Build release version
swift build -c release
# Copy to a location in your PATH
cp .build/release/gwncli /usr/local/bin/gwncli list \
--url "https://gwn_c074ad7b2950.local" \
--username admin \
--password yourpasswordgwncli set \
--url "https://gwn_c074ad7b2950.local" \
--username admin \
--password yourpassword \
--mac AA:BB:CC:DD:EE:FF \
--ssid ssid0 \
--drate 96Kbps \
--urate 96KbpsNote: Upload/download rates must be expressed as Mbps or Kbps (case-sensitive).
By rule name:
gwncli delete \
--url "https://gwn_c074ad7b2950.local" \
--username admin \
--password yourpassword \
--rule-name rule4By MAC address (deletes all rules for that device):
gwncli delete \
--url "https://gwn_c074ad7b2950.local" \
--username admin \
--password yourpassword \
--mac AA:BB:CC:DD:EE:FFCreate a file ~/.gwnaliases.txt with MAC-to-name mappings:
AA:BB:CC:DD:EE:FF Kids-iPad
11:22:33:44:55:66 AppleTV
Then use the --aliases flag:
gwncli list \
--url "https://gwn_c074ad7b2950.local" \
--username admin \
--password yourpassword \
--aliases ~/.gwnaliases.txtOutput will show friendly names:
rule0 [enabled] U: 96Kbps D:96Kbps mac: aa:bb:cc:dd:ee:ff (Kids-iPad) SSID: ssid0 "Main-WiFi"
Use --log-level to control verbosity (1=fatal, 5=debug):
gwncli list --url "..." --username admin --password pass --log-level 5Grandstream APs use self-signed certificates. On macOS, the tool ignores certificate warnings. On Linux, URLCredential(trust:) is unavailable.
Workaround: Set up nginx as a reverse proxy with proxy_ssl_verify off;:
server {
listen 443 ssl;
server_name gwn-proxy.local;
location / {
proxy_pass https://gwn_c074ad7b2950.local;
proxy_ssl_verify off;
}
}Then point gwncli to your proxy instead.
Access control example for network 192.168.1.0/24. This assumes your current public v4/v6 IP can be found in /etc/nginx/snippets/ipv4-public-address.conf and /etc/nginx/snippets/ipv6-network.conf:
server {
listen 443 ssl;
server_name gwn-proxy.local;
# SSL certificate configuration
ssl_certificate /etc/letsencrypt/live/gwn-proxy.local/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gwn-proxy.local/privkey.pem;
location / {
# Allow local network and your public IP only
satisfy any;
allow 192.168.1.0/24;
allow fd00::/8;
include /etc/nginx/snippets/ipv4-public-address.conf;
include /etc/nginx/snippets/ipv6-network.conf;
deny all;
# Proxy to Grandstream AP
proxy_pass https://gwn_c074ad7b2950.local;
proxy_ssl_verify off;
}
}Run tests:
swift testThe test suite includes JSON parsing tests and integration test helpers.
This is a personal project for my own use, but I'm happy to receive feedback, bug reports, or suggestions! Feel free to open an issue if you find something that could be improved.
MIT License - see LICENSE file for details.