def decode_eventdata(sensor_type, offset, eventdata, sdr):
    """Decode extra event data from an alert or log

    Provide a textual summary of eventdata per descriptions in
    Table 42-3 of the specification.  This is for sensor specific
    offset events only.

    :param sensor_type: The sensor type number from the event
    :param offset:  Sensor specific offset
    :param eventdata: The three bytes from the log or alert
    """
    if sensor_type == 5 and offset == 4:  # link loss, indicates which port
        return 'Port {0}'.format(eventdata[1])
    elif sensor_type == 8 and offset == 6:  # PSU cfg error
        errtype = eventdata[2] & 0b1111
        return psucfg_errors.get(errtype, 'Unknown')
    elif sensor_type == 0xc and offset == 8:  # Memory spare
        return 'Module {0}'.format(eventdata[2])
    elif sensor_type == 0xf:
        if offset == 0:  # firmware error
            return firmware_errors.get(eventdata[1], 'Unknown')
        elif offset in (1, 2):
            return firmware_progress.get(eventdata[1], 'Unknown')
    elif sensor_type == 0x10:
        if offset == 0:  # Correctable error logging on a specific memory part
            return 'Module {0}'.format(eventdata[1])
        elif offset == 1:
            return 'Reading type {0:02X}h, offset {1:02X}h'.format(
                eventdata[1], eventdata[2] & 0b1111)
        elif offset == 5:
            return '{0}%'.format(eventdata[2])
        elif offset == 6:
            return 'Processor {0}'.format(eventdata[1])
    elif sensor_type == 0x12:
        if offset == 3:
            action = (eventdata[1] & 0b1111000) >> 4
            return auxlog_actions.get(action, 'Unknown')
        elif offset == 4:
            sysactions = []
            if eventdata[1] & 0b1 << 5:
                sysactions.append('NMI')
            if eventdata[1] & 0b1 << 4:
                sysactions.append('OEM action')
            if eventdata[1] & 0b1 << 3:
                sysactions.append('Power Cycle')
            if eventdata[1] & 0b1 << 2:
                sysactions.append('Reset')
            if eventdata[1] & 0b1 << 1:
                sysactions.append('Power Down')
            if eventdata[1] & 0b1:
                sysactions.append('Alert')
            return ','.join(sysactions)
        elif offset == 5:  # Clock change event, either before or after
            if eventdata[1] & 0b10000000:
                return 'After'
            else:
                return 'Before'
    elif sensor_type == 0x19 and offset == 0:
        return 'Requested {0] while {1}'.format(eventdata[1], eventdata[2])
    elif sensor_type == 0x1d and offset == 7:
        return restart_causes.get(eventdata[1], 'Unknown')
    elif sensor_type == 0x21 and offset == 0x9:
        return '{0} {1}'.format(slot_types.get(eventdata[1], 'Unknown'),
                                eventdata[2])

    elif sensor_type == 0x23:
        phase = eventdata[1] & 0b1111
        return watchdog_boot_phases.get(phase, 'Unknown')
    elif sensor_type == 0x28:
        if offset == 4:
            return 'Sensor {0}'.format(eventdata[1])
        elif offset == 5:
            islogical = (eventdata[1] & 0b10000000)
            if islogical:
                if eventdata[2] in sdr.fru:
                    return sdr.fru[eventdata[2]].fru_name
                else:
                    return 'FRU {0}'.format(eventdata[2])
    elif sensor_type == 0x2a and offset == 3:
        return 'User {0}'.format(eventdata[1])
    elif sensor_type == 0x2b:
        return version_changes.get(eventdata[1], 'Unknown')
    elif sensor_type == 0x2c:
        cause = (eventdata[1] & 0b11110000) >> 4
        cause = fru_states.get(cause, 'Unknown')
        oldstate = eventdata[1] & 0b1111
        if oldstate != offset:
            try:
                cause += '(change from {0})'.format(
                    ipmiconst.sensor_type_offsets[0x2c][oldstate]['desc'])
            except __HOLE__:
                pass
dataset/ETHPy150Open openstack/pyghmi/pyghmi/ipmi/events.py/decode_eventdata