{"id":19141954,"url":"https://github.com/shmuelzon/ble2mqtt","last_synced_at":"2025-05-06T23:45:27.496Z","repository":{"id":74053314,"uuid":"60150042","full_name":"shmuelzon/ble2mqtt","owner":"shmuelzon","description":"A BLE to MQTT bridge","archived":false,"fork":false,"pushed_at":"2018-12-03T06:42:23.000Z","size":47,"stargazers_count":60,"open_issues_count":0,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-19T16:11:21.433Z","etag":null,"topics":["ble","bluetooth","bluez","gatt","mqtt"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shmuelzon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-01T06:08:31.000Z","updated_at":"2024-05-23T21:36:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"5f0e06fd-7b5e-468f-a51d-a7652c14c3ab","html_url":"https://github.com/shmuelzon/ble2mqtt","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shmuelzon%2Fble2mqtt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shmuelzon%2Fble2mqtt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shmuelzon%2Fble2mqtt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shmuelzon%2Fble2mqtt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shmuelzon","download_url":"https://codeload.github.com/shmuelzon/ble2mqtt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252788404,"owners_count":21804280,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ble","bluetooth","bluez","gatt","mqtt"],"created_at":"2024-11-09T07:25:23.932Z","updated_at":"2025-05-06T23:45:27.475Z","avatar_url":"https://github.com/shmuelzon.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BLE2MQTT\n\n**Depreciation Notice** - This project is no longer maintained in favor of the\n[ESP32](https://github.com/shmuelzon/esp32-ble2mqtt) variant. Pull requests and\nquestions are still welcome.\n\nThis project aims to be a BLE to MQTT bridge, i.e. expose BLE GATT\ncharacteristics as MQTT topics for bidirectional communication. It relies on the\nBlueZ DBus API and as such is supported on Linux only.\n\nFor example, if a device with a MAC address of `A0:E6:F8:50:72:53` exposes the\n[0000180f-0000-1000-8000-00805f9b34fb service](https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.battery_service.xml)\n(Battery Service) which includes the\n[00002a19-0000-1000-8000-00805f9b34fb characteristic](https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.battery_level.xml)\n(Battery Level), the `A0:E6:F8:50:72:53/BatteryService/BatteryLevel`\nMQTT topic is published with a value representing the battery level.\n\nIn order to set a GATT value, publish a message to a writable characteristic\nusing the above format suffixed with `/Set`. Note that values are byte arrays so\nwriting a 64-bit value would look like `10,231,32,24`.\n\n## Configuration\n\nWhile the basic configuration file provided in the repository\n([config.json](https://github.com/shmuelzon/ble2mqtt/blob/master/config.json))\nshould be enough for most users, it is possible to tweak it a bit to fit one's\nspecific needs.\n\nThe `mqtt` section below includes the following entries:\n```json\n{\n  \"mqtt\": {\n    \"server\": {\n      \"host\": \"127.0.0.1\",\n      \"port\": 1883\n    },\n    \"publish\": {\n      \"retain\": true\n    },\n    \"topics\" :{\n      \"device_name\": \"Address\",\n      \"set_suffix\": \"/Set\"\n    }\n  }\n}\n```\n* `server` - define which MQTT broker the application should connect to\n* `publish` - configuration for publishing topics. This object is passed as-is\n  to the [mqtt.publish()](https://github.com/mqttjs/MQTT.js#publish) method\n* `topics`\n  * `device name` - define which attribute of a device (as exposed by Bluez)\n    should be used to identify it in the MQTT topic\n  * `set_suffix` - Which suffix should be added to the MQTT value topic in order\n    to write a new value to the characteristic. Set this to an empty string if\n    you wish to use the same topic for reading and writing\n\nThe `ble` section of the configuration file includes the following default\nconfiguration:\n```json\n{\n  \"ble\": {\n    \"services\": { },\n    \"characteristics\": { }\n  }\n}\n```\n* `services` - add an additional service or override an existing definition to\n  the ones grabbed automatically on first run from http://www.bluetooth.org.\n  Each service can include a `name` field which will be used in the MQTT topic\n  instead of its UUID. For example:\n\n    ```json\n    \"services\": {\n      \"00002f00-0000-1000-8000-00805f9b34fb\": {\n        \"name\": \"Relay Service\"\n      },\n    }\n    ```\n* `characteristics` - add an additional characteristic or override an existing\n  definition to the ones grabbed automatically on first run from\n  http://www.bluetooth.org. Each characteristic can include a `name` field which\n  will be used in the MQTT topic instead of its UUID, a `types` array defining\n  how to parse the byte array reflecting the characteristic's value and a `poll`\n  value (in seconds) for the application to poll the BLE device for a new value.\n  For example:\n\n    ```json\n    \"characteristics\": {\n      \"00002a19-0000-1000-8000-00805f9b34fb\": {\n        \"//\": \"Poll the battery level characteristic every day\",\n        \"poll\": 86400\n      },\n      \"00002f01-0000-1000-8000-00805f9b34fb\": {\n        \"name\": \"Relay State\",\n        \"types\": [\n          \"boolean\"\n        ]\n      }\n    }\n    ```\n* `whitelist`/`blacklist` - An array of strings or regular expressions used to\n  match MAC addresses of devices. If `whitelist` is used, only devices with a\n  MAC address matching one of the entries will be connected while if `blacklist`\n  is used, only devices that do not match any entry will be connected to.\n\n    ```json\n    \"whitelist\": [\n      \"A0:E6:F8:.*\"\n    ]\n    ```\n\n* `passkeys` - An object containing the passkey (number 000000~999999) used for\n  out-of-band authorization. Each entry is the MAC address of the BLE device and\n  the value is the passkey to use.\n\n    ```json\n    \"passkeys\": {\n      \"B0:B4:48:D3:63:98\": 123456\n    }\n    ```\n\n## Installation\n\nThis app requires node version \u003e= 4.3.2 (need support for arrow functions) as\nwell as a fairly recent version of Bluez (\u003e= 5.40).\n\n\u003e Note that you can probably point your apt sources to stretch/testing to get\n\u003e newer versions of these packages. I, personally, haven't tried that yet\n\n### Bluez\n\nMy personal setup is a Raspberry Pi 3 utilizing its built-in Bluetooth radio. I\nneeded to build a newer version of Bluez and needed it to be a Debian package\nsince a different package (pi-bluetooth, which creates the HCI device) depends\non it. To overcome this, I ran the following:\n\n```bash\n# Get dependencies\nsudo apt-get update\nsudo apt-get install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev \\\n  libical-dev libreadline-dev checkinstall \n\n# Compile + Install Bluez 5.45\nmkdir -p ~/Downloads\nwget -O ~/Downloads/bluez-5.45.tar.xz http://www.kernel.org/pub/linux/bluetooth/bluez-5.45.tar.xz\nmkdir -p ~/code\ncd ~/code\ntar -xvf ~/Downloads/bluez-5.45.tar.xz\ncd bluez-5.45\n\n# Allow tabs to be tabs (for patches)\nbind '\\C-i:self-insert'\n \npatch -p1 \u003c\u003c EOF\n--- a/tools/hciattach.c\n+++ b/tools/hciattach.c\n@@ -1236,7 +1236,7 @@\n {\n \tstruct uart_t *u = NULL;\n \tint detach, printpid, raw, opt, i, n, ld, err;\n-\tint to = 10;\n+\tint to = 30;\n \tint init_speed = 0;\n \tint send_break = 0;\n \tpid_t pid;\n--- a/tools/hciattach_bcm43xx.c\n+++ b/tools/hciattach_bcm43xx.c\n@@ -43,7 +43,7 @@\n #include \"hciattach.h\"\n \n #ifndef FIRMWARE_DIR\n-#define FIRMWARE_DIR \"/etc/firmware\"\n+#define FIRMWARE_DIR \"/lib/firmware\"\n #endif\n \n #define FW_EXT \".hcd\"\n@@ -366,11 +366,8 @@\n \t\treturn -1;\n \n \tif (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {\n-\t\tfprintf(stderr, \"Patch not found, continue anyway\\n\");\n+\t\tfprintf(stderr, \"Patch not found for %s, continue anyway\\n\", chip_name);\n \t} else {\n-\t\tif (bcm43xx_set_speed(fd, ti, speed))\n-\t\t\treturn -1;\n-\n \t\tif (bcm43xx_load_firmware(fd, fw_path))\n \t\t\treturn -1;\n \n@@ -380,6 +377,7 @@\n \t\t\treturn -1;\n \t\t}\n \n+\t\tsleep(1);\n \t\tif (bcm43xx_reset(fd))\n \t\t\treturn -1;\n \t}\n--- a/src/bluetooth.conf\n+++ b/src/bluetooth.conf\n@@ -34,6 +34,10 @@\n     \u003callow send_destination=\"org.bluez\"/\u003e\n   \u003c/policy\u003e\n \n+  \u003cpolicy group=\"bluetooth\"\u003e\n+    \u003callow send_destination=\"org.bluez\"/\u003e\n+  \u003c/policy\u003e\n+\n   \u003cpolicy context=\"default\"\u003e\n     \u003cdeny send_destination=\"org.bluez\"/\u003e\n   \u003c/policy\u003e\n--- a/src/bluetooth.service.in\n+++ b/src/bluetooth.service.in\n@@ -6,7 +6,7 @@\n [Service]\n Type=dbus\n BusName=org.bluez\n-ExecStart=@libexecdir@/bluetoothd\n+ExecStart=@libexecdir@/bluetoothd -E\n NotifyAccess=main\n #WatchdogSec=10\n #Restart=on-failure\nEOF\n\n# Re-enable tabs\nbind '\\C-i:complete'\n\n./configure --disable-cups --disable-obex --enable-deprecated --prefix=/usr --libexecdir=/usr/lib --localstatedir=/var/lib/bluetooth/\nmake -j 4\nsudo checkinstall -y --nodoc --maintainer=shmuelzon@gmail.com\n```\n\n### Node\nTo install Node, I used the following:\n```bash\n# Install Node\ncurl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -\nsudo apt-get install -y nodejs\n```\n\n### Startup on boot\n\nRaspbian Jesse uses systemd as its init process, so I created a service file for\nit. Make sure to add your user to the `bluetooth` group so you can run this\napplication without running as root.\n\n```bash\ncat \u003c\u003c EOF \u003e ble2mqtt@$USER.service\n[Unit]\nDescription=BLE2MQTT Bridge for %i\nAfter=network.target bluetooth.service\n\n[Service]\nType=simple\nWorkingDirectory=/home/%i/code/ble2mqtt\nExecStart=/usr/bin/npm start\nUser=%i\nSendSIGKILL=no\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\nsudo mv ble2mqtt@$USER.service /lib/systemd/system/\nsudo systemctl daemon-reload\nsudo systemctl enable ble2mqtt@$USER.service\nsudo systemctl start ble2mqtt@$USER.service\n```\n\n## To Do\n\n* Add configuration file:\n  * ~~MQTT settings~~\n  * ~~Single/Split topic for get/set~~\n  * MQTT topic prefix (to distinguish between different instances of the app)\n* ~~Error handling:~~\n  * ~~What happens when an adapter/device is disconnected? Do we need to cleanup\n    anything? What happens to events on removed devices?~~\n* Pretty names (should be configurable):\n  * ~~Allow using different properties as device name~~\n    * Listen on changes in the property used for the device name as if it\n      changes, topic names (both published and subscribed) need to be updated\n  * ~~Use service/characteristic name instead of UUID~~\n    * ~~Extendable via configuration file~~\n* ~~Pretty values (convert byte array to Boolean, String, etc.):~~\n  * ~~Configuration file can define custom characteristics~~\n* Refactoring\n  * Create a separate NPM module out of the BlueZ code\n  * Lots of similar code copy-pasted, we can do better\n* ~~Security~~\n  * ~~Support pairing via AgentManager1 API~~\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshmuelzon%2Fble2mqtt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshmuelzon%2Fble2mqtt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshmuelzon%2Fble2mqtt/lists"}