node-linking

The node-linking is a Node.js module which allows you to communicate with the BLE devices supporting the Linking Profile developed by Linking Project (NTT DoCoMo) in Japan.

Usage no npm install needed!

<script type="module">
  import nodeLinking from 'https://cdn.skypack.dev/node-linking';
</script>

README

node-linking

[Japanese (日本語)]

The node-linking is a Node.js module which allows you to communicate with the BLE devices supporting the Linking Profile developed by Linking Project (NTT DoCoMo) in Japan.

The Linking Profile is a BLE profile mainly used for IoT devices such as LEDs, buttons, a variety of sensors, and so on. Though Linking Project provides documents in English, the Linking devices are available only in Japan for now.

The node-linking exposes APIs which allow you to access your Linking devices easily. You do not have to know the details of the Linking Profile.

Supported OS

The node-linking works on Linux-based OSes, such as Raspbian, Ubuntu, and so on. Unfortunately, this module does not work on Windows and Mac OS.

Dependencies

See the document of the @abandonware/noble for details on installing the @abandonware/noble.

Note that the noble has to be run as root on most of Linux environments. See the the document of the @abandonware/noble for details.

The early versions of this module depended on noble for BLE handling. But the noble seems not to support Node v10 or later versions. Now, this module is employing @abandonware/noble, which was forked from noble. For the purouse of the backward compatibility, this module works with noble on Node v8 or earlier versions.

Installation

$ cd ~
$ npm install @abandonware/noble
$ npm install node-linking

Table of Contents


Quick Start

Discovering and connecting to a Linking device

This sample code shows how to discover your Linking device, how to connect to it, and how to disconnect it. This code also shows how to get the device name and how to know which services it supports.

// Load the node-linking and get a `Linking` constructor object
const Linking = require('node-linking');
// Create a `Linking` object
const linking = new Linking();

(async () => {
  // Initialize the `LinkingDevice` object
  await linking.init();

  // Discover devices whose name starts with `Tukeru` for 5 seconds
  let device_list = await linking.discover({
    duration: 5000,
    nameFilter: 'Tukeru'
  });

  if (device_list.length === 0) {
    console.log('No device was found.');
    return;
  }

  // `LinkingDevice` object representing the found device
  let device = device_list[0];

  // The name of the device
  let name = device.advertisement.localName;
  console.log('`' + name + '` was found.');

  // Connect to the device
  console.log('Connecting to `' + name + '`...');
  await device.connect();
  console.log('Connected.');

  // Show the supported services
  console.log('This device suports:');
  for (let [name, service] of Object.entries(device.services)) {
    if (service) {
      console.log('- ' + name);
    }
  }

  // Disconnect the device
  console.log('Disconnecting...');
  await device.disconnect();
  console.log('Disconnected');
  process.exit();
})();

First of all, you have to create a Linking object from the Linking constructor object. In the code above, the variable linking is the Linking object.

Calling the init() method, the Linking object becomes ready for use. Never forget to call the method. Note that the all asynchronous methods implemented in the Linking object return a Promise object.

The discover() method of the Linking object discovers Linking devices. It takes 2 parameters in the 1st argument (The both are optional). In the code above, the discovery process waits for 5 seconds (5,000 msec) and finds devices whose name starts with Tukeru.

In the code above, the variable device is a LinkingDevice object representing the found device. You can get the device name from the LinkingDevice.advertisement.localName property.

At this moment, you are not able to interact with the device yet. You have to call the connect() method in order to interact with it. The method also investigates what type of device it is, which services it has, and so on. The process will take about 10 seconds.

Once the device is connected, you can call the all services supported by it. You can know the services supported by the device checking the LinkingDevice.services property.

The sample code above will output the result as follows:

`Tukeru_th0164271` was found.
Connecting to `Tukeru_th0164271`...
Connected.
This device suports:
- deviceName
- led
- battery
- temperature
- humidity
Disconnecting...
Disconnected

As you can see, the device supports some kind of services such as led, vibrations, temperature, etc.

Finally, you can disconnect the device using disconnect() method. The process is also asynchronous, it returns an Promise object.

Watching button actions

Some Linking devices such as "Pochiru" have a button. The Linking Profile supports to notify button actions on such devices. The code snippet blow shows how to watch the button actions.

const Linking = require('node-linking');
const linking = new Linking();

(async () => {
  await linking.init();
  let device_list = await linking.discover({
    duration: 5000,
    nameFilter: 'Pochiru'
  });
  if (device_list.length === 0) {
    console.log('No device was found.');
    return;
  }

  let device = device_list[0];
  let name = device.advertisement.localName;
  console.log('`' + name + '` was found:');

  console.log('Connecting to `' + name + '`...');
  await device.connect();
  console.log('Connected.');

  // Check if the device supports the button service
  if (device.services.button) {
    // Set a function called whenever a notification comes from the device
    device.services.button.onnotify = (res) => {
      console.log(JSON.stringify(res, null, '  '));
    };
    console.log('Now listening to the button event.');
    await linking.wait(30000);
  }

  await device.disconnect();
  console.log('Disconnected');

  process.exit();
})();

If you want to watch button actions, it is recommended to check the LinkingDeivce.services.button property. If the device supports the button service, a LinkingButton object is set to it, which exposes APIs for the button action on the device. If the device does not support the button service, null is set to it.

To watch button actions on the device, a callback function has to be set to the onnotify property, which called whenever a notification comes from the device.

The code above will output the result as follows:

{
  "buttonId": 2,
  "buttonName": "SingleClick"
}
{
  "buttonId": 4,
  "buttonName": "DoubleClick"
}
{
  "buttonId": 7,
  "buttonName": "LongClick"
}
{
  "buttonId": 9,
  "buttonName": "LongClickRelease"
}

The Linking Profile supports a variety of button actions. As you can see, you can tell which type of action occurred on the device, such as a single click, a double click, a long click, etc.

Watching sensor data

This sample code shows how to start sensor notifications and monitor sensor data coming form the device. In the code snippet, the variable device is a LinkingDevice object representing the device.

Note that the code snippet blow works after connecting to the device.

const Linking = require('node-linking');
const linking = new Linking();

(async () => {
  await linking.init();
  let device_list = await linking.discover({
    duration: 5000,
    nameFilter: 'Tukeru'
  });
  if (device_list.length === 0) {
    console.log('No device was found.');
    return;
  }

  let device = device_list[0];
  let name = device.advertisement.localName;
  console.log('`' + name + '` was found:');

  console.log('Connecting to `' + name + '`...');
  await device.connect();
  console.log('Connected.');
  console.log('------------------------------------------------');

  // Check if the device supports the temperature service
  if (device.services.temperature) {
    // Set a function called when a response comes from the device
    device.services.temperature.onnotify = (res) => {
      console.log(res.temperature + ' °C');
    };

    // Start notifications
    console.log('Starting to listen to notifications.');
    await device.services.temperature.start();
    console.log('Now listening to notifications.');

    // Wait for 10 seconds
    await linking.wait(10000);

    // Stop notification
    await device.services.temperature.stop();
    console.log('Stopped to listen to notifications.');
  }

  await device.disconnect();
  console.log('Disconnected');

  process.exit();
})();

If you want to watch temperature sensor data, it is recommended to check the LinkingDeivce.services.temperature property. If the device supports the temperature service, a LinkingTemperature object is set to it, which exposes APIs for the temperature sensor in the device. If the device does not support the temperature service, null is set to it.

Before starting the notifications, a callback function has to be set to the onnotify property, which called whenever a notification comes from the device.

Unlike the button service, the start() method has to be called. After starting notifications successfully, the function set to the onnotify property will be called whenever the temperature changes.

The stop() method of the LinkingTemperature object stops notifications. When the notifications are not necessary, it is recommended to call the method. Otherwise, the power of the battery will be drained in vain.

The code snippet above will output the result as follows:

Starting to listen to notifications.
Now listening to notifications.
27.25 °C
Stpped to listen to notifications.
Disconnected

Turning on and off LEDs

A LED is equipped in most of Linking devices. The Linking Profile supports turning on/off a LED on a device. The code blow shows how to turn on and off a LED with a color and a pattern.

const Linking = require('node-linking');
const linking = new Linking();

(async () => {
  await linking.init();
  let device_list = await linking.discover({
    duration: 5000,
    nameFilter: 'Tukeru'
  });
  if (device_list.length === 0) {
    console.log('No device was found.');
    return;
  }
  let device = device_list[0];
  let name = device.advertisement.localName;
  console.log('`' + name + '` was found:');

  console.log('Connecting to `' + name + '`...');
  await device.connect();
  console.log('Connected.');

  // Check if the device supports the LED service
  if (device.services.led) {
    // Show the supported colors
    console.log('- Supported colors:');
    Object.keys(device.services.led.colors).forEach((color) => {
      console.log('  - ' + color);
    });

    // Show the supported patterns
    console.log('- Supported patterns:');
    Object.keys(device.services.led.patterns).forEach((pattern) => {
      console.log('  - ' + pattern);
    });

    // Turn on the LED
    await device.services.led.turnOn('Red', 'Pattern1');
    console.log('The LED was turned on');

    // Wait for 5 seconds
    await linking.wait(5000);

    // Turn off the LED
    await device.services.led.turnOff();
    console.log('The LED was turned off');
  }

  await device.disconnect();
  console.log('Disconnected');

  process.exit();
})();

If you want to turn on/off a LED, it is recommended to check the LinkingDeivce.services.led property. If the device supports the LED service, the value will be a LinkingLed object exposing APIs for the LED on the device. Otherwise, it is set to `null'.

You can know the supported colors from the LinkingLed.colors and the supported patterns from the LinkingLed.patterns.

Calling the turnOn() method on the LinkingLed object, the LED will be turned on. Calling the turnOff() method, the LED will be turned off.

You can pass a color and a pattern to the turnOn() method. Running the code above, the LED will light up in red until the turnOff() method is called.

The code above will output the result as follows:

- Supported colors:
  - Red
  - Green
- Supported patterns:
  - OFF
  - Pattern1
  - Pattern2
  - Pattern3
  - Pattern4
  - Pattern5
  - Pattern6
The LED was turned on
The LED was turned off

Linking object

In order to use the node-linking, you have to load the node-linking module as follows:

const Linking = require('node-linking');

You can get an Linking constructor from the code above. Then you have to create an Linking object from the Linking constructor as follows:

const linking = new Linking();

The Linking constructor takes an argument optionally. It must be a hash object containing the properties as follows:

Property Type Required Description
noble Noble option a Noble object of the noble module

The node-linking module uses the noble module in order to interact with the Linking device(s) on BLE. If you want to interact other BLE devices using the noble module, you can create an Noble object by yourself, then pass it to this module. If you don't specify a Noble object to the noble property, this module automatically create a Noble object internally.

The sample code below shows how to pass a Nobel object to the Linking constructor.

// Create a Noble object
const noble = require('noble');

// Create a Linking object
const Linking = require('node-linking');
const linking = new Linking({'noble': noble});

In the code snippet above, the variable linking is a Linking object. The Linking object has methods as described in sections below.

init() method

A Linking object is not ready to use initially. It has to be initialized using the init() method as below:

linking.init().then(() => {
  // You can call methods implemented in the `Linking` object
}).catch((error) => {
  console.error(error);
});

The init() method returns a Promise object. Once the Linking object is initialized successfully, you can call methods as described in the sections below.

discover([params]) method

The discover method finds Linking devices. This method returns a Promise object. This method takes an argument which is a hash object containing parameters as follow:

Property Type Required Description
duration Number Optional Duration for discovery process (msec). The default value is 5000 (msec).
nameFilter String Optional If this value is set, the devices whose name (localName) does not start with the specified keyword will be ignored.
idFilter String Optional If this value is set, the device whose ID (id) does not start with the specified keyword will be ignored.
quick Boolean Optional If this value is true, this method finishes the discovery process when the first device is found, then calls the resolve() function without waiting the specified duration. The default value is false.

In the code snippet below, the duration and nameFilter are passed to the discover() method:

linking.init().then(() => {
  return linking.discover({
    duration: 5000,
    nameFilter: 'Pochiru'
  });
}).then((device_list) => {
  // Do something...
}).catch((error) => {
  console.error(error);
});

If Linking devices whose names start with "Pochiru" are found in 5 seconds, an Array object will be passed to the resolve() function, which contains LinkingDevice objects representing the found devices. See the section "LinkingDevice objects" for more details.

If you want a quick response, you can set the quick property to true.

linking.init().then(() => {
  return linking.discover({
    duration: 5000,
    idFilter: 'edcbe4062d8',
    quick: true
  });
}).then((device_list) => {
  // Do something...
}).catch((error) => {
  console.error(error);
});

In this case, it is assumed that you know the ID of the device in advance. As the quick property is set to true, the resolve() function will be called immediately after the targeted device is found regardless the value of the duration property.

ondiscover event hander

The ondiscover property on the Linking object is a event handler whenever a device is newly found in the discovery process. A LinkingDevice object is passed to the callback function set to the ondiscover property.

linking.init().then(() => {
  linking.ondiscover = (device) => {
    let ad = device.advertisement;
    console.log('- ' + ad.id + ': ' + ad.localName);
    console.log('---------------------------------------');
  };
  return linking.discover({
    duration: 10000
  });
}).then((device_list) => {
  console.log('The discovery process was finished.');
  console.log(device_list.length + ' devices were found.');
  process.exit();
}).catch((error) => {
  console.error(error);
});

The code snippet above will output the result as follows:

- edcbe4062d81: Tomoru00 02410
---------------------------------------
- da498d14138b: Furueru0098348
---------------------------------------
- c80077af0fb4: Linking Board01 00195
---------------------------------------
- d22ef3a4b7b0: Pochiru02 00313
---------------------------------------
The discovery process was finished.
4 devices were found.

scartScan([params]) method

The startScan() method starts to scan advertising packets from Linking devices. This method returns a Promise object. This method takes an argument which is a hash object containing parameters as follow:

Property Type Required Description
nameFilter String Optional If this value is set, advertising packets from the devices whose name (localName) does not start with the specified keyword will be ignored.
idFilter String Optional If this value is set, advertising packets from the devices whose ID (id) does not start with the specified keyword will be ignored.

Whenever a packet is received, the callback function set to the onadvertisement property of the Linking object will be called. When a packet is received, an LinkingAdvertisement object will be passed to the callback function.

const Linking = require('node-linking');
const linking = new Linking();

(async () => {
  await linking.init();

  // Set a callback function called when a packet is received
  linking.onadvertisement = (ad) => {
    console.log(JSON.stringify(ad, null, '  '));
  };

  // Start to scan advertising packets from Linking devices
  await linking.startScan({
    nameFilter: 'Tukeru'
  });

  // Wait for 10 seconds
  await linking.wait(10000);

  // Stop to scan
  await linking.stopScan();
  process.exit();
})();

The code snippet above will output the result as follows:

{
  "id": "df50d23f1b60",
  "uuid": "df50d23f1b60",
  "address": "df:50:d2:3f:1b:60",
  "localName": "Tukeru_th0164069",
  "serviceUuids": [
    "b3b3690150d34044808d50835b13a6cd"
  ],
  "txPowerLevel": -96,
  "rssi": -67,
  "distance": 0.03548133892335755,
  "version": 0,
  "vendorId": 0,
  "individualNumber": 164069,
  "beaconServiceId": 1,
  "beaconServiceData": {
    "name": "Temperature (°C)",
    "temperature": 25.875
  }
}
{
  "id": "df50d23f1b60",
  "uuid": "df50d23f1b60",
  "address": "df:50:d2:3f:1b:60",
  "localName": "Tukeru_th0164069",
  "serviceUuids": [
    "b3b3690150d34044808d50835b13a6cd"
  ],
  "txPowerLevel": -96,
  "rssi": -66,
  "distance": 0.03162277660168379,
  "version": 0,
  "vendorId": 0,
  "individualNumber": 164069,
  "beaconServiceId": 2,
  "beaconServiceData": {
    "name": "Humidity (%)",
    "humidity": 63
  }
}

stopScan() method

The stopScan() method stops to scan advertising packets from Linking devices. This method returns a Promise object. See the section "startScan() method" for details.

onadvertisement event handler

If a callback function is set to the onadvertisement property, the callback function will be called whenever an advertising packet is received from a Linking device during the scan is active (from the moment when the startScan() method is called, to the moment when the stopScan() method is called).

See the section "startScan() method" for details.

wait() method

The wait() method waits for the specified milliseconds. This method takes an integer representing the duration (millisecond). This method returns a Promise object.

This method has nothing to do with Linking devices. It's just an utility method. See the section "Quick Start" for details of the usage of this method.


LinkingDevice object

The LinkingDevice object represents a Linking device found by calling the discover() method of the Linking object.

connect() method

The connect() method establishes a connection with the device (i.e., pairing). This method returns a Promise object.

This method investigates what type of device it is, which services it provides, and so on. The process will take about 10 seconds. Once the pairing process finishes successfully, you can know the capabilities of the device and send commands to the device with the properties and methods implemented in the LinkingDevice object.

The code snippet below establishes a connection with a device, then it shows the device name and the supported services, finally it disconnects the device:

device.connect().then(() => {
  console.log('- Device Name: ' + device.advertisement.localName);
  console.log('- Supported services:');
  Object.keys(device.services).forEach((service_name) => {
    if(device.services[service_name] !== null) {
      console.log('  - ' + service_name);
    }
  });
  return device.disconnect();
}).then(() => {
  console.log('Disconnected');
}).catch((error) => {
  console.error(error);
});

The result will be as follows:

- Device Name: Pochiru02 00313
- Supported Services:
  - deviceName
  - battery
  - led
  - button
Disconnected

disconnect() method

The disconnect() method disconnects the device. This method returns a Promise object. See the previous section for details.

Properties

The LinkingDevice object implements the properties listed below:

Property Type Description
advertisement LinkingAdvertisement The object represents the advertisement packet received when the device was discovered. See the section "LinkingAdvertisement object" for details.
connected Boolean If the device is connected, the value is true. Otherwise, false.
services LinkingServices See the section "LinkingServices object" for details.
onconnect Function The function set to this property will be called when the device is connected. The default value is null. See the section "onconnect event handler" for details.
ondisconnect Function The function set to this property will be called when the device is disconnected. The default value is null. See the section "ondisconnect event handler" for details.

onconnect event handler

The onconnect of the LinkingDevice object is an event handler called when the device is connected. The code snippet below shows how to use the onconnect event handler:

// Set a callback function called when the device is connected
device.onconnect = () => {
  console.log('Connected.');
};

// Start to establish a connection with the device
device.connect();

Practically, the code snippet above and below do the same thing:

device.connect().then(() => {
  console.log('Connected.');
});

ondisconnect event handler

The ondisconnect of the LinkingDevice object is an event handler called when the device is disconnected. The code snippet below shows how to use the ondisconnect event handler:

device.ondisconnect = (reason) => {
  console.log('Disconnected.');
  console.dir(reason);
};

The code snippet above will output the result as follows:

Disconnected.
{ wasClean: true }

An object will be passed to the callback function set to the ondisconnect, which represents the reason why the device was disconnected. If the disconnect() method is called, the value of the wasClean property will be true. Otherwise, it will be false. That means the device was disconnected unexpectedly.


LinkingAdvertisement object

The LinkingAdvertisement object represents an advertising data coming from the Linking device. This object is just a hash object containing properties as follows:

{
  "id": "edcbe4062d81",
  "uuid": "edcbe4062d81",
  "address": "ed:cb:e4:06:2d:81",
  "localName": "Tomoru00 02410",
  "serviceUuids": [
    "b3b3690150d34044808d50835b13a6cd"
  ],
  "txPowerLevel": -66,
  "rssi": -59,
  "distance": 0.44668359215096315,
  "companyId": 738,
  "companyName": "NTT docomo",
  "version": 0,
  "vendorId": 0,
  "individualNumber": 2410,
  "beaconDataList": [
    {
      "name": "Pressed button information",
      "buttonId": 2,
      "buttonName": "SingleClick",
      "serviceId": 5
    }
  ]
}

Some properties are Linking-specific data:

Property Type Description
distance Number The distance (meter) from the host (which is running the node-linking) to the Linking device.
companyId Number Company Identifier assigned by Bluetooth SIG. As far as I know, all Linking devices set it to 783 (NTT docomo).
companyName String Company Name corresponding to the Company Identifier. (e.g., "NTT docomo" or "Unknown")
version Number Linking version number. Currently, the Linking Profile does not use this property. The specification says it is for future use. As far as I know, all Linking devices set it to 0.
vendorId Number Vendor Identifier dispensed by the Linking Project. As far as I know, all Linking devices set it to 0.
individualNumber Number Unique number for each individual device.
beaconDataList Array List of the linking service data. The structure of each service data depends on the serviceId described below.

General Service (serviceId: 0)

  "beaconDataList": [
    {
      "name": "General",
      "serviceId": 0
    }
  ]

In most cases, Though this service is included in a beacon in most cases, it has no meaningful data.

Temperature Service (serviceId: 1)

  "beaconDataList": [
    {
      "name": "Temperature (°C)",
      "temperature": 26.75,
      "serviceId": 1
    }
  ]

Humidity Service (serviceId: 2)

  "beaconDataList": [
    {
      "name": "Humidity (%)",
      "humidity": 48.375,
      "serviceId": 2
    }
  ]

Air pressure Service (serviceId: 3)

  "beaconDataList": [
    {
      "name": "Air pressure (hPa)",
      "pressure": 996,
      "serviceId": 3
    }
  ]

Remaining battery power (Threshold value or less) Service (serviceId: 4)

  "beaconDataList": [
    {
      "name": "Remaining battery power (Threshold value or less)",
      "chargeRequired": false,
      "chargeLevel": 0,
      "serviceId": 4
    }
  ]
Property Type Description
chargeRequired Boolean Indicating the device requires charging or not. If the value is true, it means "Charging required". Otherwise, it means "Charging not required".
chargeLevel Number The remaining battery power (%).

As far as I know, all Linking devices supporting this service report the same result as the sample above. That is, the required is always false, the level is always 0. I'm not sure this service works well.

Pressed button information Service (serviceId: 5)

  "beaconDataList": [
    {
      "name": "Pressed button information",
      "buttonId": 2,
      "buttonName": "SingleClick",
      "serviceId": 5
    }
  ]
Properties Type Description
buttonId Number The button ID representing a button type or a button action.
buttonName String The meaning of the buttonId.

The possible combinations of buttonId and buttonName are described below:

buttonId buttonName
0 Power
1 Return
2 SingleClick
3 Home
4 DoubleClick
5 VolumeUp
6 VolumeDown
7 LongPress
8 Pause
9 LongPressRelease
10 FastForward
11 ReWind
12 Shutter
13 Up
14 Down
15 Left
16 Right
17 Enter
18 Menu
19 Play
20 Stop

Opening/closing sensor information Service (serviceId: 6)

For now, only Oshieru supports this service. But the beacon data seems to be encrypted. It seems that we, 3rd party developers, are not allowed to handle the beacon data directly.

Human detection (Motion) sensor information Service (serviceId: 7)

  "beaconDataList": [
    {
      "name": "Human detection",
      "humanDetectionResponse": true,
      "humanDetectionCount": 199,
      "serviceId": 7
    }
  ]
Properties Type Description
humanDetectionResponse Boolean Detection flag (true: With response, false: Without response)
humanDetectionCount Number Number of With response

Vibration sensor information Service (serviceId: 8)

For now, only Kizuku supports this service. But the beacon data seems to be encrypted. It seems that we, 3rd party developers, are not allowed to handle the beacon data directly.

Illumination sensor information Service (serviceId: 9)

  "beaconDataList": [
    {
      "name": "Illuminance (lx)",
      "illuminance": 242,
      "serviceId": 9
    }
  ]

Vendor-specific information Service (serviceId: 15)

  "beaconDataList": [
    {
      "name": "Vendor",
      "bin": "000100001000",
      "serviceId": 15
    }
  ]

This is vendor-specific 12 bit data. We can not know what it means.


LinkingServices object

The LinkingServices object contains objects representing services supported in the pairing mode by the device:

Property Type Description
deviceName LinkingDeviceName This object represents a device name service which enables you to get and update the device name. This service is supported by all Linking device.
battery LinkingBattery This object represents a battery service which enables you to monitor changes of battery level. If the device does not support this service, this value is null.
led LinkingLed This object represents a LED service which enables you to turn on/off the LED on the device. If the device does not support this service, this value is null.
vibration LinkingVibration This object represents a vibration service which enables you to vibrate the device and turn off the vibration. If the device does not support this service, this value is null.
button LinkingButton This object represents a button service which enables you to monitor the changes of the button state. If the device does not support this service, this value is null.
gyroscope LinkingGyroscope This object represents a gyroscope service which enables you to monitor the sensor data. If the device does not support this service, this value is null.
accelerometer LinkingAccelerometer This object represents a accelerometer service which enables you to monitor the sensor data. If the device does not support this service, this value is null.
orientation LinkingOrientation This object represents a orientation service which enables you to monitor the sensor data. If the device does not support this service, this value is null.
temperature LinkingTemperature This object represents a temperature service which enables you to monitor the sensor data. If the device does not support this service, this value is null.
humidity LinkingHumidity This object represents a humidity service which enables you to monitor the sensor data. If the device does not support this service, this value is null.
pressure LinkingPressure This object represents a air pressure service which enables you to monitor the sensor data. If the device does not support this service, this value is null.
illuminance LinkingIlluminance This object represents a illuminance service which enables you to monitor the sensor data. If the device does not support this service, this value is null.

You can know which services are supported by the device checking if each property is null or not. The code snippet below checks if the temperature service is supported by the device.

if(device.services.temperature) {
  console.log('The device supports the temperature service.');
} else {
  console.log('The device does not support the temperature service.');
}

Note that the device may not support some services in pairing mode despite the data sheet says such services are supported. For example, though the data sheet of the Sizuku THA says it supports an air pressure sensor, it does not support the service in the pairing mode. It actually supports the service only in the beacon mode. That is, you can obtain the sensor data only from the advertising data coming from the device.


LinkingDeviceName object

This object exposes APIs which enable you to read and write the device name.

get() method

This method reads the device name set in the device.

device.services.deviceName.get().then((res) => {
  console.log(res.deviceName);
}).catch((error) => {
  console.error(error);
});

If this method successfully executed, an object will be passed to the resolve() function, which contains the properties as follows:

Property Type Description
deviceName String Device name

set(deviceName) method

This method writes the device name to the device. A new device name must be passed to this method as the first argument.

device.services.deviceName.set('New name').then(() => {
  console.log('The new name was set successfully.');
}).catch((error) => {
  console.error(error);
});

LinkingBattery object

This object exposes APIs which enable you to watch the battery status.

start() method

This method starts to watch the changes of the battery status.

device.services.battery.onnotify = (res) => {
  console.log(JSON.stringify(res, null, '  '));
};

device.services.battery.start().then((res) => {
  if(res.resultCode === 0) {
    console.log('Started to watch the changes of the battery status.');
  } else {
    console.error(res.resultCode + ': ' + res.resultText);
  }
}).catch((error) => {
  console.error(error);
});

Before call the start() method, a call back function must be set to the onnotify property.

This method returns a Promise object. If a response comes from the device, the resolve() function will be called. The LinkingResponse object will be passed to the function.

Note that the request is not necessarily accepted even if the resolve() function is called. It is recommended to check the value of the resultCode in the LinkingResponse object.

The code snippet above will output the result like this:

{
  chargeRequired: true,
  chargeLevel: 0
}

As you can see in the code snippet above, an object is passed to the resolve() function, which contains the properties as follows:

Property Type Description
chargeRequired Boolean Indicating the device requires charging or not. If the value is true, it means "Charging required". Otherwise, it means "Charging not required".
chargeLevel Number The remaining battery power (%).

As far as I know, only Sizuku 6X sends indicates for this request. But the value of the chargeRequired is always true and the value of the chargeLevel is always 0. I'm not sure this service works well.

onnotify property

After the start() method is called, the callback function set to the onnotify property will be called whenever a notification comes from the devices.

stop() method

This method stops to watch the changes of the battery status.

device.services.battery.stop().then(() => {
  console.log('Stopped');
}).catch((error) => {
  console.error(error);
});

LinkingLed object

This object exposes APIs which enable you to turn on and off the LED(s) on the device.

LinkingLedColors property

This property represents the supported colors of the LED as an Array object.

console.dir(device.services.led.colors);

The code above will output the result like this:

{ Red: 1, Green: 2 }

Each property name means a color name, each value means a color code. These values are required when you call the turnOn() method.

LinkingLedPatterns property

This property represents the supported patterns of the LED as an Array object.

console.dir(device.services.led.patterns);

The code above will output the result like this:

{ OFF: 1,
  Pattern1: 2,
  Pattern2: 3,
  Pattern3: 4,
  Pattern4: 5,
  Pattern5: 6,
  Pattern6: 7 }

Each property name means a pattern name, each value means a pattern code. These names and values are required when you call the turnOn() method.

turnOn([colorName[, patternName[, duration]]]) method

This method turns on the LED with the specified color and pattern.

device.services.led.turnOn('Red', 'Pattern2', 30).then((res) => {
  if(res.resultCode === 0) {
    console.log('The LED was turned on successfully.');
  } else {
    console.error(res.resultCode + ': ' + res.resultText);
  }
}).catch((error) => {
  console.error(error);
})

The parameter colorName or the patternName was omitted, one of the supported colors or patterns is adopted automatically.

If the parameter duration is omitted, it is set to 5 (seconds) automatically. The Linking Profile accepts any one of 0, 5, 10, 30, 60, or 180 (seconds) as the duration. If a value other than the allowed duration is specified, the nearest allowed duration is set automatically.

This method returns a Promise object. If a response comes from the device, the resolve() function will be called with the LinkingResponse object.

Note that the request is not necessarily accepted even if the resolve() method is called. It is recommended to check the value of the resultCode property in the LinkingResponse object.

turnOff() method

This method turns off the LED on the device.

device.services.led.turnOff().then((res) => {
  if(res.resultCode === 0) {
    console.log('The LED was turned off successfully.');
  } else {
    console.error(res.resultCode + ': ' + res.resultText);
  }
}).catch((error) => {
  console.error(error);
})

This method returns a Promise object. If a response comes from the device, the resolve() function will be called with the LinkingResponse object.

Note that the request is not necessarily accepted even if the resolve() method is called. It is recommended to check the value of the resultCode property in the LinkingResponse object.


LinkingVibration object

This object exposes APIs which enable you to vibrate the device and stop the vibration.

LinkingVibrationPatterns property

This property represents the supported patterns as an Array object.

console.dir(device.services.led.patterns);

The code above will output the result like this:

{ OFF: 1,
  Pattern1: 2,
  Pattern2: 3,
  Pattern3: 4,
  Pattern4: 5,
  Pattern5: 6,
  Pattern6: 7,
  Pattern7: 8 }

Each property name means a pattern name, each value means a pattern code. These names and values are required when you call the turnOn() method.

turnOn([patternName[, duration]]]) method

This method vibrates the device with the specified pattern.

device.services.vibration.turnOn('Pattern2', 5).then((res) => {
  if(res.resultCode === 0) {
    console.log('The device is vibrating successfully.');
  } else {
    console.error(res.resultCode + ': ' + res.resultText);
  }
}).catch((error) => {
  console.error(error);
})

The parameter patternName was omitted, one of the supported patterns is adopted automatically.

If the parameter duration is omitted, it is set to 5 (seconds) automatically. The Linking Profile accepts any one of 0, 5, 10, 30, 60, or 180 (seconds) as the duration. If a value other than the allowed duration is specified, the nearest allowed duration is set automatically.

This method returns a Promise object. If a response comes from the device, the resolve() function will be called with the LinkingResponse object.

Note that the request is not necessarily accepted even if the resolve() method is called. It is recommended to check the value of the resultCode property in the LinkingResponse object.

turnOff() method

This method stops the vibration.

device.services.vibration.turnOff().then((res) => {
  if(res.resultCode === 0) {
    console.log('The vibration was stopped successfully.');
  } else {
    console.error(res.resultCode + ': ' + res.resultText);
  }
}).catch((error) => {
  console.error(error);
})

This method returns a Promise object. If a response comes from the device, the resolve() function will be called with the LinkingResponse object.

Note that the request is not necessarily accepted even if the resolve() method is called. It is recommended to check the value of the resultCode property in the LinkingResponse object.


LinkingButton object

This object exposes APIs which enable you to watch the button action on the device.

onnotify property

The onnotify property is an event handler called whenever a button action is occurred on the device.

device.services.button.onnotify = (res) => {
  console.log('- Button action: ' + res.buttonName + ' (' + res.buttonId + ')');
};

The code snippet above will output the result like this:

- Button action: SingleClick (2)
- Button action: DoubleClick (4)
- Button action: LongClick (7)
- Button action: LongClickRelease (9)

LinkingGyroscope object

This object exposes APIs which enable you to watch the data reported by the gyroscope in the device.

start() method

This method starts to watch the data reported by the gyroscope in the device.

device.services.gyroscope.onnotify = (res) => {
  console.log('x: ' + res.x + ', y: ' + res.y + ', z: ' + res.z);
};

device.services.gyroscope.start().then((res) => {
  if(res.resultCode === 0) {
    console.log('Started to watch the data from the gyroscope.');
  } else {
    console.error(res.resultCode + ': ' + res.resultText);
  }
}).catch((error) => {
  console.error(error);
});

Before call the start() method, a call back function must be set to the onnotify property.

This method returns a Promise object. If a response comes from the device, the resolve() function will be called with the LinkingResponse object.

Note that the request is not necessarily accepted even if the resolve() method is called. It is recommended to check the value of the resultCode property in the LinkingResponse object.

The code snippet above will output the result like this:

x: 0.7012194991111755, y: 0.9756097793579102, z: -0.12195122241973877
x: 0.6707317233085632, y: 1.097561001777649, z: 0.21341463923454285
x: 0.6402438879013062, y: 1.1585365533828735, z: 0.18292683362960815

As you can see in the code snippet above, an object is passed to the resolve() function, which contains the properties as follows:

Property Type Description
x Float X-axis rotational
y Float Y-axis rotational
z Float Z-axis rotational

The Linking Profile specification does not define the unit of each value. As far as I tried with some devices, it seems to be deg/sec.

The gyroscope in the "Board for apps developers" is BOSCH BMI160. According to the data sheet, the unit is deg/sec. The gyroscope in the "Sizuku 6X" seems to be InvenSense MPU-6500. According to the data sheet, the unit is also deg/sec. These devices seems to put the reported data from the gyroscope on the Linking Profile directly.

onnotify property

After the start() method is called, the callback function set to the onnotify property will be called whenever a notification comes from the devices.

stop() method

This method stops to watch the data reported by the gyroscope in the device.

device.services.gyroscope.stop().then(() => {
  console.log('Stopped');
}).catch((error) => {
  console.error(error);
});

get() method

This method retrieves the latest data reported by the gyroscope in the device.

device.services.gyroscope.get().then((res) => {
  console.log(JSON.stringify(res, null, '  '));
}).catch((error) => {
  console.error(error);
});

If this method successfully executed, an object will be passed to the resolve() function, which contains the properties as follows:

Property Type Description
x Float X-axis rotational
y Float Y-axis rotational
z Float Z-axis rotational
{
  "x": 159.16159057617188,
  "y": -32.82012176513672,
  "z": -5.487804889678955
}

LinkingAccelerometer object

This object exposes APIs which enable you to watch the data reported by the accelerometer in the device.

start() method

This method starts to watch the data reported by the accelerometer in the device.

device.services.accelerometer.onnotify = (res) => {
  console.log('x: ' + res.x + ', y: ' + res.y + ', z: ' + res.z);
};

device.services.accelerometer.start().then((res) => {
  if(res.resultCode === 0) {
    console.log('Started to watch the data from the accelerometer.');
  } else {
    console.error(res.resultCode + ': ' + res.resultText);
  }
}).catch((error) => {
  console.error(error);
});

Before call the start() method, a callback function must be set to the onnotify property.

This method returns a Promise object. If a response comes from the device, the resolve() function will be called with the LinkingResponse object.

Note that the request is not necessarily accepted even if the resolve() method is called. It is recommended to check the value of the resultCode property in the LinkingResponse object.

The code snippet above will output the result like this:

x: -0.008999999612569809, y: -0.05299999937415123, z: 1
x: -0.007000000216066837, y: -0.052000001072883606, z: 1.0010000467300415
x: -0.008999999612569809, y: -0.05299999937415123, z: 1.003999948501587

As you can see in the code snippet above, an object is passed to the resolve() function, which contains the properties as follows:

Property Type Description
x Float X-axis acceleration
y Float Y-axis acceleration
z Float Z-axis acceleration

The Linking Profile specification does not define the unit of each value. As far as I tried with some devices, it seems to be G including gravity because the value of the z property is just 1.0 when the device remains quiescent.

The accelerometer in the "Board for apps developers" is BOSCH BMI160. According to the data sheet, the unit is G. The accelerometer in the "Sizuku 6X" seems to be InvenSense MPU-6500. According to the data sheet, the unit is G. Though the "BLEAD-TSH-LK" also has an accelerometer, I was not able to know what it is. Anyway, these devices seems to put the reported data from the accelerometer on the Linking Profile directly.

onnotify property

After the start() method is called, the callback function set to the onnotify property will be called whenever a notification comes from the devices.

stop() method

This method stops to watch the data reported by the accelerometer in the device.

device.services.accelerometer.stop().then(() => {
  console.log('Stopped');
}).catch((error) => {
  console.error(error);
});

get() method

This method retrieves the latest data reported by the accelerometer in the device.

device.services.accelerometer.get().then((res) => {
  console.log(JSON.stringify(res, null, '  '));
}).catch((error) => {
  console.error(error);
});

If this method successfully executed, an object will be passed to the resolve() function, which contains the properties as follows:

Property Type Description
x Float X-axis acceleration
y Float Y-axis acceleration
z Float Z-axis acceleration
{
  "x": -0.03200000151991844,
  "y": 0.004000000189989805,
  "z": 1.024999976158142
}

LinkingOrientation object

This object exposes APIs which enable you to watch the data reported by the orientation sensor in the device.

start() method

This method starts to watch the data reported by the orientation sensor in the device.

device.services.orientation.onnotify = (res) => {
  console.log('x: ' + res.x + ', y: ' + res.y + ', z: ' + res.z);
};

device.services.orientation.start().then((res) => {
  if(res.resultCode === 0) {
    console.log('Started to watch the data from the orientation sensor.');
  } else {
    console.error(res.resultCode + ': ' + res.resultText);
  }
}).catch((error) => {
  console.error(error);
});

Before call the start() method, a callback function must be set to the onnotify property.

This method returns a Promise object. If a response comes from the device, the resolve() function will be called with the LinkingResponse object.

Note that the request is not necessarily accepted even if the resolve() method is called. It is recommended to check the value of the resultCode property in the LinkingResponse object.

The code snippet above will output the result like this:

x: 1.128000020980835, y: 0.2849999964237213, z: 1.559000015258789
x: 1.128999948501587, y: 0.289000004529953, z: 1.5709999799728394
x: 1.128999948501587, y: 0.289000004529953, z: 1.5709999799728394

As you can see in the code snippet above, an object is passed to the resolve() function, which contains the properties as follows:

Property Type Description
x Float X-axis rotational angle
y Float Y-axis rotational angle
z Float Z-axis rotational angle

The Linking Profile specification does not define the unit of each value. The orientation sensor (magnetometer) in the "Board for apps developers" is STMicroelectronics LIS3MDL. According to the data sheet, the unit is gauss. But I'm not sure the unit of the value coming from the device through the Linking Profile.

onnotify property

After the start() method is called, the callback function set to the onnotify property will be called whenever a notification comes from the devices.

stop() method

This method stops to watch the data reported by the orientation sensor in the device.

device.services.orientation.stop()).then(() => {
  console.log('Stopped');
}).catch((error) => {
  console.error(error);
});

get() method

This method retrieves the latest data reported by the orientation in the device.

device.services.orientation.get().then((res) => {
  console.log(JSON.stringify(res, null, '  '));
}).catch((error) => {
  console.error(error);
});

If this method successfully executed, an object will be passed to the resolve() function, which contains the properties as follows:

Property Type Description
x Float X-axis rotational angle
y Float Y-axis rotational angle
z Float Z-axis rotational angle
{
  "x": 2.049999952316284,
  "y": -0.7599999904632568,
  "z": 0.550000011920929
}

LinkingTemperature object

This object exposes APIs which enable you to watch the data reported by the temperature sensor in the device.

<a id="Li