iwd: track per-network signal strength via Station.GetOrderedNetworks

Adds Iwd_Network.signal_dbm/have_signal and a signal_tier helper, and
calls Station.GetOrderedNetworks on station attach and on scan
completion to populate them. Enables signal-aware UI affordances.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
nemunaire 2026-04-09 11:59:48 +07:00
commit 29ded04f10
3 changed files with 71 additions and 1 deletions

View file

@ -2,9 +2,12 @@
#include "iwd_dbus.h"
#include "iwd_props.h"
#include "iwd_manager.h"
#include "iwd_network.h"
#include <stdlib.h>
#include <string.h>
static void _refresh_signals(Iwd_Device *d);
static Iwd_Station_State
_state_from_str(const char *s)
{
@ -36,7 +39,13 @@ _sta_prop_cb(void *data, const char *key, Eldbus_Message_Iter *v)
d->station_state = _state_from_str(s);
free(s);
}
else if (!strcmp(key, "Scanning")) { d->scanning = iwd_props_bool(v); }
else if (!strcmp(key, "Scanning"))
{
Eina_Bool was = d->scanning;
d->scanning = iwd_props_bool(v);
/* When a scan finishes, ask iwd for the ranked list with RSSI. */
if (was && !d->scanning) _refresh_signals(d);
}
else if (!strcmp(key, "ConnectedNetwork")) { free(d->connected_network); d->connected_network = iwd_props_str_dup(v); }
}
@ -108,6 +117,7 @@ iwd_device_attach_station(Iwd_Device *d)
d->has_station = EINA_TRUE;
d->sh_sta_props = eldbus_proxy_properties_changed_callback_add(
d->station_proxy, _on_sta_props_changed, d);
_refresh_signals(d);
}
}
@ -136,6 +146,45 @@ iwd_device_free(Iwd_Device *d)
free(d);
}
/* Reply to Station.GetOrderedNetworks: a(on) — list of (object_path, RSSI).
* RSSI is a 16-bit signed value in 100*dBm units. */
static void
_on_ordered_networks(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED)
{
Iwd_Device *d = data;
const char *en, *em;
if (eldbus_message_error_get(msg, &en, &em)) return;
Eldbus_Message_Iter *array = NULL;
if (!eldbus_message_arguments_get(msg, "a(on)", &array) || !array)
return;
const Eina_Hash *nets = d->manager ? iwd_manager_networks(d->manager) : NULL;
Eldbus_Message_Iter *entry;
Eina_Bool any = EINA_FALSE;
while (eldbus_message_iter_get_and_next(array, 'r', &entry))
{
const char *path = NULL;
int16_t rssi = 0;
if (!eldbus_message_iter_arguments_get(entry, "on", &path, &rssi)) continue;
if (!nets || !path) continue;
Iwd_Network *n = eina_hash_find(nets, path);
if (!n) continue;
n->signal_dbm = rssi;
n->have_signal = EINA_TRUE;
any = EINA_TRUE;
}
if (any && d->manager) iwd_manager_notify(d->manager);
}
static void
_refresh_signals(Iwd_Device *d)
{
if (!d || !d->station_proxy) return;
eldbus_proxy_call(d->station_proxy, "GetOrderedNetworks",
_on_ordered_networks, d, -1, "");
}
void
iwd_device_scan(Iwd_Device *d)
{

View file

@ -91,6 +91,19 @@ _on_connect_reply(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_
free(data);
}
int
iwd_network_signal_tier(const Iwd_Network *n)
{
if (!n || !n->have_signal) return 0;
/* iwd reports signal in 100*dBm. Cutoffs in dBm: -60/-67/-74/-80. */
int dbm = n->signal_dbm / 100;
if (dbm >= -60) return 4;
if (dbm >= -67) return 3;
if (dbm >= -74) return 2;
if (dbm >= -80) return 1;
return 1;
}
void
iwd_network_connect(Iwd_Network *n)
{

View file

@ -1,6 +1,7 @@
#ifndef IWD_NETWORK_H
#define IWD_NETWORK_H
#include <stdint.h>
#include <Eina.h>
#include <Eldbus.h>
@ -23,6 +24,10 @@ struct _Iwd_Network
Iwd_Security security;
Eina_Bool connected;
/* Signal strength in 100*dBm units (iwd convention). Valid iff have_signal. */
int16_t signal_dbm;
Eina_Bool have_signal;
Eldbus_Object *obj;
Eldbus_Proxy *proxy;
Eldbus_Signal_Handler *sh_props;
@ -35,6 +40,9 @@ void iwd_network_free(Iwd_Network *n);
void iwd_network_apply_props(Iwd_Network *n, Eldbus_Message_Iter *props);
/* 0 = unknown/no signal, 1..4 = weak..excellent. */
int iwd_network_signal_tier(const Iwd_Network *n);
void iwd_network_connect (Iwd_Network *n);
/* Forget acts on the KnownNetwork object referenced by this network. */
void iwd_network_forget (Iwd_Network *n);