Introduction
The original goal for this project was very specific: I wanted to send SMS alerts from Home Assistant through a GL.iNet router.
Not push notifications. Not email. Not something that depended on a phone app behaving itself. I wanted Home Assistant to be able to send an actual text message to anyone when something important happened.
That was the starting point.
Then, as usually happens with “small” projects, the scope widened. If Home Assistant could talk to the router for SMS, it could also read router state. If it could read router state, it could expose devices, VPNs, WiFi, cellular status, firewall rules, and diagnostics.
What the Project Is
`ha-glinet` is a Home Assistant integration for GL.iNet routers running 4.x firmware.
It exposes router features as native Home Assistant entities and services, including:
– SMS sending, inbox viewing, refreshing, and deleting.
– Router status sensors.
– Connected device tracking.
– WiFi interface controls.
– System LED control.
– WireGuard, OpenVPN, Tailscale, and ZeroTier controls.
– Optional cellular modem data.
– Repeater mode tools.
– Fan monitoring and threshold control.
– Firewall, DMZ, port forwarding, and WAN access controls.
– Sanitized diagnostics for troubleshooting.
The idea is simple: make the router feel like a normal part of Home Assistant instead of a separate box you only manage through its own admin page.
1) Why SMS Was the Real Starting Point
The personal reason for building this was SMS alerting.
Home Assistant is great at notifications, but most notification systems still assume the person receiving the alert has the right app installed, working internet, working push permissions, and a phone that has not decided to silently ignore everything.
SMS is boring, but boring is useful.
With a GL.iNet router that supports cellular and SMS, Home Assistant can send text alerts directly through the router. That opens up simple but powerful use cases:
– Send an alarm alert to multiple people.
– Notify someone without requiring the Home Assistant app.
– Send outage messages when internet access is unstable.
– Use cellular SMS as a fallback notification path.
– Alert family members, neighbours, or anyone else by phone number.
That was the feature I actually wanted.
The rest of the integration grew around making that reliable.
2) Working With GL.iNet on the API
One of the more interesting parts of this project was that the GL.iNet API documentation was not public.
To build the integration properly, I had to reach out to GL.iNet directly. They provided a list of available API modules that I could pick from, which became the starting point for mapping out what the integration could realistically support.
They also seemed genuinely enthusiastic about the idea of an all-in-one Home Assistant solution. At the time, GL.iNet support in Home Assistant was fragmented across smaller integrations and narrower use cases. The goal with `ha-glinet` was different: one integration that could cover router status, clients, SMS, cellular, VPNs, repeater mode, firewall tools, and diagnostics in a single place.
That collaboration made a big difference. Without access to the API module list, this would have been a much messier process of guessing, sniffing, and hoping firmware updates did not move the furniture around too much.
3) Authentication Was Not Just “Send Password, Get Token”
The GL.iNet API does not use a simple username/password request.
Authentication uses a challenge-response flow. In plain English, the integration has to:
1. Ask the router for a login challenge.
2. Read the algorithm, salt, and nonce returned by the router.
3. Generate the correct password hash.
4. Combine that with the username and nonce.
5. Send the final login request.
6. Store the session token returned by the router.
That token then has to be used for authenticated JSON-RPC calls.
This was one of the trickier parts of the project because token handling affects everything else. If authentication is flaky, the entire integration feels unreliable.
So `ha-glinet` refreshes the session proactively, retries when the router returns token errors, and triggers Home Assistant re-authentication when credentials really do need attention.
It is not glamorous code, but it is the plumbing that makes the integration feel stable.
4) Making It Feel Native in Home Assistant
I did not want this to feel like a script pretending to be an integration.
The project uses Home Assistant’s config flow, options flow, entity model, services, diagnostics, and DataUpdateCoordinator.
That means users can:
– Add the router through the Home Assistant UI.
– Configure optional features during setup.
– Adjust polling intervals.
– Enable only the modules they actually need.
– Use entities and services naturally in automations.
– Download diagnostics from the device page.
The router state is handled by a central hub object, which polls the router and shares typed data with the Home Assistant entities.
Polling is deliberately sequential rather than blasting the router with parallel requests. These devices are small routers, not database servers. Being gentle with the API makes the integration more reliable.
5) HACS Compliance Took Real Work
Making a Home Assistant custom integration work locally is one thing.
Making it clean enough for HACS is another.
The project needed the expected structure, metadata, manifest fields, versioning, documentation, branding assets, and release packaging. It also needed to behave like something people could install without reading the source code first.
That meant adding:
– A proper `manifest.json`.
– HACS metadata.
– Config flow support.
– Documentation for setup and features.
– Repository structure that matches Home Assistant expectations.
– Release ZIPs that HACS can install cleanly.
– Version consistency between project files.
This is the less exciting side of building integrations, but it matters. HACS support turns the project from “copy this folder and hope” into something people can actually install and update sensibly.
6) CI and Release Pipelines
Once the project started growing, manual checking was not enough.
The repository now uses GitHub Actions for CI and release automation.
CI checks include:
– JSON validation.
– Python compilation.
– Unit tests.
– Ruff linting.
– Version consistency checks.
The release workflow builds a HACS-friendly package and publishes GitHub releases from versioned commits.
This helps keep changes boring in the best way. If a router module changes, tests run. If packaging breaks, CI catches it. If a release is created, the artifact is built consistently.
For a project that talks to real network hardware, boring releases are a gift.
7) Optional Features Without Breaking Everything
GL.iNet routers vary a lot.
One model may have cellular support. Another may not. One may expose fan controls. Another may not. Some users care about WireGuard, others only want SMS, and others just want device tracking.
So the integration is built around optional feature groups.
If you do not enable SMS, it does not poll SMS. If your router does not support cellular, the core integration still works. If a feature is unsupported, it should be skipped cleanly rather than making setup fail.
That design keeps the integration useful across different routers without pretending every device has the same capabilities.
8) The Useful Everyday Features
Although SMS was the personal reason for the project, the wider router integration became useful in its own right.
Some of the features I use or care about most are:
– Knowing which devices are connected.
– Seeing router CPU, memory, uptime, and WAN state.
– Monitoring cellular signal and network status.
– Controlling VPN tunnels from Home Assistant.
– Managing repeater connections.
– Sending SMS alerts through automations.
– Downloading sanitized diagnostics when something behaves oddly.
The result is that the router becomes part of the smart home instead of just the thing underneath it.
Lessons from This Project
A few things stood out while building `ha-glinet`:
– SMS is old technology, but it is still incredibly useful for alerts.
– Private API documentation changes the shape of a project very quickly.
– Authentication flows deserve proper attention early.
– Router APIs vary more than you expect.
– HACS compliance is work, but it makes the project much easier to share.
– CI is worth setting up before the project gets too comfortable breaking itself.
– Optional features should fail softly.
– Local control is still the best control.
Closing Thoughts
`ha-glinet` started because I wanted Home Assistant to send SMS alerts through my GL.iNet router.
That one requirement turned into a full local integration with router monitoring, connected device tracking, VPN controls, repeater management, firewall tools, diagnostics, HACS packaging, and automated CI releases.
The most encouraging part was that GL.iNet were receptive to the idea. They understood why an all-in-one Home Assistant integration would be more useful than a set of fragmented pieces, and their API guidance helped make the project much more practical.
The project is not trying to replace the GL.iNet admin panel. It is trying to bring the useful parts of the router into Home Assistant, where they can be monitored, automated, and combined with everything else in the home.
And honestly, that is the fun part. Once the router becomes automation-aware, it stops being just networking hardware and starts becoming part of the system.
As of today. There has been approximately 450 installs of my integration. It’s a thought that scares me but also makes me excited that I’ve finally created something that contributes back to the community that i spend so much time around.
Learn More