Jump to content

Recommended Posts

Posted

image.png.da8aace5e361e95d32446fe581a6cc56.png

Spoiler
#NoTrayIcon
#AutoIt3Wrapper_UseX64=y
#include <Date.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <GuiMenu.au3>
#include <sqlite.au3>
#include <Debug.au3>

DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2)

Opt("TrayIconHide", 1)
Opt("TrayMenuMode", 3)

;~ Global Const $WM_APP = 0x8000
;~ Global Const $TRAY_CALLBACK_MSG = $WM_APP + 1
Global Const $TRAY_CALLBACK_MSG = 0x8000 + 1

Global $g_hDummyGUI = GUICreate("TrayHelper")
Global $g_iLogToFile = 0

Exit main()
Func main()
    If WinExists('STUB-' & @ScriptName) Then Exit 5
    AutoItWinSetTitle('STUB-' & @ScriptName)
    If $g_iLogToFile Then FileWriteLine(StringTrimRight(@ScriptFullPath, 4) & ".log", @CRLF & _Now() & @CRLF & "Loaded - PID:" & @AutoItPID & @CRLF)
    Local $iBGColor = 0xFF005500, $iBorderColor = 0xFF349eeb
    Local $iFGColor = 0xFFE6A800 ; 0xFFFFFFFF ; Default to White text
    _CreateNumberIcon("X", $iBGColor, $iFGColor, $iBorderColor, "..loading.." & @LF & " ")

    main_updateTrayWithInfo()
    AdlibRegister(main_updateTrayWithInfo, 600000) ; 10 min.

    While 1
        Sleep(100)
    WEnd
EndFunc   ;==>main

Func main_updateTrayWithInfo()

    Local $hTimer = TimerInit(), $aBluetoothInventory = _Bluetooth_Get_Device_Inventory()

    Local $sArray = _SQLite_Display2DResult($aBluetoothInventory, 0, True)
    ConsoleWrite($sArray)
    If $g_iLogToFile Then FileWriteLine(StringTrimRight(@ScriptFullPath, 4) & ".log", @CRLF & _Now() & @CRLF & $sArray)

    Local $sText = "?", $iLevel = "?", $iBGColor, $iBorderColor = 0xFF349eeb
    Local $iFGColor = 0xFFFFFFFF ; Default to White text

    If UBound($aBluetoothInventory) > 1 Then
        $iLevel = Int($aBluetoothInventory[1][6])
        $sText = $aBluetoothInventory[1][0] & ':  ' & $aBluetoothInventory[1][6] & @LF & '(' & $aBluetoothInventory[1][1] & ')' & @LF & ' '
    EndIf


    ; Determine the background color based on the current number
    If $iLevel >= 50 Then
        $iBGColor = 0xFF004488 ; BLUE
    ElseIf $iLevel >= 20 Then
        $iBGColor = 0xFFE6A800 ; YELLOW
        $iFGColor = 0xFF000000 ; BLACK text
    Else
        $iBGColor = 0xFFD32F2F ; RED
    EndIf

    _CreateNumberIcon($iLevel, $iBGColor, $iFGColor, $iBorderColor, $sText)

EndFunc   ;==>main_updateTrayWithInfo


Func _TrayMouseEvents($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam

    Local Const $WM_LBUTTONUP = 0x0202
    Local Const $WM_LBUTTONDBLCLK = 0x0203
    Local Const $WM_RBUTTONUP = 0x0205

    Switch $lParam
        Case $WM_LBUTTONUP
            ConsoleWrite("--> Primary Click Single!" & @CRLF)
            Return 0

        Case $WM_LBUTTONDBLCLK
            ConsoleWrite("--> Primary Double Click Action!" & @CRLF)
            ConsoleWrite("Action: You Double-Clicked the custom tray icon!" & @CRLF)
            Return 0

        Case $WM_RBUTTONUP ; This handles Secondary Click automatically (Righty OR Lefty!)
            ConsoleWrite("--> Secondary Click! (Show Context Menu)" & @CRLF)

            Local $hMenu = _GUICtrlMenu_CreatePopup()
;~          _GUICtrlMenu_InsertMenuItem($hMenu, 0, "Show Status...", 1001)
            _GUICtrlMenu_InsertMenuItem($hMenu, 1, "Reload script", 1002)
            _GUICtrlMenu_InsertMenuItem($hMenu, 2, "", 0)
            _GUICtrlMenu_InsertMenuItem($hMenu, 3, "Exit script", 1009)

            Local $tPoint = DllStructCreate("long X;long Y")
            DllCall("user32.dll", "bool", "GetCursorPos", "struct*", $tPoint)

            DllCall("user32.dll", "bool", "SetForegroundWindow", "hwnd", $hWnd)

            Local $aRet = DllCall("user32.dll", "int", "TrackPopupMenu", "handle", $hMenu, "uint", 0x0100, "int", DllStructGetData($tPoint, "X"), "int", DllStructGetData($tPoint, "Y"), "int", 0, "hwnd", $hWnd, "ptr", 0)
            Local $iSelectedID = $aRet[0]

            _GUICtrlMenu_DestroyMenu($hMenu)

            Switch $iSelectedID
                Case 1001
                    ConsoleWrite("Status: TODO" & @CRLF)

                Case 1002
                    ConsoleWrite("ReloadScript..." & @CRLF)
                    AdlibRegister(OnTrayMenu_ReloadScript, 10)

                Case 1009
                    AdlibRegister(OnTrayMenu_ExitScript, 10)

            EndSwitch

            Return 0

    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>_TrayMouseEvents

Func OnTrayMenu_ExitScript()
    AdlibUnRegister(OnTrayMenu_ExitScript)
    AutoItWinSetTitle('EXIT-' & @ScriptName)
    Exit
EndFunc   ;==>OnTrayMenu_ExitScript

Func OnTrayMenu_ReloadScript()
    AdlibUnRegister(OnTrayMenu_ReloadScript)
    AutoItWinSetTitle('RELOAD-' & @ScriptName)
    ShellExecute(@AutoItExe, '"' & @ScriptFullPath & '"')
    Exit
EndFunc   ;==>OnTrayMenu_ReloadScript


Func _CreateNumberIcon($iNumber, $iBGColor = 0xFF004488, $iFGColor = 0xFFFFFFFF, $iBorderColor = 0xFF34eb58, $sStr = "")
    Local Static $iInitGDIPlus = _UpdateTray("StartUp")
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0(16, 16)
    Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)

    _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, 4)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2)

    _GDIPlus_GraphicsClear($hGraphics, $iBorderColor)

    Local $hBrushBG = _GDIPlus_BrushCreateSolid($iBGColor)
    Local $iFillWidth = 1
    Local $iFillOtherSide = 13
    _GDIPlus_GraphicsFillRect($hGraphics, $iFillWidth, $iFillWidth, $iFillOtherSide, $iFillOtherSide, $hBrushBG)

    Local $hBrushText = _GDIPlus_BrushCreateSolid($iFGColor)
    Local $hFamily = _GDIPlus_FontFamilyCreate("Arial")

    ; Get the current DPI for the primary monitor
    Local $hDC = _WinAPI_GetDC(0)
    Local $iDPI_X = _WinAPI_GetDeviceCaps($hDC, 88) ; 88 = LOGPIXELSX
    _WinAPI_ReleaseDC(0, $hDC)

    ; Calculate the scaling ratio (96 is the standard 100% DPI)
    Local $fScale = $iDPI_X / 96

    ; Use the scale to adjust your font size dynamically
    Local $iFontSize = 8 / $fScale
    Local $hFont = _GDIPlus_FontCreate($hFamily, $iFontSize, 1)
    Local $hFormat = _GDIPlus_StringFormatCreate()
    _GDIPlus_StringFormatSetAlign($hFormat, 1)
    _GDIPlus_StringFormatSetLineAlign($hFormat, 1)
    Local $tLayout = _GDIPlus_RectFCreate(0, 0, 16, 16)

    _GDIPlus_GraphicsDrawStringEx($hGraphics, String($iNumber), $hFont, $tLayout, $hFormat, $hBrushText)

    Local $hGDI_Bitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)

    Local $aMask = DllCall("gdi32.dll", "handle", "CreateBitmap", "int", 16, "int", 16, "uint", 1, "uint", 1, "ptr", 0)
    Local $hMask = $aMask[0]

    Local $tICONINFO = DllStructCreate("int fIcon; dword xHotspot; dword yHotspot; handle hbmMask; handle hbmColor")
    DllStructSetData($tICONINFO, "fIcon", 1)
    DllStructSetData($tICONINFO, "hbmMask", $hMask)
    DllStructSetData($tICONINFO, "hbmColor", $hGDI_Bitmap)

    Local $aIcon = DllCall("user32.dll", "handle", "CreateIconIndirect", "struct*", $tICONINFO)
    Local $hIcon = $aIcon[0]

    DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hMask)
    DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hGDI_Bitmap)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrushText)
    _GDIPlus_BrushDispose($hBrushBG)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_BitmapDispose($hBitmap)

    _UpdateTray($hIcon, $sStr)
    DllCall("user32.dll", "bool", "DestroyIcon", "handle", $hIcon)

    Return 0
EndFunc   ;==>_CreateNumberIcon

Func _UpdateTray_OnShutdown()
    _UpdateTray("ShutDown", "")
    GUIRegisterMsg($TRAY_CALLBACK_MSG, "")
    If IsHWnd($g_hDummyGUI) Then GUIDelete($g_hDummyGUI)
    _GDIPlus_Shutdown()
EndFunc   ;==>_UpdateTray_OnShutdown

Func _UpdateTray($hIcon, $sStr = "")
    Local Static $iStartup = "StartUp", $_bTrayCreated = False, $_tNID = DllStructCreate("dword Size;hwnd Wnd;uint ID;uint Flags;uint CallbackMessage;handle Icon;wchar Tip[128]")

    If $iStartup = "StartUp" Then
        DllStructSetData($_tNID, "Size", DllStructGetSize($_tNID))
        DllStructSetData($_tNID, "Wnd", $g_hDummyGUI)
        DllStructSetData($_tNID, "ID", 999)
        DllStructSetData($_tNID, "Flags", 0x07)
        DllStructSetData($_tNID, "CallbackMessage", $TRAY_CALLBACK_MSG)

        GUIRegisterMsg($TRAY_CALLBACK_MSG, "_TrayMouseEvents")

        _GDIPlus_Startup()
        OnAutoItExitRegister(_UpdateTray_OnShutdown)
        $iStartup = "Running"
        If $hIcon = "StartUp" Then Return 1

    ElseIf $hIcon = "ShutDown" Then
        DllCall("shell32.dll", "bool", "Shell_NotifyIconW", "dword", 0x02, "struct*", $_tNID) ; NIM_DELETE
        _GDIPlus_Shutdown()
        Return 2
    EndIf

    DllStructSetData($_tNID, "Icon", $hIcon)
    DllStructSetData($_tNID, "Tip", String($sStr))

    If Not $_bTrayCreated Then
        DllCall("shell32.dll", "bool", "Shell_NotifyIconW", "dword", 0x00, "struct*", $_tNID)
        $_bTrayCreated = True
    Else
        DllCall("shell32.dll", "bool", "Shell_NotifyIconW", "dword", 0x01, "struct*", $_tNID)
    EndIf
EndFunc   ;==>_UpdateTray

; ======================================================================================

Func _Bluetooth_Get_Device_Inventory()
    Local $a_GetBluetoothDeviceInfo = _GetBluetoothDeviceInfo()
    Local $aError[1][1] = [["No Bluetooth Radio found or Bluetooth is turned off."]]

    ; Initialize Radio
    Local $tFindRadioParams = DllStructCreate("dword dwSize")
    DllStructSetData($tFindRadioParams, "dwSize", DllStructGetSize($tFindRadioParams))
    Local $hRadioOut = 0
    Local $aRadioCall = DllCall("Bthprops.cpl", "hwnd", "BluetoothFindFirstRadio", "ptr", DllStructGetPtr($tFindRadioParams), "hwnd*", $hRadioOut)
    If @error Or $aRadioCall[0] = 0 Then
        SetError(1)
        Return $aError
    EndIf
    Local $hRadio = $aRadioCall[2]
    Local $hRadioFindHandle = $aRadioCall[0]

    ; Search Parameters
    Local $sSearchParams = "dword dwSize; bool fReturnAuthenticated; bool fReturnRemembered; bool fReturnUnknown; bool fReturnConnected; bool fIssueInquiry; byte cTimeoutMultiplier; hwnd hRadio;"
    Local $tSearchParams = DllStructCreate($sSearchParams)
    DllStructSetData($tSearchParams, "dwSize", DllStructGetSize($tSearchParams))
    DllStructSetData($tSearchParams, "fReturnAuthenticated", 1)
    DllStructSetData($tSearchParams, "fReturnRemembered", 1)
    DllStructSetData($tSearchParams, "fReturnUnknown", 1)
    DllStructSetData($tSearchParams, "fReturnConnected", 1)
    DllStructSetData($tSearchParams, "fIssueInquiry", 1)
    DllStructSetData($tSearchParams, "cTimeoutMultiplier", 4)
    DllStructSetData($tSearchParams, "hRadio", $hRadio)

    ; Device Struct Definition
    Local $sDeviceInfo = "dword dwSize; int64 Address; dword ulClassofDevice; bool fConnected; bool fRemembered; bool fAuthenticated; " & _
            "ushort LastSeenYear; ushort LastSeenMonth; ushort LastSeenDayOfWeek; ushort LastSeenDay; ushort LastSeenHour; ushort LastSeenMinute; ushort LastSeenSecond; ushort LastSeenMS; " & _
            "ushort LastUsedYear; ushort LastUsedMonth; ushort LastUsedDayOfWeek; ushort LastUsedDay; ushort LastUsedHour; ushort LastUsedMinute; ushort LastUsedSecond; ushort LastUsedMS; " & _
            "wchar szName[248];"
    Local $tDeviceInfo = DllStructCreate($sDeviceInfo)
    DllStructSetData($tDeviceInfo, "dwSize", DllStructGetSize($tDeviceInfo))

    ; Prepare Output Array Structure (Columns: 0 to 7)
    Local $aResult[1][7] = [["Device Name", "MAC Address (Hex)", "Device Class", "Connected", "Remembered", "Last Used", "Battery Level"]]
    Local $iDeviceCount = 0

    ; Start Device Loop
    Local $aDeviceCall = DllCall("Bthprops.cpl", "hwnd", "BluetoothFindFirstDevice", "ptr", DllStructGetPtr($tSearchParams), "ptr", DllStructGetPtr($tDeviceInfo))

    If @error Or $aDeviceCall[0] = 0 Then
        DllCall("Bthprops.cpl", "bool", "BluetoothFindRadioClose", "hwnd", $hRadioFindHandle)
        DllCall("kernel32.dll", "bool", "CloseHandle", "hwnd", $hRadio)
        Return $aResult
    Else
        Local $hDeviceFindHandle = $aDeviceCall[0]
        Local $sName, $iAddress, $iClass, $bConnected, $bRemembered, $sHexMac, $sFormattedHexMac, $sLastUsed, $sBatteryVal, $iMajorClass

        While 1

            ; Get Data from API
            $sName = DllStructGetData($tDeviceInfo, "szName")
            $iAddress = DllStructGetData($tDeviceInfo, "Address")
            $iClass = DllStructGetData($tDeviceInfo, "ulClassofDevice")
            $bConnected = DllStructGetData($tDeviceInfo, "fConnected")
            $bRemembered = DllStructGetData($tDeviceInfo, "fRemembered")
            $sHexMac = StringLower(Hex($iAddress, 12))
            $sFormattedHexMac = StringRegExpReplace($sHexMac, "(.{2})(?=.)", "$1:")

            ; Parse Timestamp
            $sLastUsed = "Never"
            If DllStructGetData($tDeviceInfo, "LastUsedYear") > 0 Then
                $sLastUsed = DllStructGetData($tDeviceInfo, "LastUsedMonth") & "/" & DllStructGetData($tDeviceInfo, "LastUsedDay") & "/" & DllStructGetData($tDeviceInfo, "LastUsedYear") & _
                        " " & StringRight("00" & DllStructGetData($tDeviceInfo, "LastUsedHour"), 2) & ":" & StringRight("00" & DllStructGetData($tDeviceInfo, "LastUsedMinute"), 2)
            EndIf

            ; Fetch Live Battery if connected
            $sBatteryVal = "N/A"    ;  (Offline)"
            For $iEntry = 0 To UBound($a_GetBluetoothDeviceInfo) - 1
                If $a_GetBluetoothDeviceInfo[$iEntry][6] = $sFormattedHexMac Then $sBatteryVal = $a_GetBluetoothDeviceInfo[$iEntry][1]
            Next

            ; Major Device Class occupies bits 8 to 12
            $iMajorClass = BitShift(BitAND($iClass, 0x1F00), 8)

;~          If $iMajorClass = 4 And $bRemembered Then
            If $iMajorClass = 4 And $bConnected Then

                $iDeviceCount += 1
                ReDim $aResult[$iDeviceCount + 1][UBound($aResult, 2)]

                $aResult[$iDeviceCount][0] = $sName
                $aResult[$iDeviceCount][1] = StringUpper($sFormattedHexMac)
                $aResult[$iDeviceCount][2] = "0x" & Hex($iClass, 6)
                $aResult[$iDeviceCount][3] = ($bConnected ? "True" : "False")
                $aResult[$iDeviceCount][4] = ($bRemembered ? "True" : "False")
                $aResult[$iDeviceCount][5] = $sLastUsed
                $aResult[$iDeviceCount][6] = $sBatteryVal ; << don't work here

            EndIf

            ; Next Device
            Local $aNextCall = DllCall("Bthprops.cpl", "bool", "BluetoothFindNextDevice", "hwnd", $hDeviceFindHandle, "ptr", DllStructGetPtr($tDeviceInfo))
            If @error Or $aNextCall[0] = 0 Then ExitLoop
        WEnd

        DllCall("Bthprops.cpl", "bool", "BluetoothFindDeviceClose", "hwnd", $hDeviceFindHandle)
    EndIf

    ; Cleanup
    DllCall("Bthprops.cpl", "bool", "BluetoothFindRadioClose", "hwnd", $hRadioFindHandle)
    DllCall("kernel32.dll", "bool", "CloseHandle", "hwnd", $hRadio)

    Return $aResult
EndFunc   ;==>_Bluetooth_Get_Device_Inventory

Func _GetBluetoothDeviceInfo()
    Local Const $DIGCF_PRESENT = 0x00000002
    Local Const $DIGCF_DEVICEINTERFACE = 0x00000010

    ; Define properties to query: {GUID}, Property ID
    Local $aKeys[5][2] = [ _
            ["{a45c254e-df1c-4efd-8020-67d146a850e0}", 14], _ ; Friendly Name
            ["{104EA319-6EE2-4701-BD47-8DDBF425BBE5}", 2], _ ; Battery Level
            ["{a45c254e-df1c-4efd-8020-67d146a850e0}", 13], _ ; Manufacturer (May still be blank for Generic BT devices!)
            ["{a45c254e-df1c-4efd-8020-67d146a850e0}", 3], _ ; Hardware ID
            ["{78c34fc8-104a-4aca-9ea4-524d52996e57}", 256] _ ; Instance ID
            ]

    Local $iNumProps = UBound($aKeys)

    ; Bluetooth Device Interface Class GUID
    Local $tGUID = DllStructCreate("ulong;ushort;ushort;byte[8]")
    DllCall("ole32.dll", "long", "CLSIDFromString", "wstr", "{0000111e-0000-1000-8000-00805f9b34fb}", "ptr", DllStructGetPtr($tGUID))

    ; Handle to active Bluetooth objects
    Local $aHdev = DllCall("setupapi.dll", "handle", "SetupDiGetClassDevsW", _
            "ptr", DllStructGetPtr($tGUID), "ptr", 0, "hwnd", 0, "dword", BitOR($DIGCF_PRESENT, $DIGCF_DEVICEINTERFACE))
    If @error Or $aHdev[0] = -1 Then Return SetError(1, 0, 0)
    Local $hDevInfo = $aHdev[0]

    ; Explicit structural memory boundaries for 64-bit portability
    Local $sInterfaceDataDef = "dword cbSize;ulong;ushort;ushort;byte[8];ulong_ptr Reserved"
    Local $tDeviceInterfaceData = DllStructCreate($sInterfaceDataDef)
    DllStructSetData($tDeviceInterfaceData, "cbSize", DllStructGetSize($tDeviceInterfaceData))

    Local $sDevInfoDataDef = "dword cbSize;ulong;ushort;ushort;byte[8];ulong_ptr DevInst"
    Local $tDeviceInfoData = DllStructCreate($sDevInfoDataDef)
    DllStructSetData($tDeviceInfoData, "cbSize", DllStructGetSize($tDeviceInfoData))

    Local $iIndex = 0
    Local $aResults[50][$iNumProps]
    Local $iCount = 0

    While True
        Local $aEnum = DllCall("setupapi.dll", "bool", "SetupDiEnumDeviceInterfaces", _
                "handle", $hDevInfo, "ptr", 0, "ptr", DllStructGetPtr($tGUID), "dword", $iIndex, "ptr", DllStructGetPtr($tDeviceInterfaceData))

        If @error Or Not $aEnum[0] Then ExitLoop

        ; Match interface to specific hardware instance block
        DllCall("setupapi.dll", "bool", "SetupDiGetDeviceInterfaceDetailW", _
                "handle", $hDevInfo, "ptr", DllStructGetPtr($tDeviceInterfaceData), "ptr", 0, "dword", 0, "dword*", 0, "ptr", DllStructGetPtr($tDeviceInfoData))

        Local $bHasData = False

        ; Loop through our mapped DEVPROPKEYs
        For $i = 0 To $iNumProps - 1
            Local $tPropKey = DllStructCreate("ulong;ushort;ushort;byte[8];ulong")
            DllCall("ole32.dll", "long", "CLSIDFromString", "wstr", $aKeys[$i][0], "ptr", DllStructGetPtr($tPropKey))
            DllStructSetData($tPropKey, 5, $aKeys[$i][1])

            ; Use a generic byte buffer large enough for any standard type
            Local $tBuffer = DllStructCreate("byte[1024]")
            Local $iPropType = 0
            Local $iReqSize = 0

            ; Extract Property
            Local $aProp = DllCall("setupapi.dll", "bool", "SetupDiGetDevicePropertyW", _
                    "handle", $hDevInfo, "ptr", DllStructGetPtr($tDeviceInfoData), "ptr", DllStructGetPtr($tPropKey), _
                    "ulong*", $iPropType, "ptr", DllStructGetPtr($tBuffer), "dword", 1024, "dword*", $iReqSize, "dword", 0)

            Local $sValue = ""

            ; If extraction succeeded, cast the memory dynamically based on the returned PropertyType
            If Not @error And $aProp[0] Then
                $iPropType = $aProp[4] ; $aProp[4] holds the type of data Windows returned

                If $iPropType = 0x00000012 Or $iPropType = 0x00002012 Then
                    ; DEVPROP_TYPE_STRING or DEVPROP_TYPE_STRING_LIST
                    Local $tString = DllStructCreate("wchar[512]", DllStructGetPtr($tBuffer))
                    $sValue = DllStructGetData($tString, 1)

                ElseIf $iPropType = 0x00000003 Then
                    ; DEVPROP_TYPE_BYTE (Used for Battery Levels)
                    $sValue = DllStructGetData($tBuffer, 1, 1)
                    If $sValue >= 0 And $sValue <= 100 Then $sValue &= "%"

                ElseIf $iPropType = 0x00000007 Then
                    ; DEVPROP_TYPE_UINT32
                    Local $tInt = DllStructCreate("dword", DllStructGetPtr($tBuffer))
                    $sValue = DllStructGetData($tInt, 1)
                EndIf

                If $sValue <> "" Then $bHasData = True
            EndIf

            $aResults[$iCount][$i] = (StringLen($sValue) < 2 ? "N/A" : $sValue)
        Next

        ; Only move to the next row if the device actually had populated metadata
        If $bHasData Then $iCount += 1

        ; Dynamically resize array if you have more than 50 Bluetooth components
        If $iCount >= UBound($aResults) Then ReDim $aResults[UBound($aResults) + 20][$iNumProps]

        $iIndex += 1
    WEnd

    DllCall("setupapi.dll", "bool", "SetupDiDestroyDeviceInfoList", "handle", $hDevInfo)

    If $iCount = 0 Then Return SetError(2, 0, 0)

    ReDim $aResults[$iCount][$iNumProps + 2]

    Local $aMatch, $sFormattedMAC ; get MAC from InstanceID
    For $n = 0 To UBound($aResults) - 1
        $aMatch = StringRegExp($aResults[$n][$iNumProps - 1], "&([0-9A-Fa-f]{12})_", 1)
        If @error Then ContinueLoop
        $sFormattedMAC = StringRegExpReplace($aMatch[0], "(.{2})(?!$)", "$1:")
        If @error Then ContinueLoop
        $aResults[$n][$iNumProps + 1] = $sFormattedMAC
    Next
    Return $aResults
EndFunc   ;==>_GetBluetoothDeviceInfo

; ======================================================================================

;~ ConsoleWrite("DeviceClass desc.: " & _DecodeDeviceClass(0x240404) & @CRLF)
Func _DecodeDeviceClass($iCoD)

;~              Local $iCoD = 0x240404
;~              ; Major Service Classes (Bits 13 to 23)
;~              Local $iServiceClass = BitAND($iCoD, 0xFFE000)
;~              ; Major Device Class (Bits 8 to 12)
;~              Local $iMajorClass = BitShift(BitAND($iCoD, 0x1F00), 8) ; Will return 4 for Audio/Video
;~              ; Minor Device Class (Bits 2 to 7)
;~              Local $iMinorClass = BitShift(BitAND($iCoD, 0xFC), 2)  ; Will return 1 for Headset, 6 for Headphones



    Local $iMajorClass = BitShift(BitAND($iCoD, 0x1F00), 8)
    Local $iMinorClass = BitShift(BitAND($iCoD, 0x00FC), 2)
    Local $sMajorText = "Unknown"
    Local $sMinorText = "Generic"

    ; Look-up for Major Device Class
    Switch $iMajorClass
        Case 1
            $sMajorText = "Computer"
        Case 2
            $sMajorText = "Phone"
        Case 3
            $sMajorText = "Network Access Point"
        Case 4
            $sMajorText = "Audio/Video"
        Case 5
            $sMajorText = "Peripheral (Mouse/Keyboard)"
        Case 6
            $sMajorText = "Imaging (Printer/Scanner)"
        Case 7
            $sMajorText = "Wearable"
    EndSwitch

    ; Look-up for Minor Device Class ( for Audio/Video family )
    If $iMajorClass = 4 Then
        Switch $iMinorClass
            Case 1
                $sMinorText = "Wearable Headset"
            Case 2
                $sMinorText = "Hands-free Device"
            Case 4
                $sMinorText = "Microphone"
            Case 5
                $sMinorText = "Loudspeaker"
            Case 6
                $sMinorText = "Headphones"
            Case 7
                $sMinorText = "Portable Audio"
            Case 11
                $sMinorText = "Set-top Box"
            Case 12
                $sMinorText = "HiFi Audio Device"
            Case 13
                $sMinorText = "VCR/DVD/BlueRay"
            Case 14
                $sMinorText = "Video Camera"
            Case 15
                $sMinorText = "Display/Monitor and Loudspeaker"
        EndSwitch
    EndIf

    Return $sMajorText & " -> " & $sMinorText
EndFunc   ;==>_DecodeDeviceClass

; ======================================================================================

 

I use earbuds ( these cheaper ones because they don't bother my ears** ) and the internal batteries of each side are different. Meaning that one always dies hours before the other and I wanted a "tray indicator" because the build-in on windows one takes clicking, and the "battery low" announcement annoys me when am not close to the PC.
Now if I happen to see the battery at 40% or less I know that might as well swap them with my other set of earbuds if I feel like it.
** since I don't inset them in my ear canal ( just let them loose ), I also have a sound equalizer ( FxSound ) to make them sound better.

Code wise here are examples of a fake tray icon with clicking and Bluetooth radio, and other Bluetooth things if you scrape them out of the script.
It checks every 10 min.

P.S.: Was thinking of adding a "on new devise connected" thing, and if I ever do, I'll update the example.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting  image.gif.922e3a93535f431de08b31ee669cc446.gif
autoit_scripter_blue_userbar.png

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...