Adding Device Support - delize/home-assistant-loggamera-integration GitHub Wiki

Adding Device Support (Developer Guide)

Technical guide for developers implementing support for new Loggamera devices.

🎯 When to Use This Guide

  • You're implementing new device support
  • Creating sensor mappings for unmapped devices
  • Contributing device support to the integration
  • Understanding the technical implementation process

For end users: See Device Help to request support instead.

🔍 Analysis Phase

Required Information from Users

When a user requests device support, gather:

  1. Diagnostic output from these tools:

    python tools/loggamera_diagnostic.py API_KEY --verbose
    python tools/organization_mapper.py API_KEY --format json
    python tools/validate_sensor_mappings.py
    
  2. Device expectations - what sensors should be created

  3. API response samples for the specific device

  4. Device specifications if available

Extract Key Information

From diagnostic output, identify:

  • Device Class from API (PowerMeter, CustomDevice, etc.)
  • Available endpoints that respond for this device
  • Sensor IDs from RawData endpoint responses
  • Units and types (UnitType, ValueType)
  • Clear names if provided by API
  • Update frequency patterns

📊 API Response Analysis

Standard Endpoint Structure

{
  "Data": {
    "Values": [
      {
        "Name": "PowerInkW",
        "Value": 2.5,
        "UnitType": "kW",
        "ValueType": "DECIMAL", 
        "ClearTextName": "Current Power"
      }
    ],
    "LogDateTimeUtc": "2025-01-19T10:30:00Z"
  }
}

RawData Endpoint Structure

{
  "Data": {
    "Values": [
      {
        "Name": "544310",
        "Value": 1234.5,
        "UnitType": "kWh",
        "ValueType": "DECIMAL",
        "ClearTextName": "Total Energy"
      }
    ]
  }
}

Device Support Strategy

Scenario Strategy Implementation
Has dedicated endpoint Standard mapping Map endpoint response fields
RawData only RawData ID mapping Map numeric sensor IDs
Hybrid support Combined mapping Both standard + RawData
No endpoint Fallback only Use GenericDevice/RawData

🛠️ Implementation Steps

Step 1: Create Sensor Mappings

For Standard Endpoints

# Add to custom_components/loggamera/sensor.py
NEW_DEVICE_STANDARD_SENSORS = {
    "ApiSensorName": {
        "name": "internal_name",
        "unit": "kWh",
        "device_class": "energy",
        "state_class": "total_increasing",
        "clear_name": "User Display Name"
    },
    "AnotherSensor": {
        "name": "another_sensor",
        "unit": "°C",
        "device_class": "temperature", 
        "state_class": "measurement",
        "clear_name": "Temperature Sensor"
    }
}

For RawData-Only Devices

# Add to sensor.py
NEW_DEVICE_RAWDATA_MAPPINGS = {
    "544310": {  # Numeric sensor ID
        "name": "total_energy",
        "unit": "kWh",
        "device_class": "energy",
        "state_class": "total_increasing", 
        "clear_name": "Total Energy"
    },
    "544311": {
        "name": "flow_rate",
        "unit": "m³/h",
        "device_class": "volume_flow_rate",
        "state_class": "measurement",
        "clear_name": "Flow Rate"
    }
}

Step 2: Add Device Recognition

Update Endpoint Selection

# In _get_primary_endpoint_for_device() method
def _get_primary_endpoint_for_device(self, device_id, device_type):
    if device_type == "NewDeviceType":
        primary_endpoint = API_ENDPOINT_NEW_DEVICE
    elif device_type == "RawDataOnlyDevice":
        # No dedicated endpoint - skip to fallbacks
        primary_endpoint = None
    # ... existing logic

Add to Sensor Creation

# Update sensor creation logic
def create_standard_sensors(self, device_data, device_id, device_name, device_type):
    if device_type == "NewDeviceType":
        mappings = NEW_DEVICE_STANDARD_SENSORS
        # Create sensors using mappings
        
def create_rawdata_sensors(self, rawdata, device_id, device_name, device_type):
    if device_type == "RawDataOnlyDevice":
        mappings = NEW_DEVICE_RAWDATA_MAPPINGS
        # Create sensors using mappings

Step 3: Handle Home Assistant Integration

Device Classes

DEVICE_CLASS_MAPPING = {
    # Energy and Power
    "energy": "energy",           # kWh, Wh
    "power": "power",             # W, kW  
    "voltage": "voltage",         # V
    "current": "current",         # A
    
    # Environmental
    "temperature": "temperature", # °C
    "humidity": "humidity",       # %
    "pressure": "pressure",       # Pa, bar
    
    # Flow and Volume
    "water": "water",             # L, m³
    "volume_flow_rate": "volume_flow_rate",  # L/min, m³/h
    
    # Other
    "battery": "battery",         # %
    "signal_strength": "signal_strength"  # dBm
}

State Classes

STATE_CLASS_MAPPING = {
    "measurement": "measurement",     # Instantaneous values
    "total_increasing": "total_increasing",  # Cumulative totals
    "total": "total"                  # Totals that can decrease
}

Step 4: Error Handling

API Quirks

def fix_api_issues(clear_name, sensor_name):
    """Handle known API spelling/naming issues."""
    corrections = {
        "Voltate": "Voltage",
        "Signal-Noice": "Signal-Noise",
        # Add device-specific fixes
    }
    
    for wrong, correct in corrections.items():
        clear_name = clear_name.replace(wrong, correct)
    
    return clear_name

Missing Endpoints

def handle_missing_endpoint(device_type):
    """Handle devices without dedicated endpoints."""
    no_endpoint_devices = ["HeatMeter", "ChargingStation"]
    
    if device_type in no_endpoint_devices:
        return None  # Skip to fallbacks
    
    return get_standard_endpoint(device_type)

🧪 Testing Implementation

Development Testing

Validate Mappings

# Test sensor coverage
python tools/validate_sensor_mappings.py

# Check device discovery  
python tools/organization_mapper.py API_KEY --format json

# Test specific endpoints
python tools/loggamera_api_explorer.py API_KEY RawData --device-id DEVICE_ID

Integration Testing

# Full diagnostic
python tools/loggamera_diagnostic.py API_KEY --verbose

# Device-specific testing
python tools/comprehensive_sensor_discovery.py

User Testing Process

  1. Create development version with new support
  2. User installs and tests functionality
  3. User reports sensor accuracy and issues
  4. Iterate based on feedback
  5. Validate all sensors work correctly

Testing Checklist

  • Device appears in Home Assistant
  • All expected sensors created
  • Sensor names are user-friendly
  • Units and device classes correct
  • Values update properly
  • No "Unknown" sensors remain
  • Integration with dashboards works

📝 Implementation Examples

Standard Device Example

# PowerMeter-style device with dedicated endpoint
SOLAR_INVERTER_STANDARD_SENSORS = {
    "CurrentPowerOutput": {
        "name": "current_power_output",
        "unit": "kW", 
        "device_class": "power",
        "state_class": "measurement",
        "clear_name": "Current Power Output"
    },
    "TotalEnergyProduced": {
        "name": "total_energy_produced",
        "unit": "kWh",
        "device_class": "energy", 
        "state_class": "total_increasing",
        "clear_name": "Total Energy Produced"
    }
}

RawData-Only Example

# HeatMeter-style device using only RawData
SMART_THERMOSTAT_RAWDATA_MAPPINGS = {
    "545001": {
        "name": "current_temperature",
        "unit": "°C",
        "device_class": "temperature",
        "state_class": "measurement", 
        "clear_name": "Current Temperature"
    },
    "545002": {
        "name": "target_temperature", 
        "unit": "°C",
        "device_class": "temperature",
        "state_class": "measurement",
        "clear_name": "Target Temperature"
    },
    "545003": {
        "name": "heating_active",
        "unit": "",
        "device_class": None,
        "state_class": "measurement",
        "clear_name": "Heating Active"
    }
}

Complex Device Example

# Device using multiple endpoints
def create_complex_device_sensors(self, device_id, device_type):
    sensors = []
    
    # Standard endpoint sensors
    standard_data = self.get_device_data(device_id, device_type)
    sensors.extend(self.create_standard_sensors(standard_data))
    
    # RawData detailed sensors  
    rawdata = self.get_raw_data(device_id)
    sensors.extend(self.create_rawdata_sensors(rawdata))
    
    # Custom processing for unique capabilities
    if device_type == "ComplexDevice":
        sensors.extend(self.create_special_sensors(device_id))
    
    return sensors

📚 Documentation Updates

Update Device Support Guide

# Add to Supported-Devices.md
| **NewDevice** | ✅ Full | X sensors | Y sensors | ✅ Yes | Description |

Document Sensors

## NewDevice (Purpose)
**Integration**: Home Assistant compatibility notes

### Standard Sensors (Always Enabled)
| Sensor | Unit | Device Class | Purpose |
|--------|------|--------------|---------|
| **Sensor Name** | unit | device_class | Description |

### RawData Sensors (Enable Manually)
| Sensor | Unit | Device Class | Description |

Code Documentation

# Add clear comments explaining mapping decisions
NEW_DEVICE_MAPPINGS = {
    # Energy sensor - maps to HA energy dashboard
    "energy_sensor_id": {
        "device_class": "energy",  # Required for energy dashboard
        "state_class": "total_increasing"  # Cumulative energy
    }
}

🔄 Quality Assurance

Code Review Checklist

  • Follows existing code patterns
  • Proper Home Assistant device classes
  • Consistent naming conventions
  • Error handling for edge cases
  • Documentation updates included
  • Diagnostic tools validate correctly

User Acceptance

  • User confirms all expected sensors appear
  • Sensor names are intuitive
  • Values are accurate and update properly
  • Integration with HA features works
  • No regressions in existing functionality

🤝 Collaboration Guidelines

Working with Users

  • Request specific diagnostic output
  • Clarify expectations for sensor functionality
  • Provide clear testing instructions
  • Follow up to ensure satisfaction
  • Document lessons learned for future devices

Contributing Changes

  1. Fork repository and create feature branch
  2. Implement device support following these patterns
  3. Test thoroughly with diagnostic tools
  4. Update documentation comprehensively
  5. Submit pull request with detailed description

This guide provides the technical foundation for robust device support implementation. Always coordinate with users requesting support to ensure the implementation meets their needs.

Related Guides: