HamBook – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using HamBook.Radios;
2 using HamBook.Utilities;
3 using HamBook.Utilities.Serialization;
4 using NetSparkleUpdater.Enums;
5 using NetSparkleUpdater.SignatureVerifiers;
6 using NetSparkleUpdater.UI.WinForms;
7 using NetSparkleUpdater;
8 using Serilog;
9 using System;
10 using System.ComponentModel;
11 using System.Drawing;
12 using System.IO;
13 using System.IO.Ports;
14 using System.Reflection;
15 using System.Threading;
16 using System.Threading.Tasks;
17 using System.Windows.Forms;
18 using HamBook.Properties;
19 using HamBook.Radios.Generic;
20 using PowerState = HamBook.Radios.Generic.PowerState;
21  
22 namespace HamBook
23 {
24 public partial class Form1 : Form
25 {
26 private ScheduledContinuation _changedConfigurationContinuation;
27 private Configuration.Configuration Configuration { get; set; }
28 private SerialPort _serialPort;
29 private LogMemorySink _memorySink;
30 private ViewLogsForm _viewLogsForm;
31 private AboutForm _aboutForm;
32 private SettingsForm _settingsForm;
33 private SparkleUpdater _sparkle;
34 private readonly CancellationToken _cancellationToken;
35 private readonly CancellationTokenSource _cancellationTokenSource;
36 private CatAssemblies _catAssemblies;
37 private int _radioVFOA;
38 private int _radioVFOB;
39  
40 public bool MemorySinkEnabled { get; set; }
41  
42 private Form1()
43 {
44 _cancellationTokenSource = new CancellationTokenSource();
45 _cancellationToken = _cancellationTokenSource.Token;
46  
47 _changedConfigurationContinuation = new ScheduledContinuation();
48 }
49  
50 public Form1(Mutex mutex) : this()
51 {
52 InitializeComponent();
53  
54 _memorySink = new LogMemorySink();
55  
56 Log.Logger = new LoggerConfiguration()
57 .MinimumLevel.Debug()
58 .WriteTo.Conditional(condition => MemorySinkEnabled, configureSink => configureSink.Sink(_memorySink))
59 .WriteTo.File(Path.Combine(Constants.UserApplicationDirectory, "Logs", $"{Constants.AssemblyName}.log"),
60 rollingInterval: RollingInterval.Day)
61 .CreateLogger();
62  
63 // Start application update.
64 var manifestModuleName = Assembly.GetEntryAssembly().ManifestModule.FullyQualifiedName;
65 var icon = Icon.ExtractAssociatedIcon(manifestModuleName);
66  
67 _sparkle = new SparkleUpdater("https://hambook.grimore.org/update/appcast.xml",
68 new Ed25519Checker(SecurityMode.Strict, "LonrgxVjSF0GnY4hzwlRJnLkaxnDn2ikdmOifILzLJY="))
69 {
70 UIFactory = new UIFactory(icon),
71 RelaunchAfterUpdate = true
72 };
73 _sparkle.StartLoop(true, true);
74 }
75  
76 private async void Form1_Load(object sender, EventArgs e)
77 {
78 Configuration = await LoadConfiguration();
79  
80 // Set up serial connection.
81 _serialPort = new SerialPort(Configuration.Port, Configuration.Speed, Configuration.Parity, Configuration.DataBits, Configuration.StopBits);
82 //TODO: move to settings
83 //_serialPort.ReadTimeout = TimeSpan.FromSeconds(1).Milliseconds;
84  
85 _catAssemblies = new CatAssemblies(_serialPort, Configuration.Radio);
86  
87 try
88 {
89 switch (await _catAssemblies.CatRead<PowerState>("PS", new object[] { }, _cancellationToken))
90 {
91 case PowerState.ON:
92 Initialize();
93 break;
94 }
95 }
96 catch(Exception exception)
97 {
98 Log.Error(exception, Resources.Failed_to_read_power_state);
99 }
100 }
101  
102 private void quitToolStripMenuItem_Click(object sender, EventArgs e)
103 {
104 Close();
105 }
106  
107 private void viewLogsToolStripMenuItem_Click(object sender, EventArgs e)
108 {
109 if (_viewLogsForm != null)
110 {
111 return;
112 }
113  
114 _viewLogsForm = new ViewLogsForm(this, _memorySink, _cancellationToken);
115 _viewLogsForm.Closing += ViewLogsForm_Closing;
116 _viewLogsForm.Show();
117 }
118  
119 private void ViewLogsForm_Closing(object sender, CancelEventArgs e)
120 {
121 if (_viewLogsForm == null)
122 {
123 return;
124 }
125  
126 _viewLogsForm.Closing -= ViewLogsForm_Closing;
127 _viewLogsForm.Close();
128 _viewLogsForm = null;
129 }
130  
131 private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
132 {
133 if (_aboutForm != null)
134 {
135 return;
136 }
137  
138 _aboutForm = new AboutForm(_cancellationToken);
139 _aboutForm.Closing += AboutForm_Closing;
140 _aboutForm.Show();
141 }
142  
143 private void AboutForm_Closing(object sender, CancelEventArgs e)
144 {
145 if (_aboutForm == null)
146 {
147 return;
148 }
149  
150 _aboutForm.Dispose();
151 _aboutForm = null;
152 }
153  
154 private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
155 {
156 if (_settingsForm != null)
157 {
158 return;
159 }
160  
161 _settingsForm = new SettingsForm(Configuration, _cancellationToken);
162 _settingsForm.Closing += SettingsForm_Closing;
163 _settingsForm.Show();
164 }
165  
166 private void SettingsForm_Closing(object sender, CancelEventArgs e)
167 {
168 if (_settingsForm == null)
169 {
170 return;
171 }
172  
173 if(_settingsForm.SaveOnClose)
174 {
175 // Commit the configuration.
176 _changedConfigurationContinuation.Schedule(TimeSpan.FromSeconds(1),
177 async () => {
178 await SaveConfiguration();
179  
180 Miscellaneous.LaunchOnBootSet(Configuration.LaunchOnBoot);
181  
182 _serialPort.Dispose();
183 _serialPort = new SerialPort(Configuration.Port, Configuration.Speed, Configuration.Parity, Configuration.DataBits, Configuration.StopBits);
184  
185 }, _cancellationToken);
186 }
187  
188 _settingsForm.Dispose();
189 _settingsForm = null;
190 }
191  
192 public async Task SaveConfiguration()
193 {
194 if (!Directory.Exists(Constants.UserApplicationDirectory))
195 {
196 Directory.CreateDirectory(Constants.UserApplicationDirectory);
197 }
198  
199 switch (await Serialization.Serialize(Configuration, Constants.ConfigurationFile, "Configuration",
200 "<!ATTLIST Configuration xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>",
201 CancellationToken.None))
202 {
203 case SerializationSuccess<Configuration.Configuration> _:
204 Log.Information("Serialized configuration.");
205 break;
206 case SerializationFailure serializationFailure:
207 Log.Warning(serializationFailure.Exception.Message, "Failed to serialize configuration.");
208 break;
209 }
210 }
211  
212 public static async Task<Configuration.Configuration> LoadConfiguration()
213 {
214 if (!Directory.Exists(Constants.UserApplicationDirectory))
215 {
216 Directory.CreateDirectory(Constants.UserApplicationDirectory);
217 }
218  
219 var deserializationResult =
220 await Serialization.Deserialize<Configuration.Configuration>(Constants.ConfigurationFile,
221 Constants.ConfigurationNamespace, Constants.ConfigurationXsd, CancellationToken.None);
222  
223 switch (deserializationResult)
224 {
225 case SerializationSuccess<Configuration.Configuration> serializationSuccess:
226 return serializationSuccess.Result;
227 case SerializationFailure serializationFailure:
228 Log.Warning(serializationFailure.Exception, "Failed to load configuration.");
229 return new Configuration.Configuration();
230 default:
231 return new Configuration.Configuration();
232 }
233 }
234  
235 private void Initialize()
236 {
237 try
238 {
239 var mode = _catAssemblies.CatRead<RadioMode>("MD", new object[] { });
240 toolStripComboBox1.Text = Enum.GetName(typeof(RadioMode), mode);
241 }
242 catch(Exception exception)
243 {
244 Log.Error(exception, Resources.Failed_to_read_radio_mode);
245 }
246  
247 try
248 {
249 var fa = _catAssemblies.CatRead<int>("FA", new object[] { });
250 toolStripTextBox1.Text = $"{fa}";
251 }
252 catch(Exception exception)
253 {
254 Log.Error(exception, Resources.Failed_to_read_VFO_A);
255 }
256  
257 try
258 {
259 var fb = _catAssemblies.CatRead<int>("FB", new object[] { });
260 toolStripTextBox2.Text = $"{fb}";
261 }
262 catch (Exception exception)
263 {
264 Log.Error(exception, Resources.Failed_to_read_VFO_B);
265 }
266  
267  
268 }
269  
270 private async void updateToolStripMenuItem_Click(object sender, EventArgs e)
271 {
272 // Manually check for updates, this will not show a ui
273 var result = await _sparkle.CheckForUpdatesQuietly();
274 if (result.Status == NetSparkleUpdater.Enums.UpdateStatus.UpdateAvailable)
275 {
276 // if update(s) are found, then we have to trigger the UI to show it gracefully
277 _sparkle.ShowUpdateNeededUI();
278 return;
279 }
280  
281 MessageBox.Show(Resources.No_updates_available_at_this_time, Resources.HamBook, MessageBoxButtons.OK,
282 MessageBoxIcon.Asterisk,
283 MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, false);
284 }
285  
286 private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
287 {
288 var toolStripComboBox = (ToolStripComboBox)sender;
289 foreach (var name in Enum.GetNames(typeof(RadioMode)))
290 {
291 if (string.Equals(name, toolStripComboBox.Text, StringComparison.OrdinalIgnoreCase))
292 {
293 var field = typeof(RadioMode).GetField(name);
294 var mode = (RadioMode)field.GetValue(null);
295  
296 try
297 {
298 _catAssemblies.CatSet<RadioMode>("MD", new object[] { mode });
299 }
300 catch(Exception exception)
301 {
302 Log.Error(exception, Resources.Failed_to_set_radio_mode, mode);
303 }
304 }
305 }
306 }
307  
308 private async void onToolStripMenuItem_Click(object sender, EventArgs e)
309 {
310 try
311 {
312 await _catAssemblies.CatSet<PowerState>("PS", new object[] { PowerState.ON }, _cancellationToken);
313 Initialize();
314 }
315 catch(Exception exception)
316 {
317 Log.Error(exception, Resources.Failed_to_set_power_state);
318 }
319 }
320  
321 private async void offToolStripMenuItem_Click(object sender, EventArgs e)
322 {
323 try
324 {
325 await _catAssemblies.CatSet<PowerState>("PS", new object[] { PowerState.OFF }, _cancellationToken);
326 }
327 catch(Exception exception)
328 {
329 Log.Error(exception, Resources.Failed_to_set_power_state);
330 }
331 }
332  
333 private void toolStripTextBox1_Click(object sender, EventArgs e)
334 {
335 var toolStripTextBox = (ToolStripTextBox)sender;
336 if(int.TryParse(toolStripTextBox.Text, out var frequency))
337 {
338 _radioVFOA = frequency;
339 }
340 }
341  
342 private void toolStripTextBox1_TextChanged(object sender, EventArgs e)
343 {
344 var toolStripTextBox = (ToolStripTextBox)sender;
345 if(int.TryParse(toolStripTextBox.Text, out var frequency))
346 {
347 try
348 {
349 _catAssemblies.CatSet<int>("FA", new object[] { frequency });
350 }
351 catch (Exception exception)
352 {
353 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
354 }
355 return;
356 }
357  
358 toolStripTextBox.Text = $"{_radioVFOA}";
359 }
360  
361 private void toolStripTextBox2_TextChanged(object sender, EventArgs e)
362 {
363 var toolStripTextBox = (ToolStripTextBox)sender;
364 if (int.TryParse(toolStripTextBox.Text, out var frequency))
365 {
366 _radioVFOB = frequency;
367 }
368 }
369  
370 private void toolStripTextBox2_Click(object sender, EventArgs e)
371 {
372 var toolStripTextBox = (ToolStripTextBox)sender;
373 if (int.TryParse(toolStripTextBox.Text, out var frequency))
374 {
375 try
376 {
377 _catAssemblies.CatSet<int>("FB", new object[] { frequency });
378 }
379 catch (Exception exception)
380 {
381 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
382 }
383 return;
384 }
385  
386 toolStripTextBox.Text = $"{_radioVFOB}";
387 }
388 }
389 }