initial commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
dist
|
||||||
|
node_modules
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true, "legacy": false }],
|
||||||
|
"@babel/plugin-proposal-class-properties",
|
||||||
|
"@babel/plugin-syntax-bigint"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
Generated
+5078
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "bluezjs",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "babel index.js -d dist",
|
||||||
|
"start": "npm run build && node dist/index.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.28.3",
|
||||||
|
"@babel/core": "^7.28.5",
|
||||||
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||||
|
"@babel/plugin-proposal-decorators": "^7.28.0",
|
||||||
|
"@babel/plugin-syntax-bigint": "^7.8.3",
|
||||||
|
"@babel/preset-env": "^7.28.5",
|
||||||
|
"babel-loader": "^10.0.0",
|
||||||
|
"webpack": "^5.103.0",
|
||||||
|
"webpack-cli": "^6.0.1",
|
||||||
|
"webpack-node-externals": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dbus-next": "^0.10.2",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
import { BaseInterface } from "./base";
|
||||||
|
import dbus from "dbus-next";
|
||||||
|
|
||||||
|
export class Advertisement extends BaseInterface {
|
||||||
|
@dbus.interface.property({ signature: "s" })
|
||||||
|
Type = "peripheral";
|
||||||
|
|
||||||
|
@dbus.interface.property({ signature: "s" })
|
||||||
|
LocalName = "TestDevice";
|
||||||
|
|
||||||
|
@dbus.interface.property({ signature: "as" })
|
||||||
|
ServiceUUIDs = ["139fc001-a4ed-11ed-b9df-0242ac120003"];
|
||||||
|
//ServiceUUIDs = ["1816", "1818", "1826"];
|
||||||
|
|
||||||
|
@dbus.interface.method({ inSignature: "", outSignature: "" })
|
||||||
|
Release() {}
|
||||||
|
|
||||||
|
constructor(bus, path) {
|
||||||
|
super(bus, path, "org.bluez.LEAdvertisement1");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import dbus from "dbus-next";
|
||||||
|
|
||||||
|
export class BaseInterface extends dbus.interface.Interface {
|
||||||
|
constructor(bus, path, name) {
|
||||||
|
super(name);
|
||||||
|
this.path = path;
|
||||||
|
bus.export(path, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { BaseInterface } from "./base";
|
||||||
|
import { Variant, interface as iface } from "dbus-next";
|
||||||
|
const { method, property } = iface;
|
||||||
|
|
||||||
|
export class BaseService extends BaseInterface {
|
||||||
|
@property({ signature: "s" })
|
||||||
|
UUID;
|
||||||
|
|
||||||
|
@property({ signature: "b" })
|
||||||
|
Primary;
|
||||||
|
|
||||||
|
@property({ signature: "ao" })
|
||||||
|
get Characteristics() {
|
||||||
|
return this.characteristics.map((c) => c.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
characteristics = [];
|
||||||
|
|
||||||
|
constructor(bus, path) {
|
||||||
|
super(bus, path, "org.bluez.GattService1");
|
||||||
|
}
|
||||||
|
|
||||||
|
addCharacteristic(char) {
|
||||||
|
this.characteristics.push(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProperties() {
|
||||||
|
return {
|
||||||
|
UUID: new Variant("s", this.UUID),
|
||||||
|
Primary: new Variant("b", this.Primary),
|
||||||
|
Characteristics: new Variant("ao", this.Characteristics),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BaseCharacteritic extends BaseInterface {
|
||||||
|
@property({ signature: "o" })
|
||||||
|
Service;
|
||||||
|
|
||||||
|
@property({ signature: "s" })
|
||||||
|
UUID;
|
||||||
|
|
||||||
|
@property({ signature: "as" })
|
||||||
|
Flags;
|
||||||
|
|
||||||
|
@property({ signature: "b" })
|
||||||
|
Notifying = false;
|
||||||
|
|
||||||
|
constructor(bus, path, service, uuid, flags) {
|
||||||
|
super(bus, path, "org.bluez.GattCharacteristic1");
|
||||||
|
this.UUID = uuid;
|
||||||
|
this.Flags = flags;
|
||||||
|
this.Service = service.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@method({ inSignature: "a{sv}", outSignature: "ay" })
|
||||||
|
ReadValue(options) {
|
||||||
|
if (this.read) {
|
||||||
|
return this.read(options);
|
||||||
|
} else {
|
||||||
|
console.log("ReadValue not definied");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@method({ inSignature: "aya{sv}" })
|
||||||
|
WriteValue(value, options) {
|
||||||
|
if (this.write) {
|
||||||
|
this.write(value, options);
|
||||||
|
} else {
|
||||||
|
console.log("WriteValue not definied");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@method({})
|
||||||
|
StartNotify() {
|
||||||
|
console.log("not definied");
|
||||||
|
}
|
||||||
|
|
||||||
|
@method({})
|
||||||
|
StopNotify() {
|
||||||
|
console.log("not definied");
|
||||||
|
}
|
||||||
|
|
||||||
|
getProperties() {
|
||||||
|
return {
|
||||||
|
Service: new Variant("o", this.Service),
|
||||||
|
UUID: new Variant("s", this.UUID),
|
||||||
|
Flags: new Variant("as", this.Flags),
|
||||||
|
Value: new Variant("ay", []),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
import { systemBus, Variant, interface as iface } from "dbus-next";
|
||||||
|
|
||||||
|
const { Interface, method, property } = iface;
|
||||||
|
|
||||||
|
import { BaseService, BaseCharacteritic } from "./bluez-gatt";
|
||||||
|
import { Advertisement } from "./adv";
|
||||||
|
import { BaseInterface } from "./base";
|
||||||
|
|
||||||
|
class Application extends BaseInterface {
|
||||||
|
constructor(bus, path) {
|
||||||
|
super(bus, path, "org.freedesktop.DBus.ObjectManager");
|
||||||
|
|
||||||
|
const gattService = new MyService(bus, "/eu/atoy/service0");
|
||||||
|
|
||||||
|
this.services = [gattService];
|
||||||
|
}
|
||||||
|
|
||||||
|
@method({ outSignature: "a{oa{sa{sv}}}" })
|
||||||
|
GetManagedObjects(val) {
|
||||||
|
const reply = {};
|
||||||
|
for (const service of this.services) {
|
||||||
|
reply[service.path] = {
|
||||||
|
[service.$name]: service.getProperties(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const char of service.characteristics) {
|
||||||
|
reply[char.path] = {
|
||||||
|
[char.$name]: char.getProperties(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyService extends BaseService {
|
||||||
|
UUID = "139fc001-a4ed-11ed-b9df-0242ac120003";
|
||||||
|
Primary = true;
|
||||||
|
|
||||||
|
@property({ signature: "ao" })
|
||||||
|
get Characteristics() {
|
||||||
|
return this.characteristics.map((c) => c.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
characteristics = [];
|
||||||
|
|
||||||
|
constructor(bus, path) {
|
||||||
|
super(bus, path);
|
||||||
|
this.addCharacteristic(new PowerChar(bus, "/eu/atoy/service0/char0", this));
|
||||||
|
this.addCharacteristic(new WriteChar(bus, "/eu/atoy/service0/char1", this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PowerChar extends BaseCharacteritic {
|
||||||
|
constructor(bus, path, service) {
|
||||||
|
super(bus, path, service, "139fc002-a4ed-11ed-b9df-0242ac120003", ["read"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
read(options) {
|
||||||
|
return [0xaa, 0xcc];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WriteChar extends BaseCharacteritic {
|
||||||
|
constructor(bus, path, service) {
|
||||||
|
super(bus, path, service, "139fc003-a4ed-11ed-b9df-0242ac120003", [
|
||||||
|
"write",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(value, options) {
|
||||||
|
console.log(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const bus = systemBus();
|
||||||
|
|
||||||
|
const app = new Application(bus, "/eu/atoy");
|
||||||
|
const adv = new Advertisement(bus, "/eu/atoy/advertising");
|
||||||
|
|
||||||
|
await bus.requestName("eu.atoy");
|
||||||
|
|
||||||
|
const obj = await bus.getProxyObject("org.bluez", "/org/bluez/hci0");
|
||||||
|
const leamgr = obj.getInterface("org.bluez.LEAdvertisingManager1");
|
||||||
|
const gattmgr = obj.getInterface("org.bluez.GattManager1");
|
||||||
|
|
||||||
|
leamgr.RegisterAdvertisement("/eu/atoy/advertising", {});
|
||||||
|
console.log("BLE Advertisement registered");
|
||||||
|
gattmgr.RegisterApplication("/eu/atoy", {});
|
||||||
|
console.log("BLE GATT application registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Cycling Power Control Point 0x2A66 write/indicate
|
||||||
|
Cycling Power Feature 0x2A65 read 0x8a060100
|
||||||
|
Cycling Power Measurement 0x2A63 notif
|
||||||
|
Cycling Power Vector 0x2A64 notif
|
||||||
|
|
||||||
|
2a5d 0x00
|
||||||
|
*/
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const path = require("path");
|
||||||
|
const nodeExternals = require("webpack-node-externals");
|
||||||
|
module.exports = {
|
||||||
|
entry: "./src/index.js",
|
||||||
|
mode: "production",
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, "dist"),
|
||||||
|
filename: "bundle.js",
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: "babel-loader",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
target: "node",
|
||||||
|
externals: [nodeExternals()],
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user