Skip to content

'stateChange' is not reliably triggered on Raspberry Pi 4 #66

@fquirin

Description

@fquirin

Hi,

I've been trying to fix a number of issues that occur every time I'm trying to use noble on my Raspberry Pi 4, OS 13 (Trixie) and toggle my Bluetooth adapter.

The 1st one was discussed in issue #61 and was fixed in v2.3.13.

The 2nd one was that the stop function doesn't work on the RPi, because the PollSocket thread gets stuck in the loop waiting endlessly for a signal. This is apparently an issue specific to Linux and RPi and can be solved by the pull request of @wwaaijer discussed in issue #30 .

Now I'm stuck at a problem where the 'stateChange' event for 'poweredOn' doesn't trigger when the Bluetooth adapter starts in state 'power off'.

Here is the code to reproduce the error:

import noble from '@stoprocent/noble';

try {
  noble.on('stateChange', function (state) {
    console.log("Node.js - state change:", state);
  });

  // Wait for Adapter poweredOn state
  console.log("Node.js - wait for power on");
  await noble.waitForPoweredOnAsync(30000);

  // Start scanning first
  console.log("Node.js - start scan");
  await noble.startScanningAsync();
  console.log("Node.js - scan started");

  // Use the async generator with proper boundaries
  for await (const peripheral of noble.discoverAsync()) {
    console.log(`Node.js - Found device: ${peripheral.advertisement.localName || 'Unknown'}`);
  }

  // Clean up after discovery
  console.log("Node.js - stop scan");
  await noble.stopScanningAsync();
  console.log("Node.js - stopped scan");

} catch (error) {
  console.error('Node.js - Discovery error:', error);
  console.log("Node.js - stop scan");
  await noble.stopScanningAsync();
  console.log("Node.js - stopped scan");

  console.log("Node.js - reset noble");
  noble.reset();
  console.log("Node.js - stop noble");
  noble.stop();
  console.log("END");
}

And here are the steps:

  • Open bluetoothctl and start with power off
  • Run the test script with node test.js
  • Switch on the adapter with power on (in the bluetoothctl terminal)
  • Observe the log

I've added some DEBUG logs to BluetoothHciSocket.cpp, to better understand what's going on:

...
Node.js - wait for power on
C++ DEBUG: Called 'Start'
C++ DEBUG: PollSocket thread started
Node.js - state change: poweredOff
C++ DEBUG: Called 'Start'
C++ DEBUG: waiting for old thread to stop ...
C++ DEBUG: PollSocket thread left loop. Closing ...
C++ DEBUG: PollSocket thread started
Node.js - Discovery error: Error: Timeout waiting for Noble to be powered on
    at Timeout._onTimeout (/home/pi/node-beacon-scanner/node_modules/@stoprocent/noble/lib/noble.js:171:16)
    at listOnTimeout (node:internal/timers:581:17)
    at process.processTimers (node:internal/timers:519:7)
Node.js - stop scan
Node.js - stopped scan
Node.js - reset noble
Node.js - stop noble
C++ DEBUG: Called 'Stop'
C++ DEBUG: PollSocket thread left loop. Closing ...
END

It seems the 'poweredOn' event is never recognized, there are no Bluetooth events registered and after 30s the whole script times out. Notably the initial state of 'power off' is recognized as the first 'state change: poweredOff' event.
If I start the other way round with 'power on' I can detect events and I can shut down the script once with 'power off', but after that I'm stuck.

Any ideas what might be going on here?

Ty,
Florian

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions