Expand description
Pairing Aranet sensors with BlueZ on Linux.
Before aranet-core connects to a sensor on Linux, it pairs the sensor if
BlueZ doesn’t list it as paired. Otherwise BlueZ asks for pairing by itself
on every connection: its battery plugin reads the sensor’s Battery Level,
which needs encryption. That request needs an agent. With none registered,
as on a headless host, BlueZ refuses it and the connection’s reads can stall
until they time out; a desktop’s agent shows a pairing dialog instead. Each
pairing is one short session:
- If the sensor refused to pair less than 10 minutes ago in this process
(
AuthenticationFailedorAuthenticationRejected, as when it wants a PIN), skip it and connect without pairing. - On aranet-core’s own runtime, open a private connection to the system bus
and read the sensor’s
org.bluez.Device1.Pairedproperty. A paired sensor ends the session. - Register a
NoInputNoOutputagent at/dev/rye/aranet/agenton that connection (org.bluez.AgentManager1.RegisterAgent). - Call
org.bluez.Device1.Pairon the same connection. It gets as long as a connect that waits for BlueZ’s service discovery would. If it runs out while BlueZ still lists the sensor as not paired,CancelPairingstops it. If BlueZ doesn’t answer whether it is paired, closing the connection stops a pairing that is still running. - Unregister the agent and close the connection.
When BlueZ connects the sensor for Pair, it answers Pair only after its
service discovery has finished, which can take an Aranet4 about 20 s, but it
lists the sensor as paired as soon as the bond exists. A Pair that runs
out of time after that counts as paired and isn’t cancelled, which would
remove the new bond. The connect goes ahead, and the session keeps its
connection open, with the agent unregistered, until BlueZ answers Pair:
closing it earlier would cancel that discovery.
BlueZ sends the agent requests of a Pair call to the agent that the
calling connection registered. On a host with no other agent, BlueZ also
makes the session’s agent the default one while it is registered, so the
agent approves requests only for the object path of the sensor being paired
and rejects the rest. It always rejects AuthorizeService, and
RequestPasskey, which would need a keyboard. Closing the connection
removes the agent and cancels an unfinished pairing, even when the session
is cut short.
aranet never asks to be BlueZ’s default agent, and it keeps no agent registered between connects. Since BlueZ 5.51 the first agent to register becomes the default one, so a long-lived agent on a host without a desktop agent would receive the pairing requests of every nearby device. Scans, and sensors that are already paired, never register an agent.
A pairing that fails is logged as a warning, and the connect goes ahead unpaired, with the stall or the dialog described above. The next connect pairs again, unless the sensor refused.
The session’s agent has no display or keyboard, so it can’t pair a sensor
that asks for its PIN. Some such sensors don’t refuse (an Aranet2 with
BlueZ 5.82, for example): the pairing finishes without the PIN, then the
sensor rejects that bond at every later connect, so its reads fail while
BlueZ lists it as paired, and a new bond made the same way fails the same
way. Pair such a sensor once by hand, with its PIN; aranet then uses that
bond. To do that, stop every aranet process that uses it (a connect during
the pairing cancels it) and run bluetoothctl remove <MAC>. Then run
bluetoothctl and, at its prompt, scan on until the sensor is listed,
scan off and pair <MAC>, entering the PIN when asked. A one-line
bluetoothctl pair <MAC> registers no agent, so on a host without a
desktop agent it can’t ask for the PIN. A sensor that has lost its bond
with this computer (after a reset, for example) is still listed as paired,
and its encrypted reads fail too: remove the stale bond with
bluetoothctl remove <MAC>. The next connect then pairs it again, unless
it asks for its PIN; then pair it by hand as above.
Functions§
- ensure_
agent Deprecated - Does nothing.