blynk-provisioning 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anthony Elder
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,208 @@
1
+ Metadata-Version: 2.4
2
+ Name: blynk-provisioning
3
+ Version: 0.1.0
4
+ Summary: Unofficial, experimental Blynk.Inject-style BLE provisioning for Linux/Raspberry Pi - get a device's Blynk credentials by pairing with the Blynk app
5
+ Author: Anthony Elder
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/anthony-blynk/blynk-provisioning
8
+ Project-URL: Issues, https://github.com/anthony-blynk/blynk-provisioning/issues
9
+ Keywords: blynk,blynk-inject,ble,bluetooth,provisioning,raspberry-pi,iot,mqtt
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Topic :: Home Automation
16
+ Classifier: Topic :: System :: Hardware
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: paho-mqtt<3,>=2.0
21
+ Requires-Dist: python-dotenv>=1.0
22
+ Requires-Dist: bluez-peripheral<0.2,>=0.1.7
23
+ Dynamic: license-file
24
+
25
+ # blynk-provisioning
26
+
27
+ > **Unofficial and experimental.** A personal proof of concept, not a Blynk
28
+ > product and not covered by Blynk support. Expect changes.
29
+
30
+ Get a device's Blynk credentials via BLE pairing with the Blynk app, so a
31
+ plain Python script can talk to Blynk directly - no need for the full
32
+ [blynk-edge-agent](https://github.com/anthony-blynk/blynk-edge-agent) stack.
33
+
34
+ **Scope, deliberately narrow:** this library does exactly one thing - get
35
+ your device paired with the Blynk app and hand back a real, working
36
+ identity (server + auth token). It doesn't wrap the Blynk MQTT device
37
+ protocol itself (topics, datastreams, OTA, any of that) - `paho-mqtt`
38
+ already does MQTT well, and Blynk's own topic conventions
39
+ (`ds/<name>`, `get/ds`, `downlink/ds/<name>`) are simple enough to use
40
+ directly. If you want the fuller device SDK experience, see Blynk's
41
+ Edgent libraries for Arduino/ESP-IDF, or the
42
+ [edge-agent](https://github.com/anthony-blynk/blynk-edge-agent) project,
43
+ which do considerably more than this.
44
+
45
+ **One identity per template, per physical machine** - not one per script,
46
+ and not one overall. Blynk's own device model is one real device = one
47
+ real auth token = one connection; this library doesn't try to paper over
48
+ that. Two scripts using the *same* identity at the same time will
49
+ disconnect each other. A machine provisioning more than one template gets
50
+ a separate identity for each (see "Multiple templates" below) - that's
51
+ normal, not a workaround. If you need several logical devices represented
52
+ under a *single* template from one machine, that's what the edge-agent's
53
+ own MQTT Gateway feature is for - it doesn't need BLE pairing per device
54
+ at all.
55
+
56
+ ## Install
57
+
58
+ Linux only - needs BlueZ and NetworkManager, reached over D-Bus (tested on
59
+ Raspberry Pi OS). Not for Windows/macOS.
60
+
61
+ ```bash
62
+ sudo pip install --break-system-packages blynk-provisioning
63
+ ```
64
+
65
+ Installing with `sudo` makes it available to both `python3` and
66
+ `sudo python3`, so the examples below work as written.
67
+ `--break-system-packages` is needed because Raspberry Pi OS (like other
68
+ recent Debian-based systems) otherwise refuses to `pip install` outside a
69
+ virtual environment. pip's "Running pip as the 'root' user" warning is
70
+ expected with this install method.
71
+
72
+ **First pairing usually needs `sudo`** - WiFi setup goes through
73
+ NetworkManager, which only allows it from a local console session, not over
74
+ SSH. If the device is already on the WiFi network you choose in the app,
75
+ pairing leaves NetworkManager alone and works without `sudo`.
76
+
77
+ <details>
78
+ <summary>Prefer a virtual environment?</summary>
79
+
80
+ ```bash
81
+ python3 -m venv ~/blynk-venv
82
+ ~/blynk-venv/bin/pip install blynk-provisioning
83
+ source ~/blynk-venv/bin/activate # then plain python3 uses it
84
+ ```
85
+
86
+ `sudo` ignores an activated venv, so for runs that need it, point it at the
87
+ venv's Python: `sudo ~/blynk-venv/bin/python3 my_script.py`.
88
+ </details>
89
+
90
+ ## Quick test - Subscribe and print datastream updates
91
+
92
+ Paste and run as-is (swap in your own template ID for TMPLxxxxxxxx first):
93
+
94
+ ```bash
95
+ python3 -c "
96
+ import blynk_provisioning
97
+ creds = blynk_provisioning.get_credentials(template_id='TMPLxxxxxxxx')
98
+ client = creds.get_mqtt_client()
99
+ client.on_message = lambda c, u, m: print(f'{m.topic}: {m.payload.decode()}')
100
+ client.subscribe('downlink/#')
101
+ client.loop_forever()
102
+ "
103
+ ```
104
+
105
+ ## One-off publish
106
+
107
+ ```bash
108
+ python3 -c "
109
+ import paho.mqtt.publish as publish
110
+ import blynk_provisioning
111
+ creds = blynk_provisioning.get_credentials(template_id='TMPLxxxxxxxx')
112
+ publish.single('ds/Test', payload='42', **creds.connection_kwargs())
113
+ "
114
+ ```
115
+
116
+ The first run for a given template ID blocks until you've paired via the
117
+ Blynk app (BLE advertising starts, same flow as pairing a new edge-agent
118
+ device). Every run after that returns instantly - credentials are cached in `~/.blynk/credentials.env`.
119
+
120
+ `get_mqtt_client()` connects for you but doesn't start the network loop - call
121
+ `client.loop_forever()` to block and process messages, or
122
+ `client.loop_start()` if your script needs to do other things
123
+ concurrently.
124
+
125
+ ## Firmware version
126
+
127
+ Blynk shows a firmware version for each device - `unknown` unless you pass
128
+ your script's own version:
129
+
130
+ ```python
131
+ creds = blynk_provisioning.get_credentials(template_id="TMPLxxxxxxxx", fw_version="1.0.3")
132
+ ```
133
+
134
+ The build date shown alongside it is the script file's last-modified time.
135
+
136
+ ## Debug output
137
+
138
+ To see every message exchanged with the Blynk app during pairing, plus the
139
+ MQTT checkin, pass `debug=True` to `get_credentials()` or set `BLYNK_DEBUG=1`:
140
+
141
+ ```bash
142
+ BLYNK_DEBUG=1 python3 my_script.py
143
+ sudo BLYNK_DEBUG=1 python3 my_script.py # not "BLYNK_DEBUG=1 sudo ..." - sudo drops it
144
+ ```
145
+
146
+ The auth token is shown as its last 4 characters; WiFi password and SIM PIN
147
+ are masked. Only this library's own log is enabled - paho and D-Bus stay quiet.
148
+
149
+ ## Multiple templates
150
+
151
+ One identity per template, not one per script (see above) - but a machine
152
+ can legitimately need more than one template's identity (e.g. two
153
+ different kinds of sensor script running on the same Pi). Calling
154
+ `get_credentials()` with a different `template_id` provisions and stores a
155
+ separate identity alongside any already in the same file - they're keyed
156
+ by template internally, so they don't overwrite each other:
157
+
158
+ ```python
159
+ temp_creds = blynk_provisioning.get_credentials(template_id="TMPL_temperature")
160
+ door_creds = blynk_provisioning.get_credentials(template_id="TMPL_doorsensor")
161
+ ```
162
+
163
+ Both get their own BLE pairing ceremony the first time, and both are
164
+ cached in `~/.blynk/credentials.env` from then on.
165
+
166
+ ## Custom vendor prefix
167
+
168
+ Defaults to advertising as `"Blynk Device-XXXX"` over BLE. Enterprise/
169
+ white-labeled Blynk apps are typically configured to only discover devices
170
+ broadcasting their own vendor prefix, so pass yours if that applies:
171
+
172
+ ```python
173
+ creds = blynk_provisioning.get_credentials(
174
+ template_id="TMPLxxxxxxxx",
175
+ vendor_prefix="Acme",
176
+ )
177
+ ```
178
+
179
+ ## Sharing identity with a co-located edge-agent
180
+
181
+ If this script runs on the same machine as a full edge-agent install,
182
+ point at its own credentials file instead of provisioning a separate
183
+ identity:
184
+
185
+ ```python
186
+ creds = blynk_provisioning.get_credentials(
187
+ template_id="TMPLxxxxxxxx",
188
+ path="/opt/blynk/blynk.env",
189
+ )
190
+ ```
191
+
192
+ ## Re-pairing (device deleted on the server)
193
+
194
+ Deleting the device in Blynk invalidates its token, but the local copy
195
+ stays. `get_mqtt_client()` then raises `CredentialsRejectedError` saying so.
196
+ To pair again, replacing just that template's stored identity:
197
+
198
+ ```python
199
+ creds = blynk_provisioning.get_credentials(template_id="TMPLxxxxxxxx", reprovision=True)
200
+ ```
201
+
202
+ ## Status
203
+
204
+ Experimental (`0.1.0`), tested on a Raspberry Pi 5 with Raspberry Pi OS.
205
+ The BLE/NetworkManager/ModemManager engine underneath is adapted from
206
+ blynk-edge-agent's own `agent/ble_provisioning.py` (real, hardware-tested
207
+ code). Issues and feedback welcome on
208
+ [GitHub](https://github.com/anthony-blynk/blynk-provisioning/issues).
@@ -0,0 +1,184 @@
1
+ # blynk-provisioning
2
+
3
+ > **Unofficial and experimental.** A personal proof of concept, not a Blynk
4
+ > product and not covered by Blynk support. Expect changes.
5
+
6
+ Get a device's Blynk credentials via BLE pairing with the Blynk app, so a
7
+ plain Python script can talk to Blynk directly - no need for the full
8
+ [blynk-edge-agent](https://github.com/anthony-blynk/blynk-edge-agent) stack.
9
+
10
+ **Scope, deliberately narrow:** this library does exactly one thing - get
11
+ your device paired with the Blynk app and hand back a real, working
12
+ identity (server + auth token). It doesn't wrap the Blynk MQTT device
13
+ protocol itself (topics, datastreams, OTA, any of that) - `paho-mqtt`
14
+ already does MQTT well, and Blynk's own topic conventions
15
+ (`ds/<name>`, `get/ds`, `downlink/ds/<name>`) are simple enough to use
16
+ directly. If you want the fuller device SDK experience, see Blynk's
17
+ Edgent libraries for Arduino/ESP-IDF, or the
18
+ [edge-agent](https://github.com/anthony-blynk/blynk-edge-agent) project,
19
+ which do considerably more than this.
20
+
21
+ **One identity per template, per physical machine** - not one per script,
22
+ and not one overall. Blynk's own device model is one real device = one
23
+ real auth token = one connection; this library doesn't try to paper over
24
+ that. Two scripts using the *same* identity at the same time will
25
+ disconnect each other. A machine provisioning more than one template gets
26
+ a separate identity for each (see "Multiple templates" below) - that's
27
+ normal, not a workaround. If you need several logical devices represented
28
+ under a *single* template from one machine, that's what the edge-agent's
29
+ own MQTT Gateway feature is for - it doesn't need BLE pairing per device
30
+ at all.
31
+
32
+ ## Install
33
+
34
+ Linux only - needs BlueZ and NetworkManager, reached over D-Bus (tested on
35
+ Raspberry Pi OS). Not for Windows/macOS.
36
+
37
+ ```bash
38
+ sudo pip install --break-system-packages blynk-provisioning
39
+ ```
40
+
41
+ Installing with `sudo` makes it available to both `python3` and
42
+ `sudo python3`, so the examples below work as written.
43
+ `--break-system-packages` is needed because Raspberry Pi OS (like other
44
+ recent Debian-based systems) otherwise refuses to `pip install` outside a
45
+ virtual environment. pip's "Running pip as the 'root' user" warning is
46
+ expected with this install method.
47
+
48
+ **First pairing usually needs `sudo`** - WiFi setup goes through
49
+ NetworkManager, which only allows it from a local console session, not over
50
+ SSH. If the device is already on the WiFi network you choose in the app,
51
+ pairing leaves NetworkManager alone and works without `sudo`.
52
+
53
+ <details>
54
+ <summary>Prefer a virtual environment?</summary>
55
+
56
+ ```bash
57
+ python3 -m venv ~/blynk-venv
58
+ ~/blynk-venv/bin/pip install blynk-provisioning
59
+ source ~/blynk-venv/bin/activate # then plain python3 uses it
60
+ ```
61
+
62
+ `sudo` ignores an activated venv, so for runs that need it, point it at the
63
+ venv's Python: `sudo ~/blynk-venv/bin/python3 my_script.py`.
64
+ </details>
65
+
66
+ ## Quick test - Subscribe and print datastream updates
67
+
68
+ Paste and run as-is (swap in your own template ID for TMPLxxxxxxxx first):
69
+
70
+ ```bash
71
+ python3 -c "
72
+ import blynk_provisioning
73
+ creds = blynk_provisioning.get_credentials(template_id='TMPLxxxxxxxx')
74
+ client = creds.get_mqtt_client()
75
+ client.on_message = lambda c, u, m: print(f'{m.topic}: {m.payload.decode()}')
76
+ client.subscribe('downlink/#')
77
+ client.loop_forever()
78
+ "
79
+ ```
80
+
81
+ ## One-off publish
82
+
83
+ ```bash
84
+ python3 -c "
85
+ import paho.mqtt.publish as publish
86
+ import blynk_provisioning
87
+ creds = blynk_provisioning.get_credentials(template_id='TMPLxxxxxxxx')
88
+ publish.single('ds/Test', payload='42', **creds.connection_kwargs())
89
+ "
90
+ ```
91
+
92
+ The first run for a given template ID blocks until you've paired via the
93
+ Blynk app (BLE advertising starts, same flow as pairing a new edge-agent
94
+ device). Every run after that returns instantly - credentials are cached in `~/.blynk/credentials.env`.
95
+
96
+ `get_mqtt_client()` connects for you but doesn't start the network loop - call
97
+ `client.loop_forever()` to block and process messages, or
98
+ `client.loop_start()` if your script needs to do other things
99
+ concurrently.
100
+
101
+ ## Firmware version
102
+
103
+ Blynk shows a firmware version for each device - `unknown` unless you pass
104
+ your script's own version:
105
+
106
+ ```python
107
+ creds = blynk_provisioning.get_credentials(template_id="TMPLxxxxxxxx", fw_version="1.0.3")
108
+ ```
109
+
110
+ The build date shown alongside it is the script file's last-modified time.
111
+
112
+ ## Debug output
113
+
114
+ To see every message exchanged with the Blynk app during pairing, plus the
115
+ MQTT checkin, pass `debug=True` to `get_credentials()` or set `BLYNK_DEBUG=1`:
116
+
117
+ ```bash
118
+ BLYNK_DEBUG=1 python3 my_script.py
119
+ sudo BLYNK_DEBUG=1 python3 my_script.py # not "BLYNK_DEBUG=1 sudo ..." - sudo drops it
120
+ ```
121
+
122
+ The auth token is shown as its last 4 characters; WiFi password and SIM PIN
123
+ are masked. Only this library's own log is enabled - paho and D-Bus stay quiet.
124
+
125
+ ## Multiple templates
126
+
127
+ One identity per template, not one per script (see above) - but a machine
128
+ can legitimately need more than one template's identity (e.g. two
129
+ different kinds of sensor script running on the same Pi). Calling
130
+ `get_credentials()` with a different `template_id` provisions and stores a
131
+ separate identity alongside any already in the same file - they're keyed
132
+ by template internally, so they don't overwrite each other:
133
+
134
+ ```python
135
+ temp_creds = blynk_provisioning.get_credentials(template_id="TMPL_temperature")
136
+ door_creds = blynk_provisioning.get_credentials(template_id="TMPL_doorsensor")
137
+ ```
138
+
139
+ Both get their own BLE pairing ceremony the first time, and both are
140
+ cached in `~/.blynk/credentials.env` from then on.
141
+
142
+ ## Custom vendor prefix
143
+
144
+ Defaults to advertising as `"Blynk Device-XXXX"` over BLE. Enterprise/
145
+ white-labeled Blynk apps are typically configured to only discover devices
146
+ broadcasting their own vendor prefix, so pass yours if that applies:
147
+
148
+ ```python
149
+ creds = blynk_provisioning.get_credentials(
150
+ template_id="TMPLxxxxxxxx",
151
+ vendor_prefix="Acme",
152
+ )
153
+ ```
154
+
155
+ ## Sharing identity with a co-located edge-agent
156
+
157
+ If this script runs on the same machine as a full edge-agent install,
158
+ point at its own credentials file instead of provisioning a separate
159
+ identity:
160
+
161
+ ```python
162
+ creds = blynk_provisioning.get_credentials(
163
+ template_id="TMPLxxxxxxxx",
164
+ path="/opt/blynk/blynk.env",
165
+ )
166
+ ```
167
+
168
+ ## Re-pairing (device deleted on the server)
169
+
170
+ Deleting the device in Blynk invalidates its token, but the local copy
171
+ stays. `get_mqtt_client()` then raises `CredentialsRejectedError` saying so.
172
+ To pair again, replacing just that template's stored identity:
173
+
174
+ ```python
175
+ creds = blynk_provisioning.get_credentials(template_id="TMPLxxxxxxxx", reprovision=True)
176
+ ```
177
+
178
+ ## Status
179
+
180
+ Experimental (`0.1.0`), tested on a Raspberry Pi 5 with Raspberry Pi OS.
181
+ The BLE/NetworkManager/ModemManager engine underneath is adapted from
182
+ blynk-edge-agent's own `agent/ble_provisioning.py` (real, hardware-tested
183
+ code). Issues and feedback welcome on
184
+ [GitHub](https://github.com/anthony-blynk/blynk-provisioning/issues).
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "blynk-provisioning"
7
+ dynamic = ["version"]
8
+ description = "Unofficial, experimental Blynk.Inject-style BLE provisioning for Linux/Raspberry Pi - get a device's Blynk credentials by pairing with the Blynk app"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Anthony Elder" }]
14
+ keywords = ["blynk", "blynk-inject", "ble", "bluetooth", "provisioning", "raspberry-pi", "iot", "mqtt"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "Operating System :: POSIX :: Linux",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Topic :: Home Automation",
22
+ "Topic :: System :: Hardware",
23
+ ]
24
+ dependencies = [
25
+ "paho-mqtt>=2.0,<3",
26
+ "python-dotenv>=1.0",
27
+ "bluez-peripheral>=0.1.7,<0.2",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/anthony-blynk/blynk-provisioning"
32
+ Issues = "https://github.com/anthony-blynk/blynk-provisioning/issues"
33
+
34
+ [tool.setuptools.dynamic]
35
+ version = { attr = "blynk_provisioning.__version__" }
36
+
37
+ [tool.setuptools.packages.find]
38
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ """
2
+ blynk_provisioning - get this device's Blynk credentials via BLE pairing
3
+ with the Blynk app, so a plain Python/paho script can talk to Blynk without
4
+ needing the full blynk-edge-agent stack. See the project README for scope
5
+ and the one-off-publish / subscribe-and-print examples.
6
+ """
7
+
8
+ from .credentials import Credentials, CredentialsRejectedError, ProvisioningError, get_credentials
9
+
10
+ __all__ = ["get_credentials", "Credentials", "ProvisioningError", "CredentialsRejectedError"]
11
+
12
+ __version__ = "0.1.0"