Skip to main content

python-jebao

Python library for controlling Jebao aquarium pumps over local network.

Supported Models

  • MDP-20000: Variable-speed circulation pump (30-100% speed control)
  • MD-4.4: 4-channel dosing pump (planned)

Features

  • 🔍 UDP Discovery - Automatic device discovery with multi-subnet support
  • 🔌 Local Control - Direct TCP control, no cloud dependency
  • Full Protocol - On/Off, speed control, feed mode, status monitoring
  • 🏠 Home Assistant Ready - Designed for HA integration
  • 🔒 Type Safe - Full type hints for better IDE support

Installation

pip install python-jebao

For development:

git clone https://github.com/jrigling/python-jebao.git
cd python-jebao
pip install -e .

Quick Start

Discovery

import asyncio
from jebao import discover_devices

async def main():
    # Discover all Jebao devices on network
    devices = await discover_devices()

    for device in devices:
        print(f"Found: {device.model} at {device.ip_address}")
        print(f"  Device ID: {device.device_id}")
        print(f"  MAC: {device.mac_address}")

asyncio.run(main())

Multi-Subnet Discovery

If you have multiple network interfaces (e.g., IoT VLAN, main network):

# Discover on all interfaces
devices = await discover_devices()

# Or specify interfaces explicitly
devices = await discover_devices(interfaces=['eth0', 'eth1'])

Basic Control

from jebao import MDP20000Device

async def main():
    # Connect to device
    async with MDP20000Device(host="10.20.20.13") as pump:
        # Ensure in manual mode (exits Program mode if needed)
        await pump.ensure_manual_mode()

        # Turn on
        await pump.turn_on()

        # Set speed to 75%
        await pump.set_speed(75)

        # Check status
        await pump.update()
        print(f"State: {pump.state.name}")
        print(f"Speed: {pump.speed}%")
        print(f"Is on: {pump.is_on}")

        # Turn off
        await pump.turn_off()

asyncio.run(main())

Feed Mode

async def feed_mode_example():
    async with MDP20000Device(host="10.20.20.13") as pump:
        await pump.ensure_manual_mode()
        await pump.turn_on()
        await pump.set_speed(75)

        # Start 2-minute feed (pump stops temporarily)
        await pump.start_feed(minutes=2)
        print("Feed started, pump will auto-resume in 2 minutes")

        # Check status during feed
        await pump.update()
        print(f"In feed mode: {pump.is_feed_mode}")

        # Or cancel early
        # await pump.cancel_feed(resume_speed=75)

Long-Running Connection

async def monitor_pump():
    pump = MDP20000Device(host="10.20.20.13")

    try:
        await pump.connect()
        await pump.ensure_manual_mode()

        # Control pump
        await pump.turn_on()
        await pump.set_speed(50)

        # Monitor status periodically
        while True:
            await pump.update()
            print(f"Status: {pump.state.name} @ {pump.speed}%")
            await asyncio.sleep(30)

    finally:
        await pump.disconnect()

Device States

from jebao import DeviceState

# State values
DeviceState.OFF      # 0x10 - Manual mode, stopped
DeviceState.ON       # 0x11 - Manual mode, running
DeviceState.FEED     # 0x15 - Feed mode (temporary pause)
DeviceState.PROGRAM  # 0x19 - Program mode (scheduled)

# Check state
if pump.state == DeviceState.FEED:
    print("Pump is in feed mode")

# Helper properties
pump.is_on           # True if ON or FEED
pump.is_off          # True if OFF
pump.is_feed_mode    # True if FEED
pump.is_program_mode # True if PROGRAM
pump.is_manual_mode  # True if ON or OFF

API Reference

MDP20000Device

Connection

  • async connect(timeout=5.0) - Connect and authenticate
  • async disconnect() - Disconnect from device
  • is_connected - Check connection status
  • async update() - Refresh device status

Control

  • async turn_on() - Turn pump on
  • async turn_off() - Turn pump off
  • async set_speed(percentage) - Set speed (30-100%)

Feed Mode

  • async set_feed_duration(minutes) - Configure feed timer (1-10 minutes)
  • async start_feed(minutes=None) - Start feed mode
  • async cancel_feed(resume_speed=None) - Cancel feed and resume

Program Mode

  • async ensure_manual_mode() - Exit Program mode if active

Properties

  • state: DeviceState - Current state
  • speed: int - Current speed (30-100)
  • is_on: bool - Pump is running
  • is_off: bool - Pump is stopped
  • is_feed_mode: bool - In feed mode
  • is_program_mode: bool - In program mode
  • is_manual_mode: bool - In manual mode

Discovery

from jebao import JebaoDiscovery, discover_devices

# Convenience function
devices = await discover_devices(timeout=2.0, interfaces=['eth0'])

# Or use class directly
discovery = JebaoDiscovery()
devices = await discovery.discover(timeout=2.0, interfaces=['eth0'])

# Filter by model
mdp20000_devices = [d for d in devices if d.is_mdp20000]
md44_devices = [d for d in devices if d.is_md44]

DiscoveredDevice

device.device_id      # Device ID (e.g., "POAKSFXJNJ")
device.ip_address     # IP address
device.mac_address    # MAC address
device.product_key    # Product key
device.model          # Model name (e.g., "MDP-20000")
device.is_mdp20000    # True if MDP-20000
device.is_md44        # True if MD-4.4

Home Assistant Integration

This library is designed for use with Home Assistant. See the separate homeassistant-jebao repository for the ready-to-use HA integration.

Reliability Features

The library includes automatic retry logic for enhanced reliability:

  • Commands automatically retry up to 3 times on transient failures
  • Handles garbage byte accumulation from pump firmware
  • Exponential backoff for retry delays
  • Typical success rate >97% even with flaky network conditions

Multi-Subnet Considerations

When Home Assistant runs on a system with multiple network interfaces:

  1. Automatic Discovery: The library will scan all interfaces by default
  2. Interface Selection: You can specify which interfaces to scan
  3. Broadcast Support: Each interface gets its own broadcast address
  4. IoT VLANs: Works great with isolated IoT networks

Example: HA connected to both 192.168.1.0/24 (main) and 10.20.20.0/24 (IoT):

# Discovers on both networks automatically
devices = await discover_devices()

# Or be explicit
devices = await discover_devices(interfaces=['eth0', 'eth1'])

Error Handling

from jebao import (
    JebaoError,
    JebaoConnectionError,
    JebaoAuthenticationError,
    JebaoCommandError,
    JebaoTimeoutError,
    JebaoInvalidStateError,
)

try:
    async with MDP20000Device(host="10.20.20.13") as pump:
        await pump.turn_on()
except JebaoConnectionError:
    print("Failed to connect - check IP and network")
except JebaoAuthenticationError:
    print("Authentication failed")
except JebaoCommandError:
    print("Command execution failed")
except JebaoTimeoutError:
    print("Operation timed out")
except JebaoError as e:
    print(f"General error: {e}")

Logging

The library uses Python's standard logging:

import logging

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)

# Or just for jebao
logging.getLogger('jebao').setLevel(logging.DEBUG)

Requirements

  • Python 3.9+
  • netifaces - For multi-interface network discovery

License

MIT License - See LICENSE file

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

Credits

This library builds upon the excellent work from:

  • jebao-dosing-pump-md-4.4 by @tancou - Original Node.js implementation for MD 4.4 pumps that provided the foundation for understanding the GizWits protocol

Protocol for MDP-20000 was reverse-engineered through packet capture analysis of the official Jebao mobile app.

Disclaimer

This is an unofficial library not affiliated with Jebao. Use at your own risk. Device warranty may be affected by third-party control software.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_jebao-0.1.7.tar.gz (24.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_jebao-0.1.7-py3-none-any.whl (23.3 kB view details)

Uploaded Python 3

File details

Details for the file python_jebao-0.1.7.tar.gz.

File metadata

  • Download URL: python_jebao-0.1.7.tar.gz
  • Upload date:
  • Size: 24.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for python_jebao-0.1.7.tar.gz
Algorithm Hash digest
SHA256 6d8fac0bd65b50fdb502fd4c3c7386ef8d7ab67587b79990c75b8a39d394a7bb
MD5 051a44cedb2ade5f5865f4dc6acaa2ed
BLAKE2b-256 b5263f9d6fb8f44006abac03592149a70d3e65c249203170f24ef36a2f738b62

See more details on using hashes here.

File details

Details for the file python_jebao-0.1.7-py3-none-any.whl.

File metadata

  • Download URL: python_jebao-0.1.7-py3-none-any.whl
  • Upload date:
  • Size: 23.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for python_jebao-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 73fcf9a35b7ed35b0943d50409101fe2b8dc722c805245e66794ce44ad8090e3
MD5 d30844fe4511c3109b21725162884149
BLAKE2b-256 cbbeca0df01d682b3875dff41e13299738171a5fb67c42a2c896af72eae2902a

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.7 This release

2 files

0.1.6

2 files

0.1.5

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page