using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Diagnostics; namespace SBD_Parser { public partial class Form1 : Form { //Global Variables byte[] bytesRead; int totalBits = 8; int latbits = 0, longbits = 0, yearbits = 0, daybits = 0, hourbits = 0, minbits = 0, supplyvbits = 0, adc1bits = 0, adc2bits = 0, gpio1bits = 0, gpio2bits = 0, accxbits = 0, accybits = 0, acczbits = 0, tempbits = 0, gyroxbits = 0, gyroybits = 0, gyrozbits = 0; List filenames; int filecount = 0; StringBuilder sb = new StringBuilder(); string savepath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); public Form1() { InitializeComponent(); InitializeValues(); } private void InitializeValues() { //Initialize global variables and UI components totalBits = 8; filenames = new List(10); openFileDialog1.InitialDirectory = (string)Properties.Settings.Default["DefaultFilePath"]; filecount = 0; cmbHeaders.Items.Add(Properties.Settings.Default["Header1"]); cmbHeaders.Items.Add(Properties.Settings.Default["Header2"]); cmbHeaders.Items.Add(Properties.Settings.Default["Header3"]); cmbHeaders.SelectedIndex = 0; txtHeader.Text = cmbHeaders.SelectedItem.ToString(); SetBitsToRead(); sfdKML.Filter = "KML Files (*.kml)|*.kml"; sfdCSV.Filter = "CSV Files (*.csv)|*.csv"; } void SetBitsToRead() { //Initializes the number of bits corresponding to each data field latbits =(int)Properties.Settings.Default["latbits"]; longbits = (int)Properties.Settings.Default["longbits"]; yearbits = (int)Properties.Settings.Default["yearbits"]; daybits = (int)Properties.Settings.Default["daybits"]; hourbits = (int)Properties.Settings.Default["hourbits"]; minbits = (int)Properties.Settings.Default["minbits"]; supplyvbits = (int)Properties.Settings.Default["supplyvbits"]; adc1bits = (int)Properties.Settings.Default["adc1bits"]; adc2bits = (int)Properties.Settings.Default["adc2bits"]; gpio1bits = (int)Properties.Settings.Default["gpio1bits"]; gpio2bits = (int)Properties.Settings.Default["gpio2bits"]; accxbits = (int)Properties.Settings.Default["accxbits"]; accybits = (int)Properties.Settings.Default["accybits"]; acczbits = (int)Properties.Settings.Default["acczbits"]; tempbits =(int)Properties.Settings.Default["tempbits"]; gyroxbits = (int)Properties.Settings.Default["gyroxbits"]; gyroybits = (int)Properties.Settings.Default["gyroybits"]; gyrozbits = (int)Properties.Settings.Default["gyrozbits"]; } private void ReadFromFile(string filename) { //Reads the file a byte at a time and stores it in a //byte array called bytesRead int length = 0; txtBinary.Clear(); totalBits = 8; try { using (BinaryReader b = new BinaryReader(File.Open(filename, FileMode.Open))) { int pos = 0; length = (int)b.BaseStream.Length; bytesRead = new byte[length]; int i = 0; txtBinary.Text += "Number of Bytes : " + length.ToString() + "\r\n\r\n"; while (pos < length) { //Reading the file data byte by byte by reading a byte sized portion of the stream and //saving the data into the byte array byte v = b.ReadByte(); bytesRead[i] = v; pos += sizeof(byte); i++; } } //Calls the GetBinaryValues() function to display the bytes read //in their binary form GetBinaryBytes(bytesRead, length); } catch (Exception ex) { MessageBox.Show(ex.Message); } //Call to GetDataValues() to parse the file and display the data GetDataValues(); } private void GetBinaryBytes(byte[] bytesRead, int length) { //Displays the binary values of the bytes in the file for (int i = 0; i < bytesRead.Length; i++) { string s = Convert.ToString(bytesRead[i], 2); s = s.PadLeft(8, '0'); txtBinary.Text += s + "\r\n"; } } private int ReadBitValues(int bitstoread) { //Logic: //The no of bits to be read is added to a integer called total bits //which is the total no of bits read from readbytes til now. It starts at 8 //to account for the 8 bits in the header //bytesread is a byte array containing all the bytes read from the file //Find remainder and quotient of totalbits / 8 (q and r respectively) //m= bitstoread/8. it represents the no of bytes to read as such if r=0 //If r = 0, we have to start reading from the start of a byte in bytesread //This start byte will be bytesread[q-1] //returnval, the value to be returned is initally 0 //So, read a byte from the readbytes and add it to returnval. If there is another byte to be added to //returnval, leftshift returnval 8 bits and add the next byte to is. Continue this for all values of m //Then check if there are any more bits to be added to returnval by checking the value of //rem=bitstoread=(m*8). If there is, left shift returnval by rem bits and add the remaining value //The remaining value is found by &ing the byte bytesread[q-m-1] with revleftbits[rem] which //reveals rem no of bits on the left of the byte. revleftbits is an array of bytes. revleftbits[5] //will be the byte value corresponding to 11111000. ie itll be a byte with i no of bits on the right //Now if r!=0, that means we have to read a few bits form a byte in readbytes . That byte will be //readbytes[q]. First check if the no of bits to be read is smaller than r. If it is, all the //bits to be read will be in the same byte, bytesread[q]. So filter out the bits by &ing the //byte with revrightbits[r]. Revrightbits[i] represents a byte value that is essentially is a sequence of //1s(ones) till the value i. For ex. revrightbits[3] = 11100000. So &ing a byte with revrightbits gives u //the the i bits on the right side of the byte. So thats what I used to get the required byte. //Then rightshift the byte r-bitstoread times to get the value, since v r reading only bitstoread no of bits //and not r bits //Then follow the same procedure as the earlier case to get the full no of bits byte[] revrightbits = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; byte[] revleftbits = { 0, 128, 192, 224, 240, 248, 252, 254, 255 }; try { int returnval = 0; totalBits += bitstoread; int q = totalBits / 8; int r = totalBits % 8; int m = bitstoread / 8; if (r == 0) { for (int i = 0; i < m; i++) { returnval = returnval << 8; returnval += bytesRead[q - 1 - i]; } int rem = bitstoread - (m * 8); returnval = returnval << rem; byte rembyte = (byte)(bytesRead[q - m - 1] & (revleftbits[rem])); rembyte = (byte)(rembyte >> (8 - rem)); returnval += rembyte; return rembyte; } else { if (r < bitstoread) returnval = (byte)(bytesRead[q] & revrightbits[r]); else { byte returnbits = (byte)(bytesRead[q] & revrightbits[r]); returnval = returnbits >> (r - bitstoread); return returnval; } m = (bitstoread - r) / 8; for (int i = 0; i < m; i++) { returnval = returnval << 8; returnval += bytesRead[q - 1 - i]; } int rem = bitstoread - ((m * 8) + r); returnval = returnval << rem; byte rembyte = (byte)(bytesRead[q - m - 1] & (revleftbits[rem])); rembyte = (byte)(rembyte >> (8 - rem)); returnval += rembyte; return returnval; } } catch { //MessageBox.Show(ex.Message); } return 0; } private void GetDataValues() { //The first byte of the bytes read from the file (Header) //represents the data present in the stream //The 8 bits represent different types of data //If the bit is 1, the data is present. If 0, not present //This function checks each bit present in the header //if 1, it calls the ReadBitValue() function with an int argument //corresponding to the no of bits to be read. The totalbits integer //keeps track of how many bits have been read //ReadBitValue returns the integer value of the bits //It is then converted to the required value and displayed in the DataGridView dgvDataDisplay.Rows.Clear(); totalBits = 8; int i = 1; int bitval = 0; try { if ((bytesRead[0] & 1) == 1) { //GPS Informations bitval = ReadBitValues(latbits); double v = (bitval * .00018) - 90; AddToDGV(i++, "Latitude", v, bitval); bitval = ReadBitValues(longbits); v = (bitval * .00018) - 180; AddToDGV(i++, "Longitude", v, bitval); } if ((bytesRead[0] & 2) == 2) { //Additional GPS infromation //Year, Day, Hour, Minutes int year = 0, days = 0; bitval = ReadBitValues(yearbits); AddToDGV(i++, "Year", bitval + 2000, bitval); year = bitval + 2000; bitval = ReadBitValues(daybits); AddToDGV(i++, "Day", bitval, bitval); days = bitval; bitval = ReadBitValues(hourbits); AddToDGV(i++, "Hour", bitval, bitval); bitval = ReadBitValues(minbits); AddToDGV(i++, "Minute", bitval, bitval); DateTime dt = new DateTime(year, 1, 1); DateTime newDate = dt.AddDays(days - 1); AddToDGV(i++, "Date (mm/dd/yyyy)", newDate.Month.ToString() + "/" + newDate.Day.ToString() + "/" + newDate.Year.ToString(), 0); } if ((bytesRead[0] & 4) == 4) { //Supply Voltage (9 bits) bitval = ReadBitValues(supplyvbits); double v = (float)(bitval * 0.038672); v = Math.Round(v, 3); AddToDGV(i++, "Supply Voltage (ADC Ch 1)", v, bitval); } if ((bytesRead[0] & 8) == 8) { //ADC2 bitval = ReadBitValues(adc1bits); double v = (float)(3.3 * bitval / 4096); v = Math.Round(v, 3); AddToDGV(i++, "ADC Channel 2", v, bitval); } if ((bytesRead[0] & 16) == 16) { //ADC3 bitval = ReadBitValues(adc2bits); double v = (float)(3.3 * bitval / 4096); v = Math.Round(v, 3); AddToDGV(i++, "ADC Channel 3", v, bitval); } if ((bytesRead[0] & 32) == 32) { //GPIO 0 and 1 bitval = ReadBitValues(gpio1bits); AddToDGV(i++, "GPIO Channel 0", bitval, bitval); bitval = ReadBitValues(gpio2bits); AddToDGV(i++, "GPIO Channel 1", bitval, bitval); } if ((bytesRead[0] & 64) == 64) { //Accelelometer Data X Y, Z, and Temperature int newval = 0; bitval = ReadBitValues(accxbits); newval = bitval << 4; newval = GetTwosCompliment(bitval, 16); AddToDGV(i++, "ACC X", newval, bitval); bitval = ReadBitValues(accybits); newval = bitval << 4; newval = GetTwosCompliment(bitval, 16); AddToDGV(i++, "ACC Y", newval, bitval); bitval = ReadBitValues(acczbits); newval = bitval << 4; newval = GetTwosCompliment(newval, 16); AddToDGV(i++, "ACC X", newval, bitval); bitval = ReadBitValues(tempbits); newval = GetTwosCompliment(bitval, 8); AddToDGV(i++, "Temperature", newval + 23, bitval); } if ((bytesRead[0] & 128) == 128) { //Gyroscope Data X, Y, Z int newval = 0; bitval = ReadBitValues(gyroxbits); newval = GetTwosCompliment(bitval, gyroxbits); AddToDGV(i++, "GYRO X", newval, bitval); bitval = ReadBitValues(gyroybits); newval = GetTwosCompliment(bitval, gyroybits); AddToDGV(i++, "GYRO Y", newval, bitval); bitval = ReadBitValues(gyrozbits); newval = GetTwosCompliment(bitval, gyrozbits); AddToDGV(i++, "GYRO Z", newval, bitval); } } catch (Exception ex) { MessageBox.Show(ex.Message); } //For changing colour of alternate lines of the DataGridView this.dgvDataDisplay.RowsDefaultCellStyle.BackColor = Color.White; this.dgvDataDisplay.AlternatingRowsDefaultCellStyle.BackColor = Color.LightGray; this.dgvDataDisplay.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; //this.dgvDataDisplay.Columns[0].Width += 10; lstResults.Focus(); } private int GetTwosCompliment(int value, int noofbits) { //Returns the 2's complement value of the integer passed as argument if (value >> (noofbits - 1) == 1) return (int)(value - Math.Pow(2, noofbits)); else return (value); } private void AddToDGV(int index, string param, object v, int value) { //Adds the passed values to the DataGridView dgvDataDisplay.Rows.Add(index, param, v, value.ToString("X"), Convert.ToString(value, 2)); } private void Form1_Load(object sender, EventArgs e) { } private void opemToolStripMenuItem_Click(object sender, EventArgs e) { openFileDialog1.Filter = "All files (*.*)|*.*|sbd files (*.sbd)|(*.sbd)|txt files (*.txt)|*.txt"; openFileDialog1.Title = "Please select a file to Decode"; openFileDialog1.Multiselect = true; if (openFileDialog1.ShowDialog() == DialogResult.OK) { //filenames = new List(openFileDialog1.FileNames.Length); foreach (string fname in openFileDialog1.FileNames) { if (Path.GetExtension(fname) == ".sbd") { lstResults.Items.Add(Path.GetFileName(fname)); filenames.Add(fname); filecount++; } } if (filenames.Count > 0) { lstResults.SelectedIndex = 0; ReadFromFile(filenames[0]); } else { MessageBox.Show("Please select a valid file"); } } } private void setDefaultPathToolStripMenuItem_Click(object sender, EventArgs e) { if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) { Properties.Settings.Default["DefaultFilePath"] = folderBrowserDialog1.SelectedPath; openFileDialog1.InitialDirectory = (string)Properties.Settings.Default["DefaultFilePath"]; Properties.Settings.Default.Save(); } } private void lstResults_SelectedIndexChanged(object sender, EventArgs e) { ReadFromFile(filenames[lstResults.SelectedIndex]); } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { AboutBox ab = new AboutBox(); ab.ShowDialog(); } private void btnClear_Click(object sender, EventArgs e) { filenames.Clear(); filecount = 0; lstResults.Items.Clear(); } private void setHeadersToolStripMenuItem_Click(object sender, EventArgs e) { SetHeader h = new SetHeader(); h.ShowDialog(); } private void btnSaveFile_Click(object sender, EventArgs e) { if (txtFileName.Text != "") { try { sb.Append(txtHeader.Text + txtMessage.Text); using (StreamWriter outfile = new StreamWriter(savepath + @"\" + txtFileName.Text + ".sbd", true)) { outfile.Write(sb.ToString()); } sb.Length = 0; sb.Capacity = 0; } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { MessageBox.Show("Saved Successfully"); } } else { MessageBox.Show("Enter a file name"); } } private void cmbHeaders_SelectedIndexChanged(object sender, EventArgs e) { txtHeader.Text = cmbHeaders.SelectedItem.ToString(); } private void txtHeader_TextChanged(object sender, EventArgs e) { } private void setDefaultSavePathToolStripMenuItem_Click(object sender, EventArgs e) { if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) { Properties.Settings.Default["SaveFilePath"] = folderBrowserDialog1.SelectedPath; savepath = (string)Properties.Settings.Default["SaveFilePath"]; } } private void btnOpenSaveDirectory_Click(object sender, EventArgs e) { Process.Start(savepath); } private void lstResults_DragDrop(object sender, DragEventArgs e) { try { string[] files = (string[])(e.Data.GetData(DataFormats.FileDrop, false)); foreach (string fname in files) { if (Path.GetExtension(fname) == ".sbd") { lstResults.Items.Add(Path.GetFileName(fname)); filenames.Add(fname); filecount++; } } if (filenames.Count > 0) { lstResults.SelectedIndex = 0; ReadFromFile(filenames[0]); } else { MessageBox.Show("Please select a valid file"); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void lstResults_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.All; else e.Effect = DragDropEffects.None; } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit(); } private void saveToolStripMenuItem_Click(object sender, EventArgs e) { btnSaveFile.PerformClick(); } private void bitSettingsToolStripMenuItem_Click(object sender, EventArgs e) { BitSettings bs = new BitSettings(); bs.ShowDialog(); SetBitsToRead(); } private void lstResults_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)Keys.Delete) { if (lstResults.SelectedIndex > -1) { lstResults.ClearSelected(); } } } private void exportAsKMLToolStripMenuItem_Click(object sender, EventArgs e) { if (sfdKML.ShowDialog() == DialogResult.OK) { DataTable dtkml = new DataTable("KML"); dtkml.Columns.Add("Latitude"); dtkml.Columns.Add("Longitude"); for (int i = 0; i < lstResults.Items.Count; i++) { ReadFromFile(filenames[i]); if (bytesRead != null) { if ((bytesRead[0] & 1) == 1) { dtkml.Rows.Add(float.Parse(dgvDataDisplay.Rows[0].Cells[2].Value.ToString()), float.Parse(dgvDataDisplay.Rows[1].Cells[2].Value.ToString())); } } } if (dtkml != null && lstResults.Items.Count > 0) { XmlIO xmlio = new XmlIO(); xmlio.WriteKml(dtkml, sfdKML.FileName); MessageBox.Show("Saved Succesfully"); } else MessageBox.Show("Select atleast one file"); sfdKML.FileName = ""; } } private void exportAsCSVToolStripMenuItem_Click(object sender, EventArgs e) { if (sfdCSV.ShowDialog() == DialogResult.OK) { sb.AppendLine("File Name,Latitude,Longitude,Year,Day,Date,Hour,Minute,Supply Voltage (ADC Ch 1),ADC Channel 2,ADC Channel 3,GPIO Channel 1,GPIO Channel 2,ACC X,ACC Y,ACC Z,Temperature,GYRO X,GYRO Y,GYRO Z"); for (int i = 0; i < lstResults.Items.Count; i++) { ReadFromFile(filenames[i]); if (bytesRead != null) { string Latitude="",Longitude="",Year="",Day="", Date="",Hour="",Minute="",SupplyV="",ADC2="", ADC3="",GPIO0="",GPIO1="",ACCX="",ACCY="",ACCZ="",Temp="",GYROX="",GYROY="",GYROZ=""; for (int k = 0; k < dgvDataDisplay.Rows.Count; k++) { switch (dgvDataDisplay.Rows[k].Cells["Parameter"].Value.ToString()) { case "Latitude": Latitude = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "Longitude": Longitude = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "Year": Year = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "Day": Day = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "Date (mm/dd/yyyy)": Date = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "Hour": Hour = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "Minute": Minute = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "Supply Voltage (ADC Ch 1)": SupplyV = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "ADC Channel 2": ADC2 = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "ADC Channel 3": ADC3 = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "GPIO Channel 0": GPIO0 = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "GPIO Channel 1": GPIO1 = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "ACC X": ACCX = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "ACC Y": ACCY = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "ACC Z": ACCZ = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "Temperature": Temp = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "GYRO X": GYROX = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "GYRO Y": GYROY = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; case "GYRO Z": GYROZ = dgvDataDisplay.Rows[k].Cells["Value"].Value.ToString(); break; } } sb.AppendLine(filenames[i] +"," +Latitude + "," +Longitude+"," + Year+"," +Day+","+Date+"," +Hour+","+Minute+","+SupplyV+","+ADC2+","+ADC3+","+GPIO0+","+GPIO1+","+ACCX+","+ACCY+","+ACCZ+","+Temp+","+GYROX+","+GYROY+","+GYROZ); } } try { using (StreamWriter outfile = new StreamWriter(sfdCSV.FileName, true)) { outfile.Write(sb.ToString()); } sb.Length = 0; sb.Capacity = 0; } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { MessageBox.Show("Saved Successfully"); } sfdCSV.FileName = ""; } } private void btnLocOpenOnGoogleMaps_Click(object sender, EventArgs e) { try { if(dgvDataDisplay.Rows[0].Cells[1].Value.ToString() == "Latitude") Process.Start("http://maps.google.com/?q=" + dgvDataDisplay.Rows[0].Cells["Value"].Value.ToString() + "," + dgvDataDisplay.Rows[1].Cells["Value"].Value.ToString()); } catch { //MessageBox.Show(ex.Message); } } } }