End-User Dashboard Integration
For end-users to understand the current status of software-based optimization, they must have access to a range of information about their account, devices, and optimization performance.
The endpoints detailed below are used in the Whitelabel end-user dashboard Podero provides and can be used by Partners to build a comparable end-user experience.
Dashboard Overview Data
List All Devices
Retrieve all devices for a user to display on the dashboard:
Heat Pumps
Electric Vehicles
Solar Inverters
curl -X GET \
'https://app.podero.com/api/partners/v2.0/org/{org_id}/users/{user_id}/heat-pumps' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {auth_token}'
Returns a list of all heat pumps with complete data for each unit. curl -X GET \
'https://app.podero.com/api/partners/v2.0/org/{org_id}/users/{user_id}/electric-vehicles' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {auth_token}'
curl -X GET \
'https://app.podero.com/api/partners/v2.0/org/{org_id}/users/{user_id}/inverters' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {auth_token}'
Example Response
[
{
"id" : "497f6eca-6276-4993-bfeb-53cbbbba6f08" ,
"created_at" : "2019-08-24T14:15:22Z" ,
"updated_at" : "2019-08-24T14:15:22Z" ,
"building" : "94964bf8-4ec9-4f3f-b10e-0fe21980279e" ,
"is_authenticated" : true ,
"is_smart_optimization_active" : true ,
"device_model" : {
"manufacturer" : "Nibe" ,
"model" : "S-Series"
},
"operational_mode" : "heating" ,
"current_power_consumption_w" : 2500 ,
"indoor_actual_temperature" : 21.5 ,
"outdoor_temperature" : 5.3 ,
"consumption_last_day_kwh" : 45.3 ,
"consumption_last_week_kwh" : 287.6 ,
"consumption_last_month_kwh" : 1204.8
}
]
Key Dashboard Metrics
Device Status Indicators
Field: is_authenticatedShows if the device is successfully connected to the manufacturer’s API. def get_connection_status ( device ):
return "Connected" if device[ 'is_authenticated' ] else "Disconnected"
Field: is_smart_optimization_activeIndicates whether Podero’s optimization algorithm is actively controlling the device. def get_optimization_status ( device ):
if not device[ 'is_authenticated' ]:
return "Not Available"
return "Active" if device[ 'is_smart_optimization_active' ] else "Paused"
Field: operational_modeCurrent mode of operation (heating, cooling, standby, etc.). mode_icons = {
'heating' : '🔥' ,
'cooling' : '❄️' ,
'standby' : '⏸️' ,
'auto' : '🔄'
}
Current Readings
Display real-time or near-real-time data:
Heat Pump
Electric Vehicle
Solar Inverter
def format_heat_pump_readings ( device ):
return {
'indoor_temp' : f " { device[ 'indoor_actual_temperature' ] } °C" ,
'outdoor_temp' : f " { device[ 'outdoor_temperature' ] } °C" ,
'current_power' : f " { device[ 'current_power_consumption_w' ] } W" ,
'dhw_temp' : f " { device[ 'dhw_temperature' ] } °C"
}
def format_ev_readings ( device ):
return {
'battery_level' : f " { device[ 'battery_level' ] } %" ,
'charging_status' : device[ 'charging_status' ],
'charge_rate' : f " { device[ 'charge_rate_kw' ] } kW" ,
'range_km' : f " { device[ 'range_km' ] } km"
}
def format_inverter_readings ( device ):
return {
'current_production' : f " { device[ 'current_solar_production_w' ] } W" ,
'solar_surplus' : f " { device[ 'solar_surplus_w' ] } W" ,
'battery_level' : f " { device[ 'battery_charge_level_percent' ] } %"
}
Consumption History
Show energy consumption over different time periods:
def format_consumption_data ( device ):
return {
'today' : device[ 'consumption_last_day_kwh' ],
'this_week' : device[ 'consumption_last_week_kwh' ],
'this_month' : device[ 'consumption_last_month_kwh' ],
'last_updated' : device[ 'consumption_last_updated_at' ]
}
Single Device View
Get Specific Device Details
Retrieve detailed information for a single device:
curl -X GET \
'https://app.podero.com/api/partners/v2.0/org/{org_id}/users/{user_id}/heat-pumps/{device_id}' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {auth_token}'
Dashboard UI Components
Status Card Example
function DeviceStatusCard ({ device }) {
return (
< Card >
< h3 > { device . device_model . manufacturer } { device . device_model . model } </ h3 >
< StatusIndicator
connected = { device . is_authenticated }
optimizing = { device . is_smart_optimization_active }
/>
< MetricsGrid >
< Metric
label = "Indoor Temp"
value = { ` ${ device . indoor_actual_temperature } °C` }
/>
< Metric
label = "Current Power"
value = { ` ${ device . current_power_consumption_w } W` }
/>
< Metric
label = "Today's Consumption"
value = { ` ${ device . consumption_last_day_kwh } kWh` }
/>
</ MetricsGrid >
</ Card >
);
}
Consumption Chart Example
import matplotlib.pyplot as plt
def create_consumption_chart ( device ):
periods = [ 'Today' , 'This Week' , 'This Month' ]
consumption = [
device[ 'consumption_last_day_kwh' ],
device[ 'consumption_last_week_kwh' ],
device[ 'consumption_last_month_kwh' ]
]
plt.bar(periods, consumption)
plt.ylabel( 'Energy Consumption (kWh)' )
plt.title( 'Device Consumption Overview' )
return plt
Real-Time Updates
State data refresh frequency depends on the manufacturer’s API limitations. Some values may update every 5-15 minutes.
Polling Strategy
Implement efficient polling for dashboard updates:
import time
def poll_device_status ( device_id , interval = 300 ): # 5 minutes
"""
Poll device status at regular intervals
"""
while True :
try :
device = get_device_data(device_id)
update_dashboard(device)
# Check last update timestamp
last_updated = device[ 'current_state_last_updated_at' ]
print ( f "Last updated: { last_updated } " )
except Exception as e:
print ( f "Error polling device: { e } " )
time.sleep(interval)
Websocket Alternative
For real-time updates, consider implementing websockets on your backend to push updates to the dashboard when device state changes.
Building-Level Aggregation
Total Consumption by Building
Aggregate consumption across all devices in a building:
def get_building_consumption ( user_id , building_id ):
"""
Calculate total building consumption
"""
# Get all devices in building
heat_pumps = get_heat_pumps(user_id)
evs = get_electric_vehicles(user_id)
# Filter by building
building_devices = [
d for d in (heat_pumps + evs)
if d.get( 'building' ) == building_id
]
# Sum consumption
total_day = sum (d[ 'consumption_last_day_kwh' ] for d in building_devices)
total_week = sum (d[ 'consumption_last_week_kwh' ] for d in building_devices)
total_month = sum (d[ 'consumption_last_month_kwh' ] for d in building_devices)
return {
'day' : total_day,
'week' : total_week,
'month' : total_month
}
Savings Calculation
Display Optimization Savings
Calculate and display estimated savings from optimization:
def calculate_savings ( device , energy_price_kwh = 0.30 ):
"""
Calculate estimated savings based on optimized consumption
Note: This is a simplified example. Actual savings calculation
should use historical data and baseline consumption.
"""
# Estimated savings percentage with optimization
savings_percentage = 0.15 # 15% typical savings
consumption = device[ 'consumption_last_month_kwh' ]
optimized_cost = consumption * energy_price_kwh
baseline_cost = consumption / ( 1 - savings_percentage) * energy_price_kwh
savings = baseline_cost - optimized_cost
return {
'monthly_savings' : round (savings, 2 ),
'annual_projected' : round (savings * 12 , 2 ),
'savings_percentage' : savings_percentage * 100
}
Error Handling
Display Connection Issues
def check_device_health ( device ):
"""
Check device health and return user-friendly messages
"""
if not device[ 'is_authenticated' ]:
return {
'status' : 'error' ,
'message' : 'Device disconnected. Please reconnect in settings.' ,
'action' : 'reconnect'
}
if device.get( 'authorization_url' ):
return {
'status' : 'warning' ,
'message' : 'Device requires re-authentication.' ,
'action' : 'reauthorize' ,
'url' : device[ 'authorization_url' ]
}
# Check if data is stale
last_update = datetime.fromisoformat(device[ 'current_state_last_updated_at' ])
if (datetime.now() - last_update).total_seconds() > 3600 : # 1 hour
return {
'status' : 'warning' ,
'message' : 'Device data may be outdated.' ,
'last_update' : last_update
}
return { 'status' : 'ok' }
Best Practices
Show loading states during data fetches
Display last update timestamps
Provide clear error messages with actions
Use visual indicators for status (colors, icons)
Round consumption values appropriately
Use consistent units throughout
Show trends with charts and graphs
Highlight important changes or alerts
Next Steps