Weighing: Restructure class structure
This commit is contained in:
@ -63,7 +63,7 @@ namespace Elwig {
|
|||||||
Directory.CreateDirectory(TempPath);
|
Directory.CreateDirectory(TempPath);
|
||||||
Directory.CreateDirectory(DataPath);
|
Directory.CreateDirectory(DataPath);
|
||||||
MainDispatcher = Dispatcher;
|
MainDispatcher = Dispatcher;
|
||||||
Scales = Array.Empty<IScale>();
|
Scales = [];
|
||||||
CurrentApp = this;
|
CurrentApp = this;
|
||||||
OverrideCulture();
|
OverrideCulture();
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ namespace Elwig {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = new();
|
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = [];
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
|
branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
|
||||||
try {
|
try {
|
||||||
@ -115,23 +115,11 @@ namespace Elwig {
|
|||||||
|
|
||||||
var list = new List<IScale>();
|
var list = new List<IScale>();
|
||||||
foreach (var s in Config.Scales) {
|
foreach (var s in Config.Scales) {
|
||||||
var id = s[0];
|
|
||||||
try {
|
try {
|
||||||
var type = s[1]?.ToLower();
|
list.Add(Scale.FromConfig(s));
|
||||||
var model = s[2];
|
|
||||||
var cnx = s[3];
|
|
||||||
var empty = s[4];
|
|
||||||
var filling = s[5];
|
|
||||||
int? limit = s[6] == null ? null : int.Parse(s[6]);
|
|
||||||
var log = s[7];
|
|
||||||
if (type == "systec") {
|
|
||||||
list.Add(new SystecScale(id, model, cnx, empty, filling, limit, log));
|
|
||||||
} else {
|
|
||||||
throw new ArgumentException($"Invalid scale type: \"{type}\"");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
list.Add(new InvalidScale(id));
|
list.Add(new InvalidScale(s.Id));
|
||||||
MessageBox.Show($"Unable to create scale {s[0]}:\n\n{e.Message}", "Scale Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show($"Unable to create scale {s.Id}:\n\n{e.Message}", "Scale Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scales = list;
|
Scales = list;
|
||||||
|
@ -4,6 +4,31 @@ using System.Linq;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Elwig.Helpers {
|
namespace Elwig.Helpers {
|
||||||
|
|
||||||
|
public record struct ScaleConfig {
|
||||||
|
public string Id;
|
||||||
|
public string? Type;
|
||||||
|
public string? Model;
|
||||||
|
public string? Connection;
|
||||||
|
public string? Empty;
|
||||||
|
public string? Filling;
|
||||||
|
public string? Limit;
|
||||||
|
public string? Log;
|
||||||
|
public string? _Log;
|
||||||
|
|
||||||
|
public ScaleConfig(string id, string? type, string? model, string? cnx, string? empty, string? filling, string? limit, string? log) {
|
||||||
|
Id = id;
|
||||||
|
Type = type;
|
||||||
|
Model = model;
|
||||||
|
Connection = cnx;
|
||||||
|
Empty = empty;
|
||||||
|
Filling = filling;
|
||||||
|
Limit = limit;
|
||||||
|
_Log = log;
|
||||||
|
Log = log != null ? Path.Combine(App.DataPath, log) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class Config {
|
public class Config {
|
||||||
|
|
||||||
private readonly string FileName;
|
private readonly string FileName;
|
||||||
@ -11,8 +36,8 @@ namespace Elwig.Helpers {
|
|||||||
public string DatabaseFile = App.DataPath + "database.sqlite3";
|
public string DatabaseFile = App.DataPath + "database.sqlite3";
|
||||||
public string? DatabaseLog = null;
|
public string? DatabaseLog = null;
|
||||||
public string? Branch = null;
|
public string? Branch = null;
|
||||||
public IList<string?[]> Scales;
|
public IList<ScaleConfig> Scales;
|
||||||
private readonly List<string?[]> ScaleList = [];
|
private readonly List<ScaleConfig> ScaleList = [];
|
||||||
private static readonly string[] trueValues = ["1", "true", "yes", "on"];
|
private static readonly string[] trueValues = ["1", "true", "yes", "on"];
|
||||||
|
|
||||||
public Config(string filename) {
|
public Config(string filename) {
|
||||||
@ -34,12 +59,10 @@ namespace Elwig.Helpers {
|
|||||||
ScaleList.Clear();
|
ScaleList.Clear();
|
||||||
Scales = ScaleList;
|
Scales = ScaleList;
|
||||||
foreach (var s in scales) {
|
foreach (var s in scales) {
|
||||||
string? scaleLog = config[$"scale.{s}:log"];
|
ScaleList.Add(new(
|
||||||
if (scaleLog != null) scaleLog = Path.Combine(App.DataPath, scaleLog);
|
|
||||||
ScaleList.Add([
|
|
||||||
s, config[$"scale.{s}:type"], config[$"scale.{s}:model"], config[$"scale.{s}:connection"],
|
s, config[$"scale.{s}:type"], config[$"scale.{s}:model"], config[$"scale.{s}:connection"],
|
||||||
config[$"scale.{s}:empty"], config[$"scale.{s}:filling"], config[$"scale.{s}:limit"], scaleLog
|
config[$"scale.{s}:empty"], config[$"scale.{s}:filling"], config[$"scale.{s}:limit"], config[$"scale.{s}:log"]
|
||||||
]);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,11 +74,11 @@ namespace Elwig.Helpers {
|
|||||||
file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n");
|
file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n");
|
||||||
if (DatabaseLog != null) file.Write($"log = {DatabaseLog}\r\n");
|
if (DatabaseLog != null) file.Write($"log = {DatabaseLog}\r\n");
|
||||||
foreach (var s in ScaleList) {
|
foreach (var s in ScaleList) {
|
||||||
file.Write($"\r\n[scale.{s[0]}]\r\ntype = {s[1]}\r\nmodel = {s[2]}\r\nconnection = {s[3]}\r\n");
|
file.Write($"\r\n[scale.{s.Id}]\r\ntype = {s.Type}\r\nmodel = {s.Model}\r\nconnection = {s.Connection}\r\n");
|
||||||
if (s[4] != null) file.Write($"empty = {s[4]}\r\n");
|
if (s.Empty != null) file.Write($"empty = {s.Empty}\r\n");
|
||||||
if (s[5] != null) file.Write($"filling = {s[5]}\r\n");
|
if (s.Filling != null) file.Write($"filling = {s.Filling}\r\n");
|
||||||
if (s[6] != null) file.Write($"limit = {s[6]}\r\n");
|
if (s.Limit != null) file.Write($"limit = {s.Limit}\r\n");
|
||||||
if (s[7] != null) file.Write($"log = {s[7]}\r\n");
|
if (s._Log != null) file.Write($"log = {s._Log}\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
95
Elwig/Helpers/Weighing/Scale.cs
Normal file
95
Elwig/Helpers/Weighing/Scale.cs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
using System.IO.Ports;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Elwig.Helpers.Weighing {
|
||||||
|
public abstract class Scale : IDisposable {
|
||||||
|
|
||||||
|
protected enum Output { RTS, DTR, OUT1, OUT2 };
|
||||||
|
|
||||||
|
protected SerialPort? Serial = null;
|
||||||
|
protected SerialPort? ControlSerialEmpty = null, ControlSerialFilling = null;
|
||||||
|
protected TcpClient? Tcp = null;
|
||||||
|
protected Stream Stream;
|
||||||
|
|
||||||
|
protected readonly Output? EmptyMode = null;
|
||||||
|
protected readonly Output? FillingClearanceMode = null;
|
||||||
|
protected readonly int EmptyDelay;
|
||||||
|
|
||||||
|
public int? WeightLimit { get; private set; }
|
||||||
|
public string? LogPath { get; private set; }
|
||||||
|
|
||||||
|
public static IScale FromConfig(ScaleConfig config) {
|
||||||
|
int? limit = config.Limit != null ? int.Parse(config.Limit) : null;
|
||||||
|
if (config.Type == "SysTec-IT") {
|
||||||
|
return new SysTecITScale(config.Id, config.Model!, config.Connection!, config.Empty, config.Filling, limit, config.Log);
|
||||||
|
} else if (config.Type == "Schember-evt") {
|
||||||
|
return new SchemberEventScale(config.Id, config.Model!, config.Connection!, config.Empty, config.Filling, limit, config.Log);
|
||||||
|
} else {
|
||||||
|
throw new ArgumentException($"Invalid scale type: \"{config.Type}\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Scale(string cnx, string? empty, string? filling, int? limit, string? log) {
|
||||||
|
if (cnx.StartsWith("serial:")) {
|
||||||
|
Serial = Utils.OpenSerialConnection(cnx);
|
||||||
|
Stream = Serial.BaseStream;
|
||||||
|
} else if (cnx.StartsWith("tcp:")) {
|
||||||
|
Tcp = Utils.OpenTcpConnection(cnx);
|
||||||
|
Stream = Tcp.GetStream();
|
||||||
|
} else {
|
||||||
|
throw new ArgumentException("Unsupported scheme");
|
||||||
|
}
|
||||||
|
|
||||||
|
LogPath = log;
|
||||||
|
|
||||||
|
if (empty != null) {
|
||||||
|
var parts = empty.Split(':');
|
||||||
|
if (parts.Length == 3) {
|
||||||
|
if (parts[0] != Serial?.PortName)
|
||||||
|
ControlSerialEmpty = Utils.OpenSerialConnection($"serial://{parts[0]}:9600");
|
||||||
|
} else if (parts.Length != 2) {
|
||||||
|
throw new ArgumentException("Invalid value for 'empty'");
|
||||||
|
}
|
||||||
|
EmptyMode = ConvertOutput(parts[^2]);
|
||||||
|
EmptyDelay = int.Parse(parts[^1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WeightLimit = limit;
|
||||||
|
if (filling != null) {
|
||||||
|
var parts = filling.Split(':');
|
||||||
|
if (parts.Length == 2) {
|
||||||
|
if (parts[0] != Serial?.PortName)
|
||||||
|
ControlSerialFilling = parts[0] != ControlSerialEmpty?.PortName ? Utils.OpenSerialConnection($"serial://{parts[0]}:9600") : ControlSerialEmpty;
|
||||||
|
} else if (parts.Length != 1) {
|
||||||
|
throw new ArgumentException("Invalid value for 'filling'");
|
||||||
|
}
|
||||||
|
FillingClearanceMode = ConvertOutput(parts[^1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FillingClearanceMode != null && WeightLimit == null)
|
||||||
|
throw new ArgumentException("Weight limit has to be set, if filling clearance supervision is enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
Stream.Close();
|
||||||
|
Serial?.Close();
|
||||||
|
ControlSerialEmpty?.Close();
|
||||||
|
ControlSerialFilling?.Close();
|
||||||
|
Tcp?.Close();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Output? ConvertOutput(string? value) {
|
||||||
|
return value switch {
|
||||||
|
null => null,
|
||||||
|
"RTS" => Output.RTS,
|
||||||
|
"DTR" => Output.DTR,
|
||||||
|
"OUT1" => Output.OUT1,
|
||||||
|
"OUT2" => Output.OUT2,
|
||||||
|
_ => throw new ArgumentException($"Invalid value for argument: '{value}'"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
Elwig/Helpers/Weighing/SchemberEventScale.cs
Normal file
22
Elwig/Helpers/Weighing/SchemberEventScale.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
namespace Elwig.Helpers.Weighing {
|
||||||
|
public class SchemberEventScale : Scale, IEventScale {
|
||||||
|
|
||||||
|
public string Manufacturer => "Schember";
|
||||||
|
public int InternalScaleNr => 1;
|
||||||
|
public string Model { get; private set; }
|
||||||
|
public string ScaleId { get; private set; }
|
||||||
|
public bool IsReady { get; private set; }
|
||||||
|
public bool HasFillingClearance { get; private set; }
|
||||||
|
|
||||||
|
public SchemberEventScale(string id, string model, string cnx, string? empty = null, string? filling = null, int? limit = null, string? log = null) :
|
||||||
|
base(cnx, empty, filling, limit, log) {
|
||||||
|
ScaleId = id;
|
||||||
|
Model = model;
|
||||||
|
IsReady = true;
|
||||||
|
HasFillingClearance = false;
|
||||||
|
Stream.WriteTimeout = 250;
|
||||||
|
Stream.ReadTimeout = 6000;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Ports;
|
using System.IO.Ports;
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Elwig.Helpers.Weighing {
|
namespace Elwig.Helpers.Weighing {
|
||||||
public class SystecScale : ICommandScale {
|
public class SysTecITScale : Scale, ICommandScale {
|
||||||
|
|
||||||
protected enum Output { RTS, DTR, OUT1, OUT2 };
|
|
||||||
|
|
||||||
protected SerialPort? Serial = null;
|
|
||||||
protected SerialPort? ControlSerialEmpty = null, ControlSerialFilling = null;
|
|
||||||
protected TcpClient? Tcp = null;
|
|
||||||
protected Stream Stream;
|
|
||||||
|
|
||||||
protected readonly Output? EmptyMode = null;
|
|
||||||
protected readonly Output? FillingClearanceMode = null;
|
|
||||||
protected readonly int EmptyDelay;
|
|
||||||
|
|
||||||
public string Manufacturer => "SysTec";
|
public string Manufacturer => "SysTec";
|
||||||
public int InternalScaleNr => 1;
|
public int InternalScaleNr => 1;
|
||||||
@ -25,74 +13,15 @@ namespace Elwig.Helpers.Weighing {
|
|||||||
public string ScaleId { get; private set; }
|
public string ScaleId { get; private set; }
|
||||||
public bool IsReady { get; private set; }
|
public bool IsReady { get; private set; }
|
||||||
public bool HasFillingClearance { get; private set; }
|
public bool HasFillingClearance { get; private set; }
|
||||||
public int? WeightLimit { get; private set; }
|
|
||||||
public string? LogPath { get; private set; }
|
|
||||||
|
|
||||||
public SystecScale(string id, string model, string connection, string? empty = null, string? filling = null, int? limit = null, string? log = null) {
|
public SysTecITScale(string id, string model, string cnx, string? empty = null, string? filling = null, int? limit = null, string? log = null) :
|
||||||
|
base(cnx, empty, filling, limit, log) {
|
||||||
ScaleId = id;
|
ScaleId = id;
|
||||||
Model = model;
|
Model = model;
|
||||||
IsReady = true;
|
IsReady = true;
|
||||||
HasFillingClearance = false;
|
HasFillingClearance = false;
|
||||||
LogPath = log;
|
|
||||||
|
|
||||||
if (connection.StartsWith("serial:")) {
|
|
||||||
Serial = Utils.OpenSerialConnection(connection);
|
|
||||||
Stream = Serial.BaseStream;
|
|
||||||
} else if (connection.StartsWith("tcp:")) {
|
|
||||||
Tcp = Utils.OpenTcpConnection(connection);
|
|
||||||
Stream = Tcp.GetStream();
|
|
||||||
} else {
|
|
||||||
throw new ArgumentException("Unsupported scheme");
|
|
||||||
}
|
|
||||||
Stream.WriteTimeout = 250;
|
Stream.WriteTimeout = 250;
|
||||||
Stream.ReadTimeout = 11000;
|
Stream.ReadTimeout = 11000;
|
||||||
|
|
||||||
if (empty != null) {
|
|
||||||
var parts = empty.Split(':');
|
|
||||||
if (parts.Length == 3) {
|
|
||||||
if (parts[0] != Serial?.PortName)
|
|
||||||
ControlSerialEmpty = Utils.OpenSerialConnection($"serial://{parts[0]}:9600");
|
|
||||||
} else if (parts.Length != 2) {
|
|
||||||
throw new ArgumentException("Invalid value for 'empty'");
|
|
||||||
}
|
|
||||||
EmptyMode = ConvertOutput(parts[^2]);
|
|
||||||
EmptyDelay = int.Parse(parts[^1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
WeightLimit = limit;
|
|
||||||
if (filling != null) {
|
|
||||||
var parts = filling.Split(':');
|
|
||||||
if (parts.Length == 2) {
|
|
||||||
if (parts[0] != Serial?.PortName)
|
|
||||||
ControlSerialFilling = parts[0] != ControlSerialEmpty?.PortName ? Utils.OpenSerialConnection($"serial://{parts[0]}:9600") : ControlSerialEmpty;
|
|
||||||
} else if (parts.Length != 1) {
|
|
||||||
throw new ArgumentException("Invalid value for 'filling'");
|
|
||||||
}
|
|
||||||
FillingClearanceMode = ConvertOutput(parts[^1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FillingClearanceMode != null && WeightLimit == null)
|
|
||||||
throw new ArgumentException("Weight limit has to be set, if filling clearance supervision is enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
Stream.Close();
|
|
||||||
Serial?.Close();
|
|
||||||
ControlSerialEmpty?.Close();
|
|
||||||
ControlSerialFilling?.Close();
|
|
||||||
Tcp?.Close();
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static Output? ConvertOutput(string? value) {
|
|
||||||
return value switch {
|
|
||||||
null => null,
|
|
||||||
"RTS" => Output.RTS,
|
|
||||||
"DTR" => Output.DTR,
|
|
||||||
"OUT1" => Output.OUT1,
|
|
||||||
"OUT2" => Output.OUT2,
|
|
||||||
_ => throw new ArgumentException($"Invalid value for argument: '{value}'"),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task SendCommand(string command) {
|
protected async Task SendCommand(string command) {
|
@ -5,7 +5,7 @@ namespace Tests.WeighingTests {
|
|||||||
class ScaleTestMatzen {
|
class ScaleTestMatzen {
|
||||||
|
|
||||||
private MockScale? Mock;
|
private MockScale? Mock;
|
||||||
private SystecScale? Scale;
|
private SysTecITScale? Scale;
|
||||||
|
|
||||||
private static (string, bool) ScaleHandler(string req, int weight, string? error, int identNr) {
|
private static (string, bool) ScaleHandler(string req, int weight, string? error, int identNr) {
|
||||||
var modes = error?.Split(';') ?? [];
|
var modes = error?.Split(';') ?? [];
|
||||||
|
Reference in New Issue
Block a user