Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callback related functions were not working properly #15

Closed
tkomde opened this issue Mar 14, 2023 · 2 comments
Closed

Callback related functions were not working properly #15

tkomde opened this issue Mar 14, 2023 · 2 comments

Comments

@tkomde
Copy link

tkomde commented Mar 14, 2023

Hi, I appreciate your wonderful project!!

I tested on the basic BLE device operation, but the Callback related functions were not working properly.
If you could comment on whether it is a code issue or a Node binding issue, that would be helpful.

Enviroments

  • Node.js v18.15.0
  • Vanilla JS (Not TS)
  • MacOS 12.6.3 (I tried it on Windows11 and it still didn't work)

Pattern 1

  • simpleble_adapter_set_callback_on_found
  • simpleble_adapter_set_callback_on_updated

I added following line in examples/node/scan.mjs (converted TS to JS).

  //Register callback
  bindings.simpleble_adapter_set_callback_on_updated(
    adapter,
    (_adapter, _peripheral, _userdata) => {
	//I want to do something here,,,
    }, null);

But I got a following errror.

# Fatal error in v8::HandleScope::CreateHandle()
# Cannot create a handle without a HandleScope

Pattern 2

  • simpleble_adapter_set_callback_on_scan_start
  • simpleble_adapter_set_callback_on_scan_stop

I added following line in examples/node/scan.mjs (converted TS to JS).

  //Register callback
  bindings.simpleble_adapter_set_callback_on_scan_start(
    adapter,
    (_adapter, _userdata) => {
    }, null);

But I got a following errror.

ERROR [SimpleBLE] /Users/runner/work/node-simpleble/node-simpleble/SimpleBLE/simpleble/src/backends/macos/AdapterBase.mm:70 scan_start - Exception during callback: Invalid argument

Pattern 3

simpleble_peripheral_notify

Simply I tested examples/node/scan.mjs (converted TS to JS). But as soon as the program received the notification, it occured segmentation fault.

import * as readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';
import { bindings } from "simpleble";

function delay(ms) {
  return new Promise((resolve)=> {
    // No need to keep the return value.
    setTimeout(resolve, ms);
  });
}

const SCAN_TIMEOUT = 2000;
const DISCONNECT_TIMEOUT = 5000;

const rl = readline.createInterface({ input, output });

try {
  const adaptersCount = bindings.simpleble_adapter_get_count();
  if (adaptersCount === 0) {
    throw new Error("No Bluetooth adapters found");
  }

  console.log(`Found ${adaptersCount} adapters`);
  const adapter = bindings.simpleble_adapter_get_handle(0);

  console.log(`Starting scan for ${SCAN_TIMEOUT / 1000} seconds`);
  bindings.simpleble_adapter_scan_start(adapter);
  await delay(SCAN_TIMEOUT);
  bindings.simpleble_adapter_scan_stop(adapter);
  console.log(`Finished scan`);

  const resultsCount = bindings.simpleble_adapter_scan_get_results_count(adapter);
  if (resultsCount === 0) {
    throw new Error("No devices found");
  }
  console.log(`Found ${resultsCount} devices`);

  for (let i = 0; i < resultsCount; i++) {
    const d = bindings.simpleble_adapter_scan_get_results_handle(adapter, i);
    const id = bindings.simpleble_peripheral_identifier(d);
    const address = bindings.simpleble_peripheral_address(d);
    const str = id.length > 0 ? `${id} [${address}]` : `[${address}]`;
    console.log(`[${i}] - ${str}`);
  }

  const indexString = await rl.question("Please select a device to connect to: ");
  const index = parseInt(indexString || "", 10);
  if (isNaN(index) || index < 0 || index >= resultsCount) {
    throw new Error("Invalid device selected");
  }

  const device = bindings.simpleble_adapter_scan_get_results_handle(adapter, index);
  const connected = bindings.simpleble_peripheral_connect(device);
  if (!connected) {
    throw new Error("Failed to connect");
  }

  const servicesCount = bindings.simpleble_peripheral_services_count(device);
  console.log(`Found ${servicesCount} services`);
  for (let i = 0; i < servicesCount; i++) {
    const service = bindings.simpleble_peripheral_services_get(device, i);
    console.log(`[${i}] - ${service.uuid}`);
  }

  const serviceString = await rl.question("Please select a service: ");
  const serviceNum = parseInt(serviceString || "", 10);
  if (isNaN(serviceNum) || serviceNum < 0 || serviceNum >= servicesCount) {
    bindings.simpleble_peripheral_disconnect(device);
    throw new Error("Invalid service selected");
  }
  const service = bindings.simpleble_peripheral_services_get(device, serviceNum);

  const charsCount = service.characteristics.length;
  console.log(`Found ${charsCount} characteristics`);
  for (let i = 0; i < charsCount; i++) {
    console.log(`[${i}] ${service.characteristics[i].uuid}`);
  }

  const charString = await rl.question("Please select a characteristic: ");
  const charNum = parseInt(charString || "", 10);
  if (isNaN(charNum) || charNum < 0 || charNum >= charsCount) {
    bindings.simpleble_peripheral_disconnect(device);
    throw new Error("Invalid characteristic selected");
  }
  const char = service.characteristics[charNum];

  const registered = bindings.simpleble_peripheral_notify(device, service.uuid, char.uuid, (_service, _characteristic, data) => {
    const nums = [];
    data.forEach((num) => {
      nums.push(num.toString(16).padStart(2, "0"));
    });
    const arr = nums.join(" ");
    console.log(`Received: ${arr}`);
  }, null);
  if (!registered) {
    console.error("Failed to register notify callback");
    bindings.simpleble_peripheral_disconnect(device);
    process.exit(1);
  }

  console.log(`Disconnecting in ${DISCONNECT_TIMEOUT / 1000} seconds`);

  await delay(DISCONNECT_TIMEOUT);
  console.log("Finished - preparing to disconnect");
  bindings.simpleble_peripheral_unsubscribe(device, service.uuid, char.uuid);
  bindings.simpleble_peripheral_disconnect(device);
  process.exit(0);

} catch (err) {
  console.error(`Error: ${err.message}`);
  process.exit(1);
}
@Symbitic
Copy link
Owner

@jins-tkomoda yeah, that's a known problem. I figured out the cause is the C++ bindings. It involves how the callback is being called and the pointer parameters.

I've mostly stopped working on Node-SimpleBLE. Instead, I'm trying to work to merge the bindings directly into node-webbluetooth. You can follow along our progress here: thegecko/webbluetooth#44 (comment)
The goal is to have a single cross-platform library that works identically across Node, Deno, and Browsers.

@tkomde
Copy link
Author

tkomde commented Mar 14, 2023

@Symbitic
Thanks for the reply! I will watch for that project.
If there is anything I can help with, I will help the project.

@tkomde tkomde closed this as completed Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants