[chronojump] runEncoder capture and minimal gui done!
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] runEncoder capture and minimal gui done!
- Date: Fri, 18 May 2018 07:43:00 +0000 (UTC)
commit d3a0254700e0ea2122a0d8bf7a84f468877b43d4
Author: Xavier de Blas <xaviblas gmail com>
Date: Fri May 18 09:41:56 2018 +0200
runEncoder capture and minimal gui done!
glade/app1.glade | 149 +++++++++++--
src/Makefile.am | 2 +
src/chronojump.cs | 5 +-
src/chronopicRegister.cs | 4 +-
src/constants.cs | 2 +-
src/forceSensor.cs | 2 +-
src/gui/chronojump.cs | 88 ++++++++
src/gui/chronopicRegister.cs | 3 +-
src/gui/forceSensor.cs | 2 +-
src/gui/runEncoder.cs | 492 ++++++++++++++++++++++++++++++++++++++++++
src/util.cs | 38 ++++
src/utilEncoder.cs | 13 +-
12 files changed, 771 insertions(+), 29 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index f2a8541..d0dfec5 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -422,6 +422,17 @@
</widget>
</child>
<child>
+ <widget class="GtkRadioMenuItem" id="radio_menuitem_mode_runs_encoder">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">Encoder races</property>
+ <property name="use_underline">True</property>
+ <property name="draw_as_radio">True</property>
+ <property name="group">radio_menuitem_mode_jumps_simple</property>
+ <signal name="activate" handler="on_radio_menuitem_mode_activate" swapped="no"/>
+ </widget>
+ </child>
+ <child>
<widget class="GtkSeparatorMenuItem" id="menuitem5">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -1727,6 +1738,9 @@
<placeholder/>
</child>
<child>
+ <placeholder/>
+ </child>
+ <child>
<widget class="GtkLabel"
id="label_start_selector_jumps">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -5595,6 +5609,39 @@ EncoderInertialCapture</property>
<property name="type">tab</property>
</packing>
</child>
+ <child>
+ <widget class="GtkHBox" id="hbox286">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <widget class="GtkLabel" id="label368">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">race encoder
stuff</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label367">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">runs encoder</property>
+ </widget>
+ <packing>
+ <property name="position">8</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="expand">False</property>
@@ -8308,6 +8355,39 @@ EncoderInertialCapture</property>
<property name="type">tab</property>
</packing>
</child>
+ <child>
+ <widget class="GtkHBox" id="hbox288">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <widget class="GtkLabel" id="label370">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">race encoder
stuff</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label369">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">runs
encoder</property>
+ </widget>
+ <packing>
+ <property name="position">8</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="expand">True</property>
@@ -12774,6 +12854,51 @@ EncoderInertialCapture</property>
<property name="type">tab</property>
</packing>
</child>
+ <child>
+ <widget class="GtkVBox" id="vbox132">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">8</property>
+ <child>
+ <widget class="GtkHBox" id="hbox290">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <widget class="GtkLabel" id="label372">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">race encoder
stuff</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label371">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">runs
encoder</property>
+ </widget>
+ <packing>
+ <property name="position">8</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="position">1</property>
@@ -19220,27 +19345,6 @@ Concentric</property>
<placeholder/>
</child>
<child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
<widget class="GtkLabel"
id="label_force_sensor_ai_rfd_a">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -27620,6 +27724,9 @@ then click this button.</property>
<child>
<placeholder/>
</child>
+ <child>
+ <placeholder/>
+ </child>
</widget>
<packing>
<property name="expand">False</property>
diff --git a/src/Makefile.am b/src/Makefile.am
index bd43bfa..a423bd9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,7 @@ SOURCES = \
gui/jumpType.cs\
gui/restTime.cs\
gui/run.cs\
+ gui/runEncoder.cs\
gui/runType.cs\
gui/reactionTime.cs\
gui/pulse.cs\
@@ -268,6 +269,7 @@ RESOURCES = \
../images/board-encoder.png,board-encoder.png \
../images/board-arduino-rfid.png,board-arduino-rfid.png \
../images/board-arduino-force.png,board-arduino-force.png \
+ ../images/board-arduino-run-encoder.png,board-arduino-run-encoder.png \
../images/chronojump-jumps-small.png,chronojump-jumps-small.png \
../images/chronojump-runs-small.png,chronojump-runs-small.png \
../images/chronojump-encoder-small.png,chronojump-encoder-small.png \
diff --git a/src/chronojump.cs b/src/chronojump.cs
index a96ceae..1c972ea 100644
--- a/src/chronojump.cs
+++ b/src/chronojump.cs
@@ -268,10 +268,11 @@ public class ChronoJump
//to store user videos and photos
Util.CreateMultimediaDirsIfNeeded();
- //to store encoder data and graphs
+
+ //to store (encoder, force sensor, run encoder) data and graphs
UtilEncoder.CreateEncoderDirIfNeeded();
- //to store force sensor data and graphs
Util.CreateForceSensorDirIfNeeded();
+ Util.CreateRunEncoderDirIfNeeded();
//TODO: when a session is deleted, encoder data has to be deleted, also multimedia videos, I suppose. Show
message to user warning about it
//TODO: encoder weight auto written depending on person loaded, and changes if it changes person or weight
diff --git a/src/chronopicRegister.cs b/src/chronopicRegister.cs
index 131ac08..45198a6 100644
--- a/src/chronopicRegister.cs
+++ b/src/chronopicRegister.cs
@@ -34,7 +34,7 @@ public class ChronopicRegisterPort
public string Port;
public bool FTDI;
public string SerialNumber;
- public enum Types { UNKNOWN, CONTACTS, ENCODER, ARDUINO_RFID, ARDUINO_FORCE }
+ public enum Types { UNKNOWN, CONTACTS, ENCODER, ARDUINO_RFID, ARDUINO_FORCE, ARDUINO_RUN_ENCODER }
public Types Type;
public bool ConnectedReal; //if connexion has been done by ChronopicInit.Do
@@ -76,6 +76,8 @@ public class ChronopicRegisterPort
return "RFID";
else if(typeStatic == Types.ARDUINO_FORCE)
return Catalog.GetString("Force sensor");
+ else if(typeStatic == Types.ARDUINO_RUN_ENCODER)
+ return "Run encoder (experimental)";
return Catalog.GetString("Unknown");
}
diff --git a/src/constants.cs b/src/constants.cs
index 0e383b2..67ec848 100644
--- a/src/constants.cs
+++ b/src/constants.cs
@@ -744,7 +744,7 @@ public class Constants
public enum Menuitem_modes {
UNDEFINED,
JUMPSSIMPLE, JUMPSREACTIVE,
- RUNSSIMPLE, RUNSINTERVALLIC,
+ RUNSSIMPLE, RUNSINTERVALLIC, RUNSENCODER,
POWERGRAVITATORY, POWERINERTIAL,
FORCESENSOR, RT, OTHER } //OTHER can be: Multichronopic, Pulse
diff --git a/src/forceSensor.cs b/src/forceSensor.cs
index 45301e6..c177449 100644
--- a/src/forceSensor.cs
+++ b/src/forceSensor.cs
@@ -570,7 +570,7 @@ public class ForceSensorGraph
scriptOptions +=
"\n#testLength\n" + testLength.ToString() + "\n" +
"#title\n" + title + "\n" +
- "#scriptsPath\n" + UtilEncoder.GetmifPath() + "\n";
+ "#scriptsPath\n" + UtilEncoder.GetScriptsPath() + "\n";
TextWriter writer = File.CreateText(Path.GetTempPath() + "Roptions.txt");
writer.Write(scriptOptions);
diff --git a/src/gui/chronojump.cs b/src/gui/chronojump.cs
index 05e346c..48dad27 100644
--- a/src/gui/chronojump.cs
+++ b/src/gui/chronojump.cs
@@ -54,6 +54,7 @@ public partial class ChronoJumpWindow
[Widget] Gtk.RadioMenuItem radio_menuitem_mode_jumps_reactive;
[Widget] Gtk.RadioMenuItem radio_menuitem_mode_runs_simple;
[Widget] Gtk.RadioMenuItem radio_menuitem_mode_runs_intervallic;
+ [Widget] Gtk.RadioMenuItem radio_menuitem_mode_runs_encoder;
[Widget] Gtk.RadioMenuItem radio_menuitem_mode_power_gravitatory;
[Widget] Gtk.RadioMenuItem radio_menuitem_mode_power_inertial;
[Widget] Gtk.RadioMenuItem radio_menuitem_mode_force_sensor;
@@ -501,6 +502,8 @@ public partial class ChronoJumpWindow
myType = currentRunType;
else if(current_menuitem_mode == Constants.Menuitem_modes.RUNSINTERVALLIC)
myType = currentRunIntervalType;
+ //else if(current_menuitem_mode == Constants.Menuitem_modes.RUNSENCODER)
+ // myType = currentRunIntervalType;
//else if(current_menuitem_mode == Constants.Menuitem_modes.FORCESENSOR
// myType = currentForceType;
else if(current_menuitem_mode == Constants.Menuitem_modes.RT)
@@ -802,6 +805,8 @@ public partial class ChronoJumpWindow
" " + ((Label) radio_menuitem_mode_runs_simple.Child).Text;
((Label) radio_menuitem_mode_runs_intervallic.Child).Text =
" " + ((Label) radio_menuitem_mode_runs_intervallic.Child).Text;
+ ((Label) radio_menuitem_mode_runs_encoder.Child).Text =
+ " " + ((Label) radio_menuitem_mode_runs_encoder.Child).Text;
((Label) radio_menuitem_mode_power_gravitatory.Child).Text =
" " + ((Label) radio_menuitem_mode_power_gravitatory.Child).Text;
@@ -1090,6 +1095,9 @@ public partial class ChronoJumpWindow
label_sprint_person_name.Text = string.Format(Catalog.GetString("Sprints of
{0}"), currentPerson.Name);
createTreeView_runs_interval_sprint (treeview_runs_interval_sprint);
}
+ //else if(current_menuitem_mode == Constants.Menuitem_modes.RUNSENCODER)
+ //{
+ //}
else if(current_menuitem_mode == Constants.Menuitem_modes.RT)
updateGraphReactionTimes();
@@ -2222,6 +2230,15 @@ public partial class ChronoJumpWindow
if(portFSOpened)
portFS.Close();
+ //cancel runEncoder capture process
+ if(capturingRunEncoder == runEncoderStatus.STARTING || capturingRunEncoder ==
runEncoderStatus.CAPTURING)
+ {
+ LogB.Information("cancelling runEncoder capture");
+ runEncoderProcessCancel = true;
+ }
+ if(portREOpened)
+ portRE.Close();
+
LogB.Information("Bye3!");
Log.End();
@@ -2259,6 +2276,9 @@ public partial class ChronoJumpWindow
modePrint = Catalog.GetString("Races simple");
else if(mode == Constants.Menuitem_modes.RUNSINTERVALLIC)
modePrint = Catalog.GetString("Races intervallic");
+ else if(mode == Constants.Menuitem_modes.RUNSENCODER)
+ //modePrint = Catalog.GetString("Races with encoder");
+ modePrint = "Races with encoder";
else if(mode == Constants.Menuitem_modes.POWERGRAVITATORY)
modePrint = Catalog.GetString("Encoder (gravitatory)");
else if(mode == Constants.Menuitem_modes.POWERINERTIAL)
@@ -3145,6 +3165,7 @@ public partial class ChronoJumpWindow
notebook_sup.CurrentPage = 0;
//notebook_capture_analyze.ShowTabs = true;
hbox_contacts_sup_capture_analyze_two_buttons.Visible = true;
+ button_threshold.Visible = true;
if(m == Constants.Menuitem_modes.JUMPSSIMPLE)
{
notebooks_change(m);
@@ -3173,6 +3194,7 @@ public partial class ChronoJumpWindow
notebook_sup.CurrentPage = 0;
//notebook_capture_analyze.ShowTabs = true;
hbox_contacts_sup_capture_analyze_two_buttons.Visible = true;
+ button_threshold.Visible = true;
button_inspect_last_test.Visible = true;
if(m == Constants.Menuitem_modes.RUNSSIMPLE)
@@ -3311,12 +3333,32 @@ public partial class ChronoJumpWindow
//notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid
for "OTHER" tests)
hbox_contacts_sup_capture_analyze_two_buttons.Visible = true;
+ button_threshold.Visible = false;
+ //notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
+ hbox_results_legend.Visible = false;
+
+ //on force sensor only show table
+ notebook_capture_graph_table.CurrentPage = 1; //"Show table"
+ notebook_capture_graph_table.ShowTabs = false;
+ }
+ else if(m == Constants.Menuitem_modes.RUNSENCODER)
+ {
+ notebook_sup.CurrentPage = 0;
+ radio_menuitem_mode_runs_encoder.Active = true;
+ notebooks_change(m);
+// on_extra_window_reaction_times_test_changed(new object(), new EventArgs());
+
+ //notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid
for "OTHER" tests)
+ hbox_contacts_sup_capture_analyze_two_buttons.Visible = false;
+ button_threshold.Visible = false;
//notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
hbox_results_legend.Visible = false;
+ /*
//on force sensor only show table
notebook_capture_graph_table.CurrentPage = 1; //"Show table"
notebook_capture_graph_table.ShowTabs = false;
+ */
}
else if(m == Constants.Menuitem_modes.RT)
{
@@ -3328,6 +3370,7 @@ public partial class ChronoJumpWindow
notebook_capture_analyze.CurrentPage = 0;
//notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid
for "OTHER" tests)
hbox_contacts_sup_capture_analyze_two_buttons.Visible = false;
+ button_threshold.Visible = true;
//notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
}
else { //m == Constants.Menuitem_modes.OTHER (contacts / other)
@@ -3339,6 +3382,7 @@ public partial class ChronoJumpWindow
notebook_capture_analyze.CurrentPage = 0;
//notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid
for "OTHER" tests)
hbox_contacts_sup_capture_analyze_two_buttons.Visible = false;
+ button_threshold.Visible = true;
//notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
}
@@ -3521,6 +3565,8 @@ public partial class ChronoJumpWindow
return Constants.Menuitem_modes.RUNSSIMPLE;
else if(radio_menuitem_mode_runs_intervallic.Active)
return Constants.Menuitem_modes.RUNSINTERVALLIC;
+ else if(radio_menuitem_mode_runs_encoder.Active)
+ return Constants.Menuitem_modes.RUNSENCODER;
else if(radio_menuitem_mode_power_gravitatory.Active)
return Constants.Menuitem_modes.POWERGRAVITATORY;
else if(radio_menuitem_mode_power_inertial.Active)
@@ -3584,6 +3630,13 @@ public partial class ChronoJumpWindow
else
radio_menuitem_mode_runs_intervallic.Active = true;
}
+ private void on_button_selector_start_runs_encoder_clicked(object o, EventArgs args)
+ {
+ if(radio_menuitem_mode_runs_encoder.Active)
+ select_menuitem_mode_toggled(Constants.Menuitem_modes.RUNSENCODER);
+ else
+ radio_menuitem_mode_runs_encoder.Active = true;
+ }
private void on_button_selector_start_encoder_clicked(object o, EventArgs args)
{
@@ -3812,6 +3865,12 @@ public partial class ChronoJumpWindow
forceProcessCancel = true;
return;
}
+ if(capturingRunEncoder == runEncoderStatus.STARTING || capturingRunEncoder ==
runEncoderStatus.CAPTURING)
+ {
+ LogB.Information("cancel clicked on runEncoder");
+ runEncoderProcessCancel = true;
+ return;
+ }
LogB.Information("cancel clicked one");
@@ -3848,6 +3907,13 @@ public partial class ChronoJumpWindow
forceProcessFinish = true;
return;
}
+ if(capturingRunEncoder == runEncoderStatus.STARTING || capturingRunEncoder ==
runEncoderStatus.CAPTURING)
+ {
+ LogB.Information("finish clicked on runEncoder");
+ runEncoderProcessFinish = true;
+ return;
+ }
+
LogB.Information("finish clicked one");
@@ -3910,6 +3976,16 @@ public partial class ChronoJumpWindow
on_buttons_force_sensor_clicked(button_execute_test, new EventArgs ());
return;
}
+ if(current_menuitem_mode == Constants.Menuitem_modes.RUNSENCODER)
+ {
+ LogB.Debug("radio_mode_runs_encoder");
+ /*
+ * runs encoder is not FTDI
+ */
+
+ on_runs_encoder_capture_clicked ();
+ return;
+ }
// stop capturing inertial on the background if we start capturing a contacts test
if(encoderThreadBG != null && encoderThreadBG.IsAlive)
@@ -4053,6 +4129,11 @@ public partial class ChronoJumpWindow
pixbuf = new Pixbuf (null, Util.GetImagePath(true) +
Constants.FileNameForceSensor);
button_image_test_zoom.Hide();
break;
+ case "RUNSENCODER":
+ //pixbuf = new Pixbuf (null, Util.GetImagePath(true) +
Constants.FileNameRunEncoder);
+ pixbuf = new Pixbuf (null, Util.GetImagePath(true) + "no_image.png");
+ button_image_test_zoom.Hide();
+ break;
case "":
pixbuf = new Pixbuf (null, Util.GetImagePath(true) + "no_image.png");
button_image_test_zoom.Hide();
@@ -6660,6 +6741,13 @@ LogB.Debug("X");
notebook_results.CurrentPage = 3;
changeTestImage(EventType.Types.RUN.ToString(),
currentRunIntervalType.Name, currentRunIntervalType.ImageFileName);
+ } else if(mode == Constants.Menuitem_modes.RUNSENCODER)
+ {
+ notebook_execute.CurrentPage = 8;
+ notebook_options_top.CurrentPage = 8;
+ notebook_results.CurrentPage = 8;
+ changeTestImage("", "", "RUNSENCODER");
+ event_execute_button_finish.Sensitive = false;
} else if(mode == Constants.Menuitem_modes.FORCESENSOR)
{
notebook_execute.CurrentPage = 4;
diff --git a/src/gui/chronopicRegister.cs b/src/gui/chronopicRegister.cs
index d66385d..bce77c6 100644
--- a/src/gui/chronopicRegister.cs
+++ b/src/gui/chronopicRegister.cs
@@ -27,7 +27,7 @@ using Mono.Unix;
public class TypePix
{
- public ChronopicRegisterPort.Types Type; //public enum Types { UNKNOWN, CONTACTS, ENCODER,
ARDUINO_FORCE, ARDUINO_RFID }
+ public ChronopicRegisterPort.Types Type; //public enum Types { UNKNOWN, CONTACTS, ENCODER,
ARDUINO_FORCE, ARDUINO_RFID, ARDUINO_RUN_ENCODER_ }
public Pixbuf Pix;
public TypePix(ChronopicRegisterPort.Types type, Pixbuf pix)
@@ -51,6 +51,7 @@ public static class TypePixList
l.Add(new TypePix(ChronopicRegisterPort.Types.ENCODER, new Pixbuf (null,
Util.GetImagePath(false) + "board-encoder.png")));
l.Add(new TypePix(ChronopicRegisterPort.Types.ARDUINO_FORCE, new Pixbuf (null,
Util.GetImagePath(false) + "board-arduino-force.png")));
l.Add(new TypePix(ChronopicRegisterPort.Types.ARDUINO_RFID, new Pixbuf (null,
Util.GetImagePath(false) + "board-arduino-rfid.png")));
+ l.Add(new TypePix(ChronopicRegisterPort.Types.ARDUINO_RUN_ENCODER, new Pixbuf (null,
Util.GetImagePath(false) + "board-arduino-run-encoder.png")));
}
public static Pixbuf GetPix(ChronopicRegisterPort.Types type)
diff --git a/src/gui/forceSensor.cs b/src/gui/forceSensor.cs
index 7d36db9..b33e1c8 100644
--- a/src/gui/forceSensor.cs
+++ b/src/gui/forceSensor.cs
@@ -1349,7 +1349,7 @@ LogB.Information(" fc R ");
button_image_test_zoom.Visible = ! modeForceSensor;
notebook_options_top.Visible = ! modeForceSensor;
- button_threshold.Visible = ! modeForceSensor;
+ //button_threshold.Visible = ! modeForceSensor;
menuitem_force_sensor_open_folder.Visible = modeForceSensor;
menuitem_force_sensor_check_version.Visible = modeForceSensor;
diff --git a/src/gui/runEncoder.cs b/src/gui/runEncoder.cs
new file mode 100644
index 0000000..ca658fc
--- /dev/null
+++ b/src/gui/runEncoder.cs
@@ -0,0 +1,492 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * ChronoJump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) 2018 Xavier de Blas <xaviblas gmail com>
+ */
+
+using System;
+using System.IO;
+using System.IO.Ports;
+using System.Threading;
+using Gtk;
+using Gdk;
+using Glade;
+using System.Text; //StringBuilder
+using System.Collections.Generic; //List<T>
+using Mono.Unix;
+
+
+public partial class ChronoJumpWindow
+{
+ Thread runEncoderCaptureThread;
+ static bool runEncoderProcessFinish;
+ static bool runEncoderProcessCancel;
+ static bool runEncoderProcessError;
+
+ static string lastRunEncoderFile = "";
+ static string lastRunEncoderFullPath = "";
+
+ //int usbDisconnectedCount;
+ //int usbDisconnectedLastTime;
+ /*
+ * runEncoderStatus:
+ * STOP is when is not used
+ * STARTING is while is waiting run encoder sensor to start capturing
+ * CAPTURING is when data is arriving
+ * COPIED_TO_TMP means data is on tmp and graph can be called
+ */
+ enum runEncoderStatus { STOP, STARTING, CAPTURING, COPIED_TO_TMP }
+ static runEncoderStatus capturingRunEncoder = runEncoderStatus.STOP;
+ /*
+ static bool redoingPoints; //don't draw while redoing points (adjusting screen)
+
+ static bool forceCaptureStartMark; //Just needed to display "Capturing message"
+ static ForceSensorValues forceSensorValues;
+
+ */
+ string runEncoderPortName;
+ SerialPort portRE; //Attention!! Don't reopen port because arduino makes reset
+ bool portREOpened;
+
+ string runEncoderNotConnectedString =
+ //Catalog.GetString("Run encoder sensor is not detected!") + " " +
+ "Run encoder sensor is not detected!" + " " +
+ Catalog.GetString("Plug cable and click on 'device' button.");
+
+
+ //this can use GTK (forceSensor not because it's managed by non-gtk thread)
+ private bool runEncoderConnect()
+ {
+ LogB.Information(" RE connect 0 ");
+ if(chronopicRegister.ConnectedOfType(ChronopicRegisterPort.Types.ARDUINO_RUN_ENCODER) == null)
+ {
+ event_execute_label_message.Text = runEncoderNotConnectedString;
+ return false;
+ }
+
+ LogB.Information(" RE connect 1 ");
+ runEncoderPortName =
chronopicRegister.ConnectedOfType(ChronopicRegisterPort.Types.ARDUINO_RUN_ENCODER).Port;
+ LogB.Information(" RE connect 2 ");
+ if(runEncoderPortName == null || runEncoderPortName == "")
+ {
+ event_execute_label_message.Text = "Please, select port!";
+ return false;
+ }
+ LogB.Information(" RE connect 3 ");
+ event_execute_label_message.Text = "Connecting ...";
+
+ portRE = new SerialPort(runEncoderPortName, 115200); //runEncoder
+ LogB.Information(" RE connect 4: opening port...");
+
+ try {
+ portRE.Open();
+ }
+ catch (System.IO.IOException)
+ {
+ event_execute_label_message.Text = runEncoderNotConnectedString;
+ return false;
+ }
+
+ LogB.Information(" RE connect 5: let arduino start");
+
+ Thread.Sleep(3000); //sleep to let arduino start reading serial event
+
+ LogB.Information(" RE connect 6: get version");
+
+ /*
+ string version = runEncoderCheckVersionDo();
+ LogB.Information("Version found: [" + version + "]");
+
+ if(version == "0.1")
+ {
+ LogB.Information(" RE connect 6b, version 0.1: adjusting parameters...");
+ }
+ */
+
+ portREOpened = true;
+ event_execute_label_message.Text = "Connected!";
+ LogB.Information(" RE connect 7: connected and adjusted!");
+ return true;
+ }
+ private void runEncoderDisconnect()
+ {
+ portRE.Close();
+ portREOpened = false;
+ event_execute_label_message.Text = "Disconnected!";
+ }
+
+ //Attention: no GTK here!!
+ private bool runEncoderSendCommand(string command, string displayMessage, string errorMessage)
+ {
+ //forceSensorOtherMessage = displayMessage;
+
+ try {
+ LogB.Information("Run Encoder command |" + command + "|");
+ portRE.WriteLine(command);
+ }
+ catch (Exception ex)
+ {
+ if(ex is System.IO.IOException || ex is System.TimeoutException)
+ {
+ LogB.Information(errorMessage);
+ portREOpened = false;
+ return false;
+ }
+ //throw;
+ }
+
+ return true;
+ }
+
+ private void on_runs_encoder_capture_clicked ()
+ {
+ runEncoderButtonsSensitive(false);
+ bool connected = runEncoderCapturePre();
+ if(! connected)
+ runEncoderButtonsSensitive(true);
+ }
+
+ //TODO: do all this with an "other" thread like in force sensor to allow connecting messages to be
displayed
+ private bool runEncoderCapturePre()
+ {
+ if(! portREOpened)
+ if(! runEncoderConnect())
+ return false;
+
+ event_execute_label_message.Text = "Please, wait ...";
+ capturingRunEncoder = runEncoderStatus.STARTING;
+
+ button_execute_test.Sensitive = false;
+ event_execute_button_finish.Sensitive = true;
+ event_execute_button_cancel.Sensitive = true;
+
+ //forceCaptureStartMark = false;
+
+ runEncoderProcessFinish = false;
+ runEncoderProcessCancel = false;
+ runEncoderProcessError = false;
+
+ //To know if USB has been disconnected
+ usbDisconnectedCount = 0;
+ usbDisconnectedLastTime = 0;
+
+ /*
+ //initialize
+ forceSensorValues = new ForceSensorValues();
+ */
+
+ event_execute_ButtonFinish.Clicked -= new EventHandler(on_finish_clicked);
+ event_execute_ButtonFinish.Clicked += new EventHandler(on_finish_clicked);
+
+ event_execute_ButtonCancel.Clicked -= new EventHandler(on_cancel_clicked);
+ event_execute_ButtonCancel.Clicked += new EventHandler(on_cancel_clicked);
+
+ event_execute_label_message.Text = "Capturing ...";
+
+ runEncoderCaptureThread = new Thread(new ThreadStart(runEncoderCaptureDo));
+ GLib.Idle.Add (new GLib.IdleHandler (pulseGTKRunEncoderCapture));
+
+ LogB.ThreadStart();
+ runEncoderCaptureThread.Start();
+ return true;
+ }
+
+ //non GTK on this method
+ private void runEncoderCaptureDo()
+ {
+ LogB.Information("runEncoderCaptureDo 0");
+ lastChangedTime = 0;
+
+ if(! runEncoderSendCommand("start_capture:", "", "Catched run encoder capturing"))
+ {
+ runEncoderProcessError = true;
+ return;
+ }
+
+ string str = "";
+ LogB.Information("runEncoderCaptureDo 1");
+ do {
+ Thread.Sleep(100); //sleep to let arduino start reading
+ try {
+ str = portRE.ReadLine();
+ } catch {
+ runEncoderProcessError = true;
+ return;
+ }
+
+ LogB.Information("init string: " + str);
+ }
+ while(! str.Contains("Starting capture"));
+
+ //forceCaptureStartMark = true;
+ capturingRunEncoder = runEncoderStatus.CAPTURING;
+
+ Util.CreateRunEncoderSessionDirIfNeeded (currentSession.UniqueID);
+
+ string nameDate = currentPerson.Name + "_" + UtilDate.ToFile(DateTime.Now);
+
+ //fileName to save the csv
+ string fileName = Util.GetRunEncoderSessionDir(currentSession.UniqueID) +
Path.DirectorySeparatorChar + nameDate + ".csv";
+
+ //lastRunEncoderFile to save the images
+ lastRunEncoderFile = nameDate;
+
+
+ TextWriter writer = File.CreateText(fileName);
+ writer.WriteLine("Pulses;Time(useconds)");
+ str = "";
+ int firstTime = 0;
+
+ while(! runEncoderProcessFinish && ! runEncoderProcessCancel && ! runEncoderProcessError)
+ {
+ //LogB.Information(string.Format("finish conditions: {0}-{1}-{2}",
+ // runEncoderProcessFinish, runEncoderProcessCancel,
runEncoderProcessError));
+
+ /*
+ * The difference between forceSensor and runEncoder is:
+ * runEncoder is not always returning data
+ * if user press "finish" button, and they don't move the encoder,
+ * this will never end:
+ * //str = portRE.ReadLine();
+ * so use the following method that allows to return a "" when there no data
+ * and then the while above will end with the runEncoderProcessFinish condition
+ */
+ str = readFromRunEncoderIfDataArrived();
+ //LogB.Information("str: " + str); //TODO: remove this log
+ if(str == "")
+ continue;
+
+ //check if there is one and only one ';'
+ if( ! (str.Contains(";") && str.IndexOf(";") == str.LastIndexOf(";")) )
+ continue;
+
+ string [] strFull = str.Split(new char[] {';'});
+ //LogB.Information("str: " + str);
+
+ LogB.Information("pulses: " + strFull[0]);
+ if(! Util.IsNumber(strFull[0], false))
+ continue;
+
+ LogB.Information("time microseconds: " + strFull[1]);
+ if(! Util.IsNumber(strFull[1], false))
+ continue;
+
+ /*
+ int time = Convert.ToInt32(strFull[0]);
+
+ //measurement does not start at 0 time. When we start receiving data, mark this as
firstTime
+ if(firstTime == 0)
+ firstTime = time;
+
+ //use this to have time starting at 0
+ time -= firstTime;
+
+ double force = Convert.ToDouble(Util.ChangeDecimalSeparator(strFull[1]));
+ */
+ int pulse = Convert.ToInt32(strFull[0]);
+ int time = Convert.ToInt32(strFull[1]);
+ writer.WriteLine(pulse.ToString() + ";" + time.ToString());
+ }
+ LogB.Information(string.Format("FINISHED WITH conditions: {0}-{1}-{2}",
+ runEncoderProcessFinish, runEncoderProcessCancel,
runEncoderProcessError));
+ LogB.Information("Calling end_capture");
+ if(! runEncoderSendCommand("end_capture:", "Ending capture ...", "Catched ending capture"))
+ {
+ runEncoderProcessError = true;
+ capturingRunEncoder = runEncoderStatus.STOP;
+ Util.FileDelete(fileName);
+ return;
+ }
+
+ LogB.Information("Waiting end_capture");
+ do {
+ Thread.Sleep(10);
+ try {
+ str = portRE.ReadLine();
+ } catch {
+ LogB.Information("Catched waiting end_capture feedback");
+ }
+ LogB.Information("waiting \"Capture ended\" string: " + str);
+ }
+ while(! str.Contains("Capture ended"));
+ LogB.Information("Success: received end_capture");
+
+ writer.Flush();
+ writer.Close();
+ ((IDisposable)writer).Dispose();
+ capturingRunEncoder = runEncoderStatus.STOP;
+
+ //port.Close();
+
+ if(runEncoderProcessCancel || runEncoderProcessError)
+ Util.FileDelete(fileName);
+ else {
+ //call graph
+ File.Copy(fileName, UtilEncoder.GetRunEncoderCSVFileName(), true); //can be
overwritten
+ lastRunEncoderFullPath = fileName;
+ capturingRunEncoder = runEncoderStatus.COPIED_TO_TMP;
+ }
+ }
+
+ private string readFromRunEncoderIfDataArrived()
+ {
+ string str = "";
+ if (portRE.BytesToRead > 0)
+ str = portRE.ReadLine();
+ //LogB.Information("PRE_get_calibrationfactor bytes: " + portFS.ReadExisting());
+
+ return str;
+ }
+
+ private bool pulseGTKRunEncoderCapture ()
+ {
+LogB.Information(" fc A ");
+ if(runEncoderCaptureThread == null)
+ {
+ Thread.Sleep (25);
+ return true;
+ }
+
+LogB.Information(" fc B ");
+ //LogB.Information(capturingRunEncoder.ToString())
+ if(! runEncoderCaptureThread.IsAlive || runEncoderProcessFinish || runEncoderProcessCancel ||
runEncoderProcessError)
+ {
+LogB.Information(" fc C ");
+ if(runEncoderProcessFinish)
+ {
+LogB.Information(" fc C finish");
+/*
+ if(capturingRunEncoder != runEncoderStatus.COPIED_TO_TMP)
+ {
+ Thread.Sleep (25); //Wait file is copied
+ return true;
+ }
+ else
+ {
+*/
+ event_execute_label_message.Text = "Saved.";
+ Thread.Sleep (250); //Wait a bit to ensure is copied
+
+ /*
+ fscPoints.InitRealWidthHeight();
+ forceSensorDoSignalGraphPlot();
+ forceSensorDoRFDGraph();
+
+ //if drawingarea has still not shown, don't paint graph because GC
screen is not defined
+ if(force_sensor_ai_drawingareaShown)
+ forceSensorDoGraphAI();
+ */
+// }
+LogB.Information(" fc C finish 2");
+ } else if(runEncoderProcessCancel || runEncoderProcessError)
+ {
+LogB.Information(" fc C cancel ");
+ if(runEncoderProcessCancel)
+ event_execute_label_message.Text = "Cancelled.";
+ else
+ event_execute_label_message.Text = runEncoderNotConnectedString;
+LogB.Information(" fc C cancel 2");
+ }
+ else
+ event_execute_label_message.Text = "";
+
+ LogB.ThreadEnding();
+
+ /*
+ * ensure runEncoderCaptureThread is ended:
+ * called: portRE.WriteLine("end_capture:");
+ * and received feedback from device
+ */
+ while(runEncoderCaptureThread.IsAlive)
+ Thread.Sleep (250);
+LogB.Information(" fc D ");
+
+ LogB.ThreadEnded();
+
+ runEncoderButtonsSensitive(true);
+ /*
+ button_force_sensor_image_save_signal.Sensitive = true;
+ button_force_sensor_analyze_recalculate.Sensitive = true;
+ */
+
+ //finish, cancel: sensitive = false
+ hideButtons();
+
+ restTime.AddOrModify(currentPerson.UniqueID, currentPerson.Name, true);
+ updateRestTimes();
+
+ return false;
+ }
+
+LogB.Information(" fc E ");
+/*
+ if(forceCaptureStartMark)
+ {
+ event_execute_label_message.Text = "Capturing ...";
+ forceCaptureStartMark = false;
+ }
+ */
+LogB.Information(" fc F ");
+
+ if(capturingRunEncoder == runEncoderStatus.CAPTURING)
+ {
+LogB.Information(" fc G ");
+
+
+LogB.Information(" fc H2 ");
+/*
+ if(usbDisconnectedLastTime == forceSensorValues.TimeLast)
+ {
+ usbDisconnectedCount ++;
+ if(usbDisconnectedCount >= 20)
+ {
+ event_execute_label_message.Text = "Disconnected!";
+ runEncoderProcessError = true;
+ return true;
+ }
+ }
+ else
+ {
+ usbDisconnectedLastTime = forceSensorValues.TimeLast;
+ usbDisconnectedCount = 0;
+ }
+ */
+
+LogB.Information(" fc I ");
+
+LogB.Information(" fc Q ");
+ }
+LogB.Information(" fc R ");
+
+ Thread.Sleep (25);
+ //LogB.Information(" RunEncoder:"+ runEncoderCaptureThread.ThreadState.ToString());
+ return true;
+ }
+
+ void runEncoderButtonsSensitive(bool sensitive)
+ {
+ button_execute_test.Sensitive = sensitive;
+
+ //other gui buttons
+ main_menu.Sensitive = sensitive;
+ hbox_contacts_sup_capture_analyze_two_buttons.Sensitive = sensitive;
+ frame_persons.Sensitive = sensitive;
+ hbox_top_person.Sensitive = sensitive;
+ hbox_chronopics_and_more.Sensitive = sensitive;
+ }
+
+}
diff --git a/src/util.cs b/src/util.cs
index c37c7d2..42cccb7 100644
--- a/src/util.cs
+++ b/src/util.cs
@@ -975,6 +975,44 @@ public class Util
* <--------------- end of force sensor suff
*/
+ /*
+ * run encoder suff ------------------>
+ */
+
+ //to store run encoder data and graphs
+ public static string GetRunEncoderDir()
+ {
+ return Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+ "Chronojump" + Path.DirectorySeparatorChar + "runEncoder");
+ }
+ public static void CreateRunEncoderDirIfNeeded ()
+ {
+ string dir = GetRunEncoderDir();
+ if( ! Directory.Exists(dir)) {
+ Directory.CreateDirectory (dir);
+ LogB.Information ("created dir:", dir);
+ }
+ }
+
+ //runEncoder organized by sessions.
+ public static string GetRunEncoderSessionDir (int sessionID)
+ {
+ return GetRunEncoderDir() + Path.DirectorySeparatorChar + sessionID.ToString();
+ }
+ public static void CreateRunEncoderSessionDirIfNeeded (int sessionID)
+ {
+ string dir = GetRunEncoderSessionDir(sessionID);
+ if( ! Directory.Exists(dir)) {
+ Directory.CreateDirectory (dir);
+ LogB.Information ("created dir:", dir);
+ }
+ }
+
+ /*
+ * <--------------- end of force sensor suff
+ */
+
//videos ar organized by sessions. Photos no.
public static string GetVideoSessionDir (int sessionID) {
diff --git a/src/utilEncoder.cs b/src/utilEncoder.cs
index 4cc9455..61aaa90 100644
--- a/src/utilEncoder.cs
+++ b/src/utilEncoder.cs
@@ -247,9 +247,20 @@ public class UtilEncoder
return System.IO.Path.Combine(Path.GetTempPath(), "sprintGraph.png");
}
- public static string GetmifPath() {
+ public static string GetScriptsPath() {
return System.IO.Path.Combine(Util.GetDataDir(), "r-scripts");
}
+
+ public static string GetRunEncoderScript() {
+ return System.IO.Path.Combine(GetSprintPath(), "sprintEncoder.R");
+ }
+ public static string GetRunEncoderCSVFileName() {
+ return Path.Combine(Path.GetTempPath(), "cj_run_encoder_data.csv");
+ }
+ public static string GetRunEncoderTempFileName() {
+ return Path.Combine(Path.GetTempPath(), "cj_run_encoder_graph.png");
+ }
+
public static string GetmifScript() {
return System.IO.Path.Combine(GetSprintPath(), "maximumIsometricForce.R");
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]