blob: 6584a4e7e28fa3ddd031c878e219ab59496c0fec [file] [log] [blame]
/*
*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** @file "mainBattery.cpp"
*
* Battery functionality for application with battery as source.
* The Reading will be set in the power configuration cluster
*/
/*****************************************************************************
* Includes Definitions
*****************************************************************************/
#include "gpBatteryMonitor.h"
#include "gpSched.h"
#include <lib/support/CHIPMem.h>
#include "App_Battery.h"
using namespace ::chip;
using namespace ::chip::app;
using namespace ::chip::TLV;
using namespace ::chip::Credentials;
using namespace ::chip::DeviceLayer;
using namespace ::chip::app::Clusters::PowerSource;
using namespace chip::app::Clusters;
/*****************************************************************************
* Macro Definitions
*****************************************************************************/
#define GP_COMPONENT_ID GP_COMPONENT_ID_APP
#define QPG_BATTERY_ENDPOINT_ID (0)
/*****************************************************************************
* Type Definitions
*****************************************************************************/
/*****************************************************************************
* Static Data Definitions
*****************************************************************************/
/*****************************************************************************
* Extern Data Definitions
*****************************************************************************/
/*****************************************************************************
* Application function prototypes
*****************************************************************************/
/*****************************************************************************
* Default class overrides
*****************************************************************************/
/*****************************************************************************
* Stack configuration
*****************************************************************************/
/*****************************************************************************
* Application function definitions
*****************************************************************************/
/*****************************************************************************
* Static Data Definitions
*****************************************************************************/
/*****************************************************************************
* Functional callbacks to application
*****************************************************************************/
void SetBatteryVoltage(uint32_t voltage)
{
SystemLayer().ScheduleLambda([voltage] {
Protocols::InteractionModel::Status status =
PowerSource::Attributes::BatVoltage::Set(QPG_BATTERY_ENDPOINT_ID, (uint32_t) voltage);
if (status != Protocols::InteractionModel::Status::Success)
{
ChipLogError(NotSpecified, "ERR: updating voltage %x", to_underlying(status));
}
});
}
void SetBatteryPercentageRemaining(DoubledPercentage value)
{
SystemLayer().ScheduleLambda([value] {
Protocols::InteractionModel::Status status =
PowerSource::Attributes::BatPercentRemaining::Set(QPG_BATTERY_ENDPOINT_ID, value);
if (status != Protocols::InteractionModel::Status::Success)
{
ChipLogError(NotSpecified, "ERR: updating percentage %x", to_underlying(status));
}
});
}
void SetBatChargeLevel(BatChargeLevelEnum level)
{
SystemLayer().ScheduleLambda([level] {
Protocols::InteractionModel::Status status = PowerSource::Attributes::BatChargeLevel::Set(QPG_BATTERY_ENDPOINT_ID, level);
if (status != Protocols::InteractionModel::Status::Success)
{
ChipLogError(NotSpecified, "ERR: updating BatChargeLevel %x", to_underlying(status));
}
});
}
/** @brief Application specific implementation of the Battery charge level
Below implementation is an reference example for battery powered devices
*/
BatChargeLevelEnum CalculateBatChargeLevel(uint32_t currentBatVoltage, DoubledPercentage doubledPercentage)
{
BatChargeLevelEnum value;
// Assign proper values to the power level dependant on battery'
if (currentBatVoltage <= APP_BATTERY_CRITICAL_THRESHOLD)
{
// battery voltage < critical battery level
value = BatChargeLevelEnum::kCritical;
}
else if (doubledPercentage > (2 * APP_BATTERY_LOW))
{
// battery remaining > 33% (2*33)
value = BatChargeLevelEnum::kOk;
}
else
{
// battery remaining < 33%
value = BatChargeLevelEnum::kWarning;
}
return value;
}
/*****************************************************************************
* --- Battery monitoring
*****************************************************************************/
/** @brief Function to retrieve Battery voltage value from system
*
* @return voltage low voltage threshold in 1mV/unit.
*/
uint32_t Application_GetLowBatteryVoltageThreshold(void)
{
return (APP_BATTERY_LOW_THRESHOLD);
}
/** @brief Function to retrieve Battery voltage value from system
*
* @param pBatteryVoltage measured battery voltage in mV
* @return success True if valid temperature value is returned.
*/
Bool Application_GetBatteryVoltage(uint32_t * pBatteryVoltage)
{
UQ2_6 voltageReading;
bool success;
// Measure Battery Voltage
if (pBatteryVoltage == NULL)
{
return false;
}
success = gpBatteryMonitor_Measure(gpBatteryMonitor_MeasurementTypeUnloadedWithRecovery, &voltageReading);
*pBatteryVoltage =
BATTERY_MONITOR_GET_INTEGER_PART(voltageReading) * 1000 + BATTERY_MONITOR_GET_FLOATING_PART(voltageReading) * 10;
return success;
}
/** @brief example function to calculate and update the battery remaining percentage
*
* @param batteryVoltage Current battery voltage in 1mV unit
* @return doubledPercentage The battery remaining percentage in a 0.5% unit
*/
DoubledPercentage Application_UpdateBatteryRemaining(uint32_t batteryVoltage)
{
/**
* Porting note:
* Add/Modify the the battery remaining percentage measurement
* according to your specific HW/Battery here.
* Currently provided is an example by converting battery voltage into remaining percentage.
*/
uint8_t remainingPercentage; // in 1% unit
if (batteryVoltage >= APP_BATTERY_FULL_THRESHOLD)
{
remainingPercentage = 100;
ChipLogProgress(NotSpecified, "Battery: FULL");
}
// Battery Section 1: Full ~ Medium
else if (batteryVoltage >= APP_BATTERY_MEDIUM_THRESHOLD)
{
remainingPercentage = (100 -
(uint8_t) (((APP_BATTERY_FULL_THRESHOLD - batteryVoltage) * (100 - APP_BATTERY_MEDIUM)) /
(APP_BATTERY_FULL_THRESHOLD - APP_BATTERY_MEDIUM_THRESHOLD)));
ChipLogProgress(NotSpecified, "Battery: above MEDIUM");
}
// Battery Section 2: Medium ~ Low
else if (batteryVoltage >= APP_BATTERY_LOW_THRESHOLD)
{
remainingPercentage =
(APP_BATTERY_MEDIUM -
(uint8_t) (((APP_BATTERY_MEDIUM_THRESHOLD - batteryVoltage) * (APP_BATTERY_MEDIUM - APP_BATTERY_LOW)) /
(APP_BATTERY_MEDIUM_THRESHOLD - APP_BATTERY_LOW_THRESHOLD)));
ChipLogProgress(NotSpecified, "Battery: above LOW");
}
// Battery Section 3: Low ~ Critical
else if (batteryVoltage >= APP_BATTERY_CRITICAL_THRESHOLD)
{
remainingPercentage = (APP_BATTERY_LOW -
(uint8_t) ((APP_BATTERY_LOW_THRESHOLD - batteryVoltage) * APP_BATTERY_LOW /
(APP_BATTERY_LOW_THRESHOLD - APP_BATTERY_CRITICAL_THRESHOLD)));
ChipLogProgress(NotSpecified, "Battery: below LOW");
}
else
{
remainingPercentage = 0;
ChipLogProgress(NotSpecified, "Battery: CRITICAL");
}
ChipLogProgress(NotSpecified, "Battery: %lu.%03luV, %d(%%)", batteryVoltage / 1000, batteryVoltage % 1000, remainingPercentage);
return remainingPercentage * 2;
}
/** @brief Function to update Power Configuration cluster attributes
*/
void Application_UpdateBattery(void)
{
uint32_t voltage;
Bool status = false;
// get current battery voltage reading
status = Application_GetBatteryVoltage(&voltage);
if (status)
{
// Update Power configuration's BatteryPercentageRemaining attribute
DoubledPercentage doubledPercentage = Application_UpdateBatteryRemaining(voltage);
// Update Power configuration's BatteryVoltage attribute
SetBatteryVoltage(voltage);
SetBatteryPercentageRemaining(doubledPercentage);
BatChargeLevelEnum level = CalculateBatChargeLevel(voltage, doubledPercentage);
SetBatChargeLevel(level);
}
else
{
ChipLogError(NotSpecified, "error reading battery voltage");
}
}
/** @brief Function to start/restart periodic update battery voltage reading
*/
void Application_StartPeriodicBatteryUpdate(void)
{
// Update Battery reading
Application_UpdateBattery();
// remove previous scheduled event first
if (gpSched_ExistsEvent(Application_StartPeriodicBatteryUpdate))
{
gpSched_UnscheduleEvent(Application_StartPeriodicBatteryUpdate);
}
// schedule the periodic battery voltage reading update
gpSched_ScheduleEvent(APP_BATTERY_UPDATE_PERIOD, Application_StartPeriodicBatteryUpdate);
}
/** @brief Function to stop periodic update battery voltage reading
*/
void Application_StopPeriodicBatteryUpdate(void)
{
// Update Battery reading
Application_UpdateBattery();
// remove periodic battery voltage reading update schedular
if (gpSched_ExistsEvent(Application_StartPeriodicBatteryUpdate))
{
gpSched_UnscheduleEvent(Application_StartPeriodicBatteryUpdate);
}
}