def scan_system():
    """
    Scans /sys/class/leds looking for entries, then examining their .../device/uevent file to obtain unique hardware
    IDs corresponding to the associated hardware. This then allows us to associate InputDevice based controllers with
    sets of zero or more LEDs. The result is a dict from hardware address to a dict of name to filename, where the name
    is the name of the LED and the filename is the brightness control to which writing a value changes the LED state.

    At the same time, scans /sys/class/power_supply looking for battery entries and analysing them in the same way.

    Hardware IDs are, in order of preference, the HID_UNIQ address (corresponding to the physical MAC of an attached
    bluetooth or similar HID device), or the PHYS corresponding to other devices. This is the same logic as used in the
    evdev based scanning to group together input nodes for composite controllers (i.e. ones with motion sensors as well
    as physical axes). It is intended to produce the same results, so the LEDs for e.g. a PS4 controller will be keyed
    on the same physical address as that returned by :func:`approxeng.input.controllers.unique_name` for all the
    InputDevice instances associated with a given controller.

    :return:
        A dict containing available LEDs, keyed on physical device ID
    """

    def find_device_hardware_id(uevent_file_path):
        hid_uniq = None
        phys = None
        for line in open(uevent_file_path, 'r').read().split('\n'):
            parts = line.split('=')
            if len(parts) == 2:
                name, value = parts
                value = value.replace('"', '')
                if name == 'HID_UNIQ' and value:
                    hid_uniq = value
                elif name == 'PHYS' and value:
                    phys = value.split('/')[0]
        if hid_uniq:
            return hid_uniq
        elif phys:
            return phys
        return None

    leds = {}
    for sub in ['/sys/class/leds/' + sub_dir for sub_dir in listdir('/sys/class/leds')]:
        led_name = sub.split(':')[-1]
        write_path = sub + '/brightness'
        device_id = find_device_hardware_id(sub + '/device/uevent')
        if device_id:
            if device_id not in leds:
                leds[device_id] = {}
            leds[device_id][led_name] = write_path

    power = {}
    for sub in ['/sys/class/power_supply/' + sub_dir for sub_dir in listdir('/sys/class/power_supply')]:
        read_path = sub + '/capacity'
        device_id = find_device_hardware_id(sub + '/device/uevent')
        if device_id:
            power[device_id] = read_path

    return {'leds': leds,
            'power': power}
Scans /sys/class/leds looking for entries, then examining their .../device/uevent file to obtain unique hardware
    IDs corresponding to the associated hardware. This then allows us to associate InputDevice based controllers with
    sets of zero or more LEDs. The result is a dict from hardware address to a dict of name to filename, where the name
    is the name of the LED and the filename is the brightness control to which writing a value changes the LED state.

    At the same time, scans /sys/class/power_supply looking for battery entries and analysing them in the same way.

    Hardware IDs are, in order of preference, the HID_UNIQ address (corresponding to the physical MAC of an attached
    bluetooth or similar HID device), or the PHYS corresponding to other devices. This is the same logic as used in the
    evdev based scanning to group together input nodes for composite controllers (i.e. ones with motion sensors as well
    as physical axes). It is intended to produce the same results, so the LEDs for e.g. a PS4 controller will be keyed
    on the same physical address as that returned by :func:`approxeng.input.controllers.unique_name` for all the
    InputDevice instances associated with a given controller.

    :return:
        A dict containing available LEDs, keyed on physical device ID