windowspython-3.xinventoryedid

Acer monitor serial number


I'm tryin to get the serial number of an Acer monitor looking into the windows registry. I'm parsing the registry with this code in Python 3:

import winreg
from winreg import HKEY_LOCAL_MACHINE

subKey = "SYSTEM\CurrentControlSet\Enum\DISPLAY"
k = winreg.OpenKey(HKEY_LOCAL_MACHINE, subKey)

with winreg.OpenKey(HKEY_LOCAL_MACHINE, subKey) as k:
    """"
        Open the key 'HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY'
        to get the info of all connected monitors
    """
    i = 0
    while True:
        try:
            with winreg.OpenKey(k, winreg.EnumKey(k, i)) as sk:
                j = 0
                while True:
                    try:
                        with winreg.OpenKey(sk, winreg.EnumKey(sk, j)) as ssk:
                            l = 0
                            while True:
                                try:
                                    if (winreg.EnumKey(ssk, l) == "Control"):
                                        try:
                                            with winreg.OpenKey(ssk, "Device Parameters") as sssk:
                                                strEDID = str(winreg.EnumValue(sssk, 0)[1])
                                                try:
                                                    modelo = strEDID[strEDID.index("\\x00\\x00\\x00\\xfc") + len("\\x00\\x00\\x00\\xfc\\x00"):].split("\\")[0]
                                                    serie = strEDID[strEDID.index("\\x00\\x00\\x00\\xff") + len("\\x00\\x00\\x00\\xff\\x00"):].split("\\")[0]
                                                except:
                                                    modelo = "Not Found"
                                                    serie = "Not Found"

                                                print ("Modelo:", modelo)
                                                print ("Serie:", serie, "\n")

                                                fo = open("salTest.txt", "a")
                                                fo.write(modelo + "\n")
                                                fo.write(serie + "\n\n")
                                                fo.close()

                                        except OSError:
                                            print ("Error")
                                        break
                                    else:
                                        l += 1
                                except OSError:
                                    break
                        j += 1
                    except OSError:
                        break
            i += 1
        except OSError:
            break

As result i get an output in the cmd window like this:

Modelo: AL1716
Serie: L4802017396L

The problem is that the "Serie" isn't the real serial number (an Acer monitor serial number have 22 characters and looks like "ETL480201781700F4B396L")
There is a way to build the real serial number with the "Serie" and the SNID that identify the monitor too.
Here is an example of two Acer monitors:

S/N ORIGINAL:           ETL48020178170 (0F4B)396L   |       # ETL480201781700F4B396L
------------------------------------------------------------------------------------
SNID:                             8170 (0F4B)=03915 |   39  # 81700391539
S/N FROM SCRIPT:          L4802017           396L   |       # L4802017396L



S/N ORIGINAL:           ETL48020178170 (2C98)396L   |       # ETL480201781702C98396L
------------------------------------------------------------------------------------
SNID:                             8170 (2C98)=11416 |   39  # 81701141639
S/N FROM SCRIPT:          L4802017           396L   |       # L4802017396L

Anyone know how to get this info?

Thanks!


Solution

  • Acer provides the serial number after the 000000ff00 flag but the middle part of the serial number is hidden earlier in the EDID string.

    So for example our EDID string looks like this:

    00ffffffffffff0004723a03c4fe603324170103682f1e78ca9265a655559f280d5054bfef80714f8140818081c0810095000101010126399030621a274068b03600da281100001c000000fd00374c1e5011000a202020202020000000fc0042323236574c0a202020202020000000ff004c58565341303031383531300a007b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    The serial number we want is this: LXVSA0013360FEC48510

    The first 8 characters of the serial number LXVSA001 is encoded as a hex string immediately after the '000000ff00' flag.

    The last 4 characters of the serial number 8510 is encoded as a hex string after this first 8 characters.

    000000ff00 4c|58|56|53|41|30|30|31|38|35|31|30|0a|        <-- EDID (hex)
               L  X  V  S  A  O  0  1  8  5  1  0 (linefeed)  <-- ascii
              (^^^^ first part ^^^^^^)(last part)
    

    Now the tricky middle part 3360fec4 is encoded as 4 strings earlier in the EDID.

    33 is at position 30 60 is at position 28 fe is at position 26 c4 is at position 24

    00ffffffffffff0004723a03
    position 24 -> c4
    position 26 -> fe
    position 28 -> 60
    position 30 -> 33
    24170103682f1e78ca9265a655559f etc
    

    When I say 'position' I mean take the EDID string as an array and index from 0. They are hard to find because they are in reverse order.

    In your example, the missing parts of your serial number 81700F4B should be located as 4 separate 2 character strings at locations 30, 28, 26, and 24 of your idid string. I can't test that because I don't have the full IDID.