B4J Code Snippet b4j Get Battery Info

Using jShell library we can get the laptop battery information as name, serial number, manufacturer, design and current capacity as well as charge remaining (taken from:https://www.b4x.com/android/forum/threads/execute-windows-vbs-scripts-from-b4j.73612/#content)

B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Private Button1 As B4XView
    Private ChargeRemaining As Int
 
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    'MainForm.Show
    Dim shl As Shell
    shl.Initialize("shl", "powercfg", _
     Array As String("/batteryreport"))
    shl.WorkingDirectory = "."
    shl.Run(10000) 'set a timeout of 10 seconds

End Sub

Sub shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    If Success And ExitCode = 0 Then
        Log("Success")
        Log("Full output: " & StdOut)
     
        ' Find the HTML file path in the output
        Dim htmlFilePath As String = ExtractHtmlFilePath(StdOut)
     
        If htmlFilePath <> "" Then
            ' Clean the path (remove trailing period if present)
            If htmlFilePath.EndsWith(".") Then
                htmlFilePath = htmlFilePath.SubString2(0, htmlFilePath.Length - 1)
            End If
         
            Log("HTML file path: " & htmlFilePath)
         
            ' Check if file exists
            If File.Exists(htmlFilePath, "") Then
                ' Read the HTML file content
                Dim html As String = File.ReadString(htmlFilePath, "")
                ParseBatteryData(html)
            Else
                ' Try alternative approach - search for battery-report.html in the Objects folder
                htmlFilePath = FindBatteryReportFile
                If htmlFilePath <> "" Then
                    Dim html As String = File.ReadString(htmlFilePath, "")
                    ParseBatteryData(html)
                Else
                    Log("Could not find battery-report.html file")
                    xui.MsgboxAsync("Could not find battery report file", "Error")
                End If
            End If
        Else
            Log("Could not extract HTML file path from output")
            ' Try to generate the report to a specific location
            GenerateBatteryReportToSpecificLocation
        End If
    Else
        Log("Error: " & StdErr)
        xui.MsgboxAsync("Failed to generate battery report: " & StdErr, "Error")
    End If
    'ExitApplication ' Optional - remove if you want app to continue
End Sub

Sub ExtractHtmlFilePath(output As String) As String
    ' Look for .html extension in the output
    Dim pattern As String = "(C:\\.*?\.html)"
    Dim matcher As Matcher = Regex.Matcher(pattern, output)
    If matcher.Find Then
        Return matcher.Group(1)
    End If
 
    ' Alternative pattern for paths with spaces or special characters
    Dim pattern2 As String = "(\w:.*?\.html)"
    Dim matcher2 As Matcher = Regex.Matcher(pattern2, output)
    If matcher2.Find Then
        Return matcher2.Group(1)
    End If
 
    Return ""
End Sub

Sub FindBatteryReportFile As String
    ' Try to find the battery report file in common locations
    Dim possiblePaths As List
    possiblePaths.Initialize
 
    ' Add current directory
    possiblePaths.Add(File.DirApp & "\battery-report.html")
 
    ' Try Objects folder (common in B4J projects)
    possiblePaths.Add(File.DirApp & "\Objects\battery-report.html")
 
    ' Try user's documents folder
    Dim j As JavaObject
    j.InitializeStatic("java.lang.System")
    Dim userHome As String = j.RunMethod("getProperty", Array As Object("user.home"))
    possiblePaths.Add(userHome & "\battery-report.html")
 
    For Each path As String In possiblePaths
        If File.Exists(path, "") Then
            Return path
        End If
    Next
 
    Return ""
End Sub

Sub GenerateBatteryReportToSpecificLocation
    ' Generate battery report to a known location
    Dim knownPath As String = File.DirApp & "\battery-report.html"
    Dim shl2 As Shell
    shl2.Initialize("shl2", "powercfg", Array As String("/batteryreport", "/output", knownPath))
    shl2.WorkingDirectory = "."
    shl2.Run(10000)
    Wait For shl2_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    If Success And ExitCode = 0 Then
        If File.Exists(knownPath, "") Then
            Dim html As String = File.ReadString(knownPath, "")
            ParseBatteryData(html)
        Else
            xui.MsgboxAsync("Failed to generate battery report to known location", "Error")
        End If
    Else
        xui.MsgboxAsync("Failed to generate battery report: " & StdErr, "Error")
    End If
End Sub

Sub ParseBatteryData(html As String)
    Try
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        ' Parse for DESIGN CAPACITY - multiple possible patterns
        Dim designCapacity As String = ""
        Dim patterns As List
        patterns.Initialize
     
        ' Try different possible patterns
        patterns.Add("DESIGN CAPACITY</span></td><td>(\d+,\d+)\s*mWh")
        patterns.Add("DESIGN CAPACITY[^>]*>(\d+,\d+)\s*mWh")
        patterns.Add("DESIGN CAPACITY.*?<td[^>]*>(\d+,\d+)")
        patterns.Add(">DESIGN CAPACITY<.*?<td[^>]*>(\d+,\d+)")
     
        For Each pattern As String In patterns
            Dim matcher As Matcher = Regex.Matcher(pattern, html)
            If matcher.Find Then
                designCapacity = matcher.Group(1)
                Exit
            End If
        Next
     
        ' Parse for FULL CHARGE CAPACITY
        Dim fullChargeCapacity As String = ""
        Dim patterns2 As List
        patterns2.Initialize
     
        patterns2.Add("FULL CHARGE CAPACITY</span></td><td>(\d+,\d+)\s*mWh")
        patterns2.Add("FULL CHARGE CAPACITY[^>]*>(\d+,\d+)\s*mWh")
        patterns2.Add("FULL CHARGE CAPACITY.*?<td[^>]*>(\d+,\d+)")
        patterns2.Add(">FULL CHARGE CAPACITY<.*?<td[^>]*>(\d+,\d+)")
     
        For Each pattern As String In patterns2
            Dim matcher As Matcher = Regex.Matcher(pattern, html)
            If matcher.Find Then
                fullChargeCapacity = matcher.Group(1)
                Exit
            End If
        Next
     
        If designCapacity <> "" And fullChargeCapacity <> "" Then
            ' Remove commas for calculation
            Dim designClean As String = designCapacity.Replace(",", "")
            Dim fullChargeClean As String = fullChargeCapacity.Replace(",", "")
         
            ' Convert to numbers
            Dim designVal As Int = designClean
            Dim fullChargeVal As Int = fullChargeClean
         
            ' Calculate battery health percentage
            Dim health As Double = (fullChargeVal / designVal) * 100
         
            ' Display results
            Log("Design Capacity: " & designCapacity & " mWh")
            Log("Full Charge Capacity: " & fullChargeCapacity & " mWh")
            Log("Battery Health: " & NumberFormat(health, 1, 2) & "%")
            Log("Battery Manufacturer: " & ParseBatteryManufacturer(html))
            Log("Serial  Number:" & ParseBatterySerialNumber(html))
            Log("Chemistry:" & ParseBatteryChemistry(html) )
         
         
            ' Show in a message box
            xui.MsgboxAsync("Battery Status:" & CRLF & CRLF & _
                "✓ Design Capacity: " & designCapacity & " mWh" & CRLF & _
                "✓ Full Charge Capacity: " & fullChargeCapacity & " mWh" & CRLF & CRLF & _
                "🔋 Battery Health: " & NumberFormat(health, 1, 2) & "%"  & CRLF & CRLF & _
                "Battery Name: " & ParseBatteryName(html)  & CRLF & CRLF & _
                "Battery Manufacturer: " & ParseBatteryManufacturer(html) & CRLF & CRLF & _
                "Serial number: " & ParseBatterySerialNumber(html)  & CRLF & CRLF & _
                "Chemistry: " & ParseBatteryChemistry(html) , "Battery Report")
            BatteryChargeRemain
        Else
            Log("Could not find battery capacity data in HTML")
            Log("HTML snippet search:")
            ' Try a more aggressive search
            FindCapacityValues(html)
        End If
    Catch
        Log("Error parsing HTML: " & LastException)
        xui.MsgboxAsync("Error parsing battery data", "Error")
    End Try
End Sub

Sub FindCapacityValues(html As String)
    ' Alternative: Look for any numbers that look like capacities (typically in thousands)
    Dim pattern As String = "(\d{1,3}(?:,\d{3})+)\s*mWh"
    Dim matcher As Matcher = Regex.Matcher(pattern, html)
    Dim matches As List
    matches.Initialize
 
    Do While matcher.Find
        matches.Add(matcher.Group(1))
    Loop
 
    If matches.Size >= 2 Then
        ' Assume first two large numbers are the capacities
        Dim designCapacity As String = matches.Get(0)
        Dim fullChargeCapacity As String = matches.Get(1)
     
        ' Remove commas for calculation
        Dim designClean As String = designCapacity.Replace(",", "")
        Dim fullChargeClean As String = fullChargeCapacity.Replace(",", "")
     
        Dim designVal As Int = designClean
        Dim fullChargeVal As Int = fullChargeClean
        Dim health As Double = (fullChargeVal / designVal) * 100
     
        xui.MsgboxAsync("Battery Status (auto-detected):" & CRLF & CRLF & _
            "Design Capacity: ~" & designCapacity & " mWh" & CRLF & _
            "Full Charge Capacity: ~" & fullChargeCapacity & " mWh" & CRLF & CRLF & _
            "Battery Health: ~" & NumberFormat(health, 1, 2) & "%", _
            "Battery Report (Estimated)")
    Else
        ' Last resort: Save HTML to file for debugging
        File.WriteString(File.DirApp, "debug_battery.html", html)
        Log("Could not parse data. HTML saved to: " & File.DirApp & "\debug_battery.html")
        xui.MsgboxAsync("Could not parse battery data. Debug file created.", "Error")
    End If
End Sub
Sub ParseBatteryName(html As String) As String
    Dim namePatterns As List = Array As String($"NAME</span></td><td>([^<]+)"$, "Battery name.*?<td[^>]*>([^<]+)",">Name<.*?<td[^>]*>([^<]+)","Battery Name.*?:.*?<td>([^<]+)","<td>NAME</td>.*?<td>([^<]+)</td>",$"\"name\"[^>]*>([^<]+)"$)
 
    For Each pattern As String In namePatterns
        Dim matcher As Matcher = Regex.Matcher(pattern, html)
        If matcher.Find Then
            Dim name As String = matcher.Group(1).Trim
            If name.Length > 0 Then
                Return name
            End If
        End If
    Next
 
    Return "Unknown"
End Sub

Sub ParseBatteryManufacturer(html As String) As String
    Dim manufacturerPatterns As List = Array As String("MANUFACTURER</span></td><td>([^<]+)","Manufacturer.*?<td[^>]*>([^<]+)",">Manufacturer<.*?<td[^>]*>([^<]+)","Battery manufacturer.*?:.*?<td>([^<]+)","<td>MANUFACTURER</td>.*?<td>([^<]+)</td>",$"\"manufacturer\"[^>]*>([^<]+)"$,"Mfg.*?:.*?<td>([^<]+)")
 
    For Each pattern As String In manufacturerPatterns
        Dim matcher As Matcher = Regex.Matcher(pattern, html)
        If matcher.Find Then
            Dim manufacturer As String = matcher.Group(1).Trim
            If manufacturer.Length > 0 Then
                Return manufacturer
            End If
        End If
    Next
 
    Return "Unknown"
End Sub
Sub ParseBatterySerialNumber(html As String) As String
    Dim serialPatterns As List = Array As String("SERIAL NUMBER</span></td><td>([^<]+)","Serial.*?number.*?<td[^>]*>([^<]+)",">Serial number<.*?<td[^>]*>([^<]+)","Battery serial.*?:.*?<td>([^<]+)","<td>SERIAL NUMBER</td>.*?<td>([^<]+)</td>",$"\"serial.*?\"[^>]*>([^<]+)"$,$"SN.*?:.*?<td>([^<]+)"$,$"Serial.*?:.*?<td>([^<]+)"$)
 
    For Each pattern As String In serialPatterns
        Dim matcher As Matcher = Regex.Matcher(pattern, html)
        If matcher.Find Then
            Dim serial As String = matcher.Group(1).Trim
            If serial.Length > 0 Then
                Return serial
            End If
        End If
    Next
 
    Return "Unknown"
End Sub

Sub ParseBatteryChemistry(html As String) As String
    Dim chemistryPatterns As List = Array As String("CHEMISTRY</span></td><td>([^<]+)","Chemistry.*?<td[^>]*>([^<]+)",">Chemistry<.*?<td[^>]*>([^<]+)","Battery chemistry.*?:.*?<td>([^<]+)","<td>CHEMISTRY</td>.*?<td>([^<]+)</td>",$"\"chemistry\"[^>]*>([^<]+)"$,"Battery type.*?:.*?<td>([^<]+)")
 
    For Each pattern As String In chemistryPatterns
        Dim matcher As Matcher = Regex.Matcher(pattern, html)
        If matcher.Find Then
            Dim chemistry As String = matcher.Group(1).Trim
            If chemistry.Length > 0 Then
                Return chemistry
            End If
        End If
    Next
 
    Return "Unknown"
End Sub
Sub ExtractAdditionalBatteryInfo(html As String) As String
    Try
        Dim info As String
        ' Extract battery cycles if available
        Dim cyclePattern As String = "CYCLE COUNT</span></td><td>(\d+)"
        Dim cycleMatcher As Matcher = Regex.Matcher(cyclePattern, html)
        If cycleMatcher.Find Then
            info= info & "Cycle Count: " & cycleMatcher.Group(1) & CRLF
        End If
     
        ' Extract manufacture date if available
        Dim datePattern As String = "MANUFACTURE DATE</span></td><td>([^<]+)"
        Dim dateMatcher As Matcher = Regex.Matcher(datePattern, html)
        If dateMatcher.Find Then
            info= info & "Manufacture Date: " & dateMatcher.Group(1) & CRLF
        End If
    Catch
        Log(LastException.Message)
        ' Ignore errors in additional info extraction
    End Try
    Return info
End Sub

Sub BatteryChargeRemain
    Log("Reading battery status...")
    Dim BatterySh As Shell
    BatterySh.Initialize("Battery", "c:\windows\system32\cscript.exe", Array As String("//nologo", "battery.vbs"))
    BatterySh.WorkingDirectory = "WinBattery\"
    BatterySh.Run(10000)
 
End Sub

Sub Battery_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    If Success And ExitCode = 0 Then
        If IsNumber(StdOut) Then
            ChargeRemaining= StdOut
            Log ("Charge remainig: " & ChargeRemaining)
            xui.MsgboxAsync(ChargeRemaining, "Charge Remaining")
        Else
            Log("Oops... Battery not found...")
        End If
 
    Else
        Log("Error: " & StdErr & StdOut)
 
    End If
 
End Sub
Example output:



1770416256514.png
 
Last edited:
Top