using System; using System.IO; using System.IO.Ports; using System.Text; using System.Threading.Tasks; namespace Elwig.Helpers.Weighing { public class GassnerScale : Scale, ICommandScale { public string Manufacturer => "Gassner"; 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 GassnerScale(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 = 11000; } protected Task SendCommand(char command) => SendCommand(Convert.ToByte(command)); protected async Task SendCommand(byte command) { byte[] cmd = [command]; await Stream.WriteAsync(cmd); if (LogPath != null) await File.AppendAllTextAsync(LogPath, Encoding.ASCII.GetString(cmd)); } protected async Task ReceiveResponse() { var line = await Reader.ReadUntilAsync('\x03'); if (LogPath != null) await File.AppendAllTextAsync(LogPath, $"{line}\r\n"); if (line == null || line.Length < 4 || !line.StartsWith('\x02')) { throw new IOException("Invalid response from scale"); } var status = line[1..3]; if (status[0] == 'E' || status[1] != 'S') { string msg = $"Unbekannter Fehler (Fehler code {status})"; switch (status[1]) { case 'M': msg = "Waage in Bewegung"; break; } throw new IOException($"Waagenfehler {status}: {msg}"); } else if (status[0] != ' ') { throw new IOException($"Invalid response from scale (error code {status})"); } return line[1..^1]; } protected async Task Weigh(bool incIdentNr) { await SendCommand(incIdentNr ? '\x05' : '?'); string record = await ReceiveResponse(); if (record.Length != 45) throw new IOException("Invalid response from scale: Received record has invalid size"); var line = record[2..]; var brutto = line[ 0.. 7].Trim(); var tara = line[ 7..14].Trim(); var netto = line[14..21].Trim(); var scaleNr = line[21..23].Trim(); var identNr = line[23..29].Trim(); var date = line[29..37]; var time = line[37..43]; identNr = identNr.Length > 0 && identNr != "0" ? identNr : null; var parsedDate = DateOnly.ParseExact(date, "yyyyMMdd"); return new() { Weight = int.Parse(netto), WeighingId = identNr, FullWeighingId = identNr, Date = parsedDate, Time = TimeOnly.ParseExact(time, "HHmmss"), }; } public async Task Weigh() { return await Weigh(true); } public async Task GetCurrentWeight() { return await Weigh(false); } public async Task Empty() { SerialPort? p = ControlSerialEmpty ?? Serial; if (EmptyMode == Output.RTS && p != null) { p.RtsEnable = true; await Task.Delay(EmptyDelay); p.RtsEnable = false; } else if (EmptyMode == Output.DTR && p != null) { p.DtrEnable = true; await Task.Delay(EmptyDelay); p.DtrEnable = false; } } protected Task SetFillingClearance(bool status) { SerialPort? p = ControlSerialFilling ?? Serial; if (FillingClearanceMode == Output.RTS && p != null) { p.RtsEnable = status; } else if (FillingClearanceMode == Output.DTR && p != null) { p.DtrEnable = status; } return Task.CompletedTask; } public async Task GrantFillingClearance() { await SetFillingClearance(true); } public async Task RevokeFillingClearance() { await SetFillingClearance(false); } } }