// Notes : // Sortable date/time pattern. 2009-06-15T13:45:30 culture invariant, standard ISO 8601 // Universal sortable date/time pattern. 2009-06-15 20:45:30Z culture invariant, must be in UTC // General date/time pattern (long time). 15/06/2009 13:45:30 locale dependent, such as (es-ES) // // Excel date-time formats supported // 3/14/01 13:30 if for en-US // private bool bParseSerOneDataLine(string strInputLine) { bool bResult = true; // first add this data line to microcontroller serial port log file EXACTLY as it was sent to us // this will include data packets AND any non-data messages and errors too bLogDataToFile(strInputLine); if (true == m_dataparser.bParseOneDataLine(strInputLine)) { // get new data element Generic12Vbattery.strctBattMonData stNewBattDataPacket = m_dataparser.stbtGetParsedData(); // enqueue new element m_frmBattMon.cnquBattDataQueue.Enqueue(stNewBattDataPacket); // count this as good iteration m_slLogIterCnt += 1; Debug.WriteLine("Ser_Port_Listener::bParseSerOneDataLine(->{" + stNewBattDataPacket.dblBatVolts.ToString("0.#;0") + "V," + stNewBattDataPacket.dblBatAmperes.ToString("+#.#;-#.#;0") + "A}; len=" + m_frmBattMon.cnquBattDataQueue.Count.ToString() + ")"); } else { // count this as an error iteration // tell Form1 that we did get an error reading battery data packet m_frmBattMon.m_lSerPortErrCnt += 1; Debug.WriteLine("Ser_Port_Listener::bParseSerOneDataLine(ERROR or non-data line) {" + strInputLine + "}"); }; return(bResult); } // end of bParseSerOneDataLine()
public bool bAddBattDataToChart(Generic12Vbattery.strctBattMonData stOneNewBattDataPacket) { bool bRes = false; bAddDataTo_V_A_Chart(CurrentVoltageChart, CurrentVoltageChart.Series[0], CurrentVoltageChart.Series[1], stOneNewBattDataPacket); return(bRes); }
public bool bValuateBatteryDataViaForm(Generic12Vbattery.strctBattMonData stNewBattData, int ciIterationNo) { bool bRes = false; bRes = m_batBattery.bValuateBatteryData(stNewBattData, ciIterationNo); // also save this new battery data paket as most recent in form1 m_stRecentBattData = stNewBattData; return(bRes); }
// private static string szDateTimePatternISO8601Sortable = @"yyyy-MM-ddTHH:mm:ss.fff"; public bool bLogDataToCSVFile(Generic12Vbattery.strctBattMonData stGivenBattData, int iChrgLvl) { bool bResult = false; string strOneLineToLog = string.Empty; if (true == bLoggingToFile) { if (null == m_OutCSVfile) { // open file if not currently open m_OutCSVfile = new System.IO.StreamWriter(szBatMonCSVFileName, true); } ; // log to file, format if needed // datetime,volts,apmps,t°C,{D|I|C},milliCoulombsIn, milliCoulombsOut,report reason #if ISO8601OUT // ISO 8601 sortable format // strOneLineToLog="\"" + dtNowDateTime.ToString(szDateTimePatternISO8601Sortable)+ "." + dtNowDateTime.Millisecond; #else // format date-time per Excel custom date-time format specification, supplied as argument strOneLineToLog = "\"" + stGivenBattData.dtBattDateTime.ToString(szDateTimePatternExcelCstm); #endif strOneLineToLog += "\",\""; strOneLineToLog += stGivenBattData.dblBatVolts.ToString() + "\",\""; strOneLineToLog += stGivenBattData.dblBatAmperes.ToString("+#.#;-#.#;0") + "\",\""; strOneLineToLog += stGivenBattData.dblBattTemp.ToString("+#.#;-#.#;0") + "\",\""; strOneLineToLog += stGivenBattData.chBattState + "\",\""; strOneLineToLog += iChrgLvl + "\",\""; strOneLineToLog += stGivenBattData.liQIn + "\",\""; strOneLineToLog += stGivenBattData.liQOut + "\""; // print entire line to the log file // will be like his : "19-12-2013 17:36:01.34.nnn","12.4","-0.3","13.6","D","99","67868","78979" m_OutCSVfile.WriteLine(strOneLineToLog); // close file every 25 write to avoid data loss if reset if (m_slMeasIterCnt > 0 && m_slMeasIterCnt % 25 == 0) { m_OutCSVfile.Flush(); m_OutCSVfile.Close(); m_OutCSVfile.Dispose(); m_OutCSVfile = null; } ; } ; return(bResult); } // end of bLogDataToCSVFile
// private void FromFileRadioButton1_CheckedChanged(object sender, EventArgs e) { Debug.WriteLine("++Form1::OnFromFileRadioButton1()"); int iFromRecordedFuelGaugeLvl = -1; int iFuelGaugeLvl_D = -1; int iFuelGaugeLvl_NL = -1; int iFuelGaugeLvl_C = -1; // if selected if (true == FromFileRadioButton1.Checked) { if (true == bIsRunning) { // stop if running bOnStopMonitoring(true); // disable start button } ; StartStopButton.Enabled = false; SerPortNameTextBox.Enabled = false; this.Text = "Battery Monitor - Recorded data; file "; // clear chart // CurrentVoltageChart.Series.Clear(); // clear data stored in voltage and current series CurrentVoltageChart.Series[0].Points.Clear(); CurrentVoltageChart.Series[1].Points.Clear(); // then restore zoom window view of X axis // load data from file into chart StreamReader strmReader = null; OpenFileDialog openFileDialog1 = new OpenFileDialog(); if (strPreviousOpenedFileDir.Length != 0) { openFileDialog1.InitialDirectory = strPreviousOpenedFileDir; // path as in "c:\\" ; openFileDialog1.RestoreDirectory = true; } ; // open CFile dialog and navigate to batt_mon log file on PC openFileDialog1.Filter = "Batt mon log files (*.log)|*.log|All files (*.*)|*.*"; openFileDialog1.FilterIndex = 1; openFileDialog1.RestoreDirectory = true; // OR read from SD card from arduino microcontroller if (openFileDialog1.ShowDialog() == DialogResult.OK) { Debug.WriteLine("Form1::OnFromFileRadioButton1() CFile dialog : file selected=" + openFileDialog1.FileName.ToString()); try { strmReader = new StreamReader(openFileDialog1.FileName); if (null != strmReader) { batt_data_parser prsDataparser = new batt_data_parser(); Debug.WriteLine("Form1::OnFromFileRadioButton1() Opened file " + openFileDialog1.FileName.ToString() + " ok."); this.Text += openFileDialog1.SafeFileName; // save folder name of successfully opened file strPreviousOpenedFileDir = System.IO.Path.GetDirectoryName(openFileDialog1.FileName); using (strmReader) { // store the current battery information for later comparison int iCurrNumOfDischChrgCycles = m_batBattery.iGetNumStartingCycles(); String strOneDatapacketFromFile = null; int iLineCntr = 0; int iErrorCntFromFile = 0; ErrorCountTextBox.Text = " "; // start busy cursor // Cursor.Current = Cursors.WaitCursor; UseWaitCursor = true; // clear out SoC bar indicators iUpdate3ChangePcntBars(0, 0, 0); ChargeProgressBarD.BackColor = Color.Gray; ChargeProgressBarNL.BackColor = Color.Gray; ChargeProgressBarC.BackColor = Color.Gray; // code to read the stream here. while (strmReader.Peek() >= 0) { strOneDatapacketFromFile = strmReader.ReadLine().ToString(); if (strOneDatapacketFromFile.Length > 0) { // Debug.WriteLine("Form1::OnFromFileRadioButton1() Line: ["+iLineCntr.ToString() + "] " +strOneDatapacketFromFile); // parse one data packet into fields if (true == prsDataparser.bParseOneDataLine(strOneDatapacketFromFile)) { // if fields are okay, then feed chart series with it m_stRecentBattData = prsDataparser.stbtGetParsedData(); bAddBattDataToChart(m_stRecentBattData); // be sure we process starter mtr load case if there is one m_batBattery.bValuateBatteryData(m_stRecentBattData, iLineCntr); // and then update text fields for R and CA accordingly iLineCntr += 1; if (iLineCntr % 100 == 0) { Debug.WriteLine("Form1::OnFromFileRadioButton1() Added " + iLineCntr.ToString() + " Data packets"); // Debug.WriteLine("Form1::OnFromFileRadioButton1() Batt average current="+m_batBattery.getLastAveCurrent().ToString("+0.0;-0.0;0")+" A"); } ; // update counts live on the form m_slMeasIterCnt += 1; IterCntTextBox.Text = m_slMeasIterCnt.ToString(); // determine SoC level and battery state iFromRecordedFuelGaugeLvl = iGetBattLifePrc(); // update SoC bar indicators accordingly switch (m_stRecentBattData.chBattState) { case 'D': if (-1 != iFromRecordedFuelGaugeLvl) { iFuelGaugeLvl_D = iFromRecordedFuelGaugeLvl; } break; case 'I': if (-1 != iFromRecordedFuelGaugeLvl) { iFuelGaugeLvl_NL = iFromRecordedFuelGaugeLvl; } break; case 'C': if (-1 != iFromRecordedFuelGaugeLvl) { iFuelGaugeLvl_C = iFromRecordedFuelGaugeLvl; } break; default: Debug.WriteLine("Form1::OnFromFileRadioButton1() Chrg% error! Unknown battery state " + m_stRecentBattData.chBattState); break; } ; if (iLineCntr % 10 == 0) { iUpdate3ChangePcntBars(iFuelGaugeLvl_C, iFuelGaugeLvl_NL, iFuelGaugeLvl_D); System.Threading.Thread.Sleep(10); } ; } else { // data bad, ignore iErrorCntFromFile += 1; Debug.WriteLine("Form1::OnFromFileRadioButton1() Failed to parse Line: [" + iLineCntr.ToString() + "] " + strOneDatapacketFromFile); ErrorCountTextBox.Text = iErrorCntFromFile.ToString(); // count errors }; } ; // end IF of if(strOneDatapacketFromFile.Length // Release build only // add some responsiveness Application.DoEvents(); } ; // end of while(strmReader.Peek()) // end busy cursor // Cursor.Current = Cursors.Default; UseWaitCursor = false; // we finished adding data from file. We may get new discharge-charge cycles added, so Debug.WriteLine("Form1::OnFromFileRadioButton1() Finished reading batery data from " + openFileDialog1.FileName.ToString()); Debug.WriteLine("Form1::OnFromFileRadioButton1() Processed " + iLineCntr.ToString() + " lines of data."); Debug.WriteLine("Form1::OnFromFileRadioButton1() Found " + iErrorCntFromFile.ToString() + " errors."); string strTemp = null; strTemp = "Finished reading batery data from " + openFileDialog1.FileName.ToString() + "\r\n"; strTemp += "Processed " + iLineCntr.ToString() + " lines of data.\r\n"; strTemp += "Found " + iErrorCntFromFile.ToString() + " errors.\r\n"; int iNumOfNewDchrgChrgCyles = m_batBattery.iGetNumStartingCycles() - iCurrNumOfDischChrgCycles; // tell user what kind of information was added to our battery class instance if (iNumOfNewDchrgChrgCyles > 0) { Debug.WriteLine("Form1::OnFromFileRadioButton1() Added " + iNumOfNewDchrgChrgCyles.ToString() + " new discharge-charge cycles."); strTemp += "Added " + iNumOfNewDchrgChrgCyles.ToString() + " new discharge-charge cycles."; } else { Debug.WriteLine("Form1::OnFromFileRadioButton1() Did not find any new discharge-charge cycles."); strTemp += " Did not find any new discharge-charge cycles."; }; MessageBox.Show(strTemp); // update listbox from discharge-charge cycles array bUpdateListBoxAndCntFromMmapDschrgChrgCycles(); // once all data are added, resize X axis zoom and scale bResizeXAxisAndZoom(CurrentVoltageChart, CurrentVoltageChart.Series[0]); // and also update R and CA if there was any starting cycle detected if (true == m_batBattery.bWasEngineStarted()) { R_Ohm_TextBox1.Text = "<=" + m_batBattery.dblGetBattInternalResistance().ToString("0.000"); CA_textBox2.Text = ">=" + m_batBattery.dblGetBattCA().ToString("#") + " A"; // at " + stcBattDatStarterOff.dblBattTemp.ToString("+#;-#;0")+ "°C"; } ; // Debug.WriteLine("Form1::OnFromFileRadioButton1() Batt Current ave="+m_batBattery.getLastAveCurrent().ToString("+#.#;-#.#;0")); }; // end of using(strmReader) } else { Debug.WriteLine("Form1::OnFromFileRadioButton1() FAILED to open file " + openFileDialog1.FileName.ToString() + " !"); }; } catch (Exception ex) { MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); }; } else { Debug.WriteLine("Form1::OnFromFileRadioButton1() CFile dialog CANCELLed"); }; } ; Debug.WriteLine("--Form1::OnFromFileRadioButton1()"); } // end of FromFileRadioButton1_CheckedChanged()
// updates combined voltage and current chart series1 is Volts, series2 is Amperes // uses microcontroller supplied date-time // X axis fo chart must be DateTime data type private bool bAddDataTo_V_A_Chart(Chart chrtOneChart, Series sCurrent, Series sVoltage, Generic12Vbattery.strctBattMonData stBattDataPckt) { bool bRes = true; // Debug.WriteLine("++Form1::bAddDataTo_V_A_Chart()"); // obtain a reference to given data series if (null == sVoltage || null == sCurrent) { Debug.WriteLine("Form1::bAddDataTo_V_A_Chart() error - null series!"); bRes = false; } else { // now add {date-time, U,I and t°} as new data point, separately to current and voltage graphs sCurrent.Points.AddXY(stBattDataPckt.dtBattDateTime, stBattDataPckt.dblBatAmperes); sVoltage.Points.AddXY(stBattDataPckt.dtBattDateTime, stBattDataPckt.dblBatVolts); }; return(bRes); } // end of bAddDataTo_V_A_Chart()