| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945 | using System;using System.Collections.Generic;namespace Comal.Classes.Entities.GPSTracker{    internal class GPSTrackerTools    {        /*        function decode()        {            let stream = document.getElementById("encoded").value.trim();                let num_messages = stream.split("0255").length - 1;            let messages = stream.split("0255");            messages.shift();                let decoded_messages = [num_messages];                for (let i = 0; i < num_messages; i++)            {                let byte_stream = [];                                        if (isHex(stream))                {                    byte_stream = getHex("0255" + messages[i]);                }                    let decoded_object = parseOysterGSM(byte_stream);                                    decoded_messages.push(decoded_object);            }                decoded_messages.shift();                            if (decoded_messages.includes(null))                document.getElementById("decoded").innerHTML = "Invalid stream";            else if (decoded_messages.includes(false))                document.getElementById("decoded").innerHTML = "Using deprecated fields";            else                document.getElementById("decoded").innerHTML = JSON.stringify(decoded_messages, null, 2);        }        */        public string[] Decode(string payload)        {            var results = new List<string>();            var messages = payload.Split(new[] { "0255" }, StringSplitOptions.RemoveEmptyEntries);            foreach (var message in messages)            {                //if (IsHex(message))                //{                //    byte[] bytes = GetHex(String.Concat("0255", message));                //    String result = parseOysterGSM(bytes);                //    results.Add(result);                //}            }            return results.ToArray();        }        /*        function isHex(value)        {            if (value.length == 0)                return false;                if (value.startsWith('0x') || value.startsWith('0X'))            {                value = value.substring(2);            }                let reg_exp = /^[0 - 9a - fA - F] +$/;                if (reg_exp.test(value) && value.length % 2 == 0)            {                return true;            }            else            {                return false;            }        }        */        /*        function getHex(value)        {            if (value.startsWith('0x') || value.startsWith('0X'))            {                value = value.substring(2);            }                let num_bytes = value.length / 2;            let bytes = [];                for (let i = 0; i < num_bytes; i++)            {                bytes.push(parseInt(value.substring(i * 2, (i * 2) + 2), 16));            }                return bytes;        }        */    }}/*        <script>            function parseOysterGSM(buffer)            {                if (buffer == null)                    return null;                let message_type = buffer[2];                switch (message_type)                {                    case 0: //hello request                        return parseHelloRequest(buffer);                    case 1: //hello response                        return parseHelloResponse(buffer);                    case 4: //data record upload                        return parseRecordUpload(buffer);                                            case 5: //commit request                        return parseCommitRequest(buffer);                    case 6: //commit response                        return parseCommitResponse(buffer);                    case 14: //canned response 1 - not being used                        return null                    case 22: //canned response 2 - not being used                        return null                    default:                        return null;                }            }            function parseLittleEndianInt32(buffer, offset)            {                return (buffer[offset + 3] << 24) +                    (buffer[offset + 2] << 16) +                    (buffer[offset + 1] << 8) +                    (buffer[offset]);            }            function parseLittleEndianInt16(buffer, offset)            {                let result = (buffer[offset + 1] << 8) + buffer[offset];                if ((result & 0x8000) > 0)                    result = result - 0x10000;                return result;            }            function parseHexToASCII(buffer, start, end)             {                let sub_array = buffer.slice(start, end);                let result = '';                for (let i = 0; i < sub_array.length; i++)                result += String.fromCharCode(sub_array[i]);                return result;            }            function parseDecToHex(buffer)            {                let hex_result = '';                buffer.forEach(element => {                    hex_result += element.toString(16);                });                return hex_result;            }            function parseDecToBin(buffer)            {                let bin_result = parseInt(buffer).toString(2);                return bin_result;            }            function parseSliceInt(value, start, length)            {                let binary = parseInt(value).toString(2).padStart(8,"0").slice(start, start + length);                                if (binary.includes("1"))                {                    return parseInt(binary, 2);                }                return 0;            }            function parseSliceInt16(value, start, length)            {                let binary = parseInt(value).toString(2).padStart(16,"0").slice(start, start + length);                                if (binary.includes("1"))                {                    return parseInt(binary, 2);                }                return 0;            }            function parseGPSData(value)            {                let utc_date_time = parseLittleEndianInt32(value, 0);                let latitude = parseLittleEndianInt32(value, 4);                let longitude = parseLittleEndianInt32(value, 8);                let altitude = parseLittleEndianInt16(value, 12);                let ground_speed = parseLittleEndianInt16(value, 14);                let speed_accuracy_estimate = value[16];                let heading = value[17];                let pdop = value[18];                let position_accuracy_estimate = value[19];                let status_flags = parseDecToBin(value[20]);                return {                    UTCDateTime: utc_date_time,                    Latitude: latitude,                    Longitude: longitude,                    Altitude: altitude,                    GroundSpeed: ground_speed,                    SpeedAccuracyEstimate: speed_accuracy_estimate,                    Heading: heading,                    PDOP: pdop,                    PositionAccuracyEstimate: position_accuracy_estimate,                    StatusFlags: status_flags                }            }            function parseDebugEvent(length, value)            {                let severity = parseSliceInt(value[0], 6, 2);                let module_id = parseSliceInt(value[0], 1, 5);                let event_code = value[1];                let ascii_debug_string = parseHexToASCII(value, 2, length);                return {                    Severity: severity,                    ModuleID: module_id,                    EventCode: event_code,                    ASCIIDebugString: ascii_debug_string                }            }            function parseDigitalData(value)            {                let digital_inputs = parseLittleEndianInt32(value, 0);                let digital_outputs = parseLittleEndianInt16(value, 4);                let status_flags = parseDecToBin(parseLittleEndianInt16(value, 6));                return {                    DigitalInputs: digital_inputs,                    DigitalOutputs: digital_outputs,                    StatusFlags: status_flags                }            }            function parseDriverOperatorID(length, value)            {                let driver_id_type = value[0];                let driver_id_data = ''                                if (driver_id_type == 1 || driver_id_type == 2)                {                    driver_id_data = value.slice(1, length - 1);                }                else{                    driver_id_data = parseHexToASCII(value, 1, length);                }                return {                    DriverIDType: driver_id_type,                    DriverIDData: driver_id_data                }            }            function parseSDI12Identification(length, value)            {                let device_address = value[0];                let sdi12_identification = parseHexToASCII(value, 1, length);                return {                    DeviceAddress: device_address,                    SDI12Identification: sdi12_identification                }            }            function parseSDI12Measurement(length, value)            {                let sdi12_measurement_type = value[0];                let measurements = [];                for (let i = 0; i < length; i += 4)                {                    measurements.push(parseLittleEndianInt32(value, 1 + i ));                }                return {                    SDI12MeasurementType: sdi12_measurement_type,                    Measurements: measurements                }            }            function parseINT16AnalogueData(length, value)            {                let analogue_objects = []                for (let i = 0; i < length; i+=3)                {                    let current_analogue_number = value[i];                    let current_analogue_value = parseLittleEndianInt16(value, 1 + i);                    let current_analogue_object = {                        AnalogueNumber: current_analogue_number,                        Value: current_analogue_value                    }                    analogue_objects.push(current_analogue_object);                }                return {                    INT16AnalogueData: analogue_objects                }            }            function parseINT32AnalogueData(length, value)            {                let analogue_objects = []                for (let i = 0; i < length; i+=5)                {                    let current_analogue_number = value[i];                    let current_analogue_value = parseLittleEndianInt32(value, 1 + i);                    let current_analogue_object = {                        AnalogueNumber: current_analogue_number,                        Value: current_analogue_value                    }                    analogue_objects.push(current_analogue_object);                }                return {                    INT32AnalogueData: analogue_objects                }            }            function parseDevice3rdPartyAsyncMessage(value)            {                let hex_result = parseDecToHex(value);                return {                    Device3rdPartyAsyncMessage: hex_result                }            }            function parseProjectCode(value)            {                let ascii_project_code = parseHexToASCII(value);                return {                    ProjectCode: ascii_project_code                }            }            function parseTripTypeCode(value)            {                let ascii_trip_type_code = parseHexToASCII(value);                return {                    TripTypeCode: ascii_trip_type_code                }            }            function parseDeviceTripTypeAndData(value)            {                let device_trip_type = value[0];                let movement_trip_trimming_amount = parseLittleEndianInt16(value, 1);                return {                    DeviceTripType: device_trip_type,                    MovementTripTrimmingAmount: movement_trip_trimming_amount                }            }            function parseGarminFMIStopResponse(value)            {                let message_id = parseLittleEndianInt32(value, 0);                let message_response = value[4];                return {                    MessageID: message_id,                    MessageResponse: message_response                }            }            function parseAccelerometerTraceHeader(value)            {                let accident_id = parseLittleEndianInt32(value, 0);                let force_matrix = [3][3];                let force_counter = 4;                                for (let i = 0; i < 3; i++)                {                    for (let j = 0; j < 3; j++)                    {                        force_matrix[i][j] = parseLittleEndianInt32(value, force_counter);                        force_counter += 4;                    }                }                let filter_pole = parseLittleEndianInt32(value, 40);                let filter_gain = parseLittleEndianInt32(value, 44);                let final_input = [3];                for (let i = 0; i < 3; i++)                {                    final_input.push(parseLittleEndianInt16(value, 48 + i*2));                }                let trigger_point_in_samples = parseLittleEndianInt16(value, 54);                let number_of_samples = parseLittleEndianInt16(value, 56);                return {                    AccidentID: accident_id,                    ForceMatrix: force_matrix,                    FilterPole: filter_pole,                    FilterGain: filter_gain,                    FinalInput: final_input,                    TriggerPointInSamples: trigger_point_in_samples,                    NumberSamples: number_of_samples                }            }            function parseAccelerometerTraceSampples(length, value)            {                let accident_id = parseLittleEndianInt32(value, 0);                let num_samples = (length - 4) / 6;                let samples = [num_samples][3];                let sample_counter = 2;                for (let i = 0; i < num_samples; i++)                {                    for (let j = 0; j < 3; j++)                    {                        samples[i][j] = parseLittleEndianInt16(value, force_counter);                        sample_counter += 2;                    }                }                return {                    AccidentID: accident_id,                    Samples: samples                }            }            function parseAccidentData(value)            {                let accident_id = parseLittleEndianInt32(value, 0);                let gps_utc_date_time = parseLittleEndianInt32(value, 4);                let latitude = parseLittleEndianInt32(value, 8);                let longitude = parseLittleEndianInt32(value, 12);                let altitude = parseLittleEndianInt16(value, 16);                let ground_speed = parseLittleEndianInt16(value, 18);                let speed_accuracy_estimate = value[20];                let heading = value[21];                let pdop = value[22];                let position_accuracy_estimate = value[23];                let gps_status_flags = parseDecToBin(value[24]);                let max_x_delta_velocity = parseSliceInt16(parseLittleEndianInt16(value, 25), 0, 10);                let max_y_delta_velocity = parseSliceInt16(parseLittleEndianInt16(value, 26), 2, 10);                let max_z_delta_velocity = parseSliceInt16(parseLittleEndianInt16(value, 27), 4, 10);                let delta_orientation = parseSliceInt16(parseLittleEndianInt16(value, 28), 6, 1);                return {                    AccidentID: accident_id,                    GPSUTCDateTime: gps_utc_date_time,                    Latitude: latitude,                    Longitude: longitude,                    Altitude: altitude,                    GroundSpeed: ground_speed,                    SpeedAccuracyEstimate: speed_accuracy_estimate,                    Heading: heading,                    PDOP: pdop,                    PositionAccuracyEstimate: position_accuracy_estimate,                    GPSStatusFlags: gps_status_flags,                    MaximumXDeltaVelocity: max_x_delta_velocity,                    MaximumYDeltaVelocity: max_y_delta_velocity,                    MaximumZDeltaVelocity: max_z_delta_velocity,                    DeltaOrientation: delta_orientation                }            }            function parseProfileCounterID(id)            {                switch(id)                {                    case 0: return "Internal Battery Voltage"                    case 1: return "Internal Battery"                    case 2: return "Est. Battery Capacity Used"                    case 3: return "Maximum Temperature"                    case 4: return "Initial Internal Battery Voltage"                    case 5: return "Average Successful GPS Fix Time"                    case 6: return "Average Failed GPS Fix Time"                    case 7: return "Average GPS Freshen Time"                    case 8: return "Average Wakeups Per Trip"                    case 128: return "Successful Uploads"                    case 129: return "Successful Upload Time"                    case 130: return "Failed Uploads"                    case 131: return "Failed Upload Time"                    case 132: return "Successful GPS Fixes"                    case 133: return "Successful GPS Fix Time"                    case 134: return "Failed GPS Fixes"                    case 135: return "Failed GPS Fix Time"                    case 136: return "GPS Freshen Attempts"                    case 137: return "GPS Freshen Time"                    case 138: return "Accelerometer Wakeups"                    case 139: return "Trips"                    case 140: return "GPS Fixes Due to ‘Upload on Jostle’"                    case 141: return "Uploads Due to ‘Upload on Jostle’"                    case 142: return "Uptime"                    case 143: return "Tx Count"                    case 144: return "Rx Count"                    case 145: return "Successful Wifi Scans"                    case 146: return "Failed Wifi Scans"                    default: return "Unknown ID"                }            }            function parseProfilingCounters(length, value)            {                let counter = 0;                let profiling_counters = [];                while (counter != length)                {                    let counter_id = value[counter];                    let counter_id_description = parseProfileCounterID(counter_id);                                        counter++;                    let counter_value = null;                    let counter_id_top_bit = parseInt(parseInt(counter_id).toString(2).padStart(8, "0").slice(0, 1), 2);                    if (counter_id_top_bit == 0)                    {                        counter_value = parseLittleEndianInt16(value, counter)                        counter += 2;                    }                    else                    {                        counter_value = parseLittleEndianInt32(value, counter)                        counter += 4;                    }                    profiling_counters.push([counter_id, counter_id_description, counter_value]);                }                return {                    ProfilingCounterPairs: profiling_counters                }            }            function parseHighGEvent(value)            {                let peak_g_force = parseLittleEndianInt16(value, 0);                let avg_abs_g_force = parseLittleEndianInt16(value, 2);                let duration = parseLittleEndianInt16(value, 4);                return {                    PeakGForce: peak_g_force,                    AverageAbsoluteGForce: avg_abs_g_force,                    Duration: duration                }            }            function parseWiFiLocationScan(length, value)            {                let mac_address_array = [];                let signal_strength_array = [];                let channel_num_array = [];                let data_field_length = 8;                let max_entries = 30;                for (let iteration = 0; iteration < length / data_field_length; iteration++)                {                    if (iteration > max_entries) break;                    let mac_address = [6];                    for (let i = 0; i < 6; i++)                    {                        mac_address[i] = parseDecToHex(value[i + iteration * data_field_length]);                    }                    let signal_strength = value[6 + iteration * data_field_length];                    let channel_num = parseSliceInt(value[7 + iteration * data_field_length], 0, 4);                    mac_address_array.push(mac_address);                    signal_strength_array.push(signal_strength);                    channel_num_array.push(channel_num);                }                return {                    MACAddress: mac_address_array,                    SignalStrength: signal_strength_array,                    ChanelNum: channel_num_array                }            }            function parseTripOdometerRunHours(value)            {                let trip_distance = parseLittleEndianInt32(value, 0);                let trip_run_hours = parseLittleEndianInt32(value, 4);                return {                    TripDistance: trip_distance,                    TripRunHours: trip_run_hours                }            }            function parseDeviceOdometerRunHours(length, value)            {                let device_odo = parseLittleEndianInt32(value, 0);                let run_hours = parseLittleEndianInt32(value, 4);                if (length == 12)                {                    let secondary_run_hours = parseLittleEndianInt32(value, 8);                    return {                        DeviceOdo: device_odo,                        RunHours: run_hours,                        SecondaryRunHours: secondary_run_hours                    }                }                return {                    DeviceOdo: device_odo,                    RunHours: run_hours                }            }            function parseCellTowerScan(length, value)            {                let cell_id_array = [];                let location_area_code_array = [];                let mobile_country_code_array = [];                let mobile_network_code_array = []                let data_field_length = 10;                let max_entries = 20;                for (let iteration = 0; iteration < length / data_field_length; iteration++)                {                    if (iteration > max_entries) break;                    let cell_id = parseLittleEndianInt32(value, 0 + iteration * data_field_length);                    let location_area_code = parseLittleEndianInt16(value, 4 + iteration * data_field_length);                    let mobile_country_code = parseLittleEndianInt16(value, 6 + iteration * data_field_length);                    let mobile_network_code = parseLittleEndianInt16(value, 8 + iteration * data_field_length);                    cell_id_array.push(cell_id);                    location_area_code_array.push(location_area_code);                    mobile_country_code_array.push(mobile_country_code);                    mobile_network_code_array.push(mobile_network_code);                }                return {                    CellID: cell_id_array,                    LocationAreaCode: location_area_code_array,                    MobileCountryCode: mobile_country_code_array,                    MobileNetworkCode: mobile_network_code_array                }            }            function parseDataField(id, length, value)            {                switch(id)                {                    case 0: //GPS Data                        return parseGPSData(value);                    case 1: //Debug Event                        return parseDebugEvent(length, value);                    case 2: //Digital Data                        return parseDigitalData(value);                    case 3: //Driver or Operator ID                        return parseDriverOperatorID(length, value);                    case 4: //SDI-12 Device Identification                        return parseSDI12Identification(length, value);                    case 5: //SDI-12 Measurement                        return parseSDI12Measurement(length, value);                    case 6: //INT16 Analogue Data                        return parseINT16AnalogueData(length, value);                    case 7: //INT32 Analogue Data                        return parseINT32AnalogueData(length, value);                    case 9: //Device 3rd Party Async Message                        return parseDevice3rdPartyAsyncMessage(value);                    case 10: //Project Code                        return parseProjectCode(value);                    case 11: //Trip Type Code                        return parseTripTypeCode(value);                    case 12: //Not implemented due to lack of use                        return null                    case 13: //RF Tag data - Deprecated                        return false                                        case 14: //RF Tag Lost - Deprecated                        return false                    case 15: //Device Trip Type and Data                        return parseDeviceTripTypeAndData(value);                    case 16: //Garmin FMI Stop Response                        return parseGarminFMIStopResponse(value);                    case 17: //Accident Data                        return parseAccidentData(value);                                        case 18: //Accelerometer Trace Header                        return parseAccelerometerTraceHeader(value);                    case 19: //Accelerometer Trace Samples                        return parseAccelerometerTraceSampples(length, value);                    case 20: //V5 RF Message - Functionality no longer offered                        return false                    case 21: //Profiling Counters                        return parseProfilingCounters(length, value);                    case 22: //Not currently required                        return null                    case 23: //Deprecated                        return false                    case 24: //High-G Event                        return parseHighGEvent(value);                                        case 25: //WiFi Location Scan                        return parseWiFiLocationScan(length, value);                    case 26: //Trip Odometer, Run Hours                        return parseTripOdometerRunHours(value);                    case 27: //Device Odometer, Run Hours                        return parseDeviceOdometerRunHours(length, value);                    case 28: //Cell Tower Scan                        return parseCellTowerScan(length, value);                                        default:                        return null;                }            }            //Test: 02550031009CFC0100333539363836303735383531303431003839343034373030303030303037373639313435003A01010400000000            function parseHelloRequest(buffer)            {                let sync_chars = "0" + parseDecToHex([buffer[0], buffer[1]]);                let message_type = buffer[2];                let payload_length = parseLittleEndianInt16(buffer, 3);                let serial_num = parseLittleEndianInt32(buffer, 5);                let imei = parseHexToASCII(buffer, 9, 24);                let sim_iccid = parseHexToASCII(buffer, 25, 45);                let product_id = buffer[46];                let hardware_rev = buffer[47];                let firmware_major = buffer[48];                let firmware_minor = buffer[49];                let flags = parseDecToBin(parseLittleEndianInt32(buffer, 50));                return {                    SyncChars: sync_chars,                    MessageType: message_type,                    PayloadLength: payload_length,                    SerialNum: serial_num,                    IMEI: imei,                    SIMICCID: sim_iccid,                    ProductID: product_id,                    HardwareRev: hardware_rev,                    FirmwareMajor: firmware_major,                    FirmwareMinor: firmware_minor,                    Flags: flags                };            }            //Test: 0255010800677C370200000000            function parseHelloResponse(buffer)            {                let sync_chars = "0" + parseDecToHex([buffer[0], buffer[1]]);                let message_type = buffer[2];                let payload_length = parseLittleEndianInt16(buffer, 3);                let utc_date_time = parseLittleEndianInt32(buffer, 5);                let flags = parseDecToBin(parseLittleEndianInt32(buffer, 9));                return {                    SyncChars: sync_chars,                    MessageType: message_type,                    PayloadLength: payload_length,                    UTCDateTime: utc_date_time,                    Flags: flags                };            }            //Test (single record): 0255043D003d004746000096D684020b001502D48402F043F4EC2A6909452B001F00050011230302080000000000000A00060F041D0001FE0F021E0005000003BF08            //Test (multiple record): 0255047A003d004746000096D684020b001502D48402F043F4EC2A6909452B001F00050011230302080000000000000A00060F041D0001FE0F021E0005000003BF083d004746000096D684020b001502D48402F043F4EC2A6909452B001F00050011230302080000000000000A00060F041D0001FE0F021E0005000003BF08            function parseRecordUpload(buffer)            {                let sync_chars = "0" + parseDecToHex([buffer[0], buffer[1]]);                let message_type = buffer[2];                let payload_length = parseLittleEndianInt16(buffer, 3);                                let iterated_payload_length = 0;                let record_objects = [];                                while (iterated_payload_length < payload_length)                {                    let record_length = parseLittleEndianInt16(buffer, 5 + iterated_payload_length);                    let record_seq_num = parseLittleEndianInt32(buffer, 7 + iterated_payload_length);                    let record_rtc_date_time = parseLittleEndianInt32(buffer, 11 + iterated_payload_length);                    let record_log_reason = buffer[15 + iterated_payload_length];                    let record_keys = [];                    let record_values = [];                    let record_current_length = 11;                    let record_data_fields = [];                    let record_parsed_data_fields = [];                    while (record_current_length < record_length)                    {                        let data_field_id = buffer[record_current_length + 5 + iterated_payload_length];                        let data_field_length = buffer[record_current_length + 6 + iterated_payload_length];                        if (data_field_length == 255)                        {                            data_field_length = parseLittleEndianInt16(buffer, record_current_length + 7 + iterated_payload_length);                            record_current_length += 2;                        }                        record_keys.push([data_field_id, data_field_length]);                        record_current_length += 2;                        let current_values = [];                        for (let i = 0; i < data_field_length; i++)                        {                            current_values.push(buffer[record_current_length + 5 + i + iterated_payload_length])                        }                        record_values.push(current_values);                        record_current_length += data_field_length;                        record_data_fields.push([[data_field_id, data_field_length], current_values]);                        record_parsed_data_fields.push(parseDataField(data_field_id, data_field_length, current_values));                    }                    let record = {                        Length: record_length,                        SequenceNumber: record_seq_num,                        RTCDateTime: record_rtc_date_time,                        LogReason: record_log_reason,                        DataFields: record_parsed_data_fields                    }                    record_objects.push(record)                                        iterated_payload_length += record_length;                }                return {                    SyncChars: sync_chars,                    MessageType: message_type,                    PayloadLength: payload_length,                    Records: record_objects                };            }            //Test: 0255050000            function parseCommitRequest(buffer)            {                let sync_chars = "0" + parseDecToHex([buffer[0], buffer[1]]);                let message_type = buffer[2];                let payload_length = parseLittleEndianInt16(buffer, 3);                return {                    SyncChars: sync_chars,                    MessageType: message_type,                    PayloadLength: payload_length,                }            }            //Test: 025506010001            function parseCommitResponse(buffer)            {                let sync_chars = "0" + parseDecToHex([buffer[0], buffer[1]]);                let message_type = buffer[2];                let payload_length = parseLittleEndianInt16(buffer, 3);                let flags = parseDecToBin(buffer[5]);                return {                    SyncChars: sync_chars,                    MessageType: message_type,                    PayloadLength: payload_length,                    Flags: flags                }            }            //Test (combined): 02550031009CFC0100333539363836303735383531303431003839343034373030303030303037373639313435003A010104000000000255010800677C3702000000000255047A003d004746000096D684020b001502D48402F043F4EC2A6909452B001F00050011230302080000000000000A00060F041D0001FE0F021E0005000003BF083d004746000096D684020b001502D48402F043F4EC2A6909452B001F00050011230302080000000000000A00060F041D0001FE0F021E0005000003BF080255050000025506010001        </script>    </body></html> */
 |