temp commit: branch changing

This commit is contained in:
Stoyan Zlatev 2024-07-30 14:02:14 +02:00
parent 44688c5dc4
commit d4f6fa1eb1
76 changed files with 2037 additions and 1120 deletions

View File

@ -3,14 +3,71 @@
using Common.Utils.Extensions;
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
//var connector = new EregisterConnector();
var econnector = new EregisterConnector.EregisterConnector();
//connector.InitInspection();
econnector.InitInspection();
}
//var payloadLength = 32;
//var payload = new Byte[payloadLength];
//for (var i = 0; i < 32; i++)
//{
// payload[i] = (Byte)(i + 1);
//}
//var withAddress = new Byte[payloadLength + 4];
//Array.Copy(payload, 0, withAddress, 4, payloadLength);
//var keyLength = 16;
//var key = new Byte[keyLength];
//for (var i = 0; i < keyLength; i++)
//{
// payload[i] = (Byte)(keyLength - i);
//}
//Console.WriteLine(BitConverter.ToString(key));
//Console.WriteLine(BitConverter.ToString(withAddress));
//Console.WriteLine(BitConverter.ToString(Encrypt(payload, key, 0)));
static Byte[] Encrypt(Byte[] bytes, Byte[] key, Int32 address)
{
var requestBytesList = new List<Byte>(bytes);
var addressBytes = address.ToBigEndianBytes();
requestBytesList.InsertRange(9, addressBytes);
var bytesToEncryptCount = requestBytesList.Count; // 4(address) + 2(crc)
var keyByte = Byte.MaxValue;
var reference = address;
for (Int32 encryptIndex = 0; encryptIndex < bytesToEncryptCount; encryptIndex++, encryptIndex++)
{
// Update KeyDefinition for this byte
keyByte += (Byte)(((reference >> ((keyByte & 0x3) << 3)) & 0xFF) >> ((keyByte >> 6) & 1));
// Update the unencrypted reference before the byte gets encrypted
reference = reference << 8;
reference += requestBytesList[encryptIndex];
// Encrypt the data by applying the resepective key
requestBytesList[encryptIndex] ^= key[(keyByte >> 2) & 0x0F];
// Check if data has to be inverted
if (keyByte > 127)
{
requestBytesList[encryptIndex] = (Byte)~requestBytesList[encryptIndex];
}
}
return requestBytesList.ToArray();
}
}
}

View File

@ -64,10 +64,12 @@
<Compile Include="SIRTConstants.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SIRTTask.cs" />
<Compile Include="SIRTTask[TRequest].cs" />
<Compile Include="Tasks\ActivateSIRTTask.cs" />
<Compile Include="Tasks\IdentifySIRTTask.cs" />
<Compile Include="Tasks\ReadPamPoolTask.cs" />
<Compile Include="Tasks\WritePamTask.cs" />
<Compile Include="Tasks\RPAMTask.cs" />
<Compile Include="Tasks\WPAMTask.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Utils\Crc16Ccitt\Crc16Ccitt.csproj">

View File

@ -0,0 +1,57 @@
namespace Common.Hardware.Interfaces.Ports.SIRT
{
using Common.Hardware.Interfaces.Ports.SIRT.Responses;
using System;
public abstract class SIRTTask<TRequest> : SIRTTask where TRequest : SIRTRequest, new()
{
protected readonly TRequest request;
protected SIRTTask(UInt32 timeoutSeconds = TIMEOUT_SECONDS)
{
this.request = new TRequest();
this.Cmd = this.request.message.Cmd;
}
protected SIRTTask(TRequest request, UInt32 timeoutSeconds = TIMEOUT_SECONDS)
: this(timeoutSeconds)
=> this.request = request;
public override UInt32 Address
{
get => this.request.Address;
set => this.request.Address = value;
}
public override Byte[] Payload
{
get => this.request.Payload;
set => this.request.Payload = value;
}
internal override void BeginAddResponse(AcknOrAnswerResponse response)
{
this.BeginAddResponse();
var done = this.AcknOrAnswerReceived(response);
this.EndAddResponse(done);
}
internal override void BeginAddResponse(FromAirResponse response)
{
this.BeginAddResponse();
var done = this.FromAirReceived(response);
this.EndAddResponse(done);
}
protected virtual Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response) => false;
protected virtual Boolean FromAirReceived(FromAirResponse response) => false;
protected override Byte[] GetRequestBytes() => this.request;
}
}

View File

@ -27,22 +27,29 @@
this.DataReceived += this.SirtBroadcaster_DataReceived;
}
public String SIRTID { get; private set; }
public UInt16 Frequency { get; private set; }
public event Action<String, Int32> Activated;
public event Action<UInt32> EndpointAvailable;
public event Action<UInt32[]> PamPoolChanged;
public String SIRTID { get; private set; }
public UInt16 Frequency { get; private set; }
public void Run(SIRTTask task)
{
task.AddressChanged += (oldAddress, newAddress) =>
{
task.Done += _ =>
{
/// Remove old address from the tasks pool
this.tasks.TryRemove(oldAddress, out var _);
};
/// Add the new address to the tasks pool
this.tasks
.GetOrAdd(newAddress, new Queue<SIRTTask>())
.Enqueue(task);
/// Remove old address from the pam pool
this.Write(new WritePamRequest
{
DelPamAdr = true,
@ -116,6 +123,8 @@
this.Run(identificationTask);
manuelResetEventSlim.Wait();
manuelResetEventSlim.Reset();
this.Activated?.Invoke(this.SIRTID, this.Frequency);
}
private void SirtBroadcaster_DataReceived(Byte[] data)
@ -160,8 +169,6 @@
{
if (state is SIRTBroadcaster broadcaster)
{
var awaiter = new ManualResetEventSlim();
/// Loop while cancellation requested ...
while (!broadcaster.cancellationToken.IsCancellationRequested)
{
@ -190,11 +197,12 @@
/// When current task is not running and is not cancelled or done ...
if (!current.IsRunning)
{
var notWritePamTask = current.Type != SIRTConstants.WritePam;
var notInPamPool = !broadcaster.pamPool.Values.ToArray().Any(x => x == current.Address);
var notWritePamTask = current.Cmd != SIRTConstants.WritePam;
var pamPoolNotFull = !broadcaster.pamPool.Values.Any(x => x == 0);
var notInPamPool = !broadcaster.pamPool.Values.Any(x => x == current.Address);
/// ... and also is write to pam task and is not into the pam pool ...
if (notWritePamTask || notInPamPool)
if (notWritePamTask || (pamPoolNotFull && notInPamPool))
{
/// ... mark as running ...
current.IsRunning = true;
@ -207,16 +215,7 @@
/// Break and go to the next address with tasks.
break;
}
/// Break in case the pam pool is full.
if (pamPool.Count > 0 && !pamPool.Values.Any(x => x == 0))
{
break;
}
}
awaiter.Wait(250, broadcaster.cancellationToken);
awaiter.Reset();
}
}
}, this, this.cancellationToken)
@ -249,8 +248,6 @@
task.Done += _ => awaiter.Set();
task.AddressesParsed += addresses =>
{
broadcaster.PamPoolChanged?.Invoke(addresses);
var length = addresses.Length;
for (Byte i = 0; i < length; i++)
@ -265,10 +262,7 @@
broadcaster.Run(task);
awaiter.Wait(broadcaster.cancellationToken);
awaiter.Reset();
awaiter.Wait(500, broadcaster.cancellationToken);
awaiter.Wait();
awaiter.Reset();
}
}

View File

@ -1,67 +1,60 @@
namespace Common.Hardware.Interfaces.Ports.SIRT
{
using Common.Hardware.Interfaces.Ports.SIRT.Requests;
using Common.Hardware.Interfaces.Ports.SIRT.Responses;
using System;
public abstract class SIRTTask
{
protected readonly SIRTRequest request;
private readonly UInt32 timeout;
protected const UInt32 TIMEOUT_SECONDS = 60;
protected readonly UInt32 timeout;
private WriteRegRequest writeRegRequest;
private ReadRegRequest readRegRequest;
private ReadPamRequest readPamRequest;
public SIRTTask(SIRTRequest request, UInt32 timeout = 10)
public SIRTTask(UInt32 timeoutSeconds = TIMEOUT_SECONDS)
{
this.request = request;
this.timeout = timeout;
this.Type = this.request.message.Cmd;
this.Address = this.request.Address;
this.timeout = timeoutSeconds;
this.Timestamp = DateTime.MinValue;
}
protected SIRTTask(WriteRegRequest writeRegRequest)
{
this.writeRegRequest = writeRegRequest;
}
protected SIRTTask(ReadRegRequest readRegRequest)
{
this.readRegRequest = readRegRequest;
}
protected SIRTTask(ReadPamRequest readPamRequest)
{
this.readPamRequest = readPamRequest;
}
public event Action<SIRTTask> Done;
public event Action<SIRTTask> Cancelled;
public event Action<UInt32, UInt32> AddressChanged;
public Byte Type { get; }
public virtual UInt32 Address { get; set; }
public Boolean IsRunning { get; internal set; }
public virtual Byte[] Payload { get; set; }
public Boolean IsRunning { get; set; }
public Byte Cmd { get; protected set; }
public DateTime Timestamp { get; protected set; }
public Boolean IsDone { get; protected set; }
public Boolean IsCancelled { get; protected set; }
public DateTime? Timestamp { get; protected set; }
internal abstract void BeginAddResponse(AcknOrAnswerResponse response);
internal void BeginAddResponse(AcknOrAnswerResponse response)
{
if (this.CanReceiveResponses())
{
var done = this.AcknOrAnswerReceived(response);
this.EndAddResponse(done);
}
}
internal void BeginAddResponse(FromAirResponse response)
{
if (this.CanReceiveResponses())
{
var done = this.FromAirReceived(response);
this.EndAddResponse(done);
}
}
protected virtual Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response)
{
return false;
}
protected virtual Boolean FromAirReceived(FromAirResponse response)
{
return false;
}
internal abstract void BeginAddResponse(FromAirResponse response);
protected void NotifyCancelled()
{
@ -78,38 +71,30 @@
}
protected void NotifyAddressChanged(UInt32 oldAddress, UInt32 newAddress)
=> this.AddressChanged?.Invoke(oldAddress, newAddress);
protected void BeginAddResponse()
{
this.Address = newAddress;
this.AddressChanged?.Invoke(oldAddress, newAddress);
}
protected virtual Byte[] GetRequestBytes() => this.request;
private Boolean CanReceiveResponses()
{
var canReceiveResponses = !this.IsDone && !this.IsCancelled;
if (canReceiveResponses && this.Timestamp is null)
if (this.Timestamp == DateTime.MinValue)
{
this.Timestamp = DateTime.Now;
}
return canReceiveResponses;
}
private void EndAddResponse(Boolean isDone)
protected void EndAddResponse(Boolean isDone)
{
if (isDone)
{
this.NotifyDone();
}
else if ((DateTime.Now - this.Timestamp.Value).TotalSeconds > this.timeout)
else if ((DateTime.Now - this.Timestamp).TotalSeconds > this.timeout)
{
this.NotifyCancelled();
}
}
public static implicit operator Byte[] (SIRTTask task) => task.request;
protected abstract Byte[] GetRequestBytes();
public static implicit operator Byte[] (SIRTTask task) => task.GetRequestBytes();
}
}

View File

@ -36,6 +36,21 @@
}
}) { }
protected override Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response) => response.IsValid;
protected Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response) => response.IsValid;
protected override Byte[] GetRequestBytes()
{
throw new NotImplementedException();
}
internal override void BeginAddResponse(AcknOrAnswerResponse response)
{
throw new NotImplementedException();
}
internal override void BeginAddResponse(FromAirResponse response)
{
throw new NotImplementedException();
}
}
}

View File

@ -15,7 +15,7 @@
public event Action<String> Identified;
protected override Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response)
protected Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response)
{
if (!response.IsValid)
{
@ -36,5 +36,20 @@
return identified;
}
protected override Byte[] GetRequestBytes()
{
throw new NotImplementedException();
}
internal override void BeginAddResponse(AcknOrAnswerResponse response)
{
throw new NotImplementedException();
}
internal override void BeginAddResponse(FromAirResponse response)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,19 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Tasks
{
using Common.Hardware.Interfaces.Ports.SIRT.Requests;
using System;
public class RPAMTask : SIRTTask<ReadPamRequest>
{
public RPAMTask(UInt32 timeoutSeconds = TIMEOUT_SECONDS) : base(timeoutSeconds)
{
}
public Boolean PamStruct
{
get => this.request.PamStruct;
set => this.request.PamStruct = value;
}
}
}

View File

@ -14,7 +14,7 @@
public event Action<UInt32[]> AddressesParsed;
protected override Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response)
protected Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response)
{
if (!response.IsValid)
{
@ -55,5 +55,20 @@
return parsed;
}
protected override Byte[] GetRequestBytes()
{
throw new NotImplementedException();
}
internal override void BeginAddResponse(AcknOrAnswerResponse response)
{
throw new NotImplementedException();
}
internal override void BeginAddResponse(FromAirResponse response)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,56 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Tasks
{
using Common.Hardware.Interfaces.Ports.SIRT.Requests;
using System;
public class WPAMTask : SIRTTask<WritePamRequest>
{
public WPAMTask(UInt32 timeoutSeconds = TIMEOUT_SECONDS) : base(timeoutSeconds)
{
}
public Boolean WakeUpModul
{
get => this.request.WakeUpModul;
set => this.request.WakeUpModul = value;
}
public Boolean WakeUpCmd
{
get => this.request.WakeUpCmd;
set => this.request.WakeUpCmd = value;
}
public Boolean IgnoreTimeout
{
get => this.request.IgnoreTimeout;
set => this.request.IgnoreTimeout = value;
}
public Boolean DelPamSemi
{
get => this.request.DelPamSemi;
set => this.request.DelPamSemi = value;
}
public Boolean DelPamTx
{
get => this.request.DelPamTx;
set => this.request.DelPamTx = value;
}
public Boolean DelPamAdr
{
get => this.request.DelPamAdr;
set => this.request.DelPamAdr = value;
}
public Boolean DelPamAll
{
get => this.request.DelPamAll;
set => this.request.DelPamAll = value;
}
}
}

View File

@ -1,15 +0,0 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Tasks
{
using System;
public class WritePamTask : SIRTTask
{
public WritePamTask(SIRTRequest request) : base(request)
{
}
public WritePamTask(SIRTRequest request, UInt32 timeout) : base(request, timeout)
{
}
}
}

View File

@ -42,7 +42,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="IRDASerialPort.cs" />
<Compile Include="SerialPort.cs" />
<Compile Include="SerialPortBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SerialPortBaudRate.cs" />
@ -52,6 +51,7 @@
<Compile Include="SerialPortSettings.cs" />
<Compile Include="SerialPortStopBits.cs" />
<Compile Include="SIRTSerialPort.cs" />
<Compile Include="UI1236Control.cs" />
<Compile Include="UniProSerialPort.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -1,9 +1,8 @@
namespace Common.Hardware.Interfaces.Ports
{
using System;
using System.Threading;
public class IRDASerialPort : SerialPort
public class IRDASerialPort : SerialPortBase
{
public IRDASerialPort(SerialPortSettings settings) : base(settings)
{
@ -15,33 +14,24 @@
if (data.TryParseToIrda(out var bytes))
{
for (var i = 0; i < 3; i++)
var timeout = 3;
for (var i = 0; i < timeout; i++)
{
this.serialPortBase.Write(new Byte[] { 0x01, 0x01, 0x01, 0x01 }, 0, 4);
Thread.Sleep(1);
this.serialPortBase.Write(bytes, 0, bytes.Length);
var timeout = 3;
this.Write(new Byte[] { 0x01, 0x01, 0x01, 0x01 }, 0, 4);
this.Write(bytes, 0, bytes.Length);
var answerd = false;
var buffer = new Byte[0];
while (timeout-- >= 0)
{
Thread.Sleep(50);
var _bytes = this.serialPortBase.Read();
var _bytes = this.Read();
var bytesLength = _bytes.Length;
var bufferLength = buffer.Length;
Thread.Sleep(50);
Array.Resize(ref buffer, bufferLength + bytesLength);
Thread.Sleep(50);
Array.Copy(_bytes, 0, buffer, bufferLength, bytesLength);
Thread.Sleep(50);
if (buffer.TryParseFromIrda(out _data))
{

View File

@ -1,37 +0,0 @@
namespace Common.Hardware.Interfaces.Ports
{
using System;
public abstract class SerialPort
{
internal readonly SerialPortBase serialPortBase;
public SerialPort(SerialPortSettings settings)
=> this.serialPortBase = new SerialPortBase(settings);
public event Action<String> Logging
{
add => this.serialPortBase.Logging += value;
remove => this.serialPortBase.Logging -= value;
}
public Boolean IsOpen => this.serialPortBase.IsOpen;
public virtual void Close() => this.serialPortBase.Close();
public virtual void EnsureConnected()
{
if (!this.serialPortBase.IsOpen)
{
this.serialPortBase.Close();
this.serialPortBase.Open();
}
}
protected void Notify(String message) => this.serialPortBase.Notify(message);
public virtual void Open() => this.serialPortBase.Open();
public abstract Byte[] Write(params Byte[] data);
}
}

View File

@ -2,10 +2,10 @@
{
using System;
using System.Collections.Concurrent;
using System.Threading;
using SystemSerialPort = System.IO.Ports.SerialPort;
internal class SerialPortBase
public abstract class SerialPortBase
{
private static readonly ConcurrentDictionary<String, SystemSerialPort> serialPorts
= new ConcurrentDictionary<String, SystemSerialPort>();
@ -30,7 +30,7 @@
? serialPort?.ReadBufferSize ?? default(Int32)
: default(Int32);
public void Close()
public virtual void Close()
{
try
{
@ -60,7 +60,16 @@
}
}
public void Open()
public virtual void EnsureConnected()
{
if (!this.IsOpen)
{
this.Close();
this.Open();
}
}
public virtual void Open()
{
try
{
@ -96,33 +105,6 @@
}
}
public Byte[] Read()
{
var bytes = new Byte[0];
if (serialPorts.TryGetValue(this.PortName, out var serialPort) && serialPort.IsOpen)
{
var size = this.ReadBufferSize;
var buffer = new Byte[size];
try
{
var copyLength = serialPort.Read(buffer, 0, size);
Array.Resize(ref bytes, copyLength);
Array.Copy(buffer, 0, bytes, 0, copyLength);
this.Notify($"RX|{BitConverter.ToString(bytes)}");
}
catch (Exception e)
{
this.Notify(e.ToString());
}
}
return bytes;
}
public override String ToString()
=> serialPorts.TryGetValue(this.PortName, out var serialPort)
? $"{serialPort.PortName}, " +
@ -136,7 +118,51 @@
$"{this.settings.Parity}, " +
$"{this.settings.StopBits}";
public void Write(Byte[] bytes, Int32 start, Int32 length)
public virtual Byte[] Write(params Byte[] data)
{
this.Write(data, 0, data.Length);
return data;
}
protected void Notify(String message) => this.Logging?.Invoke(message);
protected Byte[] Read(Int32 sleep = 100)
{
Thread.Sleep(sleep);
var bytes = new Byte[0];
if (serialPorts.TryGetValue(this.PortName, out var serialPort) && serialPort.IsOpen)
{
var size = this.ReadBufferSize;
var buffer = new Byte[size];
try
{
if (serialPort.IsOpen)
{
var copyLength = serialPort.Read(buffer, 0, size);
Array.Resize(ref bytes, copyLength);
Array.Copy(buffer, 0, bytes, 0, copyLength);
if (this.settings.RXLoggingEnabled)
{
this.Notify($"RX|{BitConverter.ToString(bytes)}");
}
}
}
catch (Exception e)
{
this.Notify(e.ToString());
}
}
return bytes;
}
protected void Write(Byte[] bytes, Int32 start, Int32 length, Int32 sleep = 1)
{
if (serialPorts.TryGetValue(this.PortName, out var serialPort) && serialPort.IsOpen)
{
@ -144,16 +170,18 @@
{
serialPort.Write(bytes, start, length);
this.Notify($"TX|{BitConverter.ToString(bytes)}");
if (this.settings.TXLoggingEnabled)
{
this.Notify($"TX|{BitConverter.ToString(bytes)}");
}
}
catch (Exception e)
{
this.Notify(e.ToString());
}
}
}
public void Notify(String message)
=> this.Logging?.Invoke(message);
Thread.Sleep(sleep);
}
}
}

View File

@ -2,7 +2,7 @@
{
using System;
public static class SerialPortExtensions
public static partial class SerialPortExtensions
{
public const Byte UNIPRO_START = 0x53;
public const Byte UNIPRO_PC2REG = 0x57;
@ -257,7 +257,7 @@
/// <para>n-2. .... - Checksum 0 </para>
/// <para>n-1. .... - Checksum 1 </para>
/// </summary>
public static Boolean FromUI1236(this Byte[] bytes, out Byte[] data)
public static Boolean TryParseFromUI1236(this Byte[] bytes, out Byte[] data)
{
data = new Byte[0];
@ -288,7 +288,7 @@
return false;
}
var dataLength = bytes[lengthIndex];
var dataLength = bytes[lengthIndex] - 3; // 3 = protocol bytes length (start|control|length)
if (dataIndex + dataLength > bytesLength)
{
@ -415,69 +415,5 @@
return BitConverter.GetBytes(crcSum);
}
internal class UI1236Control
{
private readonly Byte[] bits;
private UI1236Control(Byte[] bits)
=> this.bits = bits;
public Boolean E0Encryption => this.bits[0] == 1;
public Boolean E1Encryption => this.bits[1] == 1;
public Boolean E2Encryption => this.bits[2] == 1;
public Boolean ReturnResponse
{
get => this.bits[3] == 1;
set => this.bits[3] = (Byte)(value ? 1 : 0);
}
public Boolean NFNetwork => this.bits[4] == 1;
public Boolean MultipleCommands
{
get => this.bits[5] == 1;
set => this.bits[5] = (Byte)(value ? 1 : 0);
}
public Boolean LongControl
{
get => this.bits[6] == 1;
set => this.bits[6] = (Byte)(value ? 1 : 0);
}
public Boolean MultipleFrames
{
get => this.bits[7] == 1;
set => this.bits[7] = (Byte)(value ? 1 : 0);
}
public static implicit operator UI1236Control(Byte controlByte)
{
var bits = new Byte[8];
for (var i = 0; i < 8; i++)
{
bits[i] = (Byte)((controlByte >> i) & 1);
}
return new UI1236Control(bits);
}
public static implicit operator Byte(UI1236Control control)
{
var @Byte = default(Byte);
for (var i = 0; i < 8; i++)
{
@Byte ^= (Byte)(control.bits[i] << i);
}
return @Byte;
}
}
}
}

View File

@ -15,5 +15,9 @@
public SerialPortStopBits StopBits { get; set; }
public Int32 RWTimeout { get; set; } = 3000;
public Boolean RXLoggingEnabled { get; set; }
public Boolean TXLoggingEnabled { get; set; }
}
}

View File

@ -4,7 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
public class SIRTSerialPort : SerialPort
public class SIRTSerialPort : SerialPortBase
{
private CancellationTokenSource cancellationTokenSource;
private CancellationToken cancellationToken;
@ -21,7 +21,6 @@
public override void Close()
{
this.StopListening();
base.Close();
}
@ -29,27 +28,20 @@
{
base.EnsureConnected();
if (!this.listening)
if (this.listening)
{
this.StopListening();
this.StartListening();
}
this.StartListening();
}
public override void Open()
{
base.Open();
this.StartListening();
}
public override Byte[] Write(params Byte[] data)
{
this.serialPortBase.Write(data, 0, data.Length);
return data;
}
private void StartListening()
{
this.cancellationTokenSource = new CancellationTokenSource();
@ -66,9 +58,9 @@
var buffer = new Byte[0];
while (true)
while (!sirtSerialPort.cancellationToken.IsCancellationRequested)
{
var bytesIn = sirtSerialPort.serialPortBase.Read();
var bytesIn = sirtSerialPort.Read(0);
var bytesInLength = bytesIn.Length;
var bufferLength = buffer.Length;
@ -119,7 +111,7 @@
{
if (task.Exception != null)
{
sirtSerialPort.serialPortBase.Notify(task.Exception.ToString());
sirtSerialPort.Notify(task.Exception.ToString());
}
sirtSerialPort.listening = false;
@ -137,8 +129,10 @@
}
catch (Exception e)
{
this.serialPortBase.Notify(e.ToString());
this.Notify(e.ToString());
}
Thread.Sleep(1);
}
}
}

View File

@ -0,0 +1,71 @@
namespace Common.Hardware.Interfaces.Ports
{
using System;
public static partial class SerialPortExtensions
{
internal class UI1236Control
{
private readonly Byte[] bits;
private UI1236Control(Byte[] bits)
=> this.bits = bits;
public Boolean E0Encryption => this.bits[0] == 1;
public Boolean E1Encryption => this.bits[1] == 1;
public Boolean E2Encryption => this.bits[2] == 1;
public Boolean ReturnResponse
{
get => this.bits[3] == 1;
set => this.bits[3] = (Byte)(value ? 1 : 0);
}
public Boolean NFNetwork => this.bits[4] == 1;
public Boolean MultipleCommands
{
get => this.bits[5] == 1;
set => this.bits[5] = (Byte)(value ? 1 : 0);
}
public Boolean LongControl
{
get => this.bits[6] == 1;
set => this.bits[6] = (Byte)(value ? 1 : 0);
}
public Boolean MultipleFrames
{
get => this.bits[7] == 1;
set => this.bits[7] = (Byte)(value ? 1 : 0);
}
public static implicit operator UI1236Control(Byte controlByte)
{
var bits = new Byte[8];
for (var i = 0; i < 8; i++)
{
bits[i] = (Byte)((controlByte >> i) & 1);
}
return new UI1236Control(bits);
}
public static implicit operator Byte(UI1236Control control)
{
var @Byte = default(Byte);
for (var i = 0; i < 8; i++)
{
@Byte ^= (Byte)(control.bits[i] << i);
}
return @Byte;
}
}
}
}

View File

@ -1,9 +1,8 @@
namespace Common.Hardware.Interfaces.Ports
{
using System;
using System.Threading;
public class UniProSerialPort : SerialPort
public class UniProSerialPort : SerialPortBase
{
public UniProSerialPort(SerialPortSettings settings) : base(settings)
{
@ -15,31 +14,23 @@
if (data.TryParseToUniPro(out var bytes))
{
for (int i = 0; i < 3; i++)
var timeout = 3;
for (var i = 0; i < timeout; i++)
{
this.serialPortBase.Write(bytes, 0, bytes.Length);
this.Write(bytes, 0, bytes.Length);
Thread.Sleep(100);
var timeout = 3;
var answerd = false;
var buffer = new Byte[0];
while (timeout-- >= 0)
{
Thread.Sleep(100);
var _bytes = this.serialPortBase.Read();
var _bytes = this.Read();
var bytesLength = _bytes.Length;
var bufferLength = buffer.Length;
Thread.Sleep(100);
Array.Resize(ref buffer, bufferLength + bytesLength);
Thread.Sleep(100);
Array.Copy(_bytes, 0, buffer, bufferLength, bytesLength);
Thread.Sleep(100);
if (buffer.TryParseFromUniPro(out _data))
{

View File

@ -41,26 +41,57 @@
/// <summary>
/// Rate = 0.25 * 1/60 * 1/1 = .0041666667 Gal/sec which converts into a Float32 of into 0x3B888889.
/// </summary>
public float FlowRateGPM
public float FlowRateGPS
{
get => BitConverter.ToSingle(this.bytes, 4);
set
{
var flowRateGPM = value * (1F / 60) * (1F / 1);
var flowRateIEEE = BitConverter.GetBytes(flowRateGPM);
flowRateIEEE.CopyTo(this.bytes, 4);
}
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 4);
}
/// <summary>
/// 0x00015180 (86400) seconds, which is 24 hours.
/// Rate = 0.25 * 1/60 * 1/1 = .0041666667 Gal/sec which converts into a Float32 of into 0x3B888889.
/// </summary>
public float FlowRateGPM
{
get => this.FlowRateGPS * 60F;
set => this.FlowRateGPS = value / 60F;
}
/// <summary>
/// Converts the value from and to days.
/// </summary>
public uint TimeLimit
{
get => BitConverter.ToUInt32(this.bytes, 8);
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 8);
}
/// <summary>
/// Converts the value from and to days.
/// </summary>
public uint TimeLimitMinutes
{
get => this.TimeLimit / 60;
set => this.TimeLimit = value * 60;
}
/// <summary>
/// Converts the value from and to days.
/// </summary>
public uint TimeLimitHours
{
get => this.TimeLimitMinutes / 60;
set => this.TimeLimitMinutes = value * 60;
}
/// <summary>
/// Converts the value from and to days.
/// </summary>
public uint TimeLimitDays
{
get => this.TimeLimitHours / 24;
set => this.TimeLimitHours = value * 24;
}
}
public class LeakAlarm : Alarm

View File

@ -43,7 +43,7 @@
}
// 6
public byte VolumePerPulseUnit
public byte VolumePerPulseUnits
{
get => this.bytes[6];
set => this.bytes[6] = value;

View File

@ -16,16 +16,21 @@
PortName = portName,
StopBits = SerialPortStopBits.One
};
this.serialPort = new IRDASerialPort(settings);
this.serialPortBase = new IRDASerialPort(settings);
}
public override Byte[] Send(params Byte[] bytes)
{
this.serialPort.EnsureConnected();
this.serialPortBase.EnsureConnected();
if (bytes.TryParseToUI1236(out var _bytes))
{
return this.serialPort.Write(_bytes);
var __bytes = this.serialPortBase.Write(_bytes);
if (__bytes.TryParseFromUI1236(out var data))
{
return data;
}
}
return _bytes;

View File

@ -29,6 +29,9 @@
this.connection.Connect();
}
public Byte[] Send(params Byte[] bytes)
=> this.connection.Send(bytes);
public EheadPCB ViewEheadPCB()
{
var response = this.connection.Send(0xFA, 0x01);

View File

@ -9,11 +9,11 @@
{
private readonly StringBuilder records = new StringBuilder();
protected SerialPort serialPort;
protected SerialPortBase serialPortBase;
public void Connect() => this.serialPort.Open();
public void Connect() => this.serialPortBase.Open();
public void Disconnect() => this.serialPort.Close();
public void Disconnect() => this.serialPortBase.Close();
public String GetRecords()
{
@ -30,7 +30,7 @@
{
this.records.Clear();
this.serialPort.Logging += text => this.records.AppendLine(text);
this.serialPortBase.Logging += text => this.records.AppendLine(text);
}
}
}

View File

@ -16,14 +16,14 @@
PortName = portName,
StopBits = SerialPortStopBits.One
};
this.serialPort = new UniProSerialPort(settings);
this.serialPortBase = new UniProSerialPort(settings);
}
public override Byte[] Send(params Byte[] bytes)
{
this.serialPort.EnsureConnected();
this.serialPortBase.EnsureConnected();
return this.serialPort.Write(bytes);
return this.serialPortBase.Write(bytes);
}
}
}

View File

@ -4,6 +4,11 @@
public class ChangeTransmission : Pam
{
private Byte oldn;
private Byte newn;
private Byte oldt;
private Byte newt;
protected ChangeTransmission(Int32 length, Byte cmd) : base(length, cmd)
{
}
@ -12,14 +17,53 @@
{
}
public UInt16 Interval
public Byte LatWindowIntervalCount
{
get => BitConverter.ToUInt16(this.bytes, 1);
get => this.bytes[1];
set
{
var bytes = BitConverter.GetBytes(value);
this.oldn = this.newn;
this.newn = value;
Array.Copy(bytes, 0, this.bytes, 1, 2);
if (this.IsValid)
{
this.bytes[2] = this.newn;
}
else
{
this.newn = this.oldn;
this.oldn = this.bytes[2];
}
}
}
public Byte LatTXIntervalSeconds
{
get => this.bytes[2];
set
{
this.oldt = this.newt;
this.newt = value;
if (this.IsValid)
{
this.bytes[2] = this.newt;
}
else
{
this.newt = this.oldt;
this.oldt = this.bytes[2];
}
}
}
protected Boolean IsValid
{
get
{
var x = this.newt * (this.newn + 1);
return 0 < x && x <= 3600;
}
}
}

View File

@ -14,7 +14,7 @@
public Pam Append(Pam pam)
{
var appendBytes = pam.bytes;
var appendBytes = pam.ToByteArray();
var appendLength = appendBytes.Length;
var currentLength = this.bytes.Length;
var newLength = currentLength + appendLength;

View File

@ -53,7 +53,7 @@
<Compile Include="BUP.cs" />
<Compile Include="DEBUG.cs" />
<Compile Include="Endpoint.cs" />
<Compile Include="EndpointsBatch.cs" />
<Compile Include="ProgrammingBatch.cs" />
<Compile Include="EndpointTask.cs" />
<Compile Include="Epoch20000101.cs" />
<Compile Include="LAT.cs" />

View File

@ -15,9 +15,9 @@
public String HexKey { get; set; }
public EndpointTask WakeUpTask()
public EndpointTask WakeUp()
{
var request = new WritePamRequest
var request = new EndpointTask
{
Address = this.Address,
DelPamSemi = true,
@ -31,10 +31,54 @@
})
};
return new EndpointTask(request)
//return new EndpointTask(request)
//{
// HexKey = this.HexKey
//};
return request;
}
public EndpointTask InitializeForInspection()
{
var payload = new ChangeWakeUp()
{
HexKey = this.HexKey
Mode = WakeUpMode.StayAwake
}
.Append(new ChangeLATWindows
{
N = 0
})
.Append(new WMBusMode
{
WMBusEnabled = true,
InstallationModeEnabled = true,
EncryptionEnabled = true,
})
.Append(new ChangeTransmission
{
LatWindowIntervalCount = 0,
LatTXIntervalSeconds = 3
})
.Append(new ProvidePin
{
AuthLevel = AuthLevel.II
});
var request = new EndpointTask
{
Address = this.Address,
WakeUpCmd = true,
DelPamSemi = true,
Payload = payload
};
return request;
}
public EndpointTask ConfigureForInspection()
{
return new EndpointTask();
}
}
}

View File

@ -1,17 +1,17 @@
namespace Common.Hardware.WaterMeter.eRegister
{
using Common.Hardware.Interfaces.Ports.SIRT;
using Common.Hardware.Interfaces.Ports.SIRT.Responses;
using Common.Hardware.Interfaces.Ports.SIRT.Tasks;
using Common.Utils.Extensions;
using System;
using System.Collections.Generic;
public class EndpointTask : SIRTTask
public class EndpointTask : WPAMTask
{
private Byte[] key;
public EndpointTask(SIRTRequest request, UInt32 timeout = 15) : base(request, timeout)
public EndpointTask(UInt32 timeout = 15) : base(timeout)
{
}
@ -37,55 +37,7 @@
var payload = response.Payload;
var length = response.Payload.Length;
if (this.key?.Length == 16)
{
//var bytesToEncryptCount = this.request.Payload.Length + 6; // 4(address) + 2(crc)
//var keyByte = Byte.MaxValue;
//var reference = address;
//for (Int32 byteIndex = 9, encryptIndex = 0; byteIndex < bytesToEncryptCount; byteIndex++, encryptIndex++)
//{
// // Update KeyDefinition for this byte
// keyByte += (Byte)(((reference >> ((keyByte & 0x3) << 3)) & 0xFF) >> ((keyByte >> 6) & 1));
// // Update the unencrypted reference before the byte gets encrypted
// reference = reference << 8;
// reference += requestBytesList[encryptIndex];
// // Encrypt the data by applying the resepective key
// requestBytesList[encryptIndex] ^= this.key[(keyByte >> 2) & 0x0F];
// // Check if data has to be inverted
// if (keyByte > 127)
// {
// requestBytesList[encryptIndex] = (Byte)~requestBytesList[encryptIndex];
// }
//}
//byte[] Target = new byte[MessageAppFormat.Length];
//Array.Copy(MessageAppFormat, Target, MessageAppFormat.Length);
//int BeginEncryptedChars = 14;
//int EndEncryptedChars = BeginEncryptedChars + MessageAppFormat[7] - 6;
//byte Zeichen = MessageAppFormat[9];
//for (int i = BeginEncryptedChars; i < EndEncryptedChars; i++)
//{
// Zeichen += (byte)((Target[i - (Zeichen & 0x3) - 1] >> ((Zeichen >> 6) & 0x1)));
// Target[i] ^= Key[((Zeichen >> 2) & 0x0F)];
// if (Zeichen > 127)
// {
// Target[i] = (byte)~Target[i];
// }
//}
//if (TelegramCalcCRC(Target) == 0)
//{
// MessageAppFormat = Target;
// return true;
//}
//return false;
}
this.DecryptIfNecessery(payload, length);
if (length == 13)
{
@ -172,5 +124,30 @@
return bytes;
}
private void DecryptIfNecessery(Byte[] payload, Int32 length)
{
if (this.key?.Length == 16)
{
var target = new Byte[length];
Array.Copy(payload, target, length);
var end = target[7] - 6;
var token = target[9];
for (var start = 0; start < end; start++)
{
token += (Byte)(target[start - (token & 0x3) - 1] >> ((token >> 6) & 0x1));
target[start] ^= this.key[(token >> 2) & 0x0F];
if (token > 127)
{
target[start] = (Byte)~target[start];
}
}
}
}
}
}

View File

@ -7,12 +7,12 @@
using System.Collections.Generic;
using System.Linq;
public class EndpointsBatch
public class ProgrammingBatch
{
private readonly ICollection<Endpoint> endpoints;
private readonly SIRTBroadcaster broadcaster;
private readonly ICollection<Endpoint> endpoints;
public EndpointsBatch(String portName, Int32 rwTimeout = 3000)
public ProgrammingBatch(String portName, Int32 rwTimeout = 3000)
{
this.endpoints = new List<Endpoint>();
this.broadcaster = new SIRTBroadcaster(new SerialPortSettings
@ -26,13 +26,22 @@
});
}
public event Action<String, Int32> Activated
{
add => this.broadcaster.Activated += value;
remove => this.broadcaster.Activated -= value;
}
public Boolean IsConnected => this.broadcaster.IsOpen;
public void ConnectSIRT() => this.broadcaster.Open();
public void ActivateSIRT() => this.broadcaster.Open();
public IEnumerable<IEnumerable<EndpointTask>> InitInspection()
public void DeactivateSIRT() => this.broadcaster.Close();
public IEnumerable<IEnumerable<EndpointTask>> InitProgramming()
{
yield return this.endpoints.Select(x => x.WakeUpTask());
yield return this.endpoints.Select(x => x.InitializeForInspection());
yield return this.endpoints.Select(x => x.ConfigureForInspection());
}
}
}

View File

@ -11,7 +11,7 @@
public class EregisterConnector
{
private readonly EndpointsBatch endpoints;
private readonly ProgrammingBatch eprogramming;
private Application app;
private Window window;
@ -19,9 +19,15 @@
{
var portName = Appsettings.Current["SIRT.PortName"];
var _timeout = Appsettings.Current["SIRT.RWTimeout"];
var _ = Int32.TryParse(_timeout, out var timeout);
this.endpoints = new EndpointsBatch(portName, timeout);
if (Int32.TryParse(_timeout, out var timeout))
{
this.eprogramming = new ProgrammingBatch(portName, timeout);
}
else
{
this.eprogramming = new ProgrammingBatch(portName);
}
}
public void Add(Int32 posno, Int32 serialno, Int32 address, String encKey, String setup, Boolean skipChecks)
@ -34,14 +40,14 @@
var awaiter = new ManualResetEventSlim();
var threadStartCallback = new ParameterizedThreadStart((object parameter) =>
{
if (parameter is EndpointsBatch endpoints)
if (parameter is ProgrammingBatch endpoints)
{
this.app = new App();
this.window = new InitInspectionWindow();
if (this.window.DataContext is InitInspectionVM vm)
{
vm.Set(this.endpoints);
vm.InitInspection(this.eprogramming);
}
app.Run(window);
@ -50,7 +56,7 @@
});
var staThread = new Thread(threadStartCallback);
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start(this.endpoints);
staThread.Start(this.eprogramming);
awaiter.Wait();
}
}

View File

@ -5,9 +5,9 @@
</startup>
<appSettings>
<add key="PluginsDirectory" value="Z:\Programme_Sensus\plugins" />
<add key="APIURL" value="http://sla12iis01.emea.sensus.net/LaaProductionWeb" />
<!--<add key="APIURL" value="http://sla12iis01.emea.sensus.net/LaaProductionWeb" />-->
<add key="COMPorts" value="COM36" />
<add key="APIURL" value="http://localhost:52822/LaaProductionWeb" />
<add key="COMPorts" value="COM40" />
<add key="FlushMinutes" value="" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>

View File

@ -148,6 +148,10 @@
<Project>{C6BFAC88-5647-4131-90B1-4D6265E08348}</Project>
<Name>InspectionUI.Abstraction</Name>
</ProjectReference>
<ProjectReference Include="..\InspectionUI.Plugins.Omni\InspectionUI.Plugins.Omni.csproj">
<Project>{8E1431E9-9B14-4BC2-8B65-47357C97B1FC}</Project>
<Name>InspectionUI.Plugins.Omni</Name>
</ProjectReference>
<ProjectReference Include="..\InspectionUI.RemoteControl\InspectionUI.RemoteControl.csproj">
<Project>{41E949AD-FBF6-47A3-AC1D-7E17AB7F1252}</Project>
<Name>InspectionUI.RemoteControl</Name>

View File

@ -1,7 +1,7 @@
namespace InspectionUI
{
using InspectionUI.Abstraction.Interfaces;
using InspectionUI.Plugins.Omni;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
@ -68,30 +68,30 @@
get => this.plugin;
set
{
this.Set(() => this.plugin = value);
//this.Set(() => this.plugin = value);
this.Notifications = default(string);
this.IsCancelEnabled = false;
this.IsLoadEnabled = false;
this.IsStartEnabled = false;
this.testBench.Layout.Clear();
this.testBench.Layout.Refresh();
//this.Notifications = default(string);
//this.IsCancelEnabled = false;
//this.IsLoadEnabled = false;
//this.IsStartEnabled = false;
//this.testBench.Layout.Clear();
//this.testBench.Layout.Refresh();
Task.Factory
.StartNew(() =>
{
this.TestBatch = this.pluginsManager.Activate(value, this.testBench);
})
.ContinueWith(x =>
{
if (x.Exception != null)
{
this.Notifications = x.Exception.ToString();
}
//Task.Factory
// .StartNew(() =>
// {
// this.TestBatch = this.pluginsManager.Activate(value, this.testBench);
// })
// .ContinueWith(x =>
// {
// if (x.Exception != null)
// {
// this.Notifications = x.Exception.ToString();
// }
this.IsLoadEnabled = this.TestBatch != null;
this.TestBatch?.Initialize();
});
// this.IsLoadEnabled = this.TestBatch != null;
// this.TestBatch?.Initialize();
// });
}
}
@ -139,7 +139,7 @@
public ObservableCollection<string> Plugins { get; }
protected ITestBatch TestBatch { get; private set; }
protected TestBatch TestBatch { get; private set; }
public override void Dispose()
{
@ -158,7 +158,7 @@
this.IsLoadEnabled = false;
this.IsStartEnabled = false;
this.TestBatch?.LoadInspection();
this.TestBatch.LoadInspection();
})
.ContinueWith(task =>
{
@ -183,7 +183,7 @@
this.IsLoadEnabled = false;
this.IsStartEnabled = false;
this.TestBatch?.StartInspection();
this.TestBatch.StartInspection();
})
.ContinueWith(task =>
{
@ -234,33 +234,33 @@
Task.Factory
.StartNew(() =>
{
this.DispatcherInvoke(() =>
{
this.Plugins.Clear();
//this.DispatcherInvoke(() =>
//{
// this.Plugins.Clear();
foreach (var plugin in this.pluginsManager.AvailablePlugins())
{
this.Plugins.Add(plugin);
}
// //foreach (var plugin in this.pluginsManager.AvailablePlugins())
// //{
// // this.Plugins.Add(plugin);
// //}
this.PluginsDropdownVisibility = Visibility.Visible;
//= this.Plugins.Count > 1
//? Visibility.Visible
//: Visibility.Collapsed;
// this.PluginsDropdownVisibility = Visibility.Collapsed;
// //= this.Plugins.Count > 1
// //? Visibility.Visible
// //: Visibility.Collapsed;
//this.TestBatch = this.pluginsManager.Activate(null, this.testBench);
//this.IsLoadEnabled = this.TestBatch != null;
//this.TestBatch?.Initialize();
});
// this.TestBatch = this.pluginsManager.Activate(null, this.testBench);
// this.IsLoadEnabled = this.TestBatch != null;
// this.TestBatch?.Initialize();
//});
//this.DispatcherInvoke(this.Plugins.Clear);
//this.PluginsDropdownVisibility
// = this.Plugins.Count > 1
// ? Visibility.Visible
// : Visibility.Collapsed;
//this.TestBatch = this.pluginsManager.Activate(null, this.testBench);
//this.IsLoadEnabled = this.TestBatch != null;
//this.TestBatch?.Initialize();
this.DispatcherInvoke(this.Plugins.Clear);
this.PluginsDropdownVisibility
= this.Plugins.Count > 1
? Visibility.Visible
: Visibility.Collapsed;
this.TestBatch = this.pluginsManager.Activate(null, this.testBench);
this.IsLoadEnabled = this.TestBatch != null;
this.TestBatch?.Initialize();
})
.ContinueWith(task =>
{

View File

@ -2,7 +2,7 @@
{
using InspectionUI.Abstraction;
using InspectionUI.Abstraction.Interfaces;
using InspectionUI.Plugins.Omni;
using System;
using System.Collections.Generic;
using System.IO;
@ -16,24 +16,26 @@
internal bool IsActivated { get; private set; }
internal ITestBatch Activate(string plugin, ITestBench testBench)
internal TestBatch Activate(string plugin, ITestBench testBench)
{
if (!string.IsNullOrWhiteSpace(plugin) && this.entryPoints.ContainsKey(plugin))
{
var entryPoint = this.entryPoints[plugin];
var instance = Activator.CreateInstance(entryPoint, new object[] { testBench, App.Appsettings });
return new TestBatch(testBench, App.Appsettings);
if (instance is ITestBatch testBatch)
{
return testBatch;
}
}
//if (!string.IsNullOrWhiteSpace(plugin) && this.entryPoints.ContainsKey(plugin))
//{
// var entryPoint = this.entryPoints[plugin];
// var instance = Activator.CreateInstance(entryPoint, new object[] { testBench, App.Appsettings });
// if (instance is ITestBatch testBatch)
// {
// return testBatch;
// }
//}
//else
//{
// return new Plugins.Omni.TestBatch(testBench, App.Appsettings);
// return new TestBatch(testBench, App.Appsettings);
//}
return default(ITestBatch);
//return default(ITestBatch);
}
internal IEnumerable<string> AvailablePlugins()
@ -63,27 +65,27 @@
private static void CopyDirectories(string sourceDirectory, string destinationDirectory)
{
CopyFiles(sourceDirectory, destinationDirectory);
//CopyFiles(sourceDirectory, destinationDirectory);
foreach (var subDirectory in Directory.GetDirectories(sourceDirectory))
{
var subDirectoryName = new DirectoryInfo(subDirectory).Name;
var destinationSubDirectoryPath = Path.Combine(destinationDirectory, subDirectoryName);
var destinationSubDirectory = Directory.CreateDirectory(destinationSubDirectoryPath).FullName;
//foreach (var subDirectory in Directory.GetDirectories(sourceDirectory))
//{
// var subDirectoryName = new DirectoryInfo(subDirectory).Name;
// var destinationSubDirectoryPath = Path.Combine(destinationDirectory, subDirectoryName);
// var destinationSubDirectory = Directory.CreateDirectory(destinationSubDirectoryPath).FullName;
CopyDirectories(subDirectory, destinationSubDirectory);
}
// CopyDirectories(subDirectory, destinationSubDirectory);
//}
}
private static void CopyFiles(string sourceDirectory, string destinationDirectory)
{
foreach (var sourceFile in Directory.GetFiles(sourceDirectory))
{
var sourceFileName = Path.GetFileName(sourceFile);
var destinationFile = Path.Combine(destinationDirectory, sourceFileName);
//foreach (var sourceFile in Directory.GetFiles(sourceDirectory))
//{
// var sourceFileName = Path.GetFileName(sourceFile);
// var destinationFile = Path.Combine(destinationDirectory, sourceFileName);
File.Copy(sourceFile, destinationFile, true);
}
// File.Copy(sourceFile, destinationFile, true);
//}
}
}
}

View File

@ -44,13 +44,7 @@
public float FlowRateGPM
{
get => BitConverter.ToSingle(this.bytes, 4);
set
{
var flowRateGPM = value * (1F / 60) * (1F / 1);
var flowRateIEEE = BitConverter.GetBytes(flowRateGPM);
flowRateIEEE.CopyTo(this.bytes, 4);
}
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 4);
}
/// <summary>

View File

@ -147,7 +147,7 @@
ReadingPreset = configuration.Readings.Value,
RebootCount = 0,
SystemTime = Epoch20000101.UTCNow,
DeviceID = "OMNI-01"
DeviceID = defaults.DeviceID
});
if (setConfiguration.Completed)

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="DefaultSender" value="SAPImportLaatzen@xylem.com"/>
<add key="DefaultSender" value="stoyan.zlatev@xylem.com"/>
<add key="LogFolder" value="C:\Temp\PendingEmails"/>
</appSettings>
<connectionStrings>

View File

@ -11,6 +11,21 @@
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -48,5 +63,12 @@
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,193 +1,328 @@
namespace PendingEmails
{
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Threading;
using System.Timers;
using SystemTimersTimer = System.Timers.Timer;
public class Program
{
private static readonly SystemTimersTimer timer = new SystemTimersTimer();
private static void Main()
{
try
{
timer.AutoReset = true;
timer.Interval = 600_000;
timer.Elapsed += Timer_Elapsed;
while (true)
{
Timer_Elapsed(null, null);
timer.Start();
var awaiter = new ManualResetEventSlim();
awaiter.Wait();
timer.Stop();
}
}
catch (Exception e)
{
LogToFile(e);
}
}
private static void Timer_Elapsed(Object _, ElapsedEventArgs _1)
{
LogToFile($"loading pending emails");
var connectionString = ConfigurationManager.ConnectionStrings["Auftrag"].ConnectionString;
using (var connection = new SqlConnection(connectionString))
{
connection.FireInfoMessageEventOnUserErrors = true;
connection.InfoMessage += (_2, args) => LogToFile(args.Message);
connection.Open();
var updated = new HashSet<Int32>();
var countAll = 0;
using (var command = connection.CreateCommand())
{
command.CommandText = @"
SELECT [Sender]
, [Subject]
, [Body]
, [Recipients]
, [CC]
, [Id]
FROM [Messages]
WHERE [OutDate] IS NULL
ORDER BY [InDate] DESC";
using (var reader = command.ExecuteReader())
{
countAll++;
while (reader.Read())
{
try
{
var email = new MailMessage();
var from = ConfigurationManager.AppSettings["DefaultSender"];
var @default = true;
if (!reader.IsDBNull(0))
{
from = reader.GetString(0);
@default = false;
}
email.From = new MailAddress(from);
email.Subject = $"{reader.GetValue(1)}";
email.Body = $"{reader.GetValue(2)}";
$"{reader.GetValue(3)}"
.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => new MailAddress(x))
.ToList()
.ForEach(email.To.Add);
$"{reader.GetValue(4)}"
.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => new MailAddress(x))
.ToList()
.ForEach(email.CC.Add);
var emailId = reader.GetInt32(5);
if (SendEmail(email))
{
updated.Add(emailId);
}
else if (!@default)
{
email.From = new MailAddress(ConfigurationManager.AppSettings["DefaultSender"]);
if (SendEmail(email))
{
updated.Add(emailId);
}
}
}
catch (Exception e)
{
LogToFile(e);
}
}
}
}
var updatedCount = updated.Count;
if (updatedCount > 0)
{
try
{
LogToFile($"updating: {string.Join(", ", updated)}");
using (var command = connection.CreateCommand())
{
command.CommandText = $@"
UPDATE [Messages]
SET [OutDate] = GETDATE()
WHERE [Id] IN ({string.Join(", ", updated)})";
command.ExecuteNonQuery();
}
Console.WriteLine($"{updatedCount}/{countAll} email{(updatedCount == 1 ? null : "s")} sent.");
LogToFile($"{updatedCount}/{countAll} emails sent.");
}
catch (Exception e)
{
LogToFile(e);
}
}
else
{
LogToFile($"there are no pending emails to send");
}
}
}
private static Boolean SendEmail(MailMessage email)
{
try
{
using (var smtpClient = new SmtpClient("smtp.xylem.com", 587))
{
smtpClient.Timeout = 5000;
smtpClient.UseDefaultCredentials = true;
smtpClient.Send(email);
}
return true;
}
catch (Exception e)
{
LogToFile(e);
}
return false;
}
private static void LogToFile(Object e)
=> File.AppendAllText(GetOrCreateFile(), $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {e}{Environment.NewLine}");
private static String GetOrCreateFile()
{
var logFolder = ConfigurationManager.AppSettings["LogFolder"];
var logPath = Directory.CreateDirectory(logFolder).FullName;
return Path.Combine(logPath, $"{DateTime.Now:yyyy-MM-dd}.txt");
}
}
}
namespace PendingEmails
{
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Threading;
using System.Timers;
using SystemTimersTimer = System.Timers.Timer;
public static class Program
{
private static readonly SystemTimersTimer timer = new SystemTimersTimer();
private static void Main()
{
try
{
timer.AutoReset = true;
timer.Interval = 600_000;
timer.Elapsed += Timer_Elapsed;
while (true)
{
Timer_Elapsed(null, null);
timer.Start();
var awaiter = new ManualResetEventSlim();
awaiter.Wait();
timer.Stop();
}
}
catch (Exception e)
{
LogToFile(e.Message);
}
}
public class Ready
{
public string Source { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
private static void Timer_Elapsed(Object _, ElapsedEventArgs _1)
{
LogToFile($"loading pending emails");
var connectionString = ConfigurationManager.ConnectionStrings["Auftrag"].ConnectionString;
using (var connection = new SqlConnection(connectionString))
{
connection.FireInfoMessageEventOnUserErrors = true;
connection.InfoMessage += (_2, args) => LogToFile(args.Message);
connection.Open();
var ready = new List<Ready>();
using (var command = connection.CreateCommand())
{
command.CommandTimeout = 60000;
command.CommandText = @"
SELECT [Pruefstation]
, [Pruefdatum]
, [Mitarbaiter]
, [Auftrag]
, [Position]
, [Fertigungsauftrag]
, [Merkmal]
, [Bezeichnung]
, [Menge]
, [SerienNrVon]
, [SerienNrBis]
, [Kunde]
, [Kundenort]
FROM [AlleAuftraegeMitGarantieAusLetzte13Min]
ORDER BY [Pruefdatum]";
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
reader.AddToPendingMessages();
}
}
}
var updated = new HashSet<Int32>();
var countAll = 0;
using (var command = connection.CreateCommand())
{
command.CommandText = @"
SELECT [Sender]
, [Subject]
, [Body]
, [Recipients]
, [CC]
, [Id]
FROM [Messages]
WHERE [OutDate] IS NULL
ORDER BY [InDate] DESC";
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
try
{
var email = new MailMessage();
var from = ConfigurationManager.AppSettings["DefaultSender"];
email.From = new MailAddress(from);
email.Subject = $"{reader.GetValue<String>(1)}";
email.Body = $"{reader.GetValue<String>(2)}";
$"{reader.GetValue<String>(3)}"
.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => new MailAddress(x))
.ToList()
.ForEach(email.To.Add);
$"{reader.GetValue<String>(4)}"
.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => new MailAddress(x))
.ToList()
.ForEach(email.CC.Add);
var messageId = reader.GetValue<Int32>(5);
if (SendEmail(email))
{
updated.Add(messageId);
}
}
catch (Exception e)
{
LogToFile(e);
}
countAll++;
}
}
}
var updatedCount = updated.Count;
if (updatedCount > 0)
{
try
{
LogToFile($"updating: {string.Join(", ", updated)}");
using (var command = connection.CreateCommand())
{
command.CommandText = $@"
UPDATE [Messages]
SET [OutDate] = GETDATE()
WHERE [Id] IN ({string.Join(", ", updated)})";
command.ExecuteNonQuery();
}
Console.WriteLine($"{updatedCount}/{countAll} email{(updatedCount == 1 ? null : "s")} sent.");
LogToFile($"{updatedCount}/{countAll} emails sent.");
}
catch (Exception e)
{
LogToFile(e);
}
}
else
{
LogToFile($"there are no pending emails to send");
}
}
}
private static Boolean SendEmail(MailMessage email)
{
try
{
using (var smtpClient = new SmtpClient("smtp.xylem.com", 587))
{
smtpClient.UseDefaultCredentials = true;
smtpClient.Send(email);
}
return true;
}
catch (Exception e)
{
LogToFile(e);
}
return false;
}
private static void LogToFile(Object e)
=> File.AppendAllText(GetOrCreateFile(), $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {e}{Environment.NewLine}");
private static String GetOrCreateFile()
{
var logFolder = ConfigurationManager.AppSettings["LogFolder"];
var logPath = Directory.CreateDirectory(logFolder).FullName;
return Path.Combine(logPath, $"{DateTime.Now:yyyy-MM-dd}.txt");
}
private static void AddToPendingMessages(this SqlDataReader reader)
{
var psno = reader.GetValue<Int32>(0);
var date = reader.GetValue<DateTime>(1);
var empl = reader.GetValue<String>(2);
var orderno = reader.GetValue<Int32>(3);
var posno = reader.GetValue<Int32>(4);
var pono = reader.GetValue<Int32>(5);
var vako = reader.GetValue<String>(6);
var desc = reader.GetValue<String>(7);
var count = reader.GetValue<Int32>(8);
var snfrom = reader.GetValue<Int32>(9);
var snto = reader.GetValue<Int32>(10);
var client = reader.GetValue<String>(11);
var ort = reader.GetValue<String>(12);
var source = $"{orderno}/{posno}";
var subject = $"{ort} - {orderno}/{posno} erfolgreich geprüft - bitte Garantiescheine drucken und bereitlegen!";
var body = $"Auftrag: {orderno}/{posno}{Environment.NewLine}" + $"FertigungsauftragNr: {pono}{Environment.NewLine}"
+ $"{Environment.NewLine}" + $"{count} Stück {desc}{Environment.NewLine}" + $"wurde an der Prüfstation: {psno}{Environment.NewLine}" + $"am {date:dd-MM-yyyy} um {date:HH:mm} Uhr{Environment.NewLine}" + $"von {empl} vollständig geprüft.{Environment.NewLine}" + $"{Environment.NewLine}" + $"Seriennummern: {snfrom} - {snto}{Environment.NewLine}"
+ $"{Environment.NewLine}"
+ $"{vako}{Environment.NewLine}";
var connectionString = ConfigurationManager.ConnectionStrings["Auftrag"].ConnectionString;
using (var connection = new SqlConnection(connectionString))
{
connection.FireInfoMessageEventOnUserErrors = true;
connection.InfoMessage += (_2, args) => LogToFile(args.Message);
connection.Open();
var ready = new List<Ready>();
using (var command = connection.CreateCommand())
{
command.CommandText = $@"
IF (SELECT COUNT(1) FROM [Messages] WHERE [Source] = @{nameof(source)}) = 0
BEGIN
INSERT INTO [Messages]
( [Source]
, [InDate]
, [StationNr]
, [PCName]
, [IPAddress]
, [Trace]
, [Sender]
, [Subject]
, [Body]
, [IsHtml]
, [Recipients]
, [CC]
, [OutDate]
, [State])
VALUES (@{nameof(source)}
, GETDATE()
, @{nameof(psno)}
, 'localhost'
, '127.0.0.1'
, 'Xylem.Common.Service.PendingMails.Timer_Elapsed(Object, ElapsedEventArgs))'
, 'noreplay@xylem.com'
, @{nameof(subject)}
, @{nameof(body)}
, 0
, 'uwe.kubon@xylem.com'
, 'stoyan.zlatev@xylem.com'
, NULL
, 'Automatische fertigmeldung für garantiescheine')
END";
command.Parameters.AddWithValue(nameof(source), source);
command.Parameters.AddWithValue(nameof(subject), subject);
command.Parameters.AddWithValue(nameof(body), body);
command.Parameters.AddWithValue(nameof(psno), psno);
LogToFile($"Inserted: {command.ExecuteNonQuery()}");
command.Parameters.Clear();
}
}
}
private static T GetValue<T>(this SqlDataReader sqlDataReader, Int32 index, T defaultValue = default(T))
{
var value = defaultValue;
if (0 <= index && index < sqlDataReader.FieldCount && !sqlDataReader.IsDBNull(index))
{
var sqlValue = sqlDataReader.GetValue(index);
var type = Nullable.GetUnderlyingType(typeof(T));
if (type is null)
{
type = typeof(T);
}
try
{
sqlValue = Convert.ChangeType(sqlValue, type);
if (sqlValue is T expectedValue)
{
value = expectedValue;
}
}
catch (Exception e)
{
LogToFile(e);
}
}
return value;
}
}
}

View File

@ -64,6 +64,7 @@
<Compile Include="InitInspectionWindow.xaml.cs">
<DependentUpon>InitInspectionWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Models\InitInspectionM.cs" />
<Compile Include="Models\Result.cs" />
<Compile Include="Models\WritePamTask.cs" />
<Compile Include="Utilities\Appsettings.cs" />
@ -72,6 +73,7 @@
<Compile Include="Utilities\ResultToBackgroundConverter.cs" />
<Compile Include="Utilities\ResultToForegroundConverter.cs" />
<Compile Include="Utilities\ResultToStringConverter.cs" />
<Compile Include="ViewModels\InitInspectionTaskVM.cs" />
<Compile Include="ViewModels\InitInspectionVM.cs" />
<Compile Include="ViewModels\InitResultVM.cs" />
<Compile Include="ViewModels\SIRTBroadcasterViewModel.cs" />

View File

@ -2,7 +2,6 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VM="clr-namespace:Common.UI.SIRTBroadcaster.ViewModels"
xmlns:U="clr-namespace:Common.UI.SIRTBroadcaster.Utilities"
WindowStartupLocation="CenterScreen"
WindowStyle="SingleBorderWindow"
WindowState="Normal"
@ -11,264 +10,63 @@
Height="500"
FontSize="13"
FontFamily="Verdana">
<Window.Resources>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFFFFFFF"/>
</Window.Resources>
<Window.DataContext>
<VM:InitInspectionVM />
</Window.DataContext>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid Background="Gray" Margin="-1, -1, 0, 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.Resources>
<U:ResultToBackgroundConverter x:Key="Result2Background" />
<U:ResultToForegroundConverter x:Key="Result2Foreground" />
<U:ResultToStringConverter x:Key="Result2String" />
<Style TargetType="TextBlock" >
<Setter Property="Background" Value="White" />
<Setter Property="Padding" Value="10, 5" />
<Setter Property="Margin" Value="1, 1, 0, 0" />
</Style>
<Style TargetType="Button" >
<Setter Property="Background" Value="White" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Padding" Value="10, 5" />
<Setter Property="Margin" Value="1, 1, 0, 0" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<!--#region Table headers-->
<TextBlock Grid.Column="00" Grid.Row="0" Text="Einsatz" Background="LightGray" />
<TextBlock Grid.Column="01" Grid.Row="0" Text="EP: 1" Background="LightGray" />
<TextBlock Grid.Column="02" Grid.Row="0" Text="EP: 2" Background="LightGray" />
<TextBlock Grid.Column="03" Grid.Row="0" Text="EP: 3" Background="LightGray" />
<TextBlock Grid.Column="04" Grid.Row="0" Text="EP: 4" Background="LightGray" />
<TextBlock Grid.Column="05" Grid.Row="0" Text="EP: 5" Background="LightGray" />
<TextBlock Grid.Column="06" Grid.Row="0" Text="EP: 6" Background="LightGray" />
<TextBlock Grid.Column="07" Grid.Row="0" Text="EP: 7" Background="LightGray" />
<TextBlock Grid.Column="08" Grid.Row="0" Text="EP: 8" Background="LightGray" />
<TextBlock Grid.Column="09" Grid.Row="0" Text="EP: 9" Background="LightGray" />
<TextBlock Grid.Column="10" Grid.Row="0" Text="EP: 10" Background="LightGray" />
<!--#endregion-->
<!--#region Seriennummer-->
<TextBlock Grid.Column="00" Grid.Row="1" Text="Seriennummer" Background="LightGray" />
<TextBlock Grid.Column="01" Grid.Row="1" Text="{Binding Results[0].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="02" Grid.Row="1" Text="{Binding Results[1].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="03" Grid.Row="1" Text="{Binding Results[2].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="04" Grid.Row="1" Text="{Binding Results[3].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="05" Grid.Row="1" Text="{Binding Results[4].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="06" Grid.Row="1" Text="{Binding Results[5].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="07" Grid.Row="1" Text="{Binding Results[6].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="08" Grid.Row="1" Text="{Binding Results[7].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="09" Grid.Row="1" Text="{Binding Results[8].SerialNo}" Background="LightGray" />
<TextBlock Grid.Column="10" Grid.Row="1" Text="{Binding Results[9].SerialNo}" Background="LightGray" />
<!--#endregion-->
<!--#region Radioadresse-->
<TextBlock Grid.Column="00" Grid.Row="2" Text="Radioadresse" Background="LightGray" />
<TextBlock Grid.Column="01" Grid.Row="2" Text="{Binding Results[0].Address}" Background="LightGray" />
<TextBlock Grid.Column="02" Grid.Row="2" Text="{Binding Results[1].Address}" Background="LightGray" />
<TextBlock Grid.Column="03" Grid.Row="2" Text="{Binding Results[2].Address}" Background="LightGray" />
<TextBlock Grid.Column="04" Grid.Row="2" Text="{Binding Results[3].Address}" Background="LightGray" />
<TextBlock Grid.Column="05" Grid.Row="2" Text="{Binding Results[4].Address}" Background="LightGray" />
<TextBlock Grid.Column="06" Grid.Row="2" Text="{Binding Results[5].Address}" Background="LightGray" />
<TextBlock Grid.Column="07" Grid.Row="2" Text="{Binding Results[6].Address}" Background="LightGray" />
<TextBlock Grid.Column="08" Grid.Row="2" Text="{Binding Results[7].Address}" Background="LightGray" />
<TextBlock Grid.Column="09" Grid.Row="2" Text="{Binding Results[8].Address}" Background="LightGray" />
<TextBlock Grid.Column="10" Grid.Row="2" Text="{Binding Results[9].Address}" Background="LightGray" />
<!--#endregion-->
<!--#region Change wake up-->
<TextBlock Grid.Column="00" Grid.Row="3" Text="Werke aufwäcken" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="3" Content="{Binding Results[0].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="3" Content="{Binding Results[1].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="3" Content="{Binding Results[2].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="3" Content="{Binding Results[3].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="3" Content="{Binding Results[4].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="3" Content="{Binding Results[5].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="3" Content="{Binding Results[6].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="3" Content="{Binding Results[7].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="3" Content="{Binding Results[8].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].WakeUp, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="3" Content="{Binding Results[9].WakeUp, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].WakeUp, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Change transmission interval-->
<TextBlock Grid.Column="00" Grid.Row="4" Text="Übertragungsrate = 3s" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="4" Content="{Binding Results[0].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="4" Content="{Binding Results[1].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="4" Content="{Binding Results[2].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="4" Content="{Binding Results[3].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="4" Content="{Binding Results[4].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="4" Content="{Binding Results[5].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="4" Content="{Binding Results[6].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="4" Content="{Binding Results[7].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="4" Content="{Binding Results[8].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].TxInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="4" Content="{Binding Results[9].TxInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].TxInterval, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Change LAT windows N-->
<TextBlock Grid.Column="00" Grid.Row="5" Text="LAT fenster N = 0" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="5" Content="{Binding Results[0].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="5" Content="{Binding Results[1].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="5" Content="{Binding Results[2].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="5" Content="{Binding Results[3].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="5" Content="{Binding Results[4].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="5" Content="{Binding Results[5].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="5" Content="{Binding Results[6].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="5" Content="{Binding Results[7].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="5" Content="{Binding Results[8].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].LatInterval, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="5" Content="{Binding Results[9].LatInterval, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].LatInterval, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Cahnge and check MBus status-->
<TextBlock Grid.Column="00" Grid.Row="6" Text="MBus status = 7" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="6" Content="{Binding Results[0].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="6" Content="{Binding Results[1].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="6" Content="{Binding Results[2].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="6" Content="{Binding Results[3].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="6" Content="{Binding Results[4].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="6" Content="{Binding Results[5].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="6" Content="{Binding Results[6].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="6" Content="{Binding Results[7].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="6" Content="{Binding Results[8].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].Mbus, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="6" Content="{Binding Results[9].Mbus, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].Mbus, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Change metrology parameters-->
<TextBlock Grid.Column="00" Grid.Row="7" Text="Parametersatz einstellen" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="7" Content="{Binding Results[0].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="7" Content="{Binding Results[1].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="7" Content="{Binding Results[2].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="7" Content="{Binding Results[3].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="7" Content="{Binding Results[4].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="7" Content="{Binding Results[5].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="7" Content="{Binding Results[6].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="7" Content="{Binding Results[7].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="7" Content="{Binding Results[8].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].Setup, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="7" Content="{Binding Results[9].Setup, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].Setup, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Change reading-->
<TextBlock Grid.Column="00" Grid.Row="8" Text="Anzeige = (111111111)" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="8" Content="{Binding Results[0].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="8" Content="{Binding Results[1].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="8" Content="{Binding Results[2].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="8" Content="{Binding Results[3].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="8" Content="{Binding Results[4].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="8" Content="{Binding Results[5].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="8" Content="{Binding Results[6].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="8" Content="{Binding Results[7].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="8" Content="{Binding Results[8].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].Reading, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="8" Content="{Binding Results[9].Reading, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].Reading, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Change optical telegram-->
<TextBlock Grid.Column="00" Grid.Row="9" Text="LED einschalten" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="9" Content="{Binding Results[0].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="9" Content="{Binding Results[1].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="9" Content="{Binding Results[2].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="9" Content="{Binding Results[3].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="9" Content="{Binding Results[4].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="9" Content="{Binding Results[5].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="9" Content="{Binding Results[6].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="9" Content="{Binding Results[7].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="9" Content="{Binding Results[8].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].LED, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="9" Content="{Binding Results[9].LED, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].LED, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Check battery voltage-->
<TextBlock Grid.Column="00" Grid.Row="10" Text="Batteriespannung" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="10" Content="{Binding Results[0].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="10" Content="{Binding Results[1].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="10" Content="{Binding Results[2].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="10" Content="{Binding Results[3].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="10" Content="{Binding Results[4].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="10" Content="{Binding Results[5].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="10" Content="{Binding Results[6].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="10" Content="{Binding Results[7].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="10" Content="{Binding Results[8].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="10" Content="{Binding Results[9].BatteryVoltage, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].BatteryVoltage, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Check battery remaining-->
<TextBlock Grid.Column="00" Grid.Row="11" Text="Batterie übrig" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="11" Content="{Binding Results[0].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="11" Content="{Binding Results[1].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="11" Content="{Binding Results[2].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="11" Content="{Binding Results[3].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="11" Content="{Binding Results[4].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="11" Content="{Binding Results[5].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="11" Content="{Binding Results[6].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="11" Content="{Binding Results[7].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="11" Content="{Binding Results[8].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="11" Content="{Binding Results[9].BatteryRemaining, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].BatteryRemaining, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Check FW version-->
<TextBlock Grid.Column="00" Grid.Row="12" Text="FW-Version" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="12" Content="{Binding Results[0].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="12" Content="{Binding Results[1].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="12" Content="{Binding Results[2].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="12" Content="{Binding Results[3].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="12" Content="{Binding Results[4].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="12" Content="{Binding Results[5].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="12" Content="{Binding Results[6].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="12" Content="{Binding Results[7].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="12" Content="{Binding Results[8].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].FWVersion, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="12" Content="{Binding Results[9].FWVersion, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].FWVersion, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Check reboot counter-->
<TextBlock Grid.Column="00" Grid.Row="13" Text="Reboot counter" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="13" Content="{Binding Results[0].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="13" Content="{Binding Results[1].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="13" Content="{Binding Results[2].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="13" Content="{Binding Results[3].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="13" Content="{Binding Results[4].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="13" Content="{Binding Results[5].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="13" Content="{Binding Results[6].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="13" Content="{Binding Results[7].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="13" Content="{Binding Results[8].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="13" Content="{Binding Results[9].RebootCounter, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].RebootCounter, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<!--#region Change meter type-->
<TextBlock Grid.Column="00" Grid.Row="14" Text="Zählertyp C&amp;I" Background="LightGray" />
<Button Grid.Column="01" Grid.Row="14" Content="{Binding Results[0].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[0].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="02" Grid.Row="14" Content="{Binding Results[1].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[1].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="03" Grid.Row="14" Content="{Binding Results[2].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[2].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="04" Grid.Row="14" Content="{Binding Results[3].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[3].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="05" Grid.Row="14" Content="{Binding Results[4].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[4].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="06" Grid.Row="14" Content="{Binding Results[5].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[5].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="07" Grid.Row="14" Content="{Binding Results[6].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[6].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="08" Grid.Row="14" Content="{Binding Results[7].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[7].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="09" Grid.Row="14" Content="{Binding Results[8].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[8].MeterType, Converter={StaticResource Result2Foreground}}" />
<Button Grid.Column="10" Grid.Row="14" Content="{Binding Results[9].MeterType, Converter={StaticResource Result2String}}" Foreground="{Binding Results[9].MeterType, Converter={StaticResource Result2Foreground}}" />
<!--#endregion-->
<TextBox Grid.ColumnSpan="11" Grid.Column="0" Grid.Row="100" Text="{Binding State}" />
</Grid>
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Tasks}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding .}">
<ContentControl.Resources>
<DataTemplate DataType="{}">
</DataTemplate>
<DataTemplate DataType="{}">
</DataTemplate>
<DataTemplate DataType="{}">
</DataTemplate>
<DataTemplate DataType="{}">
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Window>

View File

@ -19,15 +19,7 @@
if (this.DataContext is InitInspectionVM inspection)
{
inspection.Shutdown += App.Current.Shutdown;
inspection.Start();
}
}
public void Set(EndpointsBatch endpoints)
{
if (this.DataContext is InitInspectionVM inspection)
{
inspection.Set(endpoints);
inspection.StartProgramming();
}
}
}

View File

@ -0,0 +1,22 @@
namespace Common.UI.SIRTBroadcaster.Models
{
using Common.Hardware.WaterMeter.eRegister;
using System.Collections.Generic;
public class InitInspectionM
{
private ProgrammingBatch programmingBatch;
internal void InitProgramming(ProgrammingBatch programmingBatch)
=> this.programmingBatch = programmingBatch;
internal IEnumerable<IEnumerable<EndpointTask>> ProgrammingTasks()
=> this.programmingBatch.InitProgramming();
internal void StartProgramming()
{
}
}
}

View File

@ -3,6 +3,7 @@
using Common.Hardware.Interfaces.Ports;
using Common.Hardware.Interfaces.Ports.SIRT;
using Common.Hardware.Interfaces.Ports.SIRT.Requests;
using Common.Hardware.WaterMeter.eRegister.Features;
using Common.UI.SIRTBroadcaster.Utilities;
using NLog;
@ -42,11 +43,11 @@
remove => this.broadcaster.EndpointAvailable -= value;
}
public event Action<UInt32[]> PamPoolChanged
{
add => this.broadcaster.PamPoolChanged += value;
remove => this.broadcaster.PamPoolChanged -= value;
}
//public event Action<UInt32[]> PamPoolChanged
//{
// add => this.broadcaster.PamPoolChanged += value;
// remove => this.broadcaster.PamPoolChanged -= value;
//}
public event Action<UInt32, String> ProgrammingDone;
@ -57,52 +58,85 @@
internal void StartProgramming()
{
var awaiter = new ManualResetEventSlim();
var request = new WritePamRequest
{
Address = 319020416,
DelPamSemi = true,
Payload = new Byte[]
{
0x35, 0x13, 0x03, 0xDD, 0x7f,
0x43, 0x03, 0x63, 0x93, 0x73, 0x22
}
};
var task = new WritePamTask(request);
//var request = new WritePamRequest
//{
// Address = 319020416,
// DelPamSemi = true,
// Payload = new Byte[]
// {
// 0x35, 0x13, 0x03, 0xDD, 0x7f,
// 0x43, 0x03, 0x63, 0x93, 0x73, 0x22
// }
//};
//var task = new WritePamTask(request);
task.Done += _ => awaiter.Set();
task.Cancelled += _ => awaiter.Set();
task.Logging += content =>
{
this.ProgrammingDone?.Invoke(task.Address, content);
};
//task.Done += _ => awaiter.Set();
//task.Cancelled += _ => awaiter.Set();
//task.Logging += content =>
//{
// this.ProgrammingDone?.Invoke(task.Address, content);
//};
this.broadcaster.Run(task);
//this.broadcaster.Run(task);
awaiter.Wait();
awaiter.Reset();
//awaiter.Wait();
//awaiter.Reset();
request = new WritePamRequest
{
Address = task.Address,
DelPamSemi = true,
Payload = new Byte[]
{
0x1F, 0x01, 0x08,
0x43, 0x03, 0x63, 0x93, 0x73, 0x22
}
};
task = new WritePamTask(request);
//request = new WritePamRequest
//{
// Address = task.Address,
// DelPamSemi = true,
// Payload = new Byte[]
// {
// 0x1F, 0x01, 0x08,
// 0x43, 0x03, 0x63, 0x93, 0x73, 0x22
// }
//};
//task = new WritePamTask(request);
task.Done += _ => awaiter.Set();
task.Cancelled += _ => awaiter.Set();
task.Logging += content =>
{
this.ProgrammingDone?.Invoke(task.Address, content);
};
//var payload = new ChangeWakeUp()
//{
// Mode = WakeUpMode.StayAwake
//}
//.Append(new ChangeLATWindows
//{
// N = 0
//})
//.Append(new WMBusMode
//{
// WMBusEnabled = true,
// InstallationModeEnabled = true,
// EncryptionEnabled = true,
//})
//.Append(new ChangeTransmission
//{
// LatWindowIntervalCount = 0,
// LatTXIntervalSeconds = 3
//})
//.Append(new ProvidePin
//{
// AuthLevel = AuthLevel.II
//});
this.broadcaster.Run(task);
//var request = new WritePamRequest
//{
// Address = 319020415,
// WakeUpCmd = true,
// DelPamSemi = true,
// Payload = payload
//};
awaiter.Wait();
//var task = new WritePamTask(request);
//task.Done += _ => awaiter.Set();
//task.Cancelled += _ => awaiter.Set();
//task.Logging += content =>
//{
// this.ProgrammingDone?.Invoke(task.RequestAddress, content);
//};
//this.broadcaster.Run(task);
//awaiter.Wait();
}
}
}

View File

@ -1,6 +1,7 @@
namespace Common.UI.SIRTBroadcaster.Models
{
using Common.Hardware.Interfaces.Ports.SIRT;
using Common.Hardware.Interfaces.Ports.SIRT.Requests;
using Common.Hardware.Interfaces.Ports.SIRT.Responses;
using Common.Hardware.WaterMeter.eRegister;
using Common.Utils.Extensions;
@ -10,11 +11,10 @@
using System;
using System.Collections.Generic;
public class WritePamTask : SIRTTask
public class WritePamTask : SIRTTask<WritePamRequest>
{
public WritePamTask(SIRTRequest request) : base(request)
public WritePamTask(UInt32 timeoutSeconds = 60) : base(timeoutSeconds)
{
}
public event Action<String> Logging;

View File

@ -0,0 +1,6 @@
namespace Common.UI.SIRTBroadcaster.ViewModels
{
public class InitInspectionTaskVM
{
}
}

View File

@ -1,66 +1,39 @@
namespace Common.UI.SIRTBroadcaster.ViewModels
{
using Common.Hardware.WaterMeter.eRegister;
using Common.UI.SIRTBroadcaster.Utilities;
using NLog;
using Common.UI.SIRTBroadcaster.Models;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
public class InitInspectionVM : VM
{
private readonly ILogger logger = Appsettings.CreateNLogger(nameof(InitInspectionVM));
private EndpointsBatch endpoints;
private readonly InitInspectionM model;
public InitInspectionVM()
{
var length = 10;
this.Results = new InitResultVM[length];
for (var i = 0; i < length; i++)
{
this.Results[i] = new InitResultVM();
}
this.model = new InitInspectionM();
this.Tasks = new ObservableCollection<InitInspectionTaskVM>();
}
public event Action Shutdown;
private String state;
public String State
public ObservableCollection<InitInspectionTaskVM> Tasks { get; }
public void InitInspection(ProgrammingBatch programmingBatch)
{
get => this.state;
set => this.Set(() => this.state = value);
}
this.model.InitProgramming(programmingBatch);
public InitResultVM[] Results { get; }
public void Set(EndpointsBatch endpoints)
{
this.endpoints = endpoints;
for (var i = 0; i < 10; i++)
foreach (var tasks in this.model.ProgrammingTasks())
{
this.Results[i] = new InitResultVM();
}
}
internal void Start()
internal void StartProgramming()
{
Task.Factory.StartNew(() =>
{
this.endpoints.ConnectSIRT();
this.endpoints.InitInspection();
if (this.endpoints.IsConnected)
{
Thread.Sleep(30000);
}
this.Invoke(this.Shutdown.Invoke);
});
this.model.StartProgramming();
this.Shutdown?.Invoke();
}
}
}

View File

@ -25,7 +25,7 @@
this.model = new SIRTBroadcasterModel(portName, parsed ? timeout : 3000);
this.model.DeviceAvailable += this.Model_DeviceAvailable;
this.model.PamPoolChanged += this.BroadcasterModel_PamPoolChanged;
// this.model.PamPoolChanged += this.BroadcasterModel_PamPoolChanged;
this.devices = new SortedDictionary<UInt32, Boolean>();
this.StartProgramming = new Command(this.StartProgrammingHandler);

View File

@ -447,14 +447,14 @@
var response = this.omni.Set(new RegisterSettings
{
IntPart = this.values.IntPart,
Fraction = (ushort)this.values.Fraction,
Fraction = (UInt16)this.values.Fraction,
Size = this.values.Size,
Range = this.values.Range,
VolumePerPulseUnit = 0x00,
VolumePerPulseUnits = 0x00,
MeterUnits = this.values.MeterUnits,
FlowUnits = this.values.FlowUnits,
FlowRate = this.values.FlowRate,
FactoryCorrection = (sbyte)(this.values.CalibrationFactor * 10),
FactoryCorrection = (SByte)(this.values.CalibrationFactor * 10),
FieldCorrection = 0x00,
PulseWeight = this.values.PulseWeight,
PulseWidth = this.values.PulseWidth,
@ -485,10 +485,10 @@
ProgrammableID = this.CustId.Trim(),
FactoryID = this.values.FactId.ToString(),
AlarmPercistancePeriodDays = this.values.AlarmPercistancePeriodDays,
DataLogIntervalMinutes = (ushort)this.values.DataLogIntervalMinutes,
DataLogIntervalMinutes = (UInt16)this.values.DataLogIntervalMinutes,
ManifacturingTime = this.values.ManifacturingTime,
NumberOfReadingDigits = (sbyte)this.values.NumberOfReadingDigits,
OptionalUniDirFields = (ushort)this.values.OptionalUniDirFields,
NumberOfReadingDigits = (SByte)this.values.NumberOfReadingDigits,
OptionalUniDirFields = (UInt16)this.values.OptionalUniDirFields,
ReadingPreset = this.values.ReadingPreset,
RebootCount = 0,
SystemTime = Epoch20000101.UTCNow,
@ -527,7 +527,7 @@
response = this.omni.Set(new LeakAlarm
{
FlowRateGPM = this.values.LeakAlarmGPM,
TimeLimit = (uint)this.values.LeakAlarmTime
TimeLimitHours = (UInt32)this.values.LeakAlarmTime
});
if (!response.Completed)
@ -542,7 +542,7 @@
response = this.omni.Set(new HighFlowAlarm
{
FlowRateGPM = this.values.HighFlowAlarmGPM,
TimeLimit = (uint)this.values.HighFlowAlarmTime
TimeLimitHours = (UInt32)this.values.HighFlowAlarmTime
});
if (!response.Completed)
@ -557,7 +557,7 @@
response = this.omni.Set(new ReverseFlowAlarm
{
FlowRateGPM = this.values.ReverseFlowAlarmGPM,
TimeLimit = (uint)this.values.ReverseFlowAlarmTime
TimeLimitMinutes = (UInt32)this.values.ReverseFlowAlarmTime
});
if (!response.Completed)
@ -951,3 +951,4 @@
}
}
}

View File

@ -82,6 +82,10 @@
<Project>{82D34580-23FE-4315-BC51-51D565ABAE23}</Project>
<Name>LaaProduction.Data.SQL</Name>
</ProjectReference>
<ProjectReference Include="..\..\LaaProductionWeb.Resources\LaaProductionWeb.Resources.csproj">
<Project>{DA65E376-3D35-4D96-913A-7197FCA6DF48}</Project>
<Name>LaaProductionWeb.Resources</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@ -2,7 +2,6 @@
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public class CordonelSpecialRequirement

View File

@ -6,7 +6,7 @@
public class CordonelStandardRequirement
{
[Display(Name = "Id", Description = "Die in der Datenbank zugewiesene Id. Nicht änderbar!")]
[Display(Name = "ID", Description = "Die in der Datenbank zugewiesene Id. Nicht änderbar!")]
public Int32 Id { get; set; }
[Display(Name = "Versionsnr.", Description = "Die in der Datenbank zugewiesene Versionsnr. Nicht änderbar!")]

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DA65E376-3D35-4D96-913A-7197FCA6DF48}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LaaProductionWeb.Resources</RootNamespace>
<AssemblyName>LaaProductionWeb.Resources</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UITranslations.de.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>UITranslations.de.resx</DependentUpon>
</Compile>
<Compile Include="UITranslations.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>UITranslations.resx</DependentUpon>
</Compile>
<Compile Include="UITranslations.en.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>UITranslations.en.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="UITranslations.de.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>UITranslations.de.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="UITranslations.en.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>UITranslations.en.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="UITranslations.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>UITranslations.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("LaaProductionWeb.Resources")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LaaProductionWeb.Resources")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("da65e376-3d35-4d96-913a-7197fca6df48")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,81 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace LaaProductionWeb.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class UITranslations {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal UITranslations() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LaaProductionWeb.Resources.UITranslations", typeof(UITranslations).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Die in der Datenbank zugewiesene Id. Nicht änderbar!.
/// </summary>
public static string CordonelStandardRequirement_Id_Description {
get {
return ResourceManager.GetString("CordonelStandardRequirement_Id_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ID.
/// </summary>
public static string CordonelStandardRequirement_Id_Name {
get {
return ResourceManager.GetString("CordonelStandardRequirement_Id_Name", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,126 @@
<?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>
<data name="CordonelStandardRequirement_Id_Description" xml:space="preserve">
<value>Die in der Datenbank zugewiesene Id. Nicht änderbar!</value>
</data>
<data name="CordonelStandardRequirement_Id_Name" xml:space="preserve">
<value>ID</value>
</data>
</root>

View File

@ -0,0 +1,126 @@
<?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>
<data name="CordonelStandardRequirement_Id_Description" xml:space="preserve">
<value>Die in der Datenbank zugewiesene Id. Nicht änderbar!</value>
</data>
<data name="CordonelStandardRequirement_Id_Name" xml:space="preserve">
<value>ID</value>
</data>
</root>

View File

@ -0,0 +1,126 @@
<?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>
<data name="CordonelStandardRequirement_Id_Description" xml:space="preserve">
<value>Die in der Datenbank zugewiesene Id. Nicht änderbar!</value>
</data>
<data name="CordonelStandardRequirement_Id_Name" xml:space="preserve">
<value>ID</value>
</data>
</root>

View File

@ -56,6 +56,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaaProduction.Data.Inspecti
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaaProduction.Console", "LaaProduction.Console\LaaProduction.Console.csproj", "{E8FCD0A3-714D-4436-9A20-B098E6A5537D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaaProductionWeb.Resources", "LaaProductionWeb.Resources\LaaProductionWeb.Resources.csproj", "{DA65E376-3D35-4D96-913A-7197FCA6DF48}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -122,6 +124,10 @@ Global
{E8FCD0A3-714D-4436-9A20-B098E6A5537D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8FCD0A3-714D-4436-9A20-B098E6A5537D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8FCD0A3-714D-4436-9A20-B098E6A5537D}.Release|Any CPU.Build.0 = Release|Any CPU
{DA65E376-3D35-4D96-913A-7197FCA6DF48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA65E376-3D35-4D96-913A-7197FCA6DF48}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA65E376-3D35-4D96-913A-7197FCA6DF48}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA65E376-3D35-4D96-913A-7197FCA6DF48}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -26,7 +26,7 @@
/// <summary>
/// How Int64 should user stay logged in.
/// </summary>
public static Int32 LoginTimeout => Int32.TryParse(ConfigurationManager.AppSettings.Get(nameof(LoginTimeout)), out var time) ? time : 0;
public static Int32 LoginTimeout => Int32.TryParse(ConfigurationManager.AppSettings.Get(nameof(LoginTimeout)), out var time) ? time : 30;
/// <summary>
/// Default SMTP host for sending emails.

View File

@ -3,8 +3,6 @@
using LaaProduction.Personalization.Interfaces;
using LaaProductionDI;
using System.Linq;
using IAuthorizationFilter = System.Web.Mvc.IAuthorizationFilter;
using AuthorizationContext = System.Web.Mvc.AuthorizationContext;
@ -27,27 +25,8 @@
httpContext.User = accountManagement.GetClaimsPrincipal(sessionUser);
var currentUrl = httpContext
.Request
.Url
.AbsolutePath
.Trim('/');
var exludeUrl = new[]
{
"",
"Home",
"Home/Index",
"Home/Logout",
"LaaProductionWeb",
"LaaProductionWeb/Home",
"LaaProductionWeb/Home/Index",
"LaaProductionWeb/Home/Logout",
};
if (exludeUrl.All(x => x != currentUrl))
{
httpContext.SetUrlReferer();
}
httpContext.SetUrlReferer();
httpContext.SetLanguage();
}
}
}

View File

@ -6,12 +6,14 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Mvc;
@ -20,9 +22,10 @@
/// </summary>
public static class HttpExtensions
{
const String ORDER_DATA = nameof(ORDER_DATA);
const String URL_REFERER = nameof(URL_REFERER);
const String LAA_USER = nameof(LAA_USER);
public const String ORDER_DATA = nameof(ORDER_DATA);
public const String URL_REFERER = nameof(URL_REFERER);
public const String LAA_USER = nameof(LAA_USER);
public const String LAA_LANG = nameof(LAA_LANG);
/// <summary>
/// Is a mepper method that can map to different objects by the specified setup.
@ -122,10 +125,29 @@
/// </summary>
/// <param name="httpContext"> usualy <see cref="HttpContextBase"/> implementation.</param>
public static void SetUrlReferer(this HttpContextBase httpContext)
=> httpContext
.Response
.Cookies
.Add(new HttpCookie(URL_REFERER, $"{httpContext.Request.Url}"));
{
var currentUrl = httpContext
.Request
.Url
.AbsolutePath
.Trim('/');
var exludeUrl = new[]
{
"Index",
"Logout",
"Create",
"Update",
"Delete",
};
if (exludeUrl.All(x => !currentUrl.Contains(x)))
{
httpContext
.Response
.Cookies
.Add(new HttpCookie(URL_REFERER, $"{httpContext.Request.Url}"));
}
}
/// <summary>
///
@ -280,5 +302,29 @@
return default(Int16);
}
public static void SetLanguage(this HttpContextBase httpContext, string language)
=> httpContext.Response.Cookies.Set(new HttpCookie(LAA_LANG)
{
Expires = DateTime.Now.AddYears(1),
Value = Enum.TryParse<Languages>($"{language}", out var lang) ? lang.ToString() : nameof(Languages.DE)
});
public static void SetLanguage(this HttpContextBase httpContext)
{
var languageCookie = httpContext.Request.Cookies.Get(LAA_LANG);
var currentCulture = new CultureInfo("de-DE");
if (Enum.TryParse<Languages>($"{languageCookie?.Value}", out var lang))
{
if (lang == Languages.EN)
{
currentCulture = new CultureInfo("en-US");
}
}
Thread.CurrentThread.CurrentCulture = currentCulture;
Thread.CurrentThread.CurrentUICulture = currentCulture;
}
}
}

View File

@ -0,0 +1,8 @@
namespace LaaProductionWeb.App_Infrastructure
{
public enum Languages
{
DE,
EN,
}
}

View File

@ -8,12 +8,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/svg" href="~/favicon.svg">
@Styles.Render("~/bootstrap_css")
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
@Styles.Render("~/styles_css")
<link rel="stylesheet" href="~/App_Content/css/bootstrap.min.css">
<link rel="stylesheet" href="~/App_Content/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="~/App_Content/css/styles.css">
<title>Laatzen Production Web</title>
</head>
@ -50,9 +47,11 @@
@this.RenderBody()
</main>
@Scripts.Render("~/bootstrap_js")
@Scripts.Render("~/barcodes_js")
@Scripts.Render("~/scripts_js")
@*<script src="~/App_Content/js/jquery-3.7.1.js"></script>*@
<script src="~/App_Content/js/bootstrap.bundle.min.js"></script>
<script src="~/App_Content/js/jsbarcode.all.min.js"></script>
<script src="~/App_Content/js/scripts.js"></script>
@this.RenderSection("scripts", required: false)
</body>

View File

@ -71,6 +71,17 @@
return this.View();
}
[HttpGet]
[Route("Lang/{lang}")]
public ActionResult Lang(string lang)
{
this.HttpContext.SetLanguage(lang);
var urlRefferer = this.HttpContext.GetUrlReferer();
return this.Redirect(urlRefferer);
}
public ActionResult Logout()
{

View File

@ -217,6 +217,7 @@
<Compile Include="App_Infrastructure\AuthorizationFilter.cs" />
<Compile Include="App_Infrastructure\AuthorizeBearerAttribute.cs" />
<Compile Include="App_Infrastructure\HttpExtensions.cs" />
<Compile Include="App_Infrastructure\Languages.cs" />
<Compile Include="App_Infrastructure\RazorExtensions.cs" />
<Compile Include="App_Infrastructure\RouteParameterAttribute.cs" />
<Compile Include="App_Infrastructure\RoutePrefixes.cs" />
@ -391,6 +392,10 @@
<Project>{5A3F8AA8-D8CB-4AB4-B6B7-C378A582CE75}</Project>
<Name>LaaProduction.SQL</Name>
</ProjectReference>
<ProjectReference Include="..\LaaProductionWeb.Resources\LaaProductionWeb.Resources.csproj">
<Project>{da65e376-3d35-4d96-913a-7197fca6df48}</Project>
<Name>LaaProductionWeb.Resources</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />

View File

@ -45,7 +45,7 @@
{
<li class="nav-item dropdown">
<a class="nav-link text-smallcaps dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" href="#">Reports</a>
<ul class="dropdown-menu">
<ul class="dropdown-menu" style="z-index: 1100;">
<li><a class="dropdown-item" href="~/Report/Helium">Helium</a></li>
<li><a class="dropdown-item" href="~/Report/Kottmann">Kottmann</a></li>
<li><a class="dropdown-item" href="~/Report/CordonelPressureSensor">Cordonel Pressure Sensor</a></li>
@ -82,7 +82,7 @@
{
<li class="nav-item dropdown">
<a class="nav-link text-smallcaps dropdown-toggle fw-bold text-white" data-bs-toggle="dropdown" aria-expanded="false" href="#">@this.User.FullName()</a>
<ul class="dropdown-menu dropdown-menu-end">
<ul class="dropdown-menu dropdown-menu-end" style="z-index: 1100;">
<li><a class="dropdown-item" href="~/Personalization/Employees">Personalisierung</a></li>
<li><a class="dropdown-item" href="~/Home/Logout">Abmelden</a></li>
</ul>
@ -92,11 +92,20 @@
{
<li class="nav-item dropdown">
<a class="nav-link text-smallcaps dropdown-toggle fw-bold text-white" data-bs-toggle="dropdown" aria-expanded="false" href="#">@this.User.FullName()</a>
<ul class="dropdown-menu dropdown-menu-end">
<ul class="dropdown-menu dropdown-menu-end" style="z-index: 1100;">
<li><a class="dropdown-item" href="~/Home/Logout">Abmelden</a></li>
</ul>
</li>
}
<li class="nav-item dropdown">
<a class="nav-link text-smallcaps dropdown-toggle text-white" data-bs-toggle="dropdown" aria-expanded="false" href="#">@(this.Request.Cookies.Get(HttpExtensions.LAA_LANG)?.Value ?? nameof(Languages.DE))</a>
<ul class="dropdown-menu dropdown-menu-end" style="z-index: 1100;">
@foreach (var lang in Enum.GetNames(typeof(Languages)))
{
<li><a class="dropdown-item" href="~/Lang/@lang">@lang</a></li>
}
</ul>
</li>
</ul>
</div>
</div>

View File

@ -13,28 +13,30 @@
</th>
</tr>
<tr>
<th class="text-nowrap text-smallcaps small p-2">Version</th>
<th class="text-nowrap text-smallcaps small p-2">Standard</th>
<th class="text-nowrap text-smallcaps small p-2">Key</th>
<th class="text-nowrap text-smallcaps small p-2">Region</th>
<th class="text-nowrap text-smallcaps small p-2">Size</th>
<th class="text-nowrap text-smallcaps small p-2">Prod-orderno.</th>
<th class="text-nowrap text-smallcaps small p-2">PcbId</th>
<th class="text-nowrap text-smallcaps small p-2">Is Active</th>
<th class="text-nowrap text-smallcaps small p-2">FW Version</th>
<th class="text-nowrap text-smallcaps small p-2">LUT CRC</th>
<th class="text-nowrap text-smallcaps small p-2">Check radio</th>
<th class="text-nowrap text-smallcaps small p-2">RLTY Assembly</th>
<th class="text-nowrap text-smallcaps small p-2">RLTY Shipping</th>
<th class="text-nowrap text-smallcaps small p-2">Max DBL % Assembly</th>
<th class="text-nowrap text-smallcaps small p-2">Max DBL % Shipping</th>
<th class="text-nowrap text-smallcaps small p-2">Max Storage (months)</th>
<th class="text-nowrap text-smallcaps small p-2">Max Storage (months big orders)</th>
<th class="text-nowrap text-smallcaps small p-2">Q.Curr.uA</th>
<th class="text-nowrap text-smallcaps small p-2">Estimated load %</th>
<th class="text-nowrap text-smallcaps small p-2">Last Updated</th>
<th class="text-nowrap text-smallcaps small p-2">Updated by</th>
<th class="text-nowrap text-smallcaps small p-2">Comment</th>
@{
var model = new LaaProduction.Data.Cordonel.Models.CordonelSpecialRequirement();
}
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Version)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.StandardId)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Region)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MeterSize)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.ProductionOrderNr)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.PcbId)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.IsActive)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.FwVersion)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.LutCrc)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.SkipRadioCheck)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.RequiredLifeTimeYearsAssembly)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.RequiredLifeTimeYearsShipping)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxDrainedBatteryLoadPercentAssembly)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxDrainedBatteryLoadPercentShipping)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxStorageMonths)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxStorageMonthsBigOrders)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.QuiescentCurrent_uA)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.EstimatedProductionBatteryLoadPercent)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Timestamp)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.ApprovalName)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.ApprovalComment)</th>
</tr>
</thead>
<tbody>

View File

@ -2,7 +2,6 @@
<th class="text-nowrap small p-2">@($"{Model.Id}.{Model.Version}")</th>
<td class="text-nowrap small p-2">@($"{Model.StandardId}.{Model.StandardVersion}")</td>
<td class="text-nowrap small p-2">@Model.Key</td>
<td class="text-nowrap small p-2">@Model.Region</td>
<td class="text-nowrap small p-2">@Model.MeterSize</td>
<td class="text-nowrap small p-2">@Model.ProductionOrderNr</td>

View File

@ -10,26 +10,27 @@
</th>
</tr>
<tr>
<th class="text-nowrap text-smallcaps small p-2">Version</th>
<th class="text-nowrap text-smallcaps small p-2">Key</th>
<th class="text-nowrap text-smallcaps small p-2">Region</th>
<th class="text-nowrap text-smallcaps small p-2">Group</th>
<th class="text-nowrap text-smallcaps small p-2">Meter size</th>
<th class="text-nowrap text-smallcaps small p-2">Is Active</th>
<th class="text-nowrap text-smallcaps small p-2">FW Version</th>
<th class="text-nowrap text-smallcaps small p-2">LUT CRC</th>
<th class="text-nowrap text-smallcaps small p-2">Check radio</th>
<th class="text-nowrap text-smallcaps small p-2">RLTY Assembly</th>
<th class="text-nowrap text-smallcaps small p-2">RLTY Shipping</th>
<th class="text-nowrap text-smallcaps small p-2">Max DBL % Assembly</th>
<th class="text-nowrap text-smallcaps small p-2">Max DBL % Shipping</th>
<th class="text-nowrap text-smallcaps small p-2">Max Storage (months)</th>
<th class="text-nowrap text-smallcaps small p-2">Max Storage (months big orders)</th>
<th class="text-nowrap text-smallcaps small p-2">Q.Curr.uA</th>
<th class="text-nowrap text-smallcaps small p-2">Estimated load %</th>
<th class="text-nowrap text-smallcaps small p-2">Last Updated</th>
<th class="text-nowrap text-smallcaps small p-2">Updated by</th>
<th class="text-nowrap text-smallcaps small p-2">Comment</th>
@{
var model = new LaaProduction.Data.Cordonel.Models.CordonelStandardRequirement();
}
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Version)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Region)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MeterSize)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.IsActive)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.FwVersion)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.LutCrc)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.SkipRadioCheck)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.RequiredLifeTimeYearsAssembly)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.RequiredLifeTimeYearsShipping)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxDrainedBatteryLoadPercentAssembly)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxDrainedBatteryLoadPercentShipping)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxStorageMonths)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxStorageMonthsBigOrders)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.QuiescentCurrent_uA)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.EstimatedProductionBatteryLoadPercent)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Timestamp)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.ApprovalName)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.ApprovalComment)</th>
</tr>
</thead>
<tbody>

View File

@ -1,9 +1,7 @@
@model LaaProduction.Data.Cordonel.Models.CordonelStandardRequirement
<th class="text-nowrap small p-2">@($"{Model.Id}.{Model.Version}")</th>
<th class="text-nowrap small p-2">@Model.Key</th>
<td class="text-nowrap small p-2">@Model.Region</td>
<td class="text-nowrap small p-2">@Model.ProductGroup</td>
<td class="text-nowrap small p-2">@Model.MeterSize</td>
<td class="text-nowrap small p-2 text-center">