Audit Battery
Silent install package for Audit Battery
1.2-5
System and network
System and network
#tis-audit-battery
Once the tis-audit-battery package is installed on a machine, it allows you to check the status of computer batteries. It provides detailed information about battery properties (ID, health, location, etc.). The results are recorded in the audit-battery section of the Audit Data tab of the machine.
##Example of Returned Data Format:
{
"value": {
"BATTERY_1": {
"Id": "45N1111",
"Name": "45N1111",
"Health": "73 %",
"Location": "Front",
"LongTerm": "1",
"Chemistry": "LiP",
"CycleCount": "0",
"Manufacturer": "SONY",
"SBDS_Version": "03.01",
"SerialNumber": "17531",
"Maximum_Error": "Unknown",
"DesignCapacity": "23200",
"Design_Voltage": "11100 mV",
"SBDS_Chemistry": "LiP",
"Design_Capacity": "23200 mWh",
"ManufactureDate": null,
"RelativeCapacity": "0",
"FullChargeCapacity": "16950",
"SBDS_Serial_Number": "447B",
"SBDS_Manufacture_Date": "2016-11-12",
"OEM-specific_Information": "0x00000000"
},
"BATTERY_2": {
"Id": "45N1127",
"Name": "45N1127",
"Health": "76 %",
"Location": "Rear",
"LongTerm": "1",
"Chemistry": "LION",
"CycleCount": "0",
"Manufacturer": "LGC",
"SBDS_Version": "03.01",
"SerialNumber": " 6931",
"Maximum_Error": "Unknown",
"DesignCapacity": "23480",
"Design_Voltage": "11400 mV",
"SBDS_Chemistry": "LION",
"Design_Capacity": "23480 mWh",
"ManufactureDate": null,
"RelativeCapacity": "0",
"FullChargeCapacity": "18040",
"SBDS_Serial_Number": "1B13",
"SBDS_Manufacture_Date": "2016-12-23",
"OEM-specific_Information": "0x00000000"
},
"battery_count": "2"
}
}
- package: tis-audit-battery
- name: Audit Battery
- version: 1.2-5
- categories: System and network
- maintainer: WAPT Team,Tranquil IT,Jimmy PELÉ
- licence: wapt_public
- target_os: windows
- architecture: all
- signature_date:
- size: 9.69 Ko
package : tis-audit-battery
version : 1.2-5
architecture : all
section : base
priority : optional
name : Audit Battery
categories : System and network
maintainer : WAPT Team,Tranquil IT,Jimmy PELÉ
description : Audit batteries capabilities with "powercfg /batteryreport" and dmi_info(). You will be able to pin the health of your batteries in WAPT Console
depends :
conflicts :
maturity : PROD
locale :
target_os : windows
min_wapt_version : 2.3
sources : https://support.microsoft.com/windows/caring-for-your-battery-in-windows-2db3e37f-5e7d-488e-9086-ed15320519e4
installed_size :
impacted_process :
description_fr : Vérifiez les capacités des batteries avec "powercfg /batteryreport" et dmi_info(). Vous serez en mesure d'épingler l'état de santé de vos batteries dans la console WAPT
description_pl : Audyt możliwości baterii za pomocą "powercfg /batteryreport" i dmi_info(). Będziesz mógł sprawdzić stan baterii w konsoli WAPT
description_de : Überprüfen Sie die Fähigkeiten der Batterien mit "powercfg /batteryreport" und dmi_info(). Sie können den Zustand Ihrer Batterien in der WAPT-Konsole anzeigen lassen
description_es : Audite las capacidades de las baterías con "powercfg /batteryreport" y dmi_info(). Usted será capaz de fijar la Salud de sus baterías en WAPT Consola
description_pt : Auditar as capacidades das baterias com "powercfg /batteryreport" e dmi_info(). Poderá identificar o estado das suas baterias na consola WAPT
description_it : Verificare le capacità delle batterie con "powercfg /batteryreport" e dmi_info(). Sarà possibile visualizzare lo stato di salute delle batterie nella console WAPT
description_nl : Controleer de mogelijkheden van de batterijen met "powercfg /batteryreport" en dmi_info(). U kunt de gezondheid van uw accu's vastleggen in WAPT Console
description_ru : Проведите аудит состояния батарей с помощью функций "powercfg /batteryreport" и dmi_info(). Вы сможете вывести информацию о состоянии батарей в WAPT-консоль
audit_schedule : 7d
editor :
keywords :
licence : wapt_public
homepage :
package_uuid : 9cba4fea-30e4-4e28-89bc-a9b43ca69734
valid_from :
valid_until :
forced_install_on :
changelog :
min_os_version :
max_os_version :
icon_sha256sum : 0c223120ac1a6e4cd0d0abe04cd831c7d4a4c2661947e758c0f703b656933d9a
signer : Tranquil IT
signer_fingerprint: 8c5127a75392be9cc9afd0dbae1222a673072c308c14d88ab246e23832e8c6bb
signature_date : 2026-04-14T12:33:38.000000
signed_attributes : package,version,architecture,section,priority,name,categories,maintainer,description,depends,conflicts,maturity,locale,target_os,min_wapt_version,sources,installed_size,impacted_process,description_fr,description_pl,description_de,description_es,description_pt,description_it,description_nl,description_ru,audit_schedule,editor,keywords,licence,homepage,package_uuid,valid_from,valid_until,forced_install_on,changelog,min_os_version,max_os_version,icon_sha256sum,signer,signer_fingerprint,signature_date,signed_attributes
signature : CKHTbFViurC09Bm7H3JFE7mUHOL19nWSVmgmc2wemNqYq0t08Ec6ozrWXspolxVgj6jEgyYkk7tsDpYkn7o56jsMx40sLZHjuNgFft5bhmd2HPR5A0iNmevcvtukshg81O93mFzMQP/4TcsEFndgKTxqYJXOYerywN2DTpyABup2IK8CYsgccnn9z7VrJLqk/s01VZuMmhJQ1DbnhifmdydAyvLi9IIOTcj8ciWpzGlYqanvqYkZ31xB7ywm8Z+zalE81vl+iszmTtOSLoHXjy1nyJPAM1kbLR2IWENnn6W2JNRPJII2+PqDwBex1iypUbUrFUEu2rCdaVC2NqZhDQ==
# -*- coding: utf-8 -*-
from setuphelpers import *
import os
import xml.etree.ElementTree as ET
def install():
# Audit-only package
pass
"""
powercfg /batteryreport /?
POWERCFG /BATTERYREPORT [/OUTPUT <FILENAME>] [/XML] [/TRANSFORMXML <FILENAME.XML>]
Description:
Generates a report of battery usage characteristics over the lifetime of the
system. The BATTERYREPORT command will generate an HTML report file in the
current path.
Parameter List:
/OUTPUT <FILENAME> Specify the path and filename to store the battery
report HTML or XML file.
/XML Format the report file as XML.
/DURATION <DAYS> Specify the number of days to analyze for the report.
/TRANSFORMXML <FILENAME.XML> Reformat an XML report file as HTML.
Examples:
POWERCFG /BATTERYREPORT
POWERCFG /BATTERYREPORT /OUTPUT "batteryreport.html"
POWERCFG /BATTERYREPORT /OUTPUT "batteryreport.xml" /XML
POWERCFG /BATTERYREPORT /TRANSFORMXML "batteryreport.xml"
POWERCFG /BATTERYREPORT /TRANSFORMXML "batteryreport.xml" /OUTPUT "batteryreport.html"
"""
# ------------------------------------------------------------
# Persistent path helper
# ------------------------------------------------------------
def get_private_persistent_package_file(file_name):
file_name = os.path.basename(file_name)
try:
if control.package_uuid:
installed = WAPT.is_installed(control.package)
if installed and control.package_uuid == installed.get("package_uuid"):
return makepath(WAPT.persistent_root_dir, control.package_uuid, file_name)
except Exception:
pass
return makepath(os.getcwd(), "WAPT", "persistent", file_name)
# ------------------------------------------------------------
# Battery report generation
# ------------------------------------------------------------
def get_batteryreport(output_file):
"""
Generates a battery report using powercfg.
If output_file ends with .html -> HTML, otherwise XML.
"""
ensure_dir(os.path.dirname(output_file))
if output_file.lower().endswith(".html"):
run(f'POWERCFG /BATTERYREPORT /OUTPUT "{output_file}"')
else:
run(f'POWERCFG /BATTERYREPORT /OUTPUT "{output_file}" /XML')
# ------------------------------------------------------------
# XML parsing (robust namespace handling)
# ------------------------------------------------------------
def get_batteries_from_batteryreport_xml(xml_file):
"""
Returns a list of dicts (one per battery) from powercfg batteryreport XML.
Handles Microsoft batteryreport namespace: http://schemas.microsoft.com/battery/2012
"""
NS = {"b": "http://schemas.microsoft.com/battery/2012"}
def strip_ns(tag):
return tag.split("}", 1)[-1] if "}" in tag else tag
def element_to_obj(el):
children = list(el)
if not children:
return (el.text or "").strip()
obj = {}
for ch in children:
key = strip_ns(ch.tag)
val = element_to_obj(ch)
# Repeated tags -> list
if key in obj:
if not isinstance(obj[key], list):
obj[key] = [obj[key]]
obj[key].append(val)
else:
obj[key] = val
return obj
tree = ET.parse(xml_file)
root = tree.getroot()
batteries = []
for b in root.findall("b:Batteries/b:Battery", NS):
batteries.append(element_to_obj(b))
return batteries
# ------------------------------------------------------------
# Health computation / status
# ------------------------------------------------------------
def compute_health_percent(full_charge_capacity, design_capacity):
try:
fcc = int(full_charge_capacity)
dc = int(design_capacity)
if dc <= 0:
return None
return int(fcc * 100 / dc)
except Exception:
return None
def status_from_health(health):
"""
Same logic as you had:
- WARNING if <= 50
- ERROR if <= 19 or >= 101
- OK otherwise
"""
if health is None:
return "ERROR"
if health <= 19 or health >= 101:
return "ERROR"
if health <= 50:
return "WARNING"
return "OK"
def merge_dmi_for_index(dmi_portable_list, index):
"""
Returns DMI dict for given battery index if available, else {}.
"""
if isinstance(dmi_portable_list, dict):
dmi_portable_list = [dmi_portable_list]
if not isinstance(dmi_portable_list, list):
return {}
if index < len(dmi_portable_list) and isinstance(dmi_portable_list[index], dict):
return dmi_portable_list[index]
return {}
# ------------------------------------------------------------
# WAPT audit entry point
# ------------------------------------------------------------
def audit():
"""
Correct behavior:
- Always relies on batteryreport XML to detect batteries.
- DMI Portable_Battery is OPTIONAL (enrichment only).
- Writes audit dict with battery_count + BATTERY_1..N dicts.
"""
audit_status = "OK"
# 1) Always generate and parse XML
battery_report_file = get_private_persistent_package_file("batteryreport.xml")
get_batteryreport(battery_report_file)
batteries_xml = get_batteries_from_batteryreport_xml(battery_report_file)
battery_count = len(batteries_xml)
# 2) If XML shows 0 -> no battery
if battery_count == 0:
WAPT.write_audit_data_if_changed("audit-battery", "audit-battery", {"battery_count": "0"})
print("No battery detected (batteryreport shows 0).")
return audit_status
# 3) DMI is optional
dmi_portable = dmi_info().get("Portable_Battery", None)
if isinstance(dmi_portable, dict):
dmi_portable = [dmi_portable]
if not isinstance(dmi_portable, list):
dmi_portable = []
# 4) Build audit payload
audit_dict = {"battery_count": str(battery_count)}
for i in range(battery_count):
battery_key = f"BATTERY_{i+1}"
b = batteries_xml[i] if i < len(batteries_xml) else {}
# capacities
design_capacity = b.get("DesignCapacity")
full_charge_capacity = b.get("FullChargeCapacity")
# compute health
health = compute_health_percent(full_charge_capacity, design_capacity)
if health is None:
b["Health"] = "N/A"
else:
b["Health"] = f"{health} %"
# merge DMI (optional)
b.update(merge_dmi_for_index(dmi_portable, i))
# global status
this_status = status_from_health(health)
if this_status == "ERROR":
audit_status = "ERROR"
elif this_status == "WARNING" and audit_status != "ERROR":
audit_status = "WARNING"
# friendly console output
location = b.get("Location", "Unknown")
dv = b.get("Design_Voltage", "Unknown")
dc = b.get("DesignCapacity", "?")
print(
f"{battery_key} ({location}) Health is {b.get('Health','N/A')} "
f"for the DesignCapacity {dc} mWh with Design_Voltage {dv}."
)
audit_dict[battery_key] = b
WAPT.write_audit_data_if_changed("audit-battery", "audit-battery", audit_dict)
return audit_status
fed039c6e0098b32364070a3917ba84500a4f3b57f127b4c19f94dbd43765573 : WAPT/README.md
b0b1a985b2c4c2afeb22c7d09a56da0c5e32e2046bfe65bf479897689dace1e9 : WAPT/README_fr.md
38d056ab130f7bf7c481c12636a4e9959de36561d3dfcbe54c6e3571bc0c1dc3 : WAPT/certificate.crt
54527be7fc7d47961b4eb4f436593919989050f2f7f1598f2031239402e8fb10 : WAPT/control
0c223120ac1a6e4cd0d0abe04cd831c7d4a4c2661947e758c0f703b656933d9a : WAPT/icon.png
083a5560da1aba1515928fbdfffe04b401465471d1acd56626ff2b44d2a3aa5f : luti.json
7a05cb71531cbb24401b68c5476fc96eb74ef4dd9c9002966f7c83bd3da260cd : setup.py