OpenHarmony-5.PM 子系统(2)
- 电池服务组件
- OpenHarmony-4.1-Release
1.电池服务组件
Battery Manager 提供了电池信息查询的接口,同时开发者也可以通过公共事件监听电池状态和充放电状态的变化。电池服务组件提供如下功能:
- 电池信息查询。
- 充放电状态查询。
- 关机充电。
电池服务组件架构图:
1.1.代码目录:
base/powermgr/battery_manager
├── figures # 架构图
├── frameworks # Framework层
│ ├── napi # NAPI
│ └── native # Native层
├── interfaces # 接口层
│ └── inner_api # 内部接口
├── sa_profile # SA配置文件
├── services # 服务层
│ ├── native # Native层
│ └── zidl # Zidl接口层
├── test # 测试用例
│ ├── fuzztest # Fuzz 测试
│ ├── unittest # 单元测试
│ ├── systemtest # 系统测试
│ └── utils # 测试工具
└── utils # 工具和通用层
base/powermgr/battery_manager
├── figures # 架构图
├── frameworks # Framework层
│ ├── napi # NAPI
│ └── native # Native层
├── interfaces # 接口层
│ └── inner_api # 内部接口
├── sa_profile # SA配置文件
├── services # 服务层
│ ├── native # Native层
│ └── zidl # Zidl接口层
├── test # 测试用例
│ ├── fuzztest # Fuzz 测试
│ ├── unittest # 单元测试
│ ├── systemtest # 系统测试
│ └── utils # 测试工具
└── utils # 工具和通用层
1.2.电池和充电属性接口
该模块主要提供电池状态和充放电状态的查询接口。batteryInfo类用来描述电池信息。
- powermgr_battery_manager\interfaces\inner_api\native\include\battery_info.h
1.3.Battery Service 服务启动
Battery Service 服务被打包到 foundation 进程。System Ability 管理模块用于管理系统基础能力,本服务需要向该模块注册,如果没有编写 profile 配置,则 System Ability 管理模块在启动时不会注册该服务。
powermgr_battery_manager\sa_profile\3302.json
注册信息:1 {2 "process": "foundation",3 "systemability": [4 {5 "name": 3302,6 "libpath": "libbatteryservice.z.so",7 "run-on-create": true,8 "distributed": false,9 "dump_level": 110 }11 ]12 }
- name:为对应的serviceId必须与代码中注册的serviceId保持一致;电池服务组件的serviceId为3302;
- libpath:为SystemAbility的加载路径,必配项;
- run-on-create:true表示进程启动后即向samgr组件注册该SystemAbility;false表示按需启动,即在其他模块访问到该SystemAbility时启动;必配项;
- distributed:true表示该SystemAbility为分布式SystemAbility,支持跨设备访问;false表示只有本地跨IPC访问;
- dump-level:表示systemdumper支持的level等级,默认配置1就OK;
- 注册信息配置文件:/system/profile/foundation.xml
1.3.1.注册代码
powermgr_battery_manager\services\native\src\battery_service.cpp
//调用SystemAbility接口注册BatteryService实例
const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(DelayedSpSingleton<BatteryService>::GetInstance().GetRefPtr());
//构建入参为serviceid、runoncreate
BatteryService::BatteryService(): SystemAbility(POWER_MANAGER_BATT_SERVICE_ID, true) {}
System Ability 管理模块调用 BatteryService 的启动函数实现电池服务组件的启动:
powermgr_battery_manager\services\native\src\battery_service.cpp
void BatteryService::OnStart()
{//如果已启动则返回(BatteryService是单实例服务,只会启动一个)if (ready_) {BATTERY_HILOGD(COMP_SVC, "Service is ready, nothing to do");return;}//创建BatterysrvEventHandler实例//等待CommonEventService服务启动完成之后初始化完成if (!(Init())) { //调用BatteryService::InitBATTERY_HILOGE(COMP_SVC, "Call init failed");return;}//向OHOS::HDI::ServiceManager 注册状态监听RegisterHdiStatusListener();//BatteryService服务发布到System Ability管理模块if (!Publish(this)) {BATTERY_HILOGE(COMP_SVC, "Register to system ability manager failed");return;}// 对指定SA,MISCDEVICE_SERVICE_ABILITY_ID 的监听,当监听的该SA已被publish到SAmgr后,就会触发OnAddSystemAbilityAddSystemAbilityListener(MISCDEVICE_SERVICE_ABILITY_ID);ready_ = true;
}
重点分析:
- BatteryService::Init
bool BatteryService::Init()
{InitConfig(); //解析battery_config.jsonif (!batteryNotify_) {batteryNotify_ = std::make_unique<BatteryNotify>();}VibratorInit(); //解析battery_vibrator.jsonRegisterBootCompletedCallback();return true;
}
- RegisterHdiStatusListener();
->RegisterBatteryHdiCallback();->ErrCode ret = iBatteryInterface_->Register(callback); //drivers_peripheral\battery\interfaces\hdi_service\src\battery_interface_impl.cpp(即 BatteryInterfaceImpl::Register(const sptr<IBatteryCallback>& callback))
1.3.2.BatteryInterfaceDriver 启动
BatteryInterfaceDriver 是 HDI(即驱动接口)层服务,打包在 power_host 进程。本文主要分析 batteryd 的实现。
device_info.hcs 节点配置:
/vendor/hihope/rk3568/hdf_config/uhdf/device_info.hcs
140 power :: host {
141 hostName = "power_host";
142 priority = 50;
143 uid = "power_host";
144 gid = ["power_host", "system", "log"];
145 caps = ["BLOCK_SUSPEND"];
146 power_device :: device {
147 device0 :: deviceNode {
148 policy = 2;
149 priority = 100;
150 moduleName = "libpower_driver.z.so";
151 serviceName = "power_interface_service";
152 }
153 }
154 battery_device :: device {
155 device0 :: deviceNode {
156 policy = 2;
157 priority = 100;
158 moduleName = "libbattery_driver.z.so";
159 serviceName = "battery_interface_service";
160 }
161 }
162 thermal_device :: device {
163 device0 :: deviceNode {
164 policy = 2;
165 priority = 100;
166 moduleName = "libthermal_driver.z.so";
167 serviceName = "thermal_interface_service";
168 }
169 }
170 }
驱动程序 (Driver Entry)入口中的三个主要接口:
- Bind 接口:实现驱动接口实例化绑定,如果需要发布驱动接口,会在驱动加载过程中被调用,实例化该接口的驱动服务并和 DeviceObject 绑定。
- Init 接口:实现驱动的初始化,返回错误将中止驱动加载流程。
- Release 接口:实现驱动的卸载,在该接口中释放驱动实例的软硬件资源。
batteryd 驱动程序初始化接口:
drivers_peripheral\battery\interfaces\hdi_service\src\battery_interface_driver.cpp
static struct HdfDriverEntry g_batteryInterfaceDriverEntry = {.moduleVersion = 1,.moduleName = "battery_interface_service",.Bind = HdfBatteryInterfaceDriverBind,.Init = HdfBatteryInterfaceDriverInit,.Release = HdfBatteryInterfaceDriverRelease,
};static int32_t HdfBatteryInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
{auto *hdfBatteryInterfaceHost = new (std::nothrow) HdfBatteryInterfaceHost;//绑定BatteryInterfaceDriverDispatch作为消息处理函数。hdfBatteryInterfaceHost->ioService.Dispatch = BatteryInterfaceDriverDispatch;hdfBatteryInterfaceHost->ioService.Open = nullptr;hdfBatteryInterfaceHost->ioService.Release = nullptr;auto serviceImpl = IBatteryInterface::Get(true);hdfBatteryInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,IBatteryInterface::GetDescriptor());//IO Service 完成 IPC 通信的客户端消息请求封装,IO Dispatcher 完成驱动服务端消息请求封装//客户端消息通过 IPC 通信到达服务端并分发给 IO Dispatcher 处理。deviceObject->service = &hdfBatteryInterfaceHost->ioService;return HDF_SUCCESS;
}
BatteryInterfaceImpl接口:
通过调用BatteryInterfaceImplGetInstance接口实例BatteryInterfaceImpl对象,并且调用调用BatteryInterfaceImpl::Init进行初始化。
- 初始化电池信息路径;
- 调用调用BatteryThread::StartThread.
drivers_peripheral\battery\interfaces\hdi_service\src\battery_interface_impl.cpp
extern "C" IBatteryInterface *BatteryInterfaceImplGetInstance(void)
{using OHOS::HDI::Battery::V2_0::BatteryInterfaceImpl;BatteryInterfaceImpl *service = new (std::nothrow) BatteryInterfaceImpl();if (service->Init() != HDF_SUCCESS) { //调用BatteryInterfaceImpl::Initdelete service;return nullptr;}return service;
}int32_t BatteryInterfaceImpl::Init()
{powerSupplyProvider_ = std::make_unique<OHOS::HDI::Battery::V2_0::PowerSupplyProvider>();powerSupplyProvider_->InitBatteryPath();powerSupplyProvider_->InitPowerSupplySysfs();auto& batteryConfig = BatteryConfig::GetInstance();batteryConfig.ParseConfig();loop_ = std::make_unique<OHOS::HDI::Battery::V2_0::BatteryThread>();if (batteryCallback_ != nullptr) {loop_->InitCallback(batteryCallback_);} else {BATTERY_HILOGW(COMP_HDI, "batteryCallback_ is nullptr");}loop_->StartThread(this); //调用BatteryThread::StartThreadreturn HDF_SUCCESS;
}drivers_peripheral\battery\interfaces\hdi_service\src\battery_thread.cpp
//在BatteryInterfaceImpl::Init() 启动初始化阶段启动本线程,用于处理kernel发来的消息
void BatteryThread::StartThread(void* service)
{Init(service);Run(service);
}
1.3.3.电池 batteryInfo 信息查询流程
采用NAPI (Native API)获取电池信息,NAPI 组件是一套对外接口基于Node.js N-API规范开发的原生模块扩展开发框架。NAPI组件架构图:
NAPI适合封装IO、CPU密集型、OS底层等能力并对外暴露JS接口,通过NAPI可以实现JS与C/C++代码互相访问。我们可以通过NAPI接口构建例如网络通信、串口访问、多媒体解码、传感器数据收集等模块。接口实现详见:foundation/arkui/napi。
powermgr_battery_manager\frameworks\napi\battery_info.cpp:
static napi_module g_module = {.nm_version = 1,.nm_flags = 0,.nm_filename = "batteryInfo",.nm_register_func = BatteryInit,.nm_modname = "batteryInfo",.nm_priv = ((void*)0),.reserved = {0}};extern "C" __attribute__((constructor)) void RegisterModule(void)
{napi_module_register(&g_module);
}
- BatteryInit
static napi_value BatteryInit(napi_env env, napi_value exports)
{BATTERY_HILOGD(COMP_FWK, "Enter");napi_property_descriptor desc[] = {DECLARE_NAPI_GETTER("batterySOC", BatterySOC),DECLARE_NAPI_GETTER("chargingStatus", GetChargingState),DECLARE_NAPI_GETTER("healthStatus", GetHealthState),DECLARE_NAPI_GETTER("pluggedType", GetPluggedType),DECLARE_NAPI_GETTER("voltage", GetVoltage),DECLARE_NAPI_GETTER("technology", GetTechnology),DECLARE_NAPI_GETTER("batteryTemperature", GetBatteryTemperature),DECLARE_NAPI_GETTER("isBatteryPresent", GetBatteryPresent),DECLARE_NAPI_GETTER("batteryCapacityLevel", GetCapacityLevel),DECLARE_NAPI_GETTER("estimatedRemainingChargeTime", GetRemainingChargeTime),DECLARE_NAPI_GETTER("nowCurrent", GetBatteryNowCurrent),DECLARE_NAPI_GETTER("remainingEnergy", GetBatteryRemainEnergy),DECLARE_NAPI_GETTER("totalEnergy", GetTotalEnergy),DECLARE_NAPI_FUNCTION("setBatteryConfig", SetBatteryConfig),DECLARE_NAPI_FUNCTION("getBatteryConfig", GetBatteryConfig),DECLARE_NAPI_FUNCTION("isBatteryConfigSupported", IsBatteryConfigSupported),};NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));CreateEnumPluggedType(env, exports);CreateEnumChargeState(env, exports);CreateEnumHealthState(env, exports);CreateEnumLevelState(env, exports);CreateEventBatteryChangedKey(env, exports);CreateEventBatteryChangedCode(env, exports);BATTERY_HILOGD(COMP_FWK, "Success");return exports;
}
应用调用接口获取当前设备剩余电池容量(batterySOC)为例:
applications/standard/app_samples/code/SystemFeature/DeviceManagement/DeviceManagementCollection/feature/capabilities/src/main/ets/util/
//导入模块
import batteryInfo from '@ohos.batteryInfo';60 /**
61 * 获取当前设备剩余电池电量百分比
62 */
63 public getBatterySOC(): string {
64 let soc: number = this.disposeBatterySOC(batteryInfo.batterySOC) //调用batterySOC查询接口
65 logger.info(`${this.TAG} getChargingStatus: ${soc}`)
66 return soc.toString()
67 }
68
NAPI 接口实现BatterySOC,BatterySOC调用流程:
g_battClient.GetCapacity();
->BatterySrvClient::GetCapacity()->BatteryService::GetCapacity()->BatteryInterface::GetCapacity(capacity)-> PowerSupplyProvider::ParseCapacity->PowerSupplyProvider::ReadBatterySysfsToBuff->open
详细分析:
powermgr_battery_manager\frameworks\napi\battery_info.cpp
thread_local static BatterySrvClient& g_battClient = BatterySrvClient::GetInstance();
//注册在动态库中的BatterySOC接口,实现了电池容量的查询
static napi_value BatterySOC(napi_env env, napi_callback_info info)
{napi_value napiValue = nullptr;int32_t capacity = g_battClient.GetCapacity();NAPI_CALL(env, napi_create_int32(env, capacity, &napiValue));BATTERY_HILOGD(FEATURE_BATT_INFO, "capacity %{public}d", capacity);return napiValue;
}powermgr_battery_manager\frameworks\native\src\battery_srv_client.cpp
int32_t BatterySrvClient::GetCapacity()
{auto proxy = Connect();//查找到到POWER_MANAGER_BATT_SERVICE_ID(即BatteryService)服务并赋值给proxy_//需要了解SystemAbility IPC机制,xxClient-->xxProxy-->xxStub-->xxService。RETURN_IF_WITH_RET(proxy == nullptr, INVALID_BATT_INT_VALUE);//调用BatteryService::GetCapacity()return proxy->GetCapacity();
}powermgr_battery_manager\services\native\src\battery_service.cpp
int32_t BatteryService::GetCapacity()
{if (isMockCapacity_) {BATTERY_HILOGD(FEATURE_BATT_INFO, "Return mock battery capacity");return batteryInfo_.GetCapacity();}std::shared_lock<std::shared_mutex> lock(mutex_);if (iBatteryInterface_ == nullptr) {BATTERY_HILOGE(FEATURE_BATT_INFO, "iBatteryInterface_ is nullptr");return ERR_NO_INIT;}int32_t capacity = BATTERY_FULL_CAPACITY;//调用 BatteryInterface::GetCapacity(capacity)iBatteryInterface_->GetCapacity(capacity);return capacity;
}drivers_peripheral\battery\interfaces\hdi_service\src\battery_interface_impl.cpp
// BatteryInterfaceImpl 实现IBatteryInterface的纯虚函数
int32_t BatteryInterfaceImpl::GetCapacity(int32_t& capacity)
{// 调用 PowerSupplyProvider::ParseCapacity(...)return powerSupplyProvider_->ParseCapacity(&capacity);
}drivers_peripheral\battery\interfaces\hdi_service\src\power_supply_provider.cpp
int32_t PowerSupplyProvider::ParseCapacity(int32_t* capacity) const
{char buf[MAX_BUFF_SIZE] = {0};// 从capacity的系统文件读取当前设备剩余电池容量中至bufint32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.capacityPath.c_str(), buf, sizeof(buf));if (ret != HDF_SUCCESS) {return ret;}// 转换为十进制int32_t value = ParseInt(buf);*capacity = value;return HDF_SUCCESS;
}int32_t PowerSupplyProvider::ReadBatterySysfsToBuff(const char* path, char* buf, size_t size) const
{ // ReadSysfsFile int32_t ret = ReadSysfsFile(path, buf, size);return HDF_SUCCESS;
}int32_t PowerSupplyProvider::ReadSysfsFile(const char* path, char* buf, size_t size) const
{int32_t fd = open(path, O_RDONLY, S_IRUSR | S_IRGRP | S_IROTH);size_t readSize = read(fd, buf, size - 1);buf[readSize] = '\0';Trim(buf);close(fd);return HDF_SUCCESS;
}
1.3.4.电池 batteryinfo 信息变更发布流程
BatteryThread接口:
drivers_peripheral\battery\interfaces\hdi_service\src\battery_thread.cpp
int32_t BatteryThread::Init([[maybe_unused]] void* service)
{provider_ = std::make_unique<PowerSupplyProvider>();if (provider_ != nullptr) {provider_->InitBatteryPath();provider_->InitPowerSupplySysfs();}epFd_ = epoll_create1(EPOLL_CLOEXEC); //创建epoll 实例,用于异步事件通知InitUevent(); //初始化uevent, 并且注册回调函数UeventCallbackreturn HDF_SUCCESS;
}void BatteryThread::Run(void* service)
{batteryThread_ = std::make_unique<std::thread>([this, service] { this->LoopingThreadEntry(service); });pthread_setname_np(batteryThread_->native_handle(), "battery_thread");
}void BatteryThread::LoopingThreadEntry(void* arg)
{int32_t nevents = 0;size_t size = callbacks_.size();struct epoll_event events[size];while (isRunning_) {if (!nevents) {CycleMatters();}HandleStates();int32_t timeout = epollInterval_;int32_t waitTimeout = UpdateWaitInterval();if ((timeout < 0) || (waitTimeout > 0 && waitTimeout < timeout)) {timeout = waitTimeout;}// 等待监听的所有的fd相应的事件的产生nevents = epoll_wait(epFd_, events, static_cast<int32_t>(size), timeout);if (nevents <= 0) {continue;}// 在callbacks_中,根据ueventFd_, 调用void BatteryThread::UeventCallback(void* service) for (int32_t n = 0; n < nevents; ++n) {if (events[n].data.ptr) {auto* func = const_cast<BatteryThread*>(this);(callbacks_.find(events[n].data.fd)->second)(func, arg);}}}
}//当监听到异步事件之后,调用该函数处理
void BatteryThread::UeventCallback(void* service)
{char msg[UEVENT_MSG_LEN + UEVENT_RESERVED_SIZE] = { 0 };ssize_t len = recv(ueventFd_, msg, UEVENT_MSG_LEN, 0);if (len < 0 || len >= UEVENT_MSG_LEN) {BATTERY_HILOGI(COMP_HDI, "recv return msg is invalid, len: %{public}zd", len);return;}// msg separatormsg[len] = '\0';msg[len + 1] = '\0';std::string powerUevent;if (!MatchPowerUevent(msg, powerUevent)) {return;}BATTERY_HILOGD(FEATURE_BATT_INFO, "PowerUevent msg:%{public}s", powerUevent.c_str());UpdateBatteryInfo(service, powerUevent);
}//更新电池信息
void BatteryThread::UpdateBatteryInfo(void* service, const std::string& powerUevent)
{BatteryInfo event = {};std::unique_ptr<BatterydInfo> batteryInfo = std::make_unique<BatterydInfo>();if (batteryInfo == nullptr) {BATTERY_HILOGE(FEATURE_BATT_INFO, "make_unique BatterydInfo error");return;}// 从系统文件中读取信息到batteryInfoprovider_->UpdateInfoByReadSysFile(batteryInfo.get());//将batteryInfo 赋值eventevent.capacity = batteryInfo->capacity_;event.voltage= batteryInfo->voltage_;event.temperature = batteryInfo->temperature_;event.healthState = batteryInfo->healthState_;event.pluggedType = batteryInfo->pluggedType_;event.pluggedMaxCurrent = batteryInfo->pluggedMaxCurrent_;event.pluggedMaxVoltage = batteryInfo->pluggedMaxVoltage_;event.chargeState = batteryInfo->chargeState_;event.chargeCounter = batteryInfo->chargeCounter_;event.present = batteryInfo->present_;event.technology = batteryInfo->technology_;event.curNow = batteryInfo->curNow_;event.remainEnergy = batteryInfo->remainEnergy_;event.totalEnergy = batteryInfo->totalEnergy_;event.uevent = powerUevent;if (g_callback != nullptr) {g_callback->Update(event); // 向注册的 Callback or Subscriber发送电池状态变更消息} else {BATTERY_HILOGI(FEATURE_BATT_INFO, "g_callback is nullptr");}
}
framework service端接口:
powermgr_battery_manager\services\native\src\battery_service.cpp
bool BatteryService::RegisterBatteryHdiCallback()
{std::lock_guard<std::shared_mutex> lock(mutex_);if (iBatteryInterface_ == nullptr) {iBatteryInterface_ = V2_0::IBatteryInterface::Get();BATTERY_HILOGE(COMP_SVC, "failed to get battery hdi interface");RETURN_IF_WITH_RET(iBatteryInterface_ == nullptr, false);}// 向BatteryInterface 注册一个 BatteryCallback,sptr<V2_0::IBatteryCallback> callback = new BatteryCallback();ErrCode ret = iBatteryInterface_->Register(callback);if (ret < 0) {BATTERY_HILOGE(COMP_SVC, "register callback failed");return false;}// 调用 BatteryCallback::RegisterBatteryEvent 更新回调处理函数(static)为HandleBatteryCallbackEventBatteryCallback::BatteryEventCallback eventCb =std::bind(&BatteryService::HandleBatteryCallbackEvent, this, std::placeholders::_1);BatteryCallback::RegisterBatteryEvent(eventCb);return true;
}int32_t BatteryService::HandleBatteryCallbackEvent(const V2_0::BatteryInfo& event)
{if (isMockUnplugged_ || isMockCapacity_) {return ERR_OK;}ConvertingEvent(event);RETURN_IF_WITH_RET(lastBatteryInfo_ == batteryInfo_, ERR_OK);HandleBatteryInfo();return ERR_OK;
}//根据event事件,更新batteryInfo_
void BatteryService::ConvertingEvent(const V1_2::BatteryInfo& event)
{if (!isMockCapacity_) {batteryInfo_.SetCapacity(event.capacity);}if (!isMockUnplugged_) {batteryInfo_.SetPluggedType(BatteryPluggedType(event.pluggedType));batteryInfo_.SetPluggedMaxCurrent(event.pluggedMaxCurrent);batteryInfo_.SetPluggedMaxVoltage(event.pluggedMaxVoltage);batteryInfo_.SetChargeState(BatteryChargeState(event.chargeState));}batteryInfo_.SetVoltage(event.voltage);batteryInfo_.SetTemperature(event.temperature);batteryInfo_.SetHealthState(BatteryHealthState(event.healthState));batteryInfo_.SetChargeCounter(event.chargeCounter);batteryInfo_.SetTotalEnergy(event.totalEnergy);batteryInfo_.SetCurAverage(event.curAverage);batteryInfo_.SetRemainEnergy(event.remainEnergy);batteryInfo_.SetPresent(event.present);batteryInfo_.SetTechnology(event.technology);batteryInfo_.SetNowCurrent(event.curNow);batteryInfo_.SetChargeType(GetChargeType());
}void BatteryService::HandleBatteryInfo()
{batteryLight_.UpdateColor(batteryInfo_.GetChargeState(), batteryInfo_.GetCapacity());// 若有外接电源插入/拔出,则唤醒设备WakeupDevice(batteryInfo_.GetPluggedType());// 根据batteryInfo_,更新 CalculateRemainingChargeTime(batteryInfo_.GetCapacity(), batteryInfo_.GetChargeState());// BatteryNotify 发布电池信息更新事件batteryNotify_->PublishEvents(batteryInfo_);//其他信息更新HandleTemperature(batteryInfo_.GetTemperature());HandleCapacity(batteryInfo_.GetCapacity(), batteryInfo_.GetChargeState());lastBatteryInfo_ = batteryInfo_;
}
2.电量等级定制开发
&加粗样式ensp;OpenHarmony默认提供了电量等级,根据当前的电量来定义系统统一的电量等级,如满电量、高电量、低电量、极低电量等。系统可以根据当前的电量等级对用户进行提示或处理相关业务。但是电量等级对应的电量值在不同的产品上规格是不同的,产品希望根据产品的设计规格来定制此特性。为此OpenHarmony提供了电量等级的定制方式,产品定制开发者可根据设计规格来定制此特性。battery_config.cpp(drivers_peripheral\battery\interfaces\hdi_service\src\)解析配置文件battery_config.json。
drivers/peripheral/battery/interfaces/hdi_service/profile/battery_config.json:
1 {
2 "light": {
3 "low": {
4 "soc": [0, 10],
5 "rgb": [255, 0, 0]
6 },
7 "normal": {
8 "soc": [10, 90],
9 "rgb": [255, 255, 0]
10 },
11 "high": {
12 "soc": [90, 100],
13 "rgb": [0, 255, 0]
14 }
15 },
16 "boot_actions": {
17 "sendcommonevent": [{
18 "event_name": "usual.event.BATTERY_CHANGED",
19 "scene_config": {
20 "name" : "wireless",
21 "not_equal" : "0"
22 },
23 "uevent": "battery common event"
24 }]
25 },
26 "temperature": {
27 "high": 680,
28 "low": -500
29 },
30 "soc": {
31 "shutdown": 5,
32 "critical": 10,
33 "warning": 15,
34 "low": 30,
35 "normal": 60,
36 "high": 90,
37 "full": 100
38 },
39 "charger": {
40 "current_limit":{
41 "path": "/data/service/el0/battery/current_limit"
42 },
43 "voltage_limit":{
44 "path": "/data/service/el0/battery/voltage_limit"
45 },
46 "type": {
47 "path": "/data/service/el0/battery/charger_type"
48 }
49 }
50 }
电量等级配置说明:
refer to
- https://gitee.com/openharmony/powermgr_battery_manager
- https://gitee.com/openharmony/ace_napi/tree/master
- https://forums.openharmony.cn/forum.php?mod=viewthread&tid=616
- http://test.openharmony.cn:7780/pages/v4.1/zh-cn/device-dev/subsystems/subsys-power-battery-level-customization.md
相关文章:
OpenHarmony-5.PM 子系统(2)
电池服务组件OpenHarmony-4.1-Release 1.电池服务组件 Battery Manager 提供了电池信息查询的接口,同时开发者也可以通过公共事件监听电池状态和充放电状态的变化。电池服务组件提供如下功能: 电池信息查询。充放电状态查询。关机充电。 电池服务组件架…...
三相电的相电压、线电压、额定值、有效值,变比,零序电压,零序电流,三相三线制的三角形连接,三相四线制的星形连接
在二次设备配置中经常有根电压系统相关的名词,本身不是学电气的,有些名词经常查了忘,后续工作所有遇到跟电气相关的知识总结在此帖,便于后续直接查看,避免每次都要重新查、重新梳理。 相电压和线电压的关系是根号3倍&a…...
基于 Slf4j 和 AOP 的自动化方法执行时间日志记录方案
前言 其实这个需求很简单,但是这个需求又是项目中必不可少的,尤其对于性能调优这块,但是使用哪种方式更加方便呢,这就是本篇博文需要讨论的重点 系统时间 可以通过 System.currentTimeMillis() 或 System.nanoTime() 来实现。 …...
C语言-数据结构-树
目录 一,树 1,基本术语: 2,树的性质: 3,树的遍历: 4,森林的遍历: 5,树和二叉树的转换: 6,二叉树和森林的转化: 7,树的存储: 1,双亲表示法 2、孩子链存储结构 3、孩子兄弟链存储结构 二,二叉树: 1,二叉树的性质: 2,二叉树的遍历: 3,二叉树的存储结构: 顺序存储:…...
探究音频丢字位置和丢字时间对pesq分数的影响
丢字的本质 丢字的本质是在一段音频中一小段数据变为0 丢字对主观感受的影响 1. 丢字位置 丢字的位置对感知效果有很大影响。如果丢字发生在音频信号的静音部分或低能量部分,感知可能不明显;而如果丢字发生在高能量部分或关键音素上,感知…...
【Linux】flock 文件级别的锁定
flock 是 Linux/Unix 系统中的一个命令,用于实现文件级别的锁定。它允许你在多个进程之间共享对文件的访问,但确保在同一时间只有一个进程可以访问文件,避免竞态条件(race conditions)和数据不一致问题。 flock 的基本…...
每天40分玩转Django:Django部署概述
一、Django部署概述 在开发阶段,我们通常使用Django内置的轻量级开发服务器runserver。但在生产环境中,为了应对大量并发请求,需要使用高性能的WSGI服务器,如Gunicorn、uWSGI等。同时还要配置Nginx等Web服务器作为反向代理,实现负载均衡、静态文件处理等。下面是Django部署的整…...
【unity c#】深入理解string,以及不同方式构造类与反射的性能测试(基于BenchmarkDotNet)
出这篇文章的主要一个原因就是ai回答的性能差异和实际测试完全不同,比如说是先获取构造函数再构造比Activator.CreateInstance(type)快,实际却相反 对测试结果的评价基于5.0,因为找不到unity6确切使用的net版本,根据c#9推测是net5…...
防抖和节流的方法详解和CSS文本溢出小知识
1.防抖 防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时 场景:搜索框输入发请求,一些拖拽盒子,或者滚动事件 防抖的实现:利用间歇函数 const timer =setTimeout(callback函数,间隔时间) //执行完会返回自身的这个定时器的编号//事件所触发的函…...
深度解析:Maven 和 Gradle 的使用比较及常见仓库推荐
Maven 和 Gradle 是 Java 项目中最常用的构建工具。它们各有优势,适用于不同的场景。本文将对两者进行详细的对比,并推荐一些常用的 Maven 和 Gradle 仓库,帮助开发者高效管理依赖。 一、Maven 和 Gradle 的使用比较 1.1 基本介绍 Maven 基…...
CSS---实现盒元素div内input/textarea的focus状态时给父元素加属性!
注意兼容性,低版本浏览器无效 要实现当 textarea 文本框获得焦点时,自动给其父元素添加类名或样式,您可以使用 CSS 的 :focus-within 伪类选择器。这个选择器会在元素本身或其任何子元素获得焦点时应用样式。 示例代码 假设您有以下 HTML 结…...
施耐德变频器ATV320系列技术优势:创新与安全并重
在工业自动化领域,追求高效、安全与智能已成为不可阻挡的趋势。施耐德变频器ATV320系列凭借其强大的设计标准和全球认证,成为能够帮助企业降低安装成本,提高设备性能的创新解决方案。 【全球认证,品质保障】ATV320 系列秉持施耐德…...
Dynamo:Amazon 的高可用键值仓储
大家觉得有意义和帮助记得及时关注和点赞!!! Dynamo 是 Amazon 的高可用分布式键值存储(key/value storage)系统。这篇论文发表 的时候(2007)它还只是一个内部服务,现在(改名为 DynamoDB)已经发…...
前端开发 -- 自动回复机器人【附完整源码】
一:效果展示 本项目实现了一个简单的网页聊天界面,用户可以在输入框中输入消息,并点击发送按钮或按下回车键来发送消息。机器人会根据用户发送的消息内容,通过关键字匹配来生成自动回复。 二:源代码分享 <!DOCTYP…...
离散数学 群(半群,群,交换群,循环群,对称群,置换群,置换,交代群,轮换)详细,复习笔记
半群: 设G是一个非空集合,若为G上的二元代数运算,且满足结合律,则称该代数系统(G,)为半群 性质:非空,封闭,结合律 独异点: 含有单位元的半裙 练习题: 例:设S是一个非空集合,p(S)是S的幂集,∩和U是p(S…...
Android Java 版本的 MSAA OpenGL ES 多重采样
最近多次被小伙伴问到 OpenGL 多重采样,其实前面文章里多次讲过了,就是构建2个缓冲区,多重采样缓冲区和目标解析缓冲区。 代码流程 // Framebuffer IDs private int msaaFBO; private int msaaColorBuffer; private int msaaDepthBuffer;pr…...
学习笔记之初识HALCON
目录 一、概要 二、数据结构 1、图像Image 2、Region区域 3、XLD 三、图像预处理 1、图像的变换与校正 2、图像增强 四、图像的形态学处理 1、边界提取 2、孔洞填充 3、骨架 五、图像金字塔 六、区域分割 1、区域生长 2、区域分裂与合并 七、边缘检测 1、Pre…...
嵌入式硬件杂谈(七)IGBT MOS管 三极管应用场景与区别
引言:在现代嵌入式硬件设计中,开关元件作为电路中的重要组成部分,起着至关重要的作用。三种主要的开关元件——IGBT(绝缘栅双极型晶体管)、MOSFET(金属氧化物半导体场效应晶体管)和三极管&#…...
【Rust自学】7.1. Package、Crate和定义Module
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 7.1.1. Rust的代码组织 代码组织主要包括: 那些细节可以对外暴露,而哪些细节是私有的在作用域内哪些名称有效… …...
【已解决】pyinstaller打包ico图片报错:OSError: [WinError 225] 无法成功完成操作,因为文件包含病毒或潜在的垃圾软件。
起因: pyinstaller加上 --icon 参数打包时报错。 命令如下: 解决: 关闭 Windows 的病毒防护即可,步骤如下。 点屏幕右下角通知栏,进入“病毒和威胁防护”: 打开: 关闭实时保护(…...
广东粤万润与时序数据库TDengine携手打造智慧酒店新未来:数据驱动智能化转型
在智能化转型浪潮席卷全球的当下,智慧酒店行业已然成为推进智能生活应用的先锋领域。从智能照明到环境监测,从安防系统到沉浸式影音娱乐,智慧酒店通过技术赋能为用户提供了更加舒适、高效且个性化的服务体验。然而,随着设备的增多…...
基于云计算的分布式文件存储系统设计与实现
基于云计算的分布式文件存储系统设计与实现 第一章 绪论 1.1 研究背景及意义 随着互联网技术的飞速发展,云计算作为一种新兴的计算模式,以其弹性伸缩、按需分配和成本效益高等特点,逐渐成为信息技术领域的研究热点。它为大数据处理、高性能…...
基于顺序表实现队列循环队列的处理
文章目录 1.假溢出的现象2.循环队列3.顺序表实现队列架构4.顺序表模拟实现队列5.设计循环队列(校招难度) 1.假溢出的现象 下面的这个就是我们的假溢出的这个现象的基本的来源: 我们的这个队列里面是有9个位置的,我们知道这个队列…...
leecode377.组合总和IV
本题其实是多重背包问题,对于价值和重量都是nums[i]的的物品,求装满这个容量为4的背包共有多少种排列方式 如果是组合问题,那么遍历顺序是先物品后背包,这样能保证物品按从小到大顺序依次放置,对于实例1求出来为4&…...
变量与数据类型 - 整型、浮点型、字符型等
引言 在编程中,变量和数据类型是基础中的基础。理解它们如何工作以及如何正确使用它们对于编写高效且无误的代码至关重要。本文将详细介绍 C 中的几种基本数据类型:整型、浮点型、字符型等,并通过实例帮助读者更好地理解和掌握这些概念。 一…...
selenium学习笔记(二)
文章目录 前言设计模式POMPOM概念POM优势POM设计原则POM的实现 selenium的常用操作处理动态元素截图操作勾选复选框多层框架/窗口定位操作下拉框上传文件操作处理弹窗切换窗口拖拽操作 如何处理浏览器驱动更新导致的问题selenium与网站监控监听网页内容变化监控网络请求 seleni…...
vue和uniapp中,点击按钮 传递当前item对象,并从selectData数组中删除该条item数据
在 Vue 中,可以通过点击按钮传递 item 对象,并从 selectData 数组中删除该条数据。可以使用 Array.prototype.filter() 方法来实现这一点。以下是一个示例: 说明 数据结构:selectData 是一个包含多个对象的数组,每个对象都有 id 和 name 属性。渲染列表:使用 v-for 指令…...
双柱渐变图背景图
option {backgroundColor: #1b2735,tooltip: {//提示框组件trigger: axis,//触发类型 柱状图axisPointer:{type:shadow} //触发效果 移动上去 背景效果}, xAxis: [//x轴{type: category,//坐标轴类型 离散data: [1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月],//数据axisTick:f…...
OpenHarmony怎么修改DPI密度值?RK3566鸿蒙开发板演示
本文介绍在开源鸿蒙OpenHarmony系统下,修改DPI密度值的方法,触觉智能Purple Pi OH鸿蒙开发板演示,搭载了瑞芯微RK3566四核处理器,Laval鸿蒙社区推荐开发板,已适配全新开源鸿蒙OpenHarmony5.0 Release系统,适…...
KylinOS V10 SP3下编译openGauss与dolphin插件
编译环境 KylinOS v10 sp3gcc 7.3.0make 4.3opengauss 5.0.0 mkdir -p /data/opengauss cd /data/opengauss git clone https://gitee.com/opengauss/openGauss-server.git git clone https://gitee.com/opengauss/Plugin.git wget -c https://opengauss.obs.cn-south-1.myhu…...
【入门】买杯子
描述 小明去商店买杯子,他想买价格在 10 到 20 元之间的杯子(含 10 元和 20 元),他看到货架上有 3 个不同价格的杯子,请问最终他买了几个杯子,总共花了多少钱? 比如:货架上有如下的…...
VIVO C++开发面试题及参考答案
面向过程与面向对象的区别,面向对象后的好处 面向过程编程主要关注的是程序的流程,它将一个问题分解为一系列的步骤,通过函数来实现这些步骤,数据和操作这些数据的函数是分离的。例如,在一个简单的计算学生成绩平均值的程序中,我们可能会有一些函数来输入成绩、计算总和、…...
虚拟化 | Proxmox VE 8.x 开源的虚拟化平台快速上手指南
[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] 0x00 简介说明 前言简述 描述:作为一个爱折腾的IT打工佬,时刻以学习各类新技术新知识为目标,这不正好有一台部署了VMware vSphere ESXi 虚拟化环境的服务器,由于正好安装其系统的磁盘有坏道,经常导致使用 ESXi 异…...
【原创学习笔记】近期项目中使用的西门子V20变频器总结(下篇)
上一篇我们简单介绍了下现场的变频器,现在我们来聊聊如何用手机控制变频器。 手机控制变频器的前提是变频器上必须安装智能模块,现场并为安装此模块,故不作考虑。 下面介绍一下如何实现手机或者电脑控制变频器 首先如果存在485通信&#x…...
idea 8年使用整理
文章目录 前言idea 8年使用整理1. 覆盖application配置2. 启动的时候设置编辑空间大小,并忽略最大空间3. 查询类的关系4. 查看这个方法的引用关系5. 查看方法的调用关系5.1. 查看被调用关系5.2. 查看调用关系 6. 方法分隔线7. 选择快捷键类型8. 代码预览插件9. JReb…...
Bluetooth Spec【0】蓝牙核心架构
蓝牙核心系统由一个主机、一个主控制器和零个或多个辅助控制器组成蓝牙BR/ EDR核心系统的最小实现包括了由蓝牙规范定义的四个最低层和相关协议,以及一个公共服务层协议;服务发现协议(SDP)和总体配置文件要求在通用访问配置文件&a…...
PlantUML 入门使用指南
PlantUML 入门使用指南 一、PlantUML介绍二、PlantUML的用途三、PlantUML的语法及示例3.1 用例图(Use Case Diagram)3.2 类图(Class Diagram)3.3 对象图(Object Diagram)3.4 序列图(Sequence Di…...
QT:一个TCP客户端自动连接的测试模型
版本 1:没有取消按钮 测试效果: 缺陷: 无法手动停止 测试代码 CMakeLists.txt cmake_minimum_required(VERSION 3.19) project(AutoConnect LANGUAGES CXX)find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets Network)qt_standard_project_setup(…...
IOS safari 播放 mp4 遇到的坎儿
起因 事情的起因是调试 IOS 手机下播放服务器接口返回的 mp4 文件流失败。对于没调试过移动端和 Safari 的我来说着实费了些功夫,网上和AI也没有讲明白。好在最终大概理清楚了,在这里整理出来供有缘人参考。 问题 因为直接用 IOS 手机的浏览器打开页面…...
LLM常见面试题(26-30题)--langchain篇
26,什么是langchain? 一个局域语言模型的框架,用于构建聊天机器人、生成式回答、摘要等功能。 核心思想是将不同的组件“链”在一起,连接大语言模型和外部资源,以创建更高级的语言模型应用。使得开发人员可以快速开发原型系统和…...
【Python运维】构建基于Python的自动化运维平台:用Flask和Celery
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代IT运维中,自动化运维平台扮演着至关重要的角色,它能够显著提高运维效率,减少人为错误,并且增强系统的可维护性。本文将引导读者如…...
socket编程(C++/Windows)
相关文章推荐: Socket 编程基础 面试官,不要再问我三次握手和四次挥手 TCP的三次握手与四次挥手 参考视频: https://www.bilibili.com/video/BV1aW4y1w7Ui/?spm_id_from333.337.search-card.all.click TCP通信流程 服务端 #include<…...
Spring Boot介绍、入门案例、环境准备、POM文件解读
文章目录 1.Spring Boot(脚手架)2.微服务3.环境准备3.1创建SpringBoot项目3.2导入SpringBoot相关依赖3.3编写一个主程序;启动Spring Boot应用3.4编写相关的Controller、Service3.5运行主程序测试3.6简化部署 4.Hello World探究4.1POM文件4.1.1父项目4.1.2父项目的父…...
【hackmyvm】deba靶机wp
tags: HMVnodejs反序列化CVE-2017-5941wine命令定时任务 1. 基本信息^toc 文章目录 1. 基本信息^toc2. 信息收集2.1. 端口扫描2.2. 目录扫描 3. nodejs反序列化 (CVE-2017-5941)4. www-data提权low用户5. 定时任务提权6. wine命令 提权root6.1. 利用CS获取root 靶机链接 http…...
新浪微博大数据面试题及参考答案(数据开发和数据分析)
介绍一下你所掌握的计算机网络和操作系统相关知识 计算机网络:计算机网络是将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。我掌握了网络协议…...
去除 el-input 输入框的边框(element-ui@2.15.13)
dgqdgqdeMac-mini spid-admin % yarn list --pattern element-ui yarn list v1.22.22 └─ element-ui2.15.13 ✨ Done in 0.23s.dgqdgqdeMac-mini spid-admin % yarn list vue yarn list v1.22.22 warning Filtering by arguments is deprecated. Please use the pattern opt…...
Qt 应用程序转换为服务
一、在 Windows 上将 Qt 应用程序转换为服务 方法1: 创建一个 Windows 服务应用程序: Windows 服务应用程序是一个没有用户界面的后台进程,通常由 Win32 Service 模板创建,或者直接编写 main() 函数以实现服务逻辑。 修改 Qt 应…...
C/C++ 数据结构与算法【树和森林】 树和森林 详细解析【日常学习,考研必备】带图+详细代码
一、树的存储结构 1)双亲表示法实现: 定义结构数组存放树的结点,每个结点含两个域: 数据域:存放结点本身信息。双亲域:指示本结点的双亲结点在数组中的位置。 特点:找双亲简单,找孩子难 C语…...
潇洒郎:部署Dify, 安装Ollama,Ollama下载模型,Dify配置模型
Ollama 1、安装ollama Windows版本下载:2024WindowsOllama最新0.5.4版本资源-CSDN文库, 下载速度超快,官网太慢了 双击安装,安装成功后,托盘区有Ollama图标 右键View logs打开目录 C:\Users\Administrator\AppData\Local\Oll…...
如何在 Linux 中设置 SSH 免密码登录
一般情况下,我们通过一台 Linux 服务器远程另外一台服务器时,每次远程都需要输入对端机器的密码。 ssh root192.168.21.20 有没有这样一种情况,我们不用输入密码就可以远程别的服务器呢? 答案是肯定的,如果我们在 Li…...