| 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>
 
-  */
 
 
  |