incremental
diff --git a/static/js/selController.js b/static/js/selController.js
new file mode 100644
index 0000000..7f678a8
--- /dev/null
+++ b/static/js/selController.js
@@ -0,0 +1,893 @@
+generators_list = [
+    [0x20, "BMC"],
+    [0x2C, "ME"],
+    [0x01, 0x1F, 'BIOS'],
+    [0x21, 0x3F, 'SMI Handler'],
+    [0x41, 0x5F, 'System Management Software'],
+    [0x61, 0x7F, 'OEM'],
+    [0x81, 0x8D, 'Remote Console Software 1-7'],
+    [0x8f, 0x8f, 'Terminal Mode Remote Console software'],
+];
+
+sensor_type_list =
+[
+    [0x00, "Reserved"],
+    [0x01, "Temperature"],
+    [0x02, "Voltage"],
+    [0x03, "Current"],
+    [0x04, "Fan"],
+    [0x05, "Physical Security (Chassis Intrusion)"],
+    [0x06, "Platform Security Violation Attempt"],
+    [0x07, "Processor"],
+    [0x08, "Power Supply"], 
+    [0x09, "Power Unit"],
+    [0x0A, "Cooling Device"],
+    [0x0B, "Other Units-based Sensor"],
+    [0x0C, "Memory"],
+    [0x0D, "Bay"],
+    [0x0E, "POST Memory Resize"],
+    [0x0F, "POST Error"],
+    [0x10, "Event Logging Disabled"],
+    [0x11, "Watchdog 1"],
+    [0x12, "System Event"],
+    [0x13, "Critical Interrupt"],
+    [0x14, "Button / Switch"],
+    [0x15, "Module / Board"],
+    [0x16, "Microcontroller / Coprocessor"],
+    [0x17, "Add-in Card"],
+    [0x18, "Chassis"],
+    [0x19, "Chip Set"],
+    [0x1A, "Other FRU"],
+    [0x1B, "Cable / Interconnect"],
+    [0x1C, "Terminator"],
+    [0x1D, "System Boot / Restart Initiated"],
+    [0x1E, "Boot Error"],
+    [0x1F, "Base OS Boot / Installation Status"],
+    [0x20, "OS Stop / Shutdown"],
+    [0x21, "Slot / Connector"],
+    [0x22, "System ACPI Power State"],
+    [0x23, "Watchdog 2"],
+    [0x24, "Platform Alert"],
+    [0x25, "Entity Presence"],
+    [0x26, "Monitor ASIC / IC"],
+    [0x27, "LAN"],
+    [0x28, "Management Subsystem Health"],
+    [0x29, "Battery"],
+    [0x2A, "Session Audit"],
+    [0x2B, "Version Change"],
+    [0x2C, "FRU State"],
+    [0xC0, 0xFF, "OEM RESERVED"],
+    [0x2d, 0xBF, "Reserved"]
+];
+
+event_reading_type_list = [
+    [0x01, "Threshold"],
+    [0x02, 0x0C, "Generic"],
+    [0x6F, "Sensor Specific"],
+    [0x70, 0x7F, "OEM"],
+];
+
+memory_ras_mode = {
+    0x00: "No Mode",
+    0x01: "Mirroring Mode",
+    0x02: "Lockstep Mode",
+    0x03: "Invalid RAS Mode",
+    0x04: "Rank Sparing Mode"
+};
+
+caterr_error_type = {
+    0x00: "Unknown",
+    0x01: "CATERR",
+    0x02: "CPU Core Error",
+    0x03: "CPU Icc max Mismatch",
+    0x04: "CATERR due to CPU 3-strike timeout",
+};
+
+config_error_values = {
+    0x00: " - CFG syntax error",
+    0x01: " - Chassis auto-detect error",
+    0x02: " - SDR/CFG file mismatch",
+    0x03: " - SDR or CFG file corrupted",
+    0x04: " - SDR syntax error"
+};
+
+ras_select_string = " Prior RAS: %s Seleted RAS: %s";
+
+
+function decode_bios_xeon_dimm_slot_event(generator_id, sensor_type, event_data_offset, event_data){
+    var return_string = "";
+
+    var entity_id = 0x20;  // TODO find a way to get this.  
+    // This was previously identified by sensor numbers hardcoded.
+    // 0x20 = Mem Conf Sensor;  0x2B = Rdnc Mod Sensor
+
+    //if bios generated event and sensor_type is memory
+    if (generator_id == 0x01){
+        if ((entity_id == 0x020) || (entity_id == 0x02B)){  
+            // if sensor is mem conf sensor or rdnc mod sensor
+            if ((event_data[0] & 0xA0) == 0xA0){
+                var offset = event_data[0] & 0xF
+                var prior;
+                var selected;
+                if (offset <= 1){
+                    if (entity_id == 0x02B){
+                        offset = sel_data[1] & 0xF;
+                        if (offset in memory_ras_mode){
+                            prior = memory_ras_mode[offset];
+                        }
+                    }
+                    
+                    offset = sel_data[2] & 0xF;
+                    if (offset in memory_ras_mode){
+                        selected = memory_ras_mode[offset];
+                    }
+                    if (prior == null){
+                        return_string += selected;                        
+                    } else {
+                        return_string += ras_select_string.format(prior, selected);
+                    }
+                }
+            }
+        }
+    } 
+};
+
+
+function cpu_caterr_ext_string(generator_id, sensor_type, event_data_offset, event_data){
+    var return_string = "";
+    if (event_data[0] == 0xA1)
+    {
+
+        return_string += "- CATERR type: ";
+        return_string += caterr_error_type[event_data[2]] || "Reserved";
+
+        return_string += ", CPU bitmap that causes the system CATERR:";
+        for (var cpu_number = 1; cpu_number <=4; cpu_number++){
+            if ((1 << cpu_number) & event_data[2] > 0){
+                return_string += " CPU" + cpu_number;
+            }
+        }
+    }
+    return return_string;
+};
+
+function config_error_ext_string(generator_id, sensor_type, event_data_offset, event_data){
+    var return_string = "";
+    
+    if (event_data[0] == 0x21)
+    {
+        return_string += config_error_values[event_data[1]] || " Reserved";
+    }
+    return return_string;
+};
+
+function mtm_level_change_ext_string(generator_id, sensor_type, event_data_offset, event_data){
+    var return_string = "";
+    
+    if (event_data[0] == 0x81)
+    {
+        if (event_data[1] <= 2 && event_data[1] >= 1){
+            return_string += "Level " + event_data[1];
+        } else {
+            return_string += "Reserved";
+        }
+    }
+    return return_string;
+};
+
+function vrd_hot_ext_string(generator_id, sensor_type, event_data_offset, event_data){
+    var return_string = "";
+    
+    if (event_data_offset == 0x01)
+    {
+        if (event_data[1] > 0){
+
+            return_string += " - Processor VRD HOT map:";
+            for (var cpu_number = 1; cpu_number <=4; cpu_number++){
+                if ((1 << cpu_number) & event_data[1] > 0){
+                    return_string += " CPU" + cpu_number;
+                }
+            }
+        }
+        if (event_data[2] > 0){
+            return_string += ", Memory VRD HOT map:";
+            for (var cpu_dimm_number = 1; cpu_dimm_number <=4; cpu_dimm_number++){
+                if ((1 << cpu_dimm_number) & event_data[2] > 0){
+                    return_string += " CPU" + (cpu_dimm_number-1) >> 1;
+
+                    if ((cpu_dimm_number+1) % 2 == 1){
+                        return_string += ", DIMM Channel 1/2";
+                    } else {
+                        return_string += ", DIMM Channel 3/4";
+                    }
+                }
+            }
+        }
+    }
+    return return_string;
+};
+
+function decode_drive_or_dimm_temperature_sel(generator_id, sensor_type, event_data_offset, event_data){
+    var return_string = ""
+    if (generator_id == 0x20){  // if generated from the BMC
+        if (((event_data[0] & 0xF0) == 0xA0) && (event_data[1] == 0x01)){
+            // drive temperature sel
+            // Sensor Type 0x01 (Temperature)
+            // Event Type 0x01 (Threshold)
+            // OEM Data 0 [7:4] == 0b1010 (2 bytes OEM data, extended format)
+            // OEM Data 1 (SSD Drive format)
+
+            // Get the standard string, since this is technically a standard
+            // event. Then, add the OEM data.
+
+            for (var drive_number = 0; drive_number < 8; drive_number++) {
+                if (( 1 << drive_number) & event_data[1]) {
+                    return_string += " :Drive " + drive_number;
+                }
+            }
+        } else if ((event_data[0] & 0xF0) == 0x30) {
+            // Dimm aggregate thermal margin
+            //TODO fix this
+            for (var cpu_number = 0; cpu_number < 8; cpu_number++) {
+                if ((1 <<cpu_number) & event_data[2]){
+                    cpu_number += 1;
+                    break;
+                }
+            }
+
+            if (event_data[0]){
+                for (var dimm_counter = 0; dimm_counter < 8; dimm_counter++) {
+                    if ((1 << dimm_counter) & event_data[0]){
+                        dimm_number = dimm_counter % 4;
+                        dimm_channel = dimm_counter >> 2;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
+
+/* This dict defines the states for the SEL reader.  The first level of keys
+is used to map the event type to a section.  The rest of the sections are used
+to map the individual event data to an entry.
+if the key "sensor_type" is present, it will use that entry to map a specific sensor
+type to a string and a severity.  the lowest level of dictionaries maps the offset
+to a user facing string.
+
+a custom_handler  can be added to the dict and invoked at the lowest level to
+manage non-standard sel to string implementationations or ones that require code 
+to determine.
+*/
+event_reading_type_states = {
+    0x00: "Unspecified",
+    0x01: {  // Threshold
+        0x00: ["Lower Non-critical - going low", "Degraded"],
+        0x01: ["Lower Non-critical - going high", "Degraded"],
+        0x02: ["Lower Critical - going low", "Non-Fatal"],
+        0x03: ["Lower Critical - going high", "Non-Fatal"],
+        0x04: ["Lower Non-recoverable - going low", "Fatal"],
+        0x05: ["Lower Non-recoverable - going high", "Fatal"],
+        0x06: ["Upper Non-critical - going low", "Degraded"],
+        0x07: ["Upper Non-critical - going high", "Degraded"],
+        0x08: ["Upper Critical - going low", "Non-Fatal"],
+        0x09: ["Upper Critical - going high", "Non-Fatal"],
+        0x0A: ["Upper Non-recoverable - going low", "Fatal"],
+        0x0B: ["Upper Non-recoverable - going high", "Fatal"],
+        "sensor_type": {
+            0x01: decode_drive_or_dimm_temperature_sel // hard drive
+        }
+    },
+    0x02: { //Discrete
+        0x00: "Transition to Idle",
+        0x01: "Transition to Active",
+        0x02: "Transition to Busy"
+    },
+    0x03: {
+        0x00: "State Deasserted",
+        0x01: "State Asserted",
+        "sensor_type": {
+            0x07: cpu_caterr_ext_string,
+            0x28: [mtm_level_change_ext_string, config_error_ext_string],
+            
+        }
+    },
+    0x04: {
+        0x00: "Predictive Failure deasserted",
+        0x01: ["Predictive Failure asserted", "Degraded"]
+    },
+    0x05: {
+        0x00: "Limit Not Exceeded",
+        0x01: ["Limit Exceeded", "Degraded"],
+        "sensor_type": {
+            0x01: vrd_hot_ext_string
+        }
+    },
+    0x06: {
+        0x00: "Performance Met",
+        0x01: ["Performance Lags", "Degraded"]
+    },
+    0x07: {
+        0x00: "Transition to OK",
+        0x01: ["Transition to Non-Critical from OK", "Degraded"],
+        0x02: ["Transition to Critical from less severe", "Non-Fatal"],
+        0x03: ["Transition to Non-recoverable from less severe", "Fatal"],
+        0x04: ["Transition to Non-Critical from more severe", "Degraded"],
+        0x05: ["Transition to Critical from Non-recoverable", "Non-Fatal"], 
+        0x06: ["Transition to Non-recoverable", "Fatal"],
+        0x07: ["Monitor", "Degraded"],
+        0x08: "Informational"
+    },
+    0x08: {
+        0x00: "Device Removed / Device Absent",
+        0x01: "Device Inserted / Device Present"
+    },
+    0x09: {
+        0x00: "Device Disabled",
+        0x01: "Device Enabled",
+        "sensor_type": {
+            0x0C: decode_bios_xeon_dimm_slot_event
+        }
+    },
+    0x0A: {
+        0x00: "Transition to Running",
+        0x01: "Transition to In Test",
+        0x02: "Transition to Power Off",
+        0x03: "Transition to On Line",
+        0x04: "Transition to Off Line",
+        0x05: "Transition to Off Duty",
+        0x06: "Transition to Degraded",
+        0x07: "Transition to Power Save",
+        0x08: ["Install Error", "Degraded"]
+    },
+    0x0B: {
+        0x00: "Redundancy Regained",
+        0x01: ["Redundancy Lost", "Degraded"],
+        0x02: ["Redundancy Degraded", "Degraded"],
+        0x03: "Non-redundant:Sufficient Resources from Redundant",
+        0x04: "Non-redundant:Sufficient Resources from Insufficient Resources",
+        0x05: ["Non-redundant:Insufficient Resources", "Degraded"],
+        0x06: ["Redundancy Degraded from Fully Redundant", "Degraded"],
+        0x07: ["Redundancy Degraded from Non-redundant", "Degraded"]
+    },
+    0x0C: {
+        0x00: "D0 Power State",
+        0x01: "D1 Power State",
+        0x02: "D2 Power State",
+        0x03: "D3 Power State"
+    },
+    0x6F: {  // OEM
+        "sensor_type": {
+            0x00: "",  // reserved
+            0x01: "",  // Temperature
+            0x02: "",  // Voltage
+            0x03: "",  // Current
+            0x04: "N/A",  //Fan
+            0x05: {  // General Chassis Intrusion
+                0x00: ["General Chassis Intrusion", "Degraded"],
+                0x01: ["Drive Bay intrusion", "Degraded"],
+                0x02: ["I/O Card area intrusion", "Degraded"],
+                0x03: ["Processor area intrusion", "Degraded"],
+                0x04: ["LAN Leash Lost", "Degraded"],
+                0x05: ["Unauthorized dock", "Degraded"],
+                0x06: ["FAN area intrusion", "Degraded"],
+            },
+            0x06: {  // Physical Security - Violation Attempt
+                0x00: ["Secure Mode Violation attempt", "Degraded"],
+                0x01: ["Pre-boot Password Violation - user password", "Degraded"],
+                0x02: ["Pre-boot Password Violation attempt - setup password", "Degraded"],
+                0x03: ["Pre-boot Password Violation - network boot password", "Degraded"],
+                0x04: ["Other pre-boot Password Violation", "Degraded"],
+                0x05: ["Out-of-band Access Password Violation", "Degraded"]
+            },
+            0x07: { // Processor
+                0x00: ["IERR", "Degraded"],
+                0x01: ["Thermal Trip", "Degraded"],
+                0x02: ["FRB1/BIST failure", "Degraded"],
+                0x03: ["FRB2/Hang in POST failure", "Degraded"],
+                0x04: ["FRB3/Processor Startup/Initialization failure", "Degraded"],
+                0x05: ["Configuration Error", "Degraded"],
+                0x06: ["SM BIOS Uncorrectable CPU-complex Error", "Degraded"],
+                0x07: ["Processor Presence detected", "Degraded"],
+                0x08: ["Processor disabled", "Degraded"],
+                0x09: ["Terminator Presence Detected", "Degraded"],
+                0x0A: ["Processor Automatically Throttled", "Degraded"],
+                0x0B: ["Machine Check Exception (Uncorrectable)", "Fatal"],
+                0x0C: ["Correctable Machine Check Error", "Non-Fatal"]
+            },
+            0x08: {  // Power Supply
+                0x00: "Presence detected",
+                0x01: ["Power Supply Failure detected", "Degraded"],
+                0x02: ["Predictive Failure", "Degraded"],
+                0x03: ["Power Supply input lost (AC/DC)", "Degraded"],
+                0x04: ["Power Supply input lost or out-of-range", "Degraded"],
+                0x05: ["Power Supply input out-of-range, but present", "Degraded"],
+                0x06: ["Configuration error", "Degraded"],
+                0x07: ["Power Supply Inactive (in standby state)", "Degraded"]
+            },  
+            0x09: {  // Power unit
+                0x00: "Power Off / Power Down",
+                0x01: "Power Cycle",
+                0x02: "240VA Power Down",
+                0x03: "Interlock Power Down",
+                0x04: ["AC lost / Power input lost", "Degraded"],
+                0x05: ["Soft Power Control Failure", "Degraded"],
+                0x06: ["Power Unit Failure detected", "Degraded"],
+                0x07: ["Predictive Failure", "Degraded"]
+            },
+            0x0C: { // Memory
+                0x00: ["Correctable ECC / other correctable memory error", "Degraded"],
+                0x01: ["Uncorrectable ECC", "Fatal"],
+                0x02: "Parity",
+                0x03: ["Memory Scrub Failed", "Fatal"],
+                0x04: "Memory Device Disabled",
+                0x05: ["Correctable ECC / other correctable memory error logging limit reached", "Degraded"],
+                0x06: "Presence detected",
+                0x07: ["Configuration error", "Fatal"],
+                0x08: "Spare",
+                0x09: "Memory Automatically Throttled",
+                0x0A: ["Critical Overtemperature", "Fatal"]
+            },       
+            0x0D: { // Drive Slot
+                0x00: "Drive Presence",
+                0x01: ["Drive Fault", "Fatal"],
+                0x02: ["Predictive Failure", "Fatal"],
+                0x03: "Hot Spare",
+                0x04: "Consistency Check / Parity Check in progress",
+                0x05: ["In Critical Array", "Degraded"],
+                0x06: ["In Failed Array", "Degraded"],
+                0x07: ["Rebuild/Remap in progress", "Degraded"],
+                0x08: ["Rebuild/Remap Aborted", "Degraded"]
+            },
+            0x0F: { // POST Error
+                0x00: "POST Error",
+                0x01: "System Firmware Hang",
+                0x02: "System Firmware Progress"
+            },
+            0x10: { // Event Logging Disabled
+                0x00: "Correctable Memory Error Logging Disabled",
+                0x01: "Event Type Logging Disabled",
+                0x02: "All Event Logging Disabled",
+                0x03: "All Event Logging Disabled",
+                0x04: ["SEL Full", "Degraded"],
+                0x05: ["SEL Almost Full", "Degraded"],
+                0x06: "Correctable Machine Check Error Logging Disabled"
+            },
+            0x11: { // Watchdog 1
+                0x0: ["BIOS Watchdog Reset", "Fatal"],
+                0x1: ["OS Watchdog Reset", "Fatal"],
+                0x2: ["OS Watchdog Shut Down", "Fatal"],
+                0x3: ["OS Watchdog Power Down", "Fatal"],
+                0x4: ["OS Watchdog Power Cycle", "Fatal"],
+                0x5: ["OS Watchdog NMI / Diagnostic Interrupt", "Fatal"],
+                0x6: ["OS Watchdog Expired, status only", "Fatal"],
+                0x7: ["OS Watchdog pre-timeout Interrupt, non-NMI", "Fatal"]
+            },
+            0x12: {  // System Event
+                0x0: "System Reconfigured",
+                0x1: "OEM System Boot Event",
+                0x2: ["Undetermined system hardware failure", "Fatal"],
+                0x3: ["Entry added to Auxiliary Log", "Degraded"],
+                0x4: ["PEF Action", "Degraded"],
+                0x5: "Timestamp Clock Synch"
+            },
+            0x13: {  // Critical Interrupt
+                0x0: ["Front Panel NMI / Diagnostic Interrupt", "Fatal"],
+                0x1: ["Bus Timeout", "Fatal"],
+                0x2: ["I/O channel check NMI", "Fatal"],
+                0x3: ["Software NMI", "Fatal"],
+                0x4: ["PCI PERR", "Fatal"],
+                0x5: ["PCI SERRt", "Fatal"],
+                0x6: ["EISA Fail Safe Timeout", "Fatal"],
+                0x7: ["Bus Correctable Error", "Fatal"],
+                0x8: ["Bus Uncorrectable Error", "Fatal"],
+                0x9: ["Fatal NMI (port 61h, bit 7)", "Fatal"],
+                0xA: ["Bus Fatal Error", "Fatal"],
+                0xB: ["Bus Degraded", "Fatal"]
+            },
+            0x14: {  // Button / Switch
+                0x0: "Power Button pressed",
+                0x1: "Sleep Button pressed",
+                0x2: "Reset Button pressed",
+                0x3: "FRU latch open",
+                0x4: "FRU service request button"
+            },
+            0x19: {  // Chip Set
+                0x0: ["Soft Power Control Failure", "Fatal"],
+                0x1: ["Thermal Trip", "Fatal"]
+            },
+            0x1B: {  // Cable / Interconnect
+                0x0: "Cable/Interconnect is connected",
+                0x1: ["Configuration Error - Incorrect cable connected / Incorrect interconnection", "Fatal"],
+            },
+            0x1D: {  // System Boot / Restart Initiated
+                0x0: ["Initiated by power up", "Fatal"],
+                0x1: ["Initiated by hard reset", "Fatal"],
+                0x2: ["Initiated by warm reset", "Fatal"],
+                0x3: ["User requested PXE boot", "Fatal"],
+                0x4: "Automatic boot to diagnostic",
+                0x5: ["OS / run-time software initiated hard reset", "Fatal"],
+                0x6: ["OS / run-time software initiated warm reset", "Fatal"],
+                0x7: ["System Restart", "Fatal"],
+            },
+            0x1E: {  // Boot Error
+                0x0: ["No bootable media", "Degraded"],
+                0x1: ["Non-bootable diskette left in drive", "Degraded"],
+                0x2: ["PXE Server not found", "Fatal"],
+                0x3: ["Invalid boot sector", "Fatal"],
+                0x4: ["Timeout waiting for user selection of boot source", "Fatal"],
+            },
+            0x1F: {  // Base OS Boot / Installation Status
+                0x0: "A: boot completed",
+                0x1: "C: boot completed",
+                0x2: "PXE boot completed",
+                0x3: "Diagnostic boot completed",
+                0x4: "CD-ROM boot completed",
+                0x5: "ROM boot completed",
+                0x6: "boot completed - boot device not specified",
+                0x7: "Base OS/Hypervisor Installation started",
+                0x8: "Base OS/Hypervisor Installation completed",
+                0x9: ["Base OS/Hypervisor Installation aborted", "Fatal"],
+                0xA: ["Base OS/Hypervisor Installation failed", "Fatal"]
+            },
+            0x20: {  // OS Stop / Shutdown
+                0x0: ["Critical stop during OS load / initialization", "Fatal"],
+                0x1: ["Run-time Critical Stop", "Fatal"],
+                0x2: "OS Graceful Stop",
+                0x3: "OS Graceful Shutdown",
+                0x4: "Soft Shutdown initiated by PEF",
+                0x5: ["Agent Not Responding", "Fatal"]
+            },
+            0x21: {  // Slot / Connector
+                0x0: ["Fault Status asserted", "Fatal"],
+                0x1: "Identify Status asserted",
+                0x2: "Slot / Connector Device installed/attached",
+                0x3: "Slot / Connector Ready for Device Installation",
+                0x4: "Slot/Connector Ready for Device Removal",
+                0x5: "Slot Power is Off",
+                0x6: "Slot / Connector Device Removal Request",
+                0x7: ["Interlock asserted", "Degraded"],
+                0x8: "Slot is Disabled",
+                0x9: ["Slot holds spare device", "Fatal"]
+            },
+            0x22: {  // System ACPI Power State
+                0x0: "S0 / G0 \"working\"",
+                0x1: "S1 \"sleeping with system h/w & processor context maintained\"",
+                0x2: "S2 \"sleeping, processor context lost\"",
+                0x3: "S3 \"sleeping, processor & h/w context lost, memory retained.\"",
+                0x4: "S4 \"non-volatile sleep / suspend-to disk\"",
+                0x5: "S5 / G2 \"soft-off\"",
+                0x6: "S4 / S5 soft-off, particular S4 / S5 state cannot be determined",
+                0x7: "G3 / Mechanical Off",
+                0x8: "Sleeping in an S1, S2, or S3 states",
+                0x9: "G1 sleeping",
+                0xA: "S5 entered by override",
+                0xB: "Legacy ON state",
+                0xC: "Legacy OFF state",
+                0xE: ["Unknown", "Fatal"]
+            },
+            0x23: {  // Watchdog 2
+                0x0: ["Timer expired, status only", "Non-Fatal"],
+                0x1: ["Hard Reset", "Fatal"],
+                0x2: ["Power Down", "Fatal"],
+                0x3: ["Power Cycle", "Fatal"],
+                0x8: ["Timer interrupt", "Fatal"]
+            },
+            0x24: {  // Platform Alert
+                0x0: ["platform generated page", "Non-Fatal"],
+                0x1: ["platform generated LAN alert", "Non-Fatal"],
+                0x2: ["platform Event Trap generated", "Non-Fatal"],
+                0x3: ["platform generated SNMP trap", "Non-Fatal"]
+            },
+            0x25: {  // Entity Presence
+                0x0: "Entity Present",
+                0x1: "Entity Absent",
+                0x2: "Entity Disabled"
+            },
+            0x27: {  // LAN
+                0x0: ["LAN Heartbeat Lost", "Fatal"],
+                0x1: "LAN Heartbeat"
+            },
+            0x28: {  // Management Subsystem Health
+                0x0: ["sensor access degraded or unavailable", "Fatal"],
+                0x1: ["controller access degraded or unavailable", "Fatal"],
+                0x2: ["management controller off-line", "Fatal"],
+                0x3: ["management controller unavailable", "Fatal"],
+                0x4: ["Sensor failure", "Fatal"],
+                0x5: ["FRU failure", "Fatal"]
+            },
+            0x29: {  // Battery
+                0x0: ["battery low (predictive failure)", "Fatal"],
+                0x1: ["battery failed", "Fatal"],
+                0x2: "battery presence detected"
+            },
+            0x2A: {  // Session Audit
+                0x0: "Session Activated",
+                0x1: "Session Deactivated",
+                0x2: ["Invalid Username or Password", "Non-Fatal"],
+                0x3: ["Invalid password disable", "Non-Fatal"],
+            },
+            0x2B: {  // Version Change
+                0x0: "Hardware change detected with associated Entity",
+                0x1: "Firmware or software change detected with associated Entity",
+                0x6: "Hardware Change detected with associated Entity was successful",
+                0x7: "Software or F/W Change detected with associated Entity was successful",
+                0x2: ["Hardware incompatibility detected with associated Entity", "Fatal"],
+                0x3: ["Firmware or software incompatibility detected with associated Entity", "Fatal"],
+                0x4: ["Entity is of an invalid or unsupported hardware version", "Fatal"],
+                0x5: ["Entity contains an invalid or unsupported firmware or software version", "Fatal"]
+            },
+            0x2C: {  // FRU State
+                0x0: ["FRU Not Installed", "Fatal"],
+                0x1: "FRU Inactive (in standby or \"hot spare\" state)",
+                0x2: "FRU Activation Requested",
+                0x3: "FRU Activation In Progress",
+                0x4: "FRU Active",
+                0x5: "FRU Deactivation Requested",
+                0x6: "FRU Deactivation In Progress",
+                0x7: ["FRU Communication Lost", "Fatal"]
+            }
+        }
+    }
+};
+
+
+function getSelDescription(sel_data){
+    var sel_description_string = "";
+    var severity = "Healthy";
+    try{
+        var event_data = [sel_data[13], sel_data[14], sel_data[15]];
+        var sensor_type = sel_data[10];
+
+        var this_entry;
+
+        var generator_id = sel_data[7];
+        var event_reading_type = sel_data[12] & 0x7f;
+        var event_asserted = (sel_data[12] >> 7) == 0;
+        var event_reading_type_string = getStringFromIdList(event_reading_type_list, event_reading_type);
+
+        if (event_reading_type in event_reading_type_states){
+            this_entry = event_reading_type_states[event_reading_type];
+
+            if ("sensor_type" in this_entry){
+                if (sensor_type in this_entry["sensor_type"]){
+                    this_entry = this_entry["sensor_type"][sensor_type]
+                }
+            }
+
+            if (typeof this_entry == "string"){
+                sel_description_string += this_entry;
+            } else if (typeof this_entry == "object") {
+                var event_data_offset = event_data[0] & 0xf;
+
+                if (event_data_offset in this_entry){
+                    var sensor_entity = this_entry[event_data_offset];
+                    if (typeof sensor_entity == "object"){
+                        // only apply the severity string if event was asserted
+                        // all deassertion events are considered "healthy"
+                        if (event_asserted) {
+                            severity = sensor_entity[1];
+                        }
+                        sel_description_string += sensor_entity[0];
+                    } else if (typeof sensor_entity == "string"){
+                        sel_description_string += sensor_entity;
+                    } else if (typeof sensor_entity == "function"){
+                        sel_description_string += this_handler(generator_id, sensor_type, event_data_offset, event_data)
+                    }
+                }
+            }
+        }
+
+        if (event_asserted){
+            sel_description_string += " - Asserted";
+        } else {
+            sel_description_string += " - Deasserted";
+        }
+    } catch(err) {
+        console.log("SEL decode died with error " + err)
+    }
+    return [sel_description_string, severity];
+}
+
+function parseHexString(str) { 
+    var result = [];
+    while (str.length >= 2) { 
+        result.push(parseInt(str.substring(0, 2), 16));
+        str = str.substring(2, str.length);
+    }
+    return result;
+};
+
+function getStringFromIdList(generator_id, generators_list){
+    var generator_string = null;
+    for (var generator_index = 0; generator_index < generators_list.length; generator_index++){
+        this_generator_entry = generators_list[generator_index];
+        var generator_id = generator_id & 0xFF;
+        // range based match
+        if (this_generator_entry.length === 3){
+            if (generator_id >= this_generator_entry[0] && 
+                generator_id <= this_generator_entry[1]){
+                    generator_string = this_generator_entry[2];
+                    break;
+            }
+        } else {
+            // exact match
+            if (generator_id == this_generator_entry[0]){
+                generator_string = this_generator_entry[1];
+                break
+            }
+        }
+    }
+    
+    if (generator_string == null){
+        generator_string = "(0X"
+        generator_string += ("00" + this_entry.generator_id.toString(16)).substr(-2).toUpperCase();
+        generator_string += ")"
+    }
+    return generator_string;
+};
+
+function get_sensor_names_from_sdr(sdr_list){
+    var sdr_names = {};
+
+    for (var sdr_index = 0; sdr_index < sdr_list.length; sdr_index++) {
+        var this_sdr = parseHexString(sdr_list[sdr_index].raw_data);
+
+        var sdr_type = this_sdr[3];
+        var owner = this_sdr[5];
+        var string_offset = null;
+        if (sdr_type == 0x01){
+            string_offset = 47;
+        } else if (sdr_type == 0x02){
+            string_offset = 31;
+        } else if (sdr_type == 0x02){
+            string_offset = 16;
+        }
+        if (string_offset !== null){
+            var type_length_code = this_sdr[string_offset];
+            var type_code = type_length_code >> 6;
+            var length = type_length_code & 0x3F;
+            var string_name = "";
+            var sensor_number = 0;
+            if (type_code == 0x03){
+                sensor_number = this_sdr[7];
+                for (var string_index = 0; string_index < length; string_index++){
+                    var this_character = this_sdr[string_offset + 1 + string_index];
+                    var character = String.fromCharCode(this_character);
+                    string_name += character;
+                }
+            }
+            sdr_names[(owner << 8) + sensor_number] = string_name;
+        }
+    
+    }
+    return sdr_names;
+}
+
+
+angular.module('bmcApp').controller('selController', function($scope, Restangular) {
+
+    var sdr_promise = Restangular.all('sdrentries').getList();
+    var sel_promise = Restangular.all('selentries').getList();
+    
+    //wait for all the requests to finish
+    Promise.all([sdr_promise, sel_promise])  
+    .then(function(values) {
+        
+
+        sdr_entries_incoming = values[0];
+        sel_entries_incoming = values[1];
+
+        var sensor_names = get_sensor_names_from_sdr(sdr_entries_incoming);
+
+        $scope.sel_entries.length = 0;
+        // TODO don't generate so many extra entries
+        for (var i = 0; i < 20; i++){
+            for (var entry_index = 0; entry_index < sel_entries_incoming.length; entry_index++) {
+                this_entry = new Object();
+                raw_sel = parseHexString(sel_entries_incoming[entry_index]["raw_data"])
+                
+                this_entry.id = (raw_sel[1] << 8) + raw_sel[0];
+                this_entry.generator_id = raw_sel[7];
+                this_entry.channel_number = raw_sel[8] >> 4;
+                this_entry.sensor_number = raw_sel[11];
+                this_entry.lun = raw_sel[8] & 0x03;
+                this_entry.timestamp = (raw_sel[6] << 24) + (raw_sel[5] << 16) + (raw_sel[4] << 8) + raw_sel[3];
+                this_entry.sensor_type_id = raw_sel[10];
+
+                this_entry.generator_name = getStringFromIdList(this_entry.generator_id, generators_list);
+                this_entry.sensor_type_string = getStringFromIdList(this_entry.sensor_type_id, sensor_type_list);
+                sel_description = getSelDescription(raw_sel);
+                this_entry.description_string = sel_description[0];
+                this_entry.event_severity = sel_description[1];
+
+                var sensor_uid = (this_entry.generator_id << 8) + this_entry.sensor_number;
+                if (sensor_uid in sensor_names){
+                    this_entry.sensor_name = sensor_names[sensor_uid];
+                } else {
+                    this_entry.sensor_name = "Unknown";
+                }
+
+                $scope.sel_entries.push(this_entry);
+            }
+        }
+
+        var unique_controllers = {};
+        for( var sel_index in $scope.sel_entries ){
+            unique_controllers[$scope.sel_entries[sel_index].generator_name] = 0;
+        }
+        var unique_controller_names = [];
+        for(var key in unique_controllers){
+            unique_controller_names.push(key);
+        }
+
+        $scope.unique_columns["controller"] = unique_controller_names;
+    });
+
+
+    $scope.filtered_sel = [];
+    $scope.filtered_and_sliced_sel = [];
+    $scope.sel_entries = [];
+    $scope.current_page = 1;
+    $scope.items_per_page = 10;
+    $scope.max_size = 5;
+    $scope.unique_columns = {"controller": []};
+    $scope.selectedColumns = {"controller": []};
+
+    onPageChange =  function() { 
+        var begin = (($scope.current_page - 1) * $scope.items_per_page)
+        , end = begin + $scope.items_per_page;
+        $scope.filtered_and_sliced_sel = $scope.filtered_sel.slice(begin, end)
+    };
+    
+    onFilterChange =  function() {           
+        var filtered_sel = [];
+        var sel_entries = $scope.sel_entries;
+        if ($scope.selectedColumns["controller"].length == 0){
+            filtered_sel = $scope.sel_entries;
+        } else {
+            for(var sel_entry_index = 0; sel_entry_index < sel_entries.length; sel_entry_index++){
+                entry = sel_entries[sel_entry_index];
+                for (var controller_index = 0; controller_index < $scope.selectedColumns["controller"].length; controller_index++){
+                    controller = $scope.selectedColumns["controller"][controller_index];
+                    if (angular.equals(entry.generator_name, controller)) {
+                        filtered_sel.push(entry);
+                        break;
+                    }
+                }
+            }
+        }
+
+        $scope.filtered_sel = filtered_sel;
+        onPageChange();
+    };
+
+    $scope.$watch('current_page + items_per_page ', onPageChange);
+    $scope.$watch('selectedColumns', onFilterChange, true /*deep*/);
+    $scope.$watchCollection('sel_entries', onFilterChange);
+
+    $scope.setSelectedController = function () {
+        var id = this.company;
+        if (_.contains($scope.selectedColumns["controller"], id)) {
+            $scope.selectedColumns["controller"] = _.without($scope.selectedColumns["controller"], id);
+        } else {
+            $scope.selectedColumns["controller"].push(id);
+        }
+        return false;
+    };
+
+    $scope.isChecked = function (id) {
+        if (_.contains($scope.selectedColumns["controller"], id)) {
+            return 'fa fa-check pull-right';
+        }
+        return false;
+    };
+
+    $scope.checkAll = function () {
+        $scope.selectedColumns["controller"] = $scope.unique_columns["controller"];
+    };
+
+    $scope.uncheckAll = function () {
+        $scope.selectedColumns["controller"] = [];
+    };
+});
\ No newline at end of file