Node.js bleno on Generic_x86 PC

Hi,
I have a problem with my BLE application on BalenaOS.
The device name in “BLENO_DEVICE_NAME” environment variable is ignored and it sets the UUID string instead.
Also I can’t see the characteristic that I’ve defined in the code.
The exact same code is working on the same PC with Ubuntu 18.04.
You can see the attached picture and test program for the BLE below.

Any idea why?
Thanks.

Code:

var util = require('util');
var bleno = require('@abandonware/bleno');

var BlenoPrimaryService = bleno.PrimaryService;
var Descriptor = bleno.Descriptor;
var Characteristic = bleno.Characteristic;

class BLE {

    constructor() {

        var self = this;
        this._allowStartAd = false;
        this._testInfo = { "Info": "Test", "A": "B"};
        
        this.TestCharacteristic = function () {
            self.TestCharacteristic.super_.call(this, {
                uuid: '2c7183e0-2cac-4bc8-8bc4-ef4851db51d9',
                properties: ['read'],
                descriptors: [
                    new Descriptor({
                        uuid: '2901',
                        value: 'My Test Characteristic'
                    }),
                    new Descriptor({
                        uuid: '2904',
                        value: new Buffer.from([0x04, 0x01, 0x27, 0xAD, 0x01, 0x00, 0x00]) 
                    })
                ]
            });
        };

        util.inherits(this.TestCharacteristic, Characteristic);
        
        this.TestCharacteristic.prototype.onReadRequest = function (offset, callback) {
            console.log(`BLE Info request`);
            callback(this.RESULT_SUCCESS, Buffer.from(JSON.stringify(self._testInfo), 'utf8'));
        };

        this.TestService = function() {
            self.TestService.super_.call(this, {
                uuid: 'e892c45c-f5f7-4882-96e8-3a2ff792c29c',
                characteristics: [
                    new self.TestCharacteristic()
                ]
            });
        }
        
        util.inherits(this.TestService, BlenoPrimaryService);
        this._primaryService = new this.TestService();


        bleno.on('stateChange', function (state) {
            console.log("BLE state: " + state);
            if (state === 'poweredOn') {
                console.log("BLE ON!");
                self._allowStartAd = true;
                
            } else {
                self._allowStartAd = false;
            }
        });

        bleno.on('advertisingStart', function (error) {
            if (!error) {
                bleno.setServices([self._primaryService], function (error) {
                    console.log('setServices: ' + (error ? 'error ' + error : 'success'));
                });
            } else {
                console.error(error);
            }
        });
    }

    Start(deviceName) {
        if (this._allowStartAd) {
            console.log(`Device name: ${deviceName}`);
            process.env['BLENO_DEVICE_NAME'] = deviceName;
            bleno.startAdvertising(deviceName, [this._primaryService.uuid]);
        }
    }

    Stop() {
        bleno.stopAdvertising();
        bleno.disconnect();
    }
    
}

async function main() {
    const ble = new BLE();
    setTimeout(function() {
        ble.Start("Test-BLE");
    }, 3000);

}

main();

Docker file:

FROM balenalib/genericx86-64-ext-ubuntu-node:12-build AS build
COPY package.json package.json
RUN JOBS=MAX npm install --production --unsafe-perm && npm cache verify && rm -rf /tmp/

FROM balenalib/genericx86-64-ext-ubuntu-node:12-run

RUN apt-get clean && apt-get -q update && apt-get install -yq --no-install-recommends ffmpeg
#RUN apt-get --assume-yes install net-tools
RUN apt-get --assume-yes install bluetooth bluez libbluetooth-dev libudev-dev libusb-1.0-0-dev

RUN apt-get --assume-yes install network-manager v4l-utils
WORKDIR /app
COPY --from=build ./node_modules ./node_modules
COPY ./*.js ./
COPY ./package.json ./package.json
#COPY ./start.sh ./start.sh
#ENV DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket
ENV UDEV=1

ENTRYPOINT ["node", "test.js"]

docker-compose.yml

version: '2.1'
volumes:
    resin-data:
services:
    server:
        container_name: server
        build: ./simple-ble
        network_mode: 'host'
        privileged: true
        volumes:
            - 'resin-data:/data'
            - 'resin-data:/config'      
        labels:
            io.balena.features.kernel-modules: '1'
            io.balena.features.firmware: '1'
            io.balena.features.dbus: '1'
            io.balena.features.sysfs: '1'
            io.balena.features.procfs: '1'
            io.balena.features.supervisor-api: "1"

Hi @tovi,

I would first like you to clarify when you tried the same code locally it was by directly running the code or by building a new Docker image and running a container.
If you were running this directly, then please try running it within a container so that we can confirm whether there are any inconsistencies there.

Then please try setting the BLENO_DEVICE_NAME environment variable on the balenaCloud dashboard, and check whether that value is actually picked up by bleno.
Let me also point you to the respective documentation page about how to do that:

Given those two, we should be able to reason better about what might be going wrong, causing the inconsistencies that you mentioned.

Kind regards,
Thodoris

@thgreasi thanks for your reply.
I’ve added BLENO_DEVICE_NAME environment variable and it didn’t work.
I’ve also tested it in container under Ubuntu (using the same dockerfile) and it worked.

Hi @Tovi ,

I have pushed your code to my NUC running a generic x86_64 application, and both the device name and the test characteristic are working fine for me:

Can you let us know the type of device you are testing this on?

Phil

@phil-d-wilson hi,
I’m using Beelink GK55:
http://www.bee-link.com/portal.php?mod=view&aid=144

If you need me to run some commands on it for hardware info please let me know.
Your dockerfile and docker-compose are the same as mine as well?

Yep, I copied your code into js, docker and compose files, and pushed it as-is. The only thing I had to add was a package.json which looks like:

{
    "name": "simple-ble",
    "version": "0.0.1",
    "main": "test.js",
    "scripts": {

    },
    "dependencies": {
        "util" : "0.12.3",
        "@abandonware/bleno" : "0.5.1-2"
    }
  }

I’ve installed clean Ubuntu on this PC and reproduced my issue using docker.
Then I’ve run:

sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev libusb-1.0-0-dev
sudo service bluetooth stop
sudo hciconfig hci0 up

and run the docker again. The issue solved.
How I can do those steps with balenaOS?
I have the “apt-get install” in the dockerfile but the service stop and hciconfig from start.sh didn’t work.

Hi @phil-d-wilson
Any idea how I can solve this issue?

@Tovi - can you share your dockerfile and start.sh files here?

@phil-d-wilson yes,
Dockerfile:

FROM balenalib/genericx86-64-ext-ubuntu-node:12-build AS build
COPY package.json package.json
RUN JOBS=MAX npm install --production --unsafe-perm && npm cache verify && rm -rf /tmp/
FROM balenalib/genericx86-64-ext-ubuntu-node:12-run
RUN apt-get clean && apt-get -q update && apt-get install -yq --no-install-recommends ffmpeg
RUN apt-get --assume-yes install net-tools
RUN apt-get --assume-yes install bluetooth bluez libbluetooth-dev libudev-dev libusb-1.0-0-dev
RUN apt-get --assume-yes install vainfo i965-va-driver
RUN apt-get --assume-yes install network-manager v4l-utils
RUN apt-get --assume-yes install samba samba-common-bin

WORKDIR /app
COPY --from=build ./node_modules ./node_modules
COPY ./*.js ./
COPY ./package.json ./package.json
COPY ./start.sh ./start.sh
COPY ./smb.conf /etc/samba/smb.conf

ENV DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket
ENV UDEV=1

ENTRYPOINT ["bash", "start.sh"]

start.sh:

#service bluetooth stop
#hciconfig hci0 up

logfile=$(date +'%Y-%m-%d_%H-%m-%S')
service smbd restart
mkdir -p /data/logs
echo "starting with log file ${logfile}..."
sleep 5
node server.js|& tee /data/logs/${logfile}_server.log

Have you commented out your bluetooth and hciconfig commands there?

Yes, I’ve tried with and without those lines in balenaOS.

After some more digging I figured it out by adding those lines before starting my app:

DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket busctl call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager StopUnit ss bluetooth.service replace
sleep 1
hciconfig hci0 up

Hi @Tovi thank you for sharing your solution. Can you please note the balenaOS version you had the original problem with?

I’d like to understand if we have an issue on a specific version here, since Phil couldn’t reproduce it using your original code.

Yes, I’m using: balenaOS 2.58.6+rev1

Thanks for the info @Tovi. Please let us know how it goes when you eventually upgrade the balenaOS of this device to 2.68 or later. I’m guessing that we addressed the issue you experienced already in the later versions – since Phil couldn’t reproduce this issue on balenaOS 2.68.1+rev1.

@gelbal 2.68 is not available for Generic x86_64

image

Yes, I know : )
I meant, when we eventually release that version for Generic x86_64 and you’d like to upgrade balenaOS in the future, I appreciate your check if you still need these additional lines. I suspect that you will not need it. If you still have the same issue, it’d be great to debug this further.

For now I don’t see a reason to spend more time on this issue since you kindly posted a solution for it already and we cannot reproduce it on our side running a later OS version (albeit different device type).