Skip to main content

django-micboard

codecov FOSSA Status OpenSSF Scorecard

Real-time multi-manufacturer wireless microphone monitoring for Django.

django-micboard is a community-driven, pre-production Django reusable app for monitoring wireless audio systems (Shure, Sennheiser, etc.) in real-time. It provides device discovery, telemetry, alerting, performer assignment, and multi-tenant/multi-location support with a manufacturer-agnostic plugin architecture.

  • License: AGPL-3.0-or-later
  • Status: Beta (pre-production)
  • Maintainer: Single developer (please allow time for issue/PR responses)
  • Python: 3.13+
  • Django: 5.2 through 6.1

Features

  • Multi-Manufacturer Support: Plugin architecture for Shure System API, Sennheiser SSCv2, and more
  • Real-Time Updates: Live device telemetry via WebSockets (Channels) or SSE polls
  • Device Lifecycle: Automated discovery, registration, tracking, and movement auditing
  • Wireless Monitoring: Battery levels, RF signal strength, audio levels, charging status
  • Location Management: Buildings, rooms, zones with multi-site/multi-location support
  • Performer Assignment: Map performers to devices with activity history
  • Alert System: User-specific notification rules for battery, signal, offline events
  • Regulatory Compliance: Frequency band coordination and domain auditing
  • Multi-Tenant Safe: Optional MSP (Managed Service Provider) mode with organization isolation
  • Settings Registry: Typed configuration at each definition's exact declared scope
  • Admin Interface: Beautiful Unfold admin theme with advanced filtering and history tracking

Installation

For End Users (Using the App)

Add to your Django project:

uv add "django-micboard[standard,audit]"

Use uv add "django-micboard[standard]" without the optional history app, or uv add django-micboard when only the core reusable app is needed.

In settings.py:

import os

DEBUG = os.environ.get("DJANGO_DEBUG", "False").lower() == "true"

INSTALLED_APPS = [
    # ... Django core apps ...
    "micboard",
]

# Optionally, add these for enhanced features
INSTALLED_APPS += [
    "django.contrib.sites",  # For multi-site support
    "unfold",  # Modern admin theme
    "unfold.contrib.filters",  # Unfold date and datetime range filters
    "simple_history",  # Model change tracking
    "huey.contrib.djhuey",  # Native Huey Django integration
]

HUEY = {
    "huey_class": "huey.RedisHuey",
    "name": "micboard",
    "connection": {
        "url": os.environ.get("REDIS_URL", "redis://localhost:6379/1"),
    },
    "immediate": DEBUG,
}

# Configure Micboard
MICBOARD_CONFIG = {
    "SHURE_API_BASE_URL": os.environ.get(
        "MICBOARD_SHURE_API_BASE_URL", "https://localhost:10000"
    ),
    "SHURE_API_SHARED_KEY": os.environ.get("MICBOARD_SHURE_API_SHARED_KEY"),
    "SHURE_API_TIMEOUT": int(os.environ.get("MICBOARD_SHURE_API_TIMEOUT", "10")),
    "POLL_INTERVAL": 5,  # seconds
}

# Exact hostnames allowed for credential-bearing admin API-server checks.
MICBOARD_API_SERVER_ALLOWED_HOSTS = [
    host.strip()
    for host in os.environ.get("MICBOARD_API_SERVER_ALLOWED_HOSTS", "localhost").split(",")
    if host.strip()
]

# Optional: Enable multi-tenancy
MICBOARD_MULTI_SITE_MODE = True
MICBOARD_MSP_ENABLED = False  # or True for full MSP mode
MICBOARD_SITE_ISOLATION = "site"  # or "organization", "campus"

Micboard intentionally disables generic admin import and export. A host may install the import-export extra only after defining request-aware resources that validate tenant ownership for every transferred row and explicitly opting its own admin classes into those resources.

In MSP mode, Django model permissions are necessary but do not override membership roles: viewer is read-only, operator changes performer assignments through the service-backed assignment workflow, and admin/owner may mutate rows only in their exact organization and campus scopes. Host-wide catalogs remain platform-superuser surfaces. Multi-site creation of an unassigned performer is deliberately disabled until onboarding can bind the performer and first tenant assignment atomically.

The built-in DisplayWall page renders one typed snapshot for its initial response, periodic HTML refreshes, JSON consumers, and section fragments. Micboard ships a pinned local HTMX runtime for offline and restrictive-CSP deployments. The base template still loads Bootstrap from cdn.jsdelivr.net; hosts that block that origin can override the template with a local asset.

Add to your urls.py:

from django.urls import include, path

urlpatterns = [
    path("micboard/", include("micboard.urls", namespace="micboard")),
    # ... other patterns ...
]

Run migrations:

uv run --no-sync python manage.py migrate

Host projects should commit their own app migrations and apply django-micboard's shipped migrations through Django's normal migrate command.

Run the native Huey consumer with:

uv run --no-sync python manage.py run_huey

For Development

CRITICAL: Environment & Dependency Management Policy

This project strictly forbids the use of pip, pipx, poetry, or Python's built-in venv for all environment and package management. ALL environments and dependencies must be set up and managed using uv exclusively. Any documentation, code, or CI which references or suggests non-uv patterns must be updated or escalated to project maintainers for correction. See CONTRIBUTING.md for full enforcement and escalation procedure.

Agents and automation are expected to enforce this pattern in all workflows.

  1. Clone the repository:

    git clone https://github.com/justprosound/django-micboard.git
    cd django-micboard
    
  2. Create the uv-managed environment and install every supported extra:

    uv sync --locked --all-extras
    
  3. Configure the shell environment (the example project does not load .env files implicitly):

    export DJANGO_SECRET_KEY="local-development-only"
    export MICBOARD_SHURE_API_BASE_URL="https://localhost:10000"
    export MICBOARD_SHURE_API_SHARED_KEY="your-shared-key"
    
  4. Run the example project:

    uv run --no-sync python manage.py migrate
    uv run --no-sync python manage.py createsuperuser
    uv run --no-sync python manage.py runserver
    
  5. Access the admin:

    • http://localhost:8000/admin
    • Login with your superuser credentials

Configuration

Environment Variables

The package reads Django settings, not process environment variables directly. The host-settings example above maps these variables into MICBOARD_CONFIG:

# Shure API
MICBOARD_SHURE_API_BASE_URL=https://shure-api.example.com:10000
MICBOARD_SHURE_API_SHARED_KEY=your-secret-key
MICBOARD_SHURE_API_TIMEOUT=10

# Restrict credential-bearing API server requests to explicit hostnames
MICBOARD_API_SERVER_ALLOWED_HOSTS=localhost,shure-api.example.com

Host projects may choose different variable names; set MICBOARD_CONFIG and the MICBOARD_* Django feature flags explicitly in their settings module.

Authenticated manufacturer connections require HTTPS or WSS, and certificate verification is mandatory. For an internal certificate authority, set SSL_CERT_FILE or SSL_CERT_DIR to the trusted CA bundle before starting Django or Huey.

Using the Configuration API

from micboard.services.settings.settings_service import settings as micboard_settings

# Feature flags
if micboard_settings.msp_enabled:
    ...

# Get custom settings
timeout = micboard_settings.get("SHURE_API_TIMEOUT", default=10)

# Scoped settings use the same service
value = micboard_settings.get(
    "CUSTOM_KEY",
    organization=org,
    site=site,
    default="fallback",
)

See micboard/ARCHITECTURE.md for detailed architecture documentation.

Plugin Architecture

Extend Micboard with manufacturer-specific plugins. Put each plugin in micboard/integrations/<code>/plugin.py; PluginRegistry discovers it by module and class name. For example, micboard/integrations/acme/plugin.py can contain:

from typing import Any

from micboard.services.common.base.plugin import ManufacturerPlugin


class AcmePlugin(ManufacturerPlugin):
    @property
    def name(self) -> str:
        return "Acme"

    @property
    def code(self) -> str:
        return "acme"

    def get_client(self) -> object:
        return object()

    def get_devices(self) -> list[dict[str, Any]]:
        return []

    def get_device(self, device_id: str) -> dict[str, Any] | None:
        return None

    def get_device_channels(self, device_id: str) -> list[dict[str, Any]]:
        return []

    def transform_device_data(self, api_data: dict[str, Any]) -> dict[str, Any] | None:
        return dict(api_data)

    def is_healthy(self) -> bool:
        return True

    def check_health(self) -> dict[str, Any]:
        return {"status": "healthy"}

Load the class or an instance through the registry; no central registration file is required:

from micboard.services.manufacturer.plugin_registry import PluginRegistry

plugin_class = PluginRegistry.get_plugin_class("acme")
plugin = PluginRegistry.get_plugin("acme", manufacturer=manufacturer)

Testing

Run the test suite:

# All tests
uv run --no-sync pytest

# Specific test file
uv run --no-sync pytest tests/test_settings_diff_admin.py -v

# With coverage
just coverage

# Specific markers
uv run --no-sync pytest -m unit
uv run --no-sync pytest -m integration
uv run --no-sync pytest -m django_db

Linting and prek

Use ruff and prek to keep code quality consistent:

uv run --no-sync ruff check .
uv run --no-sync ruff format .
uv run --no-sync prek run --all-files

Release Notes

  • Update CHANGELOG.md under [Unreleased] with notable changes.
  • A merged feat or fix Conventional Commit automatically starts the Prepare Release PR workflow. Run it manually from main only for backfills or controlled retries.
  • Release metadata reaches main through a protected pull request and required checks.
  • The publication workflow builds the protected merge commit once, signs Sigstore provenance and SPDX SBOM attestations, verifies the sealed files through TestPyPI, and publishes with environment-bound PEP 740 attestations.
  • Stable publication pauses once for production pypi-release environment approval. After approval, the workflow publishes to PyPI, creates or verifies the version tag at the exact release commit, and publishes a draft-first GitHub release containing the registry-signed wheel, source archive, SPDX SBOM, publish attestations, and checksums.
  • If only GitHub release assembly fails after PyPI succeeds, use the audited recovery workflow with the failed run ID, exact commit, and version. It reverifies and reuses the original retained artifact without rebuilding or touching either package registry.

Development Workflow

Agent & Research Workflow Policy

  • When you need to search programming documentation, always use the context7 tools (see AGENTS.md Quick Reference).
  • If you are unsure how to implement or use a library, use gh_grep to search for up-to-date code examples from GitHub.
  1. Install pre-commit hooks:

    uv run --no-sync prek install -f --prepare-hooks
    
  2. Run linting/formatting:

    uv run --no-sync ruff check . --fix
    uv run --no-sync ruff format .
    
  3. Type checking:

    uv run --no-sync python -m mypy micboard
    
  4. Run tests before committing:

    uv run --no-sync pytest
    uv run --no-sync prek run --all-files
    
  5. Security checks:

    uv run --no-sync bandit -r micboard -ll
    

Important Notes on Migrations

⚠️ CRITICAL: This is a pre-production reusable app, but migration history is protected:

  • DO NOT manually edit files in micboard/migrations/
  • DO NOT run makemigrations carelessly
  • ONLY create new migrations when schema changes are approved
  • NEVER delete or modify existing migrations
  • ALWAYS test migrations thoroughly before production deployment
  • USE uv run --no-sync python manage.py safemigrate in production hosts configured with django_safemigrate

See CONTRIBUTING.md for details.

Documentation

Support & Contributing

License

AGPL-3.0-or-later – This program is free software. See LICENSE for details.

Note: If you use this software in production, you may need to comply with AGPL licensing requirements, including making source code available to users.

FOSSA Status

Download files

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

Source Distribution

django_micboard-2026.8.14.1.tar.gz (448.7 kB view details)

Uploaded Source

Built Distribution

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

django_micboard-2026.8.14.1-py3-none-any.whl (590.5 kB view details)

Uploaded Python 3

File details

Details for the file django_micboard-2026.8.14.1.tar.gz.

File metadata

  • Download URL: django_micboard-2026.8.14.1.tar.gz
  • Upload date:
  • Size: 448.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for django_micboard-2026.8.14.1.tar.gz
Algorithm Hash digest
SHA256 7b140208a302aba29a6dd713c47190c8e77b51bcc1c4617e099e3dab91e0a4a5
MD5 0abab8f9b933683c253447f9194950d9
BLAKE2b-256 68f763ee15a4fb87ecef0f2fda7a33f19a4306ab931d346223327cac4a73abbf

See more details on using hashes here.

File details

Details for the file django_micboard-2026.8.14.1-py3-none-any.whl.

File metadata

  • Download URL: django_micboard-2026.8.14.1-py3-none-any.whl
  • Upload date:
  • Size: 590.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for django_micboard-2026.8.14.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8a2a71d430f263f4e153aec0cc86e41a74118335a6e5d387017086b24b3e5aed
MD5 85ec6c4570fbe188a546334f658b8574
BLAKE2b-256 80b14ff7929763783bd213a2544fd61238e74465b0b594a283a88b653b2b1a6b

See more details on using hashes here.

Release history Release notifications | RSS feed

2026.8.21.0

2 files

2026.8.15.0

2 files

This release

2026.8.14.1 This release

2 files

2026.8.14.0

2 files

2026.8.13.2

2 files

2026.8.13.1

2 files

2026.8.13.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