-
-
Notifications
You must be signed in to change notification settings - Fork 33
Development
Jezza edited this page Sep 19, 2025
·
1 revision
Want to contribute to the Petkit integration? Welcome! This page will guide you to contribute effectively to the project.
Development Environment:
- Python 3.11+
- Home Assistant Core (latest version)
- Git
- Recommended IDE: VSCode with Python extensions
Technical Knowledge:
- Python and asynchronous programming (
async/await) - Home Assistant architecture
- REST APIs and error handling
- Unit testing with
pytest
- Fork the project
git clone https://github.com/your-username/homeassistant_petkit.git
cd homeassistant_petkit- Install development dependencies
pip install -r requirements_dev.txt
pip install -r requirements_test.txt- Setup pre-commit
pre-commit install
pre-commit run --all-filescustom_components/petkit/
βββ __init__.py # Integration entry point
βββ manifest.json # Integration metadata
βββ config_flow.py # Configuration interface
βββ const.py # Global constants
βββ coordinator.py # Data manager
βββ entity.py # Base entity classes
βββ api/
β βββ __init__.py
β βββ client.py # Petkit API client
β βββ exceptions.py # Custom exceptions
βββ entities/
β βββ __init__.py
β βββ sensor.py # Sensors
β βββ switch.py # Switches
β βββ button.py # Buttons
β βββ camera.py # Cameras/media
β βββ select.py # Selectors
βββ translations/ # Translation files
βββ services/
βββ media_manager.py # Media management
βββ bluetooth_relay.py # Bluetooth relay
DataUpdateCoordinator (coordinator.py)
- Centralized data management
- Smart polling
- API error handling
API Client (api/client.py)
- Interface with Petkit API
- Authentication and session management
- Rate limiting handling
Entities (entities/)
- Implementation of different HA entity types
- API data mapping to HA
- Identify the device
# In const.py
DEVICE_TYPE_NEW = "new_device"
DEVICE_MODELS_NEW = ["model1", "model2"]- Create entities
# In entities/sensor.py
class NewDeviceBatterySensor(PetkitSensor):
def __init__(self, device, coordinator):
super().__init__(device, coordinator)
self._attr_name = f"{device.name} Battery"
self._attr_device_class = SensorDeviceClass.BATTERY
@property
def native_value(self):
return self.device.data.get("battery_level")- Add support in integration
# In __init__.py
async def async_setup_entry(hass, entry):
# Logic to add new device
if device.type == DEVICE_TYPE_NEW:
entities.extend(create_new_device_entities(device, coordinator))- API client extension
# In api/client.py
async def get_new_feature_data(self, device_id: str) -> dict:
"""Retrieve new feature data."""
url = f"{self.base_url}/devices/{device_id}/new_feature"
response = await self._request("GET", url)
return response.get("data", {})- Create new entity
# In entities/
class NewFeatureEntity(PetkitEntity):
def __init__(self, device, coordinator):
super().__init__(device, coordinator)
self._attr_name = f"{device.name} New Feature"
async def async_update(self):
data = await self.coordinator.api.get_new_feature_data(self.device.id)
self._attr_state = data.get("status")Unit Tests
# tests/test_sensor.py
import pytest
from custom_components.petkit.entities.sensor import BatterySensor
@pytest.mark.asyncio
async def test_battery_sensor():
# Mock device and coordinator
device = MockDevice()
coordinator = MockCoordinator()
sensor = BatterySensor(device, coordinator)
assert sensor.device_class == SensorDeviceClass.BATTERYIntegration Tests
# tests/test_config_flow.py
async def test_config_flow_success(hass):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == RESULT_TYPE_FORMAdding new media type
# In services/media_manager.py
class MediaManager:
async def download_new_media_type(self, device_id: str):
"""Download new media type."""
media_list = await self.api.get_new_media(device_id)
for media in media_list:
await self._download_media(media, "new_type")# Unit tests
pytest tests/ -v
# Tests with coverage
pytest tests/ --cov=custom_components.petkit --cov-report=html
# Integration tests
pytest tests/test_config_flow.py -v# Automatic formatting
black custom_components/petkit/
isort custom_components/petkit/
# Style checking
flake8 custom_components/petkit/
pylint custom_components/petkit/
# Type checking
mypy custom_components/petkit/- Development installation
# Symbolic link to your development folder
ln -s /path/to/dev/custom_components/petkit /config/custom_components/petkit- Testing with real devices
- Set up test HA environment
- Use test Petkit accounts
- Test all scenarios (connection, disconnection, errors)
class NewEntity(PetkitEntity):
"""Represents a new Petkit entity.
This entity handles specific functionality for the new device
and exposes data through the Home Assistant interface.
Attributes:
device: Associated Petkit device
coordinator: Data coordinator
"""
async def async_custom_method(self, param: str) -> bool:
"""Custom method for the entity.
Args:
param: Configuration parameter
Returns:
True if operation succeeds, False otherwise
Raises:
PetkitException: On API error
"""Adding a new language
// translations/en.json
{
"config": {
"step": {
"user": {
"title": "Petkit Configuration",
"description": "Configure your Petkit integration"
}
}
},
"entity": {
"sensor": {
"battery_level": {
"name": "Battery Level"
}
}
}
}- Fork and branch
git checkout -b feature/new-feature- Development
- Follow code conventions
- Add tests
- Document changes
- Validation
pre-commit run --all-files
pytest tests/ -v- Pull Request
- Clear description of changes
- Passing tests
- Up-to-date documentation
Naming
- Classes:
PascalCase - Functions/variables:
snake_case - Constants:
UPPER_SNAKE_CASE - Files:
snake_case.py
Docstrings
async def fetch_device_data(self, device_id: str) -> Dict[str, Any]:
"""Fetch device data.
Args:
device_id: Unique device identifier
Returns:
Dictionary containing device data
Raises:
APIException: If API returns error
NetworkException: On network issues
"""Error Handling
try:
result = await self.api.get_data()
except APIException as exc:
_LOGGER.error("API error: %s", exc)
raise UpdateFailed(f"Unable to fetch data: {exc}")
except Exception as exc:
_LOGGER.exception("Unexpected error: %s", exc)
raise- β Never log credentials
- β Use secure sessions
- β Validate all user inputs
- β Handle network timeouts
- β
Use
async/awaitcorrectly - β Avoid synchronous API calls
- β Implement smart caching
- β Limit concurrent requests
- β Support recent HA versions
- β Graceful dependency handling
- β Test on different configurations
- β Entity backward compatibility
Short term:
- Support for new device models
- Performance improvements
- Advanced configuration interface
Medium term:
- Real-time video streaming
- Google Assistant/Alexa integration
- Advanced health monitoring
Long term:
- Machine learning for pet habits
- Public API for third-party developers
- Extended IoT support
Beginner Developers:
- Simple bug fixes
- Documentation improvements
- Translation additions
Experienced Developers:
- New features
- Performance optimizations
- Architecture and design
Home Assistant Experts:
- Advanced integrations
- Standards and compliance
- Technical leadership
Join our developer-dedicated Discord channel:
Available Channels:
-
#dev-general: General discussion -
#dev-help: Technical help -
#dev-api: API questions -
#dev-testing: Test coordination
Contributors are highlighted:
- π "Contributors" section in README
- ποΈ Recognition badges
- π£ Discord announcements
- π Swag for major contributions
- Python client: py-petkit-api
- Internal API documentation
- Implementation examples
Thank you for contributing to improving the Petkit integration! πΎ