python-jebao 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 Justin Rigling
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,367 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-jebao
3
+ Version: 0.1.0
4
+ Summary: Python library for controlling Jebao aquarium pumps
5
+ Home-page: https://github.com/jrigling/python-jebao
6
+ Author: Justin Rigling
7
+ Author-email: Justin Rigling <jrigling@gmail.com>
8
+ License-Expression: MIT
9
+ Project-URL: Homepage, https://github.com/jrigling/python-jebao
10
+ Project-URL: Repository, https://github.com/jrigling/python-jebao
11
+ Project-URL: Issues, https://github.com/jrigling/python-jebao/issues
12
+ Project-URL: Documentation, https://github.com/jrigling/python-jebao#readme
13
+ Keywords: jebao,aquarium,pump,home-assistant,iot
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Home Automation
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: netifaces>=0.11.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0; extra == "dev"
31
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
32
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
33
+ Requires-Dist: black>=23.0; extra == "dev"
34
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
35
+ Requires-Dist: mypy>=1.0; extra == "dev"
36
+ Provides-Extra: build
37
+ Requires-Dist: build>=0.10.0; extra == "build"
38
+ Requires-Dist: twine>=4.0.0; extra == "build"
39
+ Dynamic: author
40
+ Dynamic: home-page
41
+ Dynamic: license-file
42
+ Dynamic: requires-python
43
+
44
+ # python-jebao
45
+
46
+ Python library for controlling Jebao aquarium pumps over local network.
47
+
48
+ ## Supported Models
49
+
50
+ - **MDP-20000**: Variable-speed circulation pump (30-100% speed control)
51
+ - **MD-4.4**: 4-channel dosing pump (planned)
52
+
53
+ ## Features
54
+
55
+ - 🔍 **UDP Discovery** - Automatic device discovery with multi-subnet support
56
+ - 🔌 **Local Control** - Direct TCP control, no cloud dependency
57
+ - ⚡ **Full Protocol** - On/Off, speed control, feed mode, status monitoring
58
+ - 🏠 **Home Assistant Ready** - Designed for HA integration
59
+ - 🔒 **Type Safe** - Full type hints for better IDE support
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install python-jebao
65
+ ```
66
+
67
+ For development:
68
+ ```bash
69
+ git clone https://github.com/jrigling/python-jebao.git
70
+ cd python-jebao
71
+ pip install -e .
72
+ ```
73
+
74
+ ## Quick Start
75
+
76
+ ### Discovery
77
+
78
+ ```python
79
+ import asyncio
80
+ from jebao import discover_devices
81
+
82
+ async def main():
83
+ # Discover all Jebao devices on network
84
+ devices = await discover_devices()
85
+
86
+ for device in devices:
87
+ print(f"Found: {device.model} at {device.ip_address}")
88
+ print(f" Device ID: {device.device_id}")
89
+ print(f" MAC: {device.mac_address}")
90
+
91
+ asyncio.run(main())
92
+ ```
93
+
94
+ ### Multi-Subnet Discovery
95
+
96
+ If you have multiple network interfaces (e.g., IoT VLAN, main network):
97
+
98
+ ```python
99
+ # Discover on all interfaces
100
+ devices = await discover_devices()
101
+
102
+ # Or specify interfaces explicitly
103
+ devices = await discover_devices(interfaces=['eth0', 'eth1'])
104
+ ```
105
+
106
+ ### Basic Control
107
+
108
+ ```python
109
+ from jebao import MDP20000Device
110
+
111
+ async def main():
112
+ # Connect to device
113
+ async with MDP20000Device(host="10.20.20.13") as pump:
114
+ # Ensure in manual mode (exits Program mode if needed)
115
+ await pump.ensure_manual_mode()
116
+
117
+ # Turn on
118
+ await pump.turn_on()
119
+
120
+ # Set speed to 75%
121
+ await pump.set_speed(75)
122
+
123
+ # Check status
124
+ await pump.update()
125
+ print(f"State: {pump.state.name}")
126
+ print(f"Speed: {pump.speed}%")
127
+ print(f"Is on: {pump.is_on}")
128
+
129
+ # Turn off
130
+ await pump.turn_off()
131
+
132
+ asyncio.run(main())
133
+ ```
134
+
135
+ ### Feed Mode
136
+
137
+ ```python
138
+ async def feed_mode_example():
139
+ async with MDP20000Device(host="10.20.20.13") as pump:
140
+ await pump.ensure_manual_mode()
141
+ await pump.turn_on()
142
+ await pump.set_speed(75)
143
+
144
+ # Start 2-minute feed (pump stops temporarily)
145
+ await pump.start_feed(minutes=2)
146
+ print("Feed started, pump will auto-resume in 2 minutes")
147
+
148
+ # Check status during feed
149
+ await pump.update()
150
+ print(f"In feed mode: {pump.is_feed_mode}")
151
+
152
+ # Or cancel early
153
+ # await pump.cancel_feed(resume_speed=75)
154
+ ```
155
+
156
+ ### Long-Running Connection
157
+
158
+ ```python
159
+ async def monitor_pump():
160
+ pump = MDP20000Device(host="10.20.20.13")
161
+
162
+ try:
163
+ await pump.connect()
164
+ await pump.ensure_manual_mode()
165
+
166
+ # Control pump
167
+ await pump.turn_on()
168
+ await pump.set_speed(50)
169
+
170
+ # Monitor status periodically
171
+ while True:
172
+ await pump.update()
173
+ print(f"Status: {pump.state.name} @ {pump.speed}%")
174
+ await asyncio.sleep(30)
175
+
176
+ finally:
177
+ await pump.disconnect()
178
+ ```
179
+
180
+ ## Device States
181
+
182
+ ```python
183
+ from jebao import DeviceState
184
+
185
+ # State values
186
+ DeviceState.OFF # 0x10 - Manual mode, stopped
187
+ DeviceState.ON # 0x11 - Manual mode, running
188
+ DeviceState.FEED # 0x15 - Feed mode (temporary pause)
189
+ DeviceState.PROGRAM # 0x19 - Program mode (scheduled)
190
+
191
+ # Check state
192
+ if pump.state == DeviceState.FEED:
193
+ print("Pump is in feed mode")
194
+
195
+ # Helper properties
196
+ pump.is_on # True if ON or FEED
197
+ pump.is_off # True if OFF
198
+ pump.is_feed_mode # True if FEED
199
+ pump.is_program_mode # True if PROGRAM
200
+ pump.is_manual_mode # True if ON or OFF
201
+ ```
202
+
203
+ ## API Reference
204
+
205
+ ### MDP20000Device
206
+
207
+ #### Connection
208
+ - `async connect(timeout=5.0)` - Connect and authenticate
209
+ - `async disconnect()` - Disconnect from device
210
+ - `is_connected` - Check connection status
211
+ - `async update()` - Refresh device status
212
+
213
+ #### Control
214
+ - `async turn_on()` - Turn pump on
215
+ - `async turn_off()` - Turn pump off
216
+ - `async set_speed(percentage)` - Set speed (30-100%)
217
+
218
+ #### Feed Mode
219
+ - `async set_feed_duration(minutes)` - Configure feed timer (1-10 minutes)
220
+ - `async start_feed(minutes=None)` - Start feed mode
221
+ - `async cancel_feed(resume_speed=None)` - Cancel feed and resume
222
+
223
+ #### Program Mode
224
+ - `async ensure_manual_mode()` - Exit Program mode if active
225
+
226
+ #### Properties
227
+ - `state: DeviceState` - Current state
228
+ - `speed: int` - Current speed (30-100)
229
+ - `is_on: bool` - Pump is running
230
+ - `is_off: bool` - Pump is stopped
231
+ - `is_feed_mode: bool` - In feed mode
232
+ - `is_program_mode: bool` - In program mode
233
+ - `is_manual_mode: bool` - In manual mode
234
+
235
+ ### Discovery
236
+
237
+ ```python
238
+ from jebao import JebaoDiscovery, discover_devices
239
+
240
+ # Convenience function
241
+ devices = await discover_devices(timeout=2.0, interfaces=['eth0'])
242
+
243
+ # Or use class directly
244
+ discovery = JebaoDiscovery()
245
+ devices = await discovery.discover(timeout=2.0, interfaces=['eth0'])
246
+
247
+ # Filter by model
248
+ mdp20000_devices = [d for d in devices if d.is_mdp20000]
249
+ md44_devices = [d for d in devices if d.is_md44]
250
+ ```
251
+
252
+ ### DiscoveredDevice
253
+
254
+ ```python
255
+ device.device_id # Device ID (e.g., "POAKSFXJNJ")
256
+ device.ip_address # IP address
257
+ device.mac_address # MAC address
258
+ device.product_key # Product key
259
+ device.model # Model name (e.g., "MDP-20000")
260
+ device.is_mdp20000 # True if MDP-20000
261
+ device.is_md44 # True if MD-4.4
262
+ ```
263
+
264
+ ## Home Assistant Integration
265
+
266
+ This library is designed for use with Home Assistant. See the separate
267
+ [homeassistant-jebao](https://github.com/jrigling/homeassistant-jebao) repository
268
+ for the ready-to-use HA integration.
269
+
270
+ ## Reliability Features
271
+
272
+ The library includes automatic retry logic for enhanced reliability:
273
+ - Commands automatically retry up to 3 times on transient failures
274
+ - Handles garbage byte accumulation from pump firmware
275
+ - Exponential backoff for retry delays
276
+ - Typical success rate >97% even with flaky network conditions
277
+
278
+ ## Multi-Subnet Considerations
279
+
280
+ When Home Assistant runs on a system with multiple network interfaces:
281
+
282
+ 1. **Automatic Discovery**: The library will scan all interfaces by default
283
+ 2. **Interface Selection**: You can specify which interfaces to scan
284
+ 3. **Broadcast Support**: Each interface gets its own broadcast address
285
+ 4. **IoT VLANs**: Works great with isolated IoT networks
286
+
287
+ Example: HA connected to both `192.168.1.0/24` (main) and `10.20.20.0/24` (IoT):
288
+
289
+ ```python
290
+ # Discovers on both networks automatically
291
+ devices = await discover_devices()
292
+
293
+ # Or be explicit
294
+ devices = await discover_devices(interfaces=['eth0', 'eth1'])
295
+ ```
296
+
297
+ ## Error Handling
298
+
299
+ ```python
300
+ from jebao import (
301
+ JebaoError,
302
+ JebaoConnectionError,
303
+ JebaoAuthenticationError,
304
+ JebaoCommandError,
305
+ JebaoTimeoutError,
306
+ JebaoInvalidStateError,
307
+ )
308
+
309
+ try:
310
+ async with MDP20000Device(host="10.20.20.13") as pump:
311
+ await pump.turn_on()
312
+ except JebaoConnectionError:
313
+ print("Failed to connect - check IP and network")
314
+ except JebaoAuthenticationError:
315
+ print("Authentication failed")
316
+ except JebaoCommandError:
317
+ print("Command execution failed")
318
+ except JebaoTimeoutError:
319
+ print("Operation timed out")
320
+ except JebaoError as e:
321
+ print(f"General error: {e}")
322
+ ```
323
+
324
+ ## Logging
325
+
326
+ The library uses Python's standard logging:
327
+
328
+ ```python
329
+ import logging
330
+
331
+ # Enable debug logging
332
+ logging.basicConfig(level=logging.DEBUG)
333
+
334
+ # Or just for jebao
335
+ logging.getLogger('jebao').setLevel(logging.DEBUG)
336
+ ```
337
+
338
+ ## Requirements
339
+
340
+ - Python 3.9+
341
+ - `netifaces` - For multi-interface network discovery
342
+
343
+ ## License
344
+
345
+ MIT License - See LICENSE file
346
+
347
+ ## Contributing
348
+
349
+ Contributions welcome! Please:
350
+
351
+ 1. Fork the repository
352
+ 2. Create a feature branch
353
+ 3. Add tests for new functionality
354
+ 4. Ensure all tests pass
355
+ 5. Submit a pull request
356
+
357
+ ## Credits
358
+
359
+ This library builds upon the excellent work from:
360
+ - [jebao-dosing-pump-md-4.4](https://github.com/tancou/jebao-dosing-pump-md-4.4) by [@tancou](https://github.com/tancou) - Original Node.js implementation for MD 4.4 pumps that provided the foundation for understanding the GizWits protocol
361
+
362
+ Protocol for MDP-20000 was reverse-engineered through packet capture analysis of the official Jebao mobile app.
363
+
364
+ ## Disclaimer
365
+
366
+ This is an unofficial library not affiliated with Jebao. Use at your own risk.
367
+ Device warranty may be affected by third-party control software.
@@ -0,0 +1,324 @@
1
+ # python-jebao
2
+
3
+ Python library for controlling Jebao aquarium pumps over local network.
4
+
5
+ ## Supported Models
6
+
7
+ - **MDP-20000**: Variable-speed circulation pump (30-100% speed control)
8
+ - **MD-4.4**: 4-channel dosing pump (planned)
9
+
10
+ ## Features
11
+
12
+ - 🔍 **UDP Discovery** - Automatic device discovery with multi-subnet support
13
+ - 🔌 **Local Control** - Direct TCP control, no cloud dependency
14
+ - ⚡ **Full Protocol** - On/Off, speed control, feed mode, status monitoring
15
+ - 🏠 **Home Assistant Ready** - Designed for HA integration
16
+ - 🔒 **Type Safe** - Full type hints for better IDE support
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install python-jebao
22
+ ```
23
+
24
+ For development:
25
+ ```bash
26
+ git clone https://github.com/jrigling/python-jebao.git
27
+ cd python-jebao
28
+ pip install -e .
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ### Discovery
34
+
35
+ ```python
36
+ import asyncio
37
+ from jebao import discover_devices
38
+
39
+ async def main():
40
+ # Discover all Jebao devices on network
41
+ devices = await discover_devices()
42
+
43
+ for device in devices:
44
+ print(f"Found: {device.model} at {device.ip_address}")
45
+ print(f" Device ID: {device.device_id}")
46
+ print(f" MAC: {device.mac_address}")
47
+
48
+ asyncio.run(main())
49
+ ```
50
+
51
+ ### Multi-Subnet Discovery
52
+
53
+ If you have multiple network interfaces (e.g., IoT VLAN, main network):
54
+
55
+ ```python
56
+ # Discover on all interfaces
57
+ devices = await discover_devices()
58
+
59
+ # Or specify interfaces explicitly
60
+ devices = await discover_devices(interfaces=['eth0', 'eth1'])
61
+ ```
62
+
63
+ ### Basic Control
64
+
65
+ ```python
66
+ from jebao import MDP20000Device
67
+
68
+ async def main():
69
+ # Connect to device
70
+ async with MDP20000Device(host="10.20.20.13") as pump:
71
+ # Ensure in manual mode (exits Program mode if needed)
72
+ await pump.ensure_manual_mode()
73
+
74
+ # Turn on
75
+ await pump.turn_on()
76
+
77
+ # Set speed to 75%
78
+ await pump.set_speed(75)
79
+
80
+ # Check status
81
+ await pump.update()
82
+ print(f"State: {pump.state.name}")
83
+ print(f"Speed: {pump.speed}%")
84
+ print(f"Is on: {pump.is_on}")
85
+
86
+ # Turn off
87
+ await pump.turn_off()
88
+
89
+ asyncio.run(main())
90
+ ```
91
+
92
+ ### Feed Mode
93
+
94
+ ```python
95
+ async def feed_mode_example():
96
+ async with MDP20000Device(host="10.20.20.13") as pump:
97
+ await pump.ensure_manual_mode()
98
+ await pump.turn_on()
99
+ await pump.set_speed(75)
100
+
101
+ # Start 2-minute feed (pump stops temporarily)
102
+ await pump.start_feed(minutes=2)
103
+ print("Feed started, pump will auto-resume in 2 minutes")
104
+
105
+ # Check status during feed
106
+ await pump.update()
107
+ print(f"In feed mode: {pump.is_feed_mode}")
108
+
109
+ # Or cancel early
110
+ # await pump.cancel_feed(resume_speed=75)
111
+ ```
112
+
113
+ ### Long-Running Connection
114
+
115
+ ```python
116
+ async def monitor_pump():
117
+ pump = MDP20000Device(host="10.20.20.13")
118
+
119
+ try:
120
+ await pump.connect()
121
+ await pump.ensure_manual_mode()
122
+
123
+ # Control pump
124
+ await pump.turn_on()
125
+ await pump.set_speed(50)
126
+
127
+ # Monitor status periodically
128
+ while True:
129
+ await pump.update()
130
+ print(f"Status: {pump.state.name} @ {pump.speed}%")
131
+ await asyncio.sleep(30)
132
+
133
+ finally:
134
+ await pump.disconnect()
135
+ ```
136
+
137
+ ## Device States
138
+
139
+ ```python
140
+ from jebao import DeviceState
141
+
142
+ # State values
143
+ DeviceState.OFF # 0x10 - Manual mode, stopped
144
+ DeviceState.ON # 0x11 - Manual mode, running
145
+ DeviceState.FEED # 0x15 - Feed mode (temporary pause)
146
+ DeviceState.PROGRAM # 0x19 - Program mode (scheduled)
147
+
148
+ # Check state
149
+ if pump.state == DeviceState.FEED:
150
+ print("Pump is in feed mode")
151
+
152
+ # Helper properties
153
+ pump.is_on # True if ON or FEED
154
+ pump.is_off # True if OFF
155
+ pump.is_feed_mode # True if FEED
156
+ pump.is_program_mode # True if PROGRAM
157
+ pump.is_manual_mode # True if ON or OFF
158
+ ```
159
+
160
+ ## API Reference
161
+
162
+ ### MDP20000Device
163
+
164
+ #### Connection
165
+ - `async connect(timeout=5.0)` - Connect and authenticate
166
+ - `async disconnect()` - Disconnect from device
167
+ - `is_connected` - Check connection status
168
+ - `async update()` - Refresh device status
169
+
170
+ #### Control
171
+ - `async turn_on()` - Turn pump on
172
+ - `async turn_off()` - Turn pump off
173
+ - `async set_speed(percentage)` - Set speed (30-100%)
174
+
175
+ #### Feed Mode
176
+ - `async set_feed_duration(minutes)` - Configure feed timer (1-10 minutes)
177
+ - `async start_feed(minutes=None)` - Start feed mode
178
+ - `async cancel_feed(resume_speed=None)` - Cancel feed and resume
179
+
180
+ #### Program Mode
181
+ - `async ensure_manual_mode()` - Exit Program mode if active
182
+
183
+ #### Properties
184
+ - `state: DeviceState` - Current state
185
+ - `speed: int` - Current speed (30-100)
186
+ - `is_on: bool` - Pump is running
187
+ - `is_off: bool` - Pump is stopped
188
+ - `is_feed_mode: bool` - In feed mode
189
+ - `is_program_mode: bool` - In program mode
190
+ - `is_manual_mode: bool` - In manual mode
191
+
192
+ ### Discovery
193
+
194
+ ```python
195
+ from jebao import JebaoDiscovery, discover_devices
196
+
197
+ # Convenience function
198
+ devices = await discover_devices(timeout=2.0, interfaces=['eth0'])
199
+
200
+ # Or use class directly
201
+ discovery = JebaoDiscovery()
202
+ devices = await discovery.discover(timeout=2.0, interfaces=['eth0'])
203
+
204
+ # Filter by model
205
+ mdp20000_devices = [d for d in devices if d.is_mdp20000]
206
+ md44_devices = [d for d in devices if d.is_md44]
207
+ ```
208
+
209
+ ### DiscoveredDevice
210
+
211
+ ```python
212
+ device.device_id # Device ID (e.g., "POAKSFXJNJ")
213
+ device.ip_address # IP address
214
+ device.mac_address # MAC address
215
+ device.product_key # Product key
216
+ device.model # Model name (e.g., "MDP-20000")
217
+ device.is_mdp20000 # True if MDP-20000
218
+ device.is_md44 # True if MD-4.4
219
+ ```
220
+
221
+ ## Home Assistant Integration
222
+
223
+ This library is designed for use with Home Assistant. See the separate
224
+ [homeassistant-jebao](https://github.com/jrigling/homeassistant-jebao) repository
225
+ for the ready-to-use HA integration.
226
+
227
+ ## Reliability Features
228
+
229
+ The library includes automatic retry logic for enhanced reliability:
230
+ - Commands automatically retry up to 3 times on transient failures
231
+ - Handles garbage byte accumulation from pump firmware
232
+ - Exponential backoff for retry delays
233
+ - Typical success rate >97% even with flaky network conditions
234
+
235
+ ## Multi-Subnet Considerations
236
+
237
+ When Home Assistant runs on a system with multiple network interfaces:
238
+
239
+ 1. **Automatic Discovery**: The library will scan all interfaces by default
240
+ 2. **Interface Selection**: You can specify which interfaces to scan
241
+ 3. **Broadcast Support**: Each interface gets its own broadcast address
242
+ 4. **IoT VLANs**: Works great with isolated IoT networks
243
+
244
+ Example: HA connected to both `192.168.1.0/24` (main) and `10.20.20.0/24` (IoT):
245
+
246
+ ```python
247
+ # Discovers on both networks automatically
248
+ devices = await discover_devices()
249
+
250
+ # Or be explicit
251
+ devices = await discover_devices(interfaces=['eth0', 'eth1'])
252
+ ```
253
+
254
+ ## Error Handling
255
+
256
+ ```python
257
+ from jebao import (
258
+ JebaoError,
259
+ JebaoConnectionError,
260
+ JebaoAuthenticationError,
261
+ JebaoCommandError,
262
+ JebaoTimeoutError,
263
+ JebaoInvalidStateError,
264
+ )
265
+
266
+ try:
267
+ async with MDP20000Device(host="10.20.20.13") as pump:
268
+ await pump.turn_on()
269
+ except JebaoConnectionError:
270
+ print("Failed to connect - check IP and network")
271
+ except JebaoAuthenticationError:
272
+ print("Authentication failed")
273
+ except JebaoCommandError:
274
+ print("Command execution failed")
275
+ except JebaoTimeoutError:
276
+ print("Operation timed out")
277
+ except JebaoError as e:
278
+ print(f"General error: {e}")
279
+ ```
280
+
281
+ ## Logging
282
+
283
+ The library uses Python's standard logging:
284
+
285
+ ```python
286
+ import logging
287
+
288
+ # Enable debug logging
289
+ logging.basicConfig(level=logging.DEBUG)
290
+
291
+ # Or just for jebao
292
+ logging.getLogger('jebao').setLevel(logging.DEBUG)
293
+ ```
294
+
295
+ ## Requirements
296
+
297
+ - Python 3.9+
298
+ - `netifaces` - For multi-interface network discovery
299
+
300
+ ## License
301
+
302
+ MIT License - See LICENSE file
303
+
304
+ ## Contributing
305
+
306
+ Contributions welcome! Please:
307
+
308
+ 1. Fork the repository
309
+ 2. Create a feature branch
310
+ 3. Add tests for new functionality
311
+ 4. Ensure all tests pass
312
+ 5. Submit a pull request
313
+
314
+ ## Credits
315
+
316
+ This library builds upon the excellent work from:
317
+ - [jebao-dosing-pump-md-4.4](https://github.com/tancou/jebao-dosing-pump-md-4.4) by [@tancou](https://github.com/tancou) - Original Node.js implementation for MD 4.4 pumps that provided the foundation for understanding the GizWits protocol
318
+
319
+ Protocol for MDP-20000 was reverse-engineered through packet capture analysis of the official Jebao mobile app.
320
+
321
+ ## Disclaimer
322
+
323
+ This is an unofficial library not affiliated with Jebao. Use at your own risk.
324
+ Device warranty may be affected by third-party control software.