...
 
Commits (8)
......@@ -55,7 +55,15 @@
<ItemGroup>
<Compile Include="Dive.cs" />
<Compile Include="DiveBundle.cs" />
<Compile Include="Readers\DiveReader.cs" />
<Compile Include="Request.cs" />
<Compile Include="DiveSelector\SelectDiveRow.cs" />
<Compile Include="DiveSelector\DiveSelector.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="DiveSelector\DiveSelector.Designer.cs">
<DependentUpon>DiveSelector.cs</DependentUpon>
</Compile>
<Compile Include="SessionStore.cs" />
<Compile Include="WebApplicationSession.cs" />
<Compile Include="Form1.cs">
......@@ -69,6 +77,7 @@
<Compile Include="Writers\DiveWriter.cs" />
<Compile Include="Writers\FileDiveWriter.cs" />
<Compile Include="Writers\LittleLogDiveWriter.cs" />
<Compile Include="Writers\SelectDiveWriter.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
......@@ -82,7 +91,12 @@
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<EmbeddedResource Include="DiveSelector\DiveSelector.resx">
<DependentUpon>DiveSelector.cs</DependentUpon>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\DataSources\DiveLogUploader.DiveSelector.DiveSelectorRow.datasource" />
<None Include="Properties\DataSources\SelectDive.datasource" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
......
This diff is collapsed.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DiveLogUploader.DiveSelector {
public partial class DiveSelectorForm : Form {
public delegate void DoneDelegate(object source, DoneEventArgs eventArgs);
public event DoneDelegate OnDone;
public BindingList<DiveSelectorRow> AvailableDives = new BindingList<DiveSelectorRow>();
public DiveSelectorForm() {
InitializeComponent();
diveSelectorRowBindingSource.DataSource = AvailableDives;
}
public void SetDives(List<Dive> dives) {
gridDives.CurrentCell = null;
AvailableDives.Clear();
foreach(var d in dives) {
AvailableDives.Add(new DiveSelectorRow {
IsSelected = true,
Dive = d
});
}
}
private void gridDives_CurrentCellChanged(object sender, EventArgs e) {
if (gridDives.CurrentRow != null) {
var rowIndex = gridDives.CurrentRow.Index;
AvailableDives[rowIndex].IsSelected = !AvailableDives[rowIndex].IsSelected;
gridDives.UpdateCellValue(0, rowIndex);
gridDives.Rows[rowIndex].Selected = true;
}
}
private void gridDives_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) {
gridDives.CurrentCell = null;
AvailableDives[0].IsSelected = true;
}
private void buttonSelectAll_Click(object sender, EventArgs e) {
foreach(var d in AvailableDives) {
d.IsSelected = true;
}
gridDives.Invalidate();
gridDives.Update();
}
private void buttonDeselectAll_Click(object sender, EventArgs e) {
foreach (var d in AvailableDives) {
d.IsSelected = false;
}
gridDives.Invalidate();
gridDives.Update();
}
private void ButtonDone_Click(object sender, EventArgs e) {
Hide();
var dives = AvailableDives.Where((d) => d.IsSelected).Select((d) => d.Dive).ToArray();
OnDone?.Invoke(this, new DoneEventArgs { dives = dives });
Close();
}
}
public class DoneEventArgs : EventArgs {
public Dive[] dives;
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="IsSelected.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="diveSelectorRowBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DiveLogUploader.DiveSelector {
public class DiveSelectorRow {
public Dive Dive;
public bool IsSelected;
public bool IIsSelected {
get { return IsSelected; }
}
public string DiveTime {
get {
var ts = new TimeSpan(0, 0, (int)Dive.DiveTime);
return ts.ToString();
}
}
public string MaxDepth {
get {
if (Dive.MaxDepth != null) {
var depth = (double)Dive.MaxDepth;
return depth.ToString("n2") + "m";
} else {
return null;
}
}
}
public string Date {
get {
return Dive.Date.ToString("yyyy-MM-dd hh:mm:ss");
}
}
}
}
This diff is collapsed.
......@@ -13,23 +13,17 @@ using System.Linq;
using System.Windows.Forms;
using static LibDiveComputer.Context;
using DiveLogUploader.Writers;
using DiveLogUploader.Readers;
namespace divecomputer_test {
public partial class Form1 : Form {
private class TargetObject {
public dc_loglevel_t logLevel;
public Context ctx;
public Device device;
public Descriptor descriptor;
public string serialPort;
public DiveBundle bundle;
}
private SessionStore Session = new SessionStore();
public Form1() {
InitializeComponent();
Session.WebAppSession.OnData += (sender, args) => {
SetAccountDetails(args.Data);
......@@ -38,16 +32,9 @@ namespace divecomputer_test {
Session.WebAppSession.OnError += (sender, err) => {
AuthErrLabel.Text = err.GetException().Message;
};
}
private Context CreateContext(dc_loglevel_t logLevel) {
var ctx = new Context();
ctx.logfunc = (IntPtr context, dc_loglevel_t loglevel, string file, uint line, string function, string message, IntPtr userdata) => {
Log(message);
};
ctx.loglevel = logLevel;
return ctx;
}
private void Form1_Load(object sender, EventArgs e) {
VersionLabel.Text = "libdivelog v" + LibDiveComputer.Version.AsString;
......@@ -117,16 +104,17 @@ namespace divecomputer_test {
LogLevelSelector.Items.Add(new KeyValuePair<dc_loglevel_t, string>(dc_loglevel_t.DC_LOGLEVEL_DEBUG, "Debug"));
LogLevelSelector.Items.Add(new KeyValuePair<dc_loglevel_t, string>(dc_loglevel_t.DC_LOGLEVEL_ALL, "All"));
LogLevelSelector.SelectedIndex = 0;
LogLevelSelector.SelectedIndex = (int)DiveReader.DefaultLogLevel;
}
public void SetAccountDetails(GetImportResponseData data) {
public void SetAccountDetails(UserData data) {
AccountPanel.Visible = true;
LoginPanel.Visible = false;
LabelAccountEmail.Text = data.user.Email;
LabelAccountName.Text = data.user.Name;
LabelAccountDiveCount.Text = data.user.DiveCount.ToString();
LabelAccountEmail.Text = data.Email;
LabelAccountName.Text = data.Name;
LabelAccountDiveCount.Text = data.DiveCount.ToString();
LabelAccountSince.Text = data.Inserted.ToString("yyyy-MM-dd hh:mm:ss");
LabelAccountComputerCount.Text = data.ComputerCount.ToString();
}
private void LogLevelSelector_SelectedValueChanged(object sender, EventArgs e) {
......@@ -152,100 +140,108 @@ namespace divecomputer_test {
var kvpComputer = (KeyValuePair<Descriptor, string>)ComputerSelector.SelectedItem;
var kvpPort = (KeyValuePair<string, string>)PortSelector.SelectedItem;
var kvpLogLevel = (KeyValuePair<dc_loglevel_t, string>)LogLevelSelector.SelectedItem;
currentTask = new TargetObject {
descriptor = kvpComputer.Key,
serialPort = kvpPort.Key,
logLevel = kvpLogLevel.Key
};
StartButton.Enabled = false;
DivecomputerWorker.RunWorkerAsync();
}
private TargetObject currentTask;
DoReadDiveComputer();
}
private void RefreshPortButton_Click(object sender, EventArgs e) {
LoadSerialPorts();
}
private void StartReading(Descriptor descriptor, string port) {
DivecomputerWorker.RunWorkerAsync();
private void DoReadDiveComputer() {
var writer = CreateWriter();
var reader = CreateReader(writer);
reader.Start();
writer.OnComplete += (_) => {
SetStartButtonEnabled(true);
writer.Dispose();
reader.Dispose();
};
}
private void DivecomputerWorker_DoWork(object sender, DoWorkEventArgs e) {
SetReadProgress(0, true);
SetWriteProgress(0, true);
var args = currentTask;
args.ctx = CreateContext(args.logLevel);
IDiveWriter writer = null;
try {
writer = CreateWriter();
writer.OnProgres += (_, total, processed) => {
SetWriteProgress((int)((float)processed / total * 100), true);
};
writer.OnComplete += (_) => {
SetWriteProgress(100, true);
};
args.device = new Device(args.ctx, args.descriptor, args.serialPort);
args.device.OnWaiting += () => { SetState("Waiting..."); };
args.device.OnProgess += (prog) => { SetReadProgress((int)((float)prog.current / prog.maximum * 100)); };
args.device.OnDeviceInfo += (devInfo) => {
SetState(string.Format("Device: {0}, firmware {1}", devInfo.serial, devInfo.firmware));
writer.SetDevice(args.device);
writer.Start();
};
args.device.OnClock += (clock) => {
Console.WriteLine(string.Format("systime: {0}, devtime: {1}", clock.systime, clock.devtime));
};
Dive lastDive = null;
args.device.OnDive += (data, size, fingerprint, fsize, udata) => {
lastDive = Dive.Parse(args.device, data, fingerprint);
writer.AddDive(lastDive);
};
args.device.Start();
SetReadProgress(100, true);
private DiveReader CreateReader(IDiveWriter writer) {
var reader = new DiveReader();
if (LogLevelSelector.SelectedItem != null) {
var kvp = (KeyValuePair<dc_loglevel_t, string>)LogLevelSelector.SelectedItem;
reader.Loglevel = kvp.Key;
}
if (PortSelector.SelectedItem != null) {
var kvp = (KeyValuePair<string, string>)PortSelector.SelectedItem;
reader.SerialPort = kvp.Key;
}
if (ComputerSelector.SelectedItem != null) {
var kvp = (KeyValuePair<Descriptor, string>)ComputerSelector.SelectedItem;
reader.DeviceDescriptor = kvp.Key;
}
reader.OnProgress += (source, args) => {
SetReadProgress(args.Precent);
};
reader.OnLogMessage += (source, args) => {
Log(args.Message);
};
reader.OnDeviceInfo += (source, args) => {
writer.SetDevice(args.Device);
writer.Start();
};
reader.OnDive += (source, args) => {
writer.AddDive(args.Dive);
};
reader.OnStateChange += (source, args) => {
if (args.State == ReadingState.Reading) {
SetState(string.Format("{0}; Device: {1}, firmware {2}", args.State.ToString(), args.Device.Serial, args.Device.Firmware));
} else {
SetState(args.State.ToString());
}
};
reader.OnComplete += (_, __) => {
writer.End();
};
reader.OnError += (source, args) => {
SetState(args.Error.Message, Color.Red);
writer.Dispose();
SetState("Saved to file");
} catch (Exception err) {
SetState("Error while reading device: " + err.Message, Color.Red);
if (writer != null) {
writer.Dispose();
}
}
SetReadProgress(100, false);
SetWriteProgress(100, false);
}
SetStartButtonEnabled(true);
};
private void DivecomputerWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
Invoke(new Action(() => {
if (currentTask.ctx != null) currentTask.ctx.Dispose();
if (currentTask.device != null) currentTask.device.Dispose();
currentTask.bundle = null;
currentTask = null;
StartButton.Enabled = true;
}));
return reader;
}
private IDiveWriter CreateWriter() {
IDiveWriter writer;
if (FileRadio.Checked) {
return new FileDiveWriter(SaveFileText.Text);
writer = new FileDiveWriter(SaveFileText.Text);
} else if(LogRadio.Checked) {
return new LittleLogDiveWriter(Session.WebAppSession.Token);
writer = new LittleLogDiveWriter(Session.WebAppSession.Token, CheckboxReadSinceLast.Checked);
} else {
throw new Exception("No target type selected");
}
if(ReadSelectRadio.Checked) {
writer = new SelectDiveWriter(writer, this);
}
writer.OnProgres += (_, args) => {
SetWriteProgress((int)((float)args.Current / args.Maximum * 100), true);
};
writer.OnComplete += (_) => {
SetWriteProgress(100, true);
};
return writer;
}
private void SetStartButtonEnabled(bool enabled) {
if (InvokeRequired) {
Invoke(new Action(() => { SetStartButtonEnabled(enabled); }));
} else {
StartButton.Enabled = enabled;
}
}
private void SetState(string text, Color? color = null) {
......
......@@ -117,13 +117,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="DivecomputerWorker.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>185, 17</value>
</metadata>
<metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>316, 17</value>
<value>18, 15</value>
</metadata>
</root>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="DiveSelectorRow" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>DiveLogUploader.DiveSelector.DiveSelectorRow, DiveLogUploader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="SelectDive" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>DiveLogUploader.SelectDive, DiveLogUploader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>
\ No newline at end of file
using DiveLogUploader;
using LibDiveComputer;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LibDiveComputer.Context;
public enum ReadingState {
Started,
Waiting,
Reading,
Complete,
}
namespace DiveLogUploader.Readers {
public class DeviceEventArgs : EventArgs {
public Device Device;
public Context Context;
}
public class ProgressEventArgs : DeviceEventArgs {
public uint Maximum;
public uint Current;
public float Ratio { get { return (float)Current / Maximum; } }
public int Precent { get { return (int)Math.Round(Ratio * 100); } }
}
public class DeviceInfoEventArgs : DeviceEventArgs {
public uint Model;
public uint Firmware;
public uint Serial;
}
public class DeviceClockEventArgs : DeviceEventArgs {
public uint DevTime;
public long SysTime;
}
public class DiveEventArgs : DeviceEventArgs {
public Dive Dive;
}
public class CompleteEventArgs : DeviceEventArgs {
}
public class StateChangedEventArgs : DeviceEventArgs {
public ReadingState State;
}
public class LogEntryEventArgs : DeviceEventArgs {
public dc_loglevel_t Loglevel;
public string File;
public uint Line;
public string Function;
public string Message;
}
public class ErrorEventArgs : EventArgs {
public Exception Error;
}
public delegate void ProgressHandle(object source, ProgressEventArgs args);
public delegate void DeviceInfoHandle(object source, DeviceInfoEventArgs args);
public delegate void ClockInfoHandle(object source, DeviceClockEventArgs args);
public delegate void DiveHandle(object source, DiveEventArgs args);
public delegate void CompleteHandle(object source, CompleteEventArgs args);
public delegate void LogMessageHandle(object source, LogEntryEventArgs args);
public delegate void StateChangeHandle(object source, StateChangedEventArgs args);
public delegate void ErrorHandle(object source, ErrorEventArgs args);
public class DiveReader : IDisposable {
public const dc_loglevel_t DefaultLogLevel = dc_loglevel_t.DC_LOGLEVEL_ERROR;
public event ProgressHandle OnProgress;
public event DeviceInfoHandle OnDeviceInfo;
public event ClockInfoHandle OnDeviceClock;
public event DiveHandle OnDive;
public event CompleteHandle OnComplete;
public event LogMessageHandle OnLogMessage;
public event StateChangeHandle OnStateChange;
public event ErrorHandle OnError;
public dc_loglevel_t Loglevel = DefaultLogLevel;
public string SerialPort;
public Descriptor DeviceDescriptor;
protected BackgroundWorker worker = new BackgroundWorker();
public DiveReader() {
worker.DoWork += (_, __) => DoWork();
}
private Context CreateContext() {
var ctx = new Context();
ctx.logfunc = (IntPtr context, dc_loglevel_t loglevel, string file, uint line, string function, string message, IntPtr userdata) => {
OnLogMessage?.Invoke(this, new LogEntryEventArgs {
Loglevel = loglevel,
File = file,
Function = function,
Line = line,
Message = message
});
};
ctx.loglevel = Loglevel;
return ctx;
}
public void Start() {
if(worker.IsBusy) {
throw new Exception("Dive Reader is already busy");
}
worker.RunWorkerAsync();
}
protected void DoWork() {
try {
var ctx = CreateContext();
var device = new Device(ctx, DeviceDescriptor, SerialPort);
device.OnWaiting += () => {
OnStateChange?.Invoke(this, new StateChangedEventArgs {
Context = ctx,
Device = device,
State = ReadingState.Waiting,
});
};
device.OnDeviceInfo += (devInfo) => {
OnDeviceInfo?.Invoke(this, new DeviceInfoEventArgs {
Context = ctx,
Device = device,
Firmware = devInfo.firmware,
Model = devInfo.model,
Serial = devInfo.serial,
});
};
device.OnClock += (clock) => {
OnStateChange?.Invoke(this, new StateChangedEventArgs {
Context = ctx,
Device = device,
State = ReadingState.Reading,
});
OnDeviceClock?.Invoke(this, new DeviceClockEventArgs {
Context = ctx,
Device = device,
DevTime = clock.devtime,
SysTime = clock.systime
});
};
device.OnProgess += (prog) => {
OnProgress?.Invoke(this, new ProgressEventArgs {
Context = ctx,
Device = device,
Current = prog.current,
Maximum = prog.maximum
});
};
device.OnDive += (data, size, fingerprint, fsize, udata) => {
OnDive?.Invoke(this, new DiveEventArgs {
Dive = Dive.Parse(device, data, fingerprint)
});
};
OnStateChange?.Invoke(this, new StateChangedEventArgs {
Context = ctx,
Device = device,
State = ReadingState.Started,
});
device.Start();
OnComplete?.Invoke(this, new CompleteEventArgs {
Context = ctx,
Device = device,
});
OnStateChange?.Invoke(this, new StateChangedEventArgs {
Context = ctx,
Device = device,
State = ReadingState.Complete,
});
device.Dispose();
ctx.Dispose();
} catch(Exception ex) {
OnError?.Invoke(this, new ErrorEventArgs {
Error = ex
});
}
}
public void Dispose() {
}
}
}
......@@ -21,19 +21,24 @@ namespace DiveLogUploader {
[JsonProperty("name")]
public string Name;
[JsonProperty("inserted")]
public DateTime Inserted;
[JsonProperty("dive_count")]
public int DiveCount;
}
public class GetImportResponseData {
[JsonProperty("user")]
public UserData user;
[JsonProperty("buddy_count")]
public int BuddyCount;
[JsonProperty("tag_count")]
public int TagCount;
[JsonProperty("computer_count")]
public int ComputerCount;
}
public class DataEventArgs : EventArgs {
public GetImportResponseData Data;
public UserData Data;
}
public class LoginResponseData {
......@@ -101,7 +106,7 @@ namespace DiveLogUploader {
}
}
private GetImportResponseData Data;
private UserData Data;
public bool IsLoggedIn {
get { return Token != null; }
......@@ -150,13 +155,13 @@ namespace DiveLogUploader {
private async Task GetData() {
try {
var result = await Request.JsonAsync<GetImportResponseData>(
BASE_URL + "import",
var result = await Request.JsonAsync<UserData>(
BASE_URL + "user/profile",
HttpVerb.GET,
TokenHeader(Token)
);
if (result == null || result.user == null) {
if (result == null) {
throw new Exception("Invalid response from server");
}
......
......@@ -6,33 +6,34 @@ using System.Threading;
namespace DiveLogUploader.Writers {
public class ProgresEventArgs : EventArgs {
public uint Maximum;
public uint Current;
public float Ratio { get { return (float)Current / Maximum; } }
public int Precent { get { return (int)Math.Round(Ratio * 100); } }
}
public delegate void OnCompleteHandler(object sender);
public delegate void OnProgresHandler(object sender, int total, int processed);
public delegate void OnProgresHandler(object sender, ProgresEventArgs args);
public interface IDiveWriter: IDisposable {
event OnCompleteHandler OnComplete;
event OnProgresHandler OnProgres;
void SetDevice(Device device);
void AddDive(Dive dive);
void Start();
void End();
}
public abstract class AsyncDiveWriter : IDiveWriter {
public event OnCompleteHandler OnComplete;
public event OnProgresHandler OnProgres;
public int Total = 0;
public int Processed = 0;
public uint Total = 0;
public uint Processed = 0;
protected Device device;
protected BackgroundWorker worker;
......@@ -52,7 +53,10 @@ namespace DiveLogUploader.Writers {
queue.Enqueue(dive);
Total += 1;
}
OnProgres?.Invoke(this, Total, Processed);
OnProgres?.Invoke(this, new ProgresEventArgs {
Maximum = Total,
Current = Processed,
});
waitEvent.Set();
}
......@@ -68,7 +72,6 @@ namespace DiveLogUploader.Writers {
isDone = true;
waitEvent.Set();
doneEvent.WaitOne();
}
public virtual void SetDevice(Device d) {
......@@ -92,7 +95,10 @@ namespace DiveLogUploader.Writers {
}
if (item != null) {
ProcessDive(item);
OnProgres?.Invoke(this, Total, Processed);
OnProgres?.Invoke(this, new ProgresEventArgs {
Current = Processed,
Maximum = Total,
});
} else {
waitEvent.WaitOne();
}
......@@ -102,9 +108,8 @@ namespace DiveLogUploader.Writers {
protected virtual void Done() {
OnComplete?.Invoke(this);
doneEvent.Set();
}
protected abstract void ProcessDive(Dive dive);
}
}
\ No newline at end of file
......@@ -9,6 +9,7 @@ namespace DiveLogUploader.Writers {
/// A dive writer which Writes everything to the disk
/// </summary>
public class FileDiveWriter : AsyncDiveWriter, IDisposable {
public bool IsStarted { get; protected set; } = false;
protected StreamWriter fileWriter;
protected JsonWriter writer;
protected JsonSerializer serializer;
......@@ -31,17 +32,18 @@ namespace DiveLogUploader.Writers {
writer.WritePropertyName("Dives");
writer.WriteStartArray();
IsStarted = true;
base.Start();
}
public override void End() {
if (isDone) return;
protected override void Done() {
base.End();
writer.WriteEndArray();
writer.WriteEndObject();
base.Done();
}
protected override void ProcessDive(Dive dive) {
......@@ -50,7 +52,7 @@ namespace DiveLogUploader.Writers {
public override void Dispose() {
base.Dispose();
writer.Close();
fileWriter.Close();
}
......
......@@ -36,10 +36,13 @@ namespace DiveLogUploader.Writers {
/// </summary>
/// <remarks>LittleDiveLog is a side project still under development</remarks>
public class LittleLogDiveWriter : AsyncDiveWriter {
protected string token;
protected int computerId;
public LittleLogDiveWriter(string tok): base() {
token = tok;
protected string Token;
protected int ComputerId;
protected bool UseFingerprint;
public LittleLogDiveWriter(string token, bool useFingerprint): base() {
Token = token;
UseFingerprint = useFingerprint;
}
public override void SetDevice(Device d) {
......@@ -49,24 +52,24 @@ namespace DiveLogUploader.Writers {
WebApplicationSession.BASE_URL + "computer",
HttpVerb.POST,
new Computer(d),
WebApplicationSession.TokenHeader(token)
WebApplicationSession.TokenHeader(Token)
);
computerId = resp.computer_id;
ComputerId = resp.computer_id;
if (resp.last_fingerprint != null) {
if (UseFingerprint && resp.last_fingerprint != null) {
var fingerprint = Convert.FromBase64String(resp.last_fingerprint);
d.SetFingerprint(fingerprint);
}
}
protected override void ProcessDive(Dive d) {
var boundDive = new ComputerBoundDive(d, computerId);
var boundDive = new ComputerBoundDive(d, ComputerId);
var resp = Request.Json<Dive, PostDiveResponse>(
WebApplicationSession.BASE_URL + "dive",
HttpVerb.POST,
boundDive,
WebApplicationSession.TokenHeader(token)
WebApplicationSession.TokenHeader(Token)
);
}
}
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DiveLogUploader.DiveSelector;
using LibDiveComputer;
using System.Windows.Forms;
namespace DiveLogUploader.Writers {
public class SelectDiveWriter : IDiveWriter, IDisposable {
public List<Dive> Dives = new List<Dive>();
public DiveSelectorForm Selector;
protected IDiveWriter Target;
protected Form BaseForm;
public SelectDiveWriter(IDiveWriter target, Form baseForm = null) {
Target = target;
BaseForm = baseForm;
Selector = new DiveSelectorForm();
Selector.OnDone += (_, args) => {
if(BaseForm != null) {
BaseForm.Focus();
}
foreach (var dive in args.dives) {
Target.AddDive(dive);
}
Target.End();
};
}
public event OnCompleteHandler OnComplete {
add { Target.OnComplete += value; }
remove { Target.OnComplete -= value; }
}
public event OnProgresHandler OnProgres {
add { Target.OnProgres += value; }
remove { Target.OnProgres -= value; }
}
public void AddDive(Dive dive) {
Dives.Add(dive);
}
public void Dispose() {
Selector.Dispose();
Target.Dispose();
}
public void End() {
Selector.SetDives(Dives);
ShowSelector();
}
public void ShowSelector() {
if (BaseForm != null && BaseForm.InvokeRequired) {
BaseForm.Invoke(new Action(() => { ShowSelector(); }));
} else {
Selector.ShowDialog();
}
}
public void SetDevice(Device device) {
Target.SetDevice(device);
}
public void Start() {
Target.Start();
}
}
}