just some refactoring

This commit is contained in:
Stoyan Zlatev 2024-07-05 11:00:24 +02:00
parent c5ecb784bb
commit 736bfb6ba1
46 changed files with 779 additions and 241 deletions

View File

@ -36,58 +36,26 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<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="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CordonelPreadjustmentUi\CordonelPreadjustmentUi.csproj">
<Project>{D0C8D887-ED52-40AB-A069-90BCE0E801E2}</Project>
<Name>CordonelPreadjustmentUi</Name>
</ProjectReference>
<ProjectReference Include="..\Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SIRT\Common.Hardware.Interfaces.Ports.SIRT.csproj">
<Project>{B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD}</Project>
<Name>Common.Hardware.Interfaces.Ports.SIRT</Name>
</ProjectReference>
<ProjectReference Include="..\Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports\Common.Hardware.Interfaces.Ports.csproj">
<Project>{9AE071C0-DB12-4E09-A3C7-43F6DCD518D6}</Project>
<Name>Common.Hardware.Interfaces.Ports</Name>
</ProjectReference>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Hardware\WaterMeter\OmniPlus\Common.Hardware.WaterMeter.OmniPlus.Features\Common.Hardware.WaterMeter.OmniPlus.Features.csproj">
<Project>{9D89FA2A-1217-4CE9-B217-E7602B974EA9}</Project>
<Name>Common.Hardware.WaterMeter.OmniPlus.Features</Name>
</ProjectReference>
<ProjectReference Include="..\Hardware\WaterMeter\OmniPlus\Common.Hardware.WaterMeter.OmniPlus\Common.Hardware.WaterMeter.OmniPlus.csproj">
<Project>{6480CC2A-AB54-4A26-8413-D5141431C080}</Project>
<Name>Common.Hardware.WaterMeter.OmniPlus</Name>
</ProjectReference>
<ProjectReference Include="..\OmniPlus\OmniPlus\OmniPlus.csproj">
<Project>{F8D84B9A-0FCF-4083-B067-8C39B7314152}</Project>
<Name>OmniPlus</Name>
</ProjectReference>
<ProjectReference Include="..\SoftwareAccessHelper\SoftwareAccessHelper.csproj">
<Project>{A33E3C6D-EAAE-4A20-A0EE-F9E6922FD029}</Project>
<Name>SoftwareAccessHelper</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,32 +1,35 @@
namespace CommonConsole
using Common.Hardware.WaterMeter.OmniPlus.Features;
using System;
namespace CommonConsole
{
using Common.Hardware.Interfaces.Ports;
using Common.Hardware.Interfaces.Ports.SIRT;
using System;
public static class Program
{
public static void Main()
{
var broadcaster = new SirtBroadcaster(new SerialPortSettings
var systemTime = new SystemTime
{
BaudRate = SerialPortBaudRate.X115200,
DataBits = SerialPortDataBits.X8,
Parity = SerialPortParity.None,
PortName = "COM6",
StopBits = SerialPortStopBits.One,
RWTimeout = -1
});
broadcaster.Open();
Console.WriteLine($"READY: {broadcaster.Ready}");
Console.WriteLine($"SIRT-ID: {broadcaster.SirtId}");
Console.WriteLine($"FREQUENCY: {broadcaster.Frequency:0 MHz}");
Console.ReadKey();
broadcaster.Close();
DateTime = DateTime.Now
};
Console.WriteLine(systemTime.SecondsSince);
var initilalSystemTime = new SystemTime
{
SecondsSince = BitConverter.ToUInt32(new byte[] { 0x69, 0x65, 0x08, 0x2C }, 0)
};
Console.WriteLine(initilalSystemTime.SecondsSince);
Console.WriteLine(initilalSystemTime.DateTime);
}
}
}
}
/*
* 01
* 38-31-36-32-33-31-33-30-33-37-36-31-00-00-00-00
* 69-65-08-2C
* 9B-AD-16-2E
* 02
* 52-31-2E-32-34-2C-4F-4D-4E-49-2D-30-31-2C-52-30-2E-33-2E-31-38-00-00-00-00-00
* 00-DC-0C-C8
* 38
* 00-00-00
*/

View File

@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -59,15 +60,17 @@
<Compile Include="Messages\Payloads\Semi.cs" />
<Compile Include="Requests\ReadPamRequest.cs" />
<Compile Include="Requests\ReadRegRequest.cs" />
<Compile Include="Requests\SIRTRequest.cs" />
<Compile Include="Requests\WritePamRequest.cs" />
<Compile Include="Requests\WriteRegRequest.cs" />
<Compile Include="Responses\AckOrAnswerResponse.cs" />
<Compile Include="Responses\FromAirResponse.cs" />
<Compile Include="SirtMessage.cs" />
<Compile Include="SirtBroadcaster.cs" />
<Compile Include="SirtConstants.cs" />
<Compile Include="Responses\SIRTResponse.cs" />
<Compile Include="SIRTMessage.cs" />
<Compile Include="SIRTBroadcaster.cs" />
<Compile Include="SIRTConstants.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SirtTask.cs" />
<Compile Include="SIRTTask.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common.Hardware.Interfaces.Ports\Common.Hardware.Interfaces.Ports.csproj">

View File

@ -4,7 +4,7 @@
using System;
public class ReadPamRequest : SirtMessage
public class ReadPamRequest : SIRTRequest
{
/// <summary>
/// <list>
@ -20,16 +20,16 @@
/// </summary>
public Boolean PamStruct
{
get => this.P1 == 1;
set => this.P1 = (Byte)(value ? 1 : 0);
get => this.message.P1 == 1;
set => this.message.P1 = (Byte)(value ? 1 : 0);
}
protected override Byte[] ToByteArray()
{
this.Start = SirtConstants.Pc2Sirt;
this.Cmd = SirtConstants.ReadPam;
this.message.Start = SIRTConstants.Pc2Sirt;
this.message.Cmd = SIRTConstants.ReadPam;
return base.ToByteArray();
return this.message.ToByteArray();
}
}
}

View File

@ -4,21 +4,20 @@
using System;
public class ReadRegRequest : SirtMessage
public class ReadRegRequest : SIRTRequest
{
public Byte ReadLength
{
get => this.P2;
set => this.P2 = value;
get => this.message.P2;
set => this.message.P2 = value;
}
protected override Byte[] ToByteArray()
{
this.Start = SirtConstants.Pc2Sirt;
this.Cmd = SirtConstants.ReadReg;
this.P2 = this.ReadLength;
this.message.Start = SIRTConstants.Pc2Sirt;
this.message.Cmd = SIRTConstants.ReadReg;
return base.ToByteArray();
return this.message.ToByteArray();
}
}
}

View File

@ -0,0 +1,26 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Requests
{
using System;
public abstract class SIRTRequest
{
internal readonly SIRTMessage message = new SIRTMessage();
public UInt32 Address
{
get => this.message.Address;
set => this.message.Address = value;
}
public Byte[] Payload
{
get => this.message.Payload;
set => this.message.Payload = value;
}
protected abstract Byte[] ToByteArray();
public static implicit operator Byte[] (SIRTRequest request)
=> request.ToByteArray();
}
}

View File

@ -5,10 +5,13 @@
using System;
public class WritePamRequest : SirtMessage
public class WritePamRequest : SIRTRequest
{
private readonly P811 parameter811 = default(Byte);
public WritePamRequest()
=> this.parameter811 = this.message.P1;
/// <summary>
/// <inheritdoc cref="P811.WakeUpModul"/>
/// </summary>
@ -74,11 +77,11 @@
protected override Byte[] ToByteArray()
{
this.Start = SirtConstants.Pc2Sirt;
this.Cmd = SirtConstants.WritePam;
this.P1 = this.parameter811;
this.message.Start = SIRTConstants.Pc2Sirt;
this.message.Cmd = SIRTConstants.WritePam;
this.message.P1 = this.parameter811;
return base.ToByteArray();
return this.message.ToByteArray();
}
}
}

View File

@ -4,15 +4,20 @@
using System;
public class WriteRegRequest : SirtMessage
public class WriteRegRequest : SIRTRequest
{
public Byte WriteLength
{
get => this.message.P2;
set => this.message.P2 = value;
}
protected override Byte[] ToByteArray()
{
this.Start = SirtConstants.Pc2Sirt;
this.Cmd = SirtConstants.WriteReg;
this.P2 = this.Length;
this.message.Start = SIRTConstants.Pc2Sirt;
this.message.Cmd = SIRTConstants.WriteReg;
return base.ToByteArray();
return this.message.ToByteArray();
}
}
}

View File

@ -4,12 +4,12 @@
using System;
public class AckOrAnswerResponse : SirtMessage
public class AckOrAnswerResponse : SIRTResponse
{
private readonly P12 parameterP12;
public AckOrAnswerResponse(Byte[] bytes) : base(bytes)
=> this.parameterP12 = this.P1;
=> this.parameterP12 = this.message.P1;
/// <summary>
/// <inheritdoc cref="P12.BufFull"/>
@ -51,6 +51,6 @@
/// </summary>
public Boolean WildCardAddr => this.parameterP12.WildCardAddr;
public Byte LastCmd => this.P2;
public Byte LastCmd => this.message.P2;
}
}

View File

@ -4,14 +4,14 @@
using System;
public class FromAirResponse : SirtMessage
public class FromAirResponse : SIRTResponse
{
private readonly P11 parameterP11;
private Int32 mhz;
public FromAirResponse(Byte[] bytes) : base(bytes)
=> this.parameterP11 = this.P1;
=> this.parameterP11 = this.message.P1;
/// <summary>
/// <inheritdoc cref="P11.SrcChannel"/>
@ -59,8 +59,8 @@
set
{
this.mhz = value;
this.ReceivePowerDbm = this.CalculateReceivePowerDbm(this.mhz, this.P2);
this.ReceivePowerPer = this.CalculateReceivePowerPer(this.mhz, this.P2);
this.ReceivePowerDbm = this.CalculateReceivePowerDbm(this.mhz, this.message.P2);
this.ReceivePowerPer = this.CalculateReceivePowerPer(this.mhz, this.message.P2);
}
}

View File

@ -0,0 +1,17 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Responses
{
using System;
public class SIRTResponse
{
internal readonly SIRTMessage message;
public SIRTResponse(Byte[] bytes) => this.message = new SIRTMessage(bytes);
public Byte Cmd => this.message.Cmd;
public UInt32 Address => this.message.Address;
public Byte[] Payload => this.message.Payload;
}
}

View File

@ -2,18 +2,22 @@
{
using Common.Hardware.Interfaces.Ports.SIRT.Parameters;
using Common.Hardware.Interfaces.Ports.SIRT.Requests;
using Common.Hardware.Interfaces.Ports.SIRT.Responses;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class SirtBroadcaster : SirtSerialPort
public class SIRTBroadcaster : SIRTSerialPort
{
private static readonly ConcurrentDictionary<UInt32, Queue<SirtTask>> tasks
= new ConcurrentDictionary<UInt32, Queue<SirtTask>>();
private static readonly ConcurrentDictionary<UInt32, DateTime> availableDevices
= new ConcurrentDictionary<UInt32, DateTime>();
private static readonly ConcurrentDictionary<UInt32, Queue<SIRTTask>> tasks
= new ConcurrentDictionary<UInt32, Queue<SIRTTask>>();
public SirtBroadcaster(SerialPortSettings settings) : base(settings)
public SIRTBroadcaster(SerialPortSettings settings) : base(settings)
=> this.DataReceived += this.SirtBroadcaster_DataReceived;
public String SirtId { get; private set; }
@ -22,11 +26,15 @@
public Boolean Ready { get; private set; }
public event Action<UInt32> DeviceAvailable;
public event Action<UInt32> DeviceUnavailable;
public override void Open()
{
base.Open();
_ = this.Write(new WriteRegRequest
_ = this.Send(new WriteRegRequest
{
Address = 0x20000000,
Payload = new Byte[]
@ -55,7 +63,7 @@
});
var manuelResetEventSlim = new ManualResetEventSlim();
var sirtTask = this.Write(new ReadRegRequest
var sirtTask = this.Send(new ReadRegRequest
{
ReadLength = 8,
Address = 0x11001820
@ -79,21 +87,25 @@
manuelResetEventSlim.Set();
};
manuelResetEventSlim.Wait();
manuelResetEventSlim.Wait(10000);
if (!this.Ready)
{
this.Close();
}
else
{
this.RemoveUnavailableDevices();
}
}
public SirtTask Write(SirtMessage request)
public SIRTTask Send(SIRTRequest request)
{
var task = new SirtTask(request);
var task = new SIRTTask(request);
task.Done += Task_Done;
var queue = tasks
.GetOrAdd(task.Address, new Queue<SirtTask>());
.GetOrAdd(task.Address, new Queue<SIRTTask>());
queue.Enqueue(task);
if (queue.Count == 1)
@ -104,7 +116,60 @@
return task;
}
private void Task_Done(SirtTask task)
private void RemoveUnavailableDevices()
{
Task.Factory
.StartNew(state =>
{
if (state is SIRTBroadcaster broadcaster)
{
while (true)
{
var now = DateTime.Now;
foreach (var address in availableDevices.Keys)
{
if (availableDevices.TryGetValue(address, out var timestamp) && (now - timestamp).TotalSeconds > 30)
{
availableDevices.TryRemove(address, out var _);
broadcaster.DeviceUnavailable?.Invoke(address);
}
}
Thread.Sleep(10000);
}
}
}, this, CancellationToken.None)
.ContinueWith(task =>
{
if (task.Exception != null && task.AsyncState is SIRTBroadcaster broadcaster)
{
broadcaster.Notify(task.Exception.ToString());
}
}, CancellationToken.None);
}
private void SirtBroadcaster_DataReceived(Byte[] data)
{
var response = new SIRTResponse(data);
var address = response.Address;
if (tasks.TryGetValue(address, out var queue) && queue.Count > 0)
{
queue.Peek().AddResponse(response);
}
availableDevices.AddOrUpdate(address,
addValueFactory: key =>
{
this.DeviceAvailable?.Invoke(key);
return DateTime.Now;
},
updateValueFactory: (_1, _2) => DateTime.Now);
}
private void Task_Done(SIRTTask task)
{
if (tasks.TryGetValue(task.Address, out var queue))
{
@ -123,15 +188,5 @@
}
}
}
private void SirtBroadcaster_DataReceived(Byte[] data)
{
var response = new SirtMessage(data);
if (tasks.TryGetValue(response.Address, out var queue) && queue.Count > 0)
{
queue.Peek().AddResponse(response);
}
}
}
}

View File

@ -2,7 +2,7 @@
{
using System;
public static class SirtConstants
public static class SIRTConstants
{
public const Int32 CmdIndex = 1;
public const Int32 LengthIndex = 8;

View File

@ -4,18 +4,18 @@
using System;
public class SirtMessage
internal class SIRTMessage
{
private Byte[] bytes;
private Int32 bytesLength;
public SirtMessage()
public SIRTMessage()
{
this.bytes = new Byte[SirtConstants.MinLength];
this.bytes = new Byte[SIRTConstants.MinLength];
this.bytesLength = this.bytes.Length;
}
public SirtMessage(Byte[] bytes)
public SIRTMessage(Byte[] bytes)
{
this.bytes = bytes;
this.bytesLength = this.bytes.Length;
@ -71,7 +71,7 @@
set
{
this.bytes[8] = value;
var newLength = SirtConstants.MinLength + value;
var newLength = SIRTConstants.MinLength + value;
Array.Resize(ref this.bytes, newLength);
this.bytesLength = this.bytes.Length;
@ -96,7 +96,7 @@
}
this.Length = (Byte)value.Length;
var newLength = SirtConstants.MinLength + this.Length;
var newLength = SIRTConstants.MinLength + this.Length;
Array.Resize(ref this.bytes, newLength);
Array.Copy(value, 0, this.bytes, 9, this.Length);
@ -116,24 +116,24 @@
public override String ToString()
=> BitConverter.ToString(this.ToByteArray());
protected virtual Byte[] ToByteArray()
internal Byte[] ToByteArray()
{
var crc = CRC1021.CalculateCRC1021(this.bytes, 1, this.bytesLength - 3);
this.bytes[this.bytesLength - 3] = crc.MSB;
this.bytes[this.bytesLength - 2] = crc.LSB;
this.bytes[this.bytesLength - 1] = SirtConstants.StopByte;
this.bytes[this.bytesLength - 1] = SIRTConstants.StopByte;
return this.bytes;
}
public static implicit operator SirtMessage(Byte[] bytes)
=> new SirtMessage(bytes);
public static implicit operator SIRTMessage(Byte[] bytes)
=> new SIRTMessage(bytes);
public static implicit operator Byte[](SirtMessage message)
public static implicit operator Byte[](SIRTMessage message)
=> message.ToByteArray();
public static implicit operator String (SirtMessage message)
public static implicit operator String (SIRTMessage message)
=> message.ToString();
}
}

View File

@ -1,29 +1,32 @@
namespace Common.Hardware.Interfaces.Ports.SIRT
{
using Common.Hardware.Interfaces.Ports.SIRT.Requests;
using Common.Hardware.Interfaces.Ports.SIRT.Responses;
using System;
using System.Collections.Generic;
public class SirtTask
public class SIRTTask
{
private readonly SirtMessage request;
private readonly ICollection<SirtMessage> responses;
private readonly SIRTRequest request;
private readonly ICollection<SIRTResponse> responses;
public SirtTask(SirtMessage request)
internal SIRTTask(SIRTRequest request)
{
this.request = request;
this.Address = this.request.Address;
this.responses = new List<SirtMessage>();
this.responses = new List<SIRTResponse>();
}
public event Action<SirtTask> Done;
public event Action<SIRTTask> Done;
public UInt32 Address { get; }
public Boolean IsDone { get; private set; }
public SirtMessage Last { get; private set; }
public SIRTResponse Last { get; private set; }
internal void AddResponse(SirtMessage response)
internal void AddResponse(SIRTResponse response)
{
if (!this.IsDone)
{
@ -32,8 +35,8 @@
this.responses.Add(response);
if ((response.Cmd == SirtConstants.FromAir && response.Payload[0] == SirtConstants.Semi)
|| (response.Cmd == SirtConstants.AckOrAnswer && response.Payload.Length > 0))
if ((response.Cmd == SIRTConstants.FromAir && response.Payload[0] == SIRTConstants.Semi)
|| (response.Cmd == SIRTConstants.AckOrAnswer && response.Payload.Length > 0))
{
this.IsDone = true;
@ -41,7 +44,7 @@
}
}
public static implicit operator Byte[](SirtTask task)
public static implicit operator Byte[](SIRTTask task)
=> task.request;
}
}

View File

@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -40,7 +41,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="IrdaSerialPort.cs" />
<Compile Include="IRDASerialPort.cs" />
<Compile Include="SerialPort.cs" />
<Compile Include="SerialPortBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@ -50,7 +51,7 @@
<Compile Include="SerialPortParity.cs" />
<Compile Include="SerialPortSettings.cs" />
<Compile Include="SerialPortStopBits.cs" />
<Compile Include="SirtSerialPort.cs" />
<Compile Include="SIRTSerialPort.cs" />
<Compile Include="UniProSerialPort.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -3,9 +3,9 @@
using System;
using System.Threading;
public class IrdaSerialPort : SerialPort
public class IRDASerialPort : SerialPort
{
public IrdaSerialPort(SerialPortSettings settings) : base(settings)
public IRDASerialPort(SerialPortSettings settings) : base(settings)
{
}
@ -15,7 +15,7 @@
if (data.TryParseToIrda(out var bytes))
{
for (int i = 0; i < 3; i++)
for (var i = 0; i < 3; i++)
{
this.serialPortBase.Write(new Byte[] { 0x01, 0x01, 0x01, 0x01 }, 0, 4);

View File

@ -28,6 +28,8 @@
}
}
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

@ -42,21 +42,21 @@
serialPort.Dispose();
serialPort = null;
this.NotifyInfoMessage($"Disconnected: {this}");
this.Notify($"Disconnected: {this}");
}
else
{
this.NotifyInfoMessage($"{this.PortName} is null!");
this.Notify($"{this.PortName} is null!");
}
}
else
{
this.NotifyInfoMessage($"{this.PortName} dose not exists!");
this.Notify($"{this.PortName} dose not exists!");
}
}
catch (Exception e)
{
this.NotifyInfoMessage(e.ToString());
this.Notify(e.ToString());
}
}
@ -83,16 +83,16 @@
{
serialPort.Open();
this.NotifyInfoMessage($"Connected: {this}");
this.Notify($"Connected: {this}");
}
else
{
this.NotifyInfoMessage($"{this.PortName} cann't be addedd!");
this.Notify($"{this.PortName} cann't be addedd!");
}
}
catch (Exception e)
{
this.NotifyInfoMessage(e.ToString());
this.Notify(e.ToString());
}
}
@ -113,11 +113,11 @@
Buffer.BlockCopy(buffer, 0, bytes, 0, bytesToCopy);
this.NotifyInfoMessage($"RX|{BitConverter.ToString(bytes)}");
this.Notify($"RX|{BitConverter.ToString(bytes)}");
}
catch (Exception e)
{
this.NotifyInfoMessage(e.ToString());
this.Notify(e.ToString());
}
}
@ -150,16 +150,16 @@
serialPort.Write(bytes, start, length);
}
this.NotifyInfoMessage($"TX|{BitConverter.ToString(bytes)}");
this.Notify($"TX|{BitConverter.ToString(bytes)}");
}
catch (Exception e)
{
this.NotifyInfoMessage(e.ToString());
this.Notify(e.ToString());
}
}
}
public void NotifyInfoMessage(String state)
public void Notify(String state)
=> this.Logging?.Invoke(state);
}
}

View File

@ -4,14 +4,14 @@
using System.Threading;
using System.Threading.Tasks;
public class SirtSerialPort : SerialPort
public class SIRTSerialPort : SerialPort
{
private CancellationTokenSource cancellationTokenSource;
private CancellationToken cancellationToken;
private Task listener;
private bool listening;
public SirtSerialPort(SerialPortSettings settings) : base(settings)
public SIRTSerialPort(SerialPortSettings settings) : base(settings)
{
}
@ -56,7 +56,7 @@
this.cancellationToken = this.cancellationTokenSource.Token;
this.listener = Task.Factory.StartNew(asyncState =>
{
if (asyncState is SirtSerialPort sirtSerialPort)
if (asyncState is SIRTSerialPort sirtSerialPort)
{
sirtSerialPort.listening = true;
@ -115,11 +115,11 @@
}, this, this.cancellationToken)
.ContinueWith(task =>
{
if (task.AsyncState is SirtSerialPort sirtSerialPort)
if (task.AsyncState is SIRTSerialPort sirtSerialPort)
{
if (task.Exception != null)
{
sirtSerialPort.serialPortBase.NotifyInfoMessage(task.Exception.ToString());
sirtSerialPort.serialPortBase.Notify(task.Exception.ToString());
}
sirtSerialPort.listening = false;
@ -137,7 +137,7 @@
}
catch (Exception e)
{
this.serialPortBase.NotifyInfoMessage(e.ToString());
this.serialPortBase.Notify(e.ToString());
}
}
}

View File

@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View File

@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View File

@ -16,7 +16,7 @@
PortName = portName,
StopBits = SerialPortStopBits.One
};
this.serialPort = new IrdaSerialPort(settings);
this.serialPort = new IRDASerialPort(settings);
}
public override Byte[] Send(params Byte[] bytes)

View File

@ -0,0 +1,53 @@
<?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>{E19C1694-132E-477C-86CB-8E146D5F59B0}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Common.Hardware.WaterMeter.eRegister.Features</RootNamespace>
<AssemblyName>Common.Hardware.WaterMeter.eRegister.Features</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="PamBuilder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SIRT\Common.Hardware.Interfaces.Ports.SIRT.csproj">
<Project>{B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD}</Project>
<Name>Common.Hardware.Interfaces.Ports.SIRT</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,55 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Interfaces.Ports.SIRT.Requests;
using System;
public class PamBuilder
{
public class PamFeatures
{
public Boolean WakeUpModul { get; set; }
public Boolean WakeUpCmd { get; set; }
public Boolean IgnoreTimeout { get; set; }
public Boolean DelPamSemi { get; set; }
public Boolean DelPamTx { get; set; }
public Boolean DelPamAdr { get; set; }
public Boolean DelPamAll { get; set; }
public UInt32 Address { get; set; }
internal Byte[] Payload { get; set; }
}
public class MultiPamFeatures : PamFeatures
{
}
public static WritePamRequest MultiPamCommand(Action<MultiPamFeatures> featuresBuilder)
{
var features = new MultiPamFeatures();
featuresBuilder?.Invoke(features);
return new WritePamRequest
{
Address = features.Address,
DelPamAdr = features.DelPamAdr,
DelPamAll = features.DelPamAll,
DelPamSemi = features.DelPamSemi,
DelPamTx = features.DelPamTx,
IgnoreTimeout = features.IgnoreTimeout,
WakeUpCmd = features.WakeUpCmd,
WakeUpModul = features.WakeUpModul,
Payload = features.Payload
};
}
}
}

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("Common.Hardware.WaterMeter.eRegister.Features")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Common.Hardware.WaterMeter.eRegister.Features")]
[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("e19c1694-132e-477c-86cb-8e146d5f59b0")]
// 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

@ -23,6 +23,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View File

@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View File

@ -25,6 +25,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View File

@ -5,8 +5,6 @@
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class TestBatchAttribute : Attribute
{
private readonly string displayName;
public TestBatchAttribute(string displayName)
=> this.DisplayName = displayName;

View File

@ -50,7 +50,7 @@
<DebugType>none</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>InspectionUI.Plugins.Omni.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<RegisterForComInterop>false</RegisterForComInterop>
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
<DebugSymbols>false</DebugSymbols>
@ -97,7 +97,6 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="InspectionUI.Plugins.Omni.ruleset" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Rules for InspectionUI.Plugins.Omni" Description="Code analysis rules for InspectionUI.Plugins.Omni.csproj." ToolsVersion="15.0">
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
<Rule Id="CA1001" Action="Warning" />
<Rule Id="CA1009" Action="Warning" />
<Rule Id="CA1016" Action="Warning" />
<Rule Id="CA1033" Action="Warning" />
<Rule Id="CA1049" Action="Warning" />
<Rule Id="CA1060" Action="Warning" />
<Rule Id="CA1061" Action="Warning" />
<Rule Id="CA1063" Action="Warning" />
<Rule Id="CA1065" Action="Warning" />
<Rule Id="CA1301" Action="Warning" />
<Rule Id="CA1400" Action="Warning" />
<Rule Id="CA1401" Action="Warning" />
<Rule Id="CA1403" Action="Warning" />
<Rule Id="CA1404" Action="Warning" />
<Rule Id="CA1405" Action="Warning" />
<Rule Id="CA1410" Action="Warning" />
<Rule Id="CA1415" Action="Warning" />
<Rule Id="CA1821" Action="Warning" />
<Rule Id="CA1900" Action="Warning" />
<Rule Id="CA1901" Action="Warning" />
<Rule Id="CA2002" Action="Warning" />
<Rule Id="CA2100" Action="Warning" />
<Rule Id="CA2101" Action="Warning" />
<Rule Id="CA2108" Action="Warning" />
<Rule Id="CA2111" Action="Warning" />
<Rule Id="CA2112" Action="Warning" />
<Rule Id="CA2114" Action="Warning" />
<Rule Id="CA2116" Action="Warning" />
<Rule Id="CA2117" Action="Warning" />
<Rule Id="CA2122" Action="Warning" />
<Rule Id="CA2123" Action="Warning" />
<Rule Id="CA2124" Action="Warning" />
<Rule Id="CA2126" Action="Warning" />
<Rule Id="CA2131" Action="Warning" />
<Rule Id="CA2132" Action="Warning" />
<Rule Id="CA2133" Action="Warning" />
<Rule Id="CA2134" Action="Warning" />
<Rule Id="CA2137" Action="Warning" />
<Rule Id="CA2138" Action="Warning" />
<Rule Id="CA2140" Action="Warning" />
<Rule Id="CA2141" Action="Warning" />
<Rule Id="CA2146" Action="Warning" />
<Rule Id="CA2147" Action="Warning" />
<Rule Id="CA2149" Action="Warning" />
<Rule Id="CA2200" Action="Warning" />
<Rule Id="CA2202" Action="Warning" />
<Rule Id="CA2207" Action="Warning" />
<Rule Id="CA2212" Action="Warning" />
<Rule Id="CA2213" Action="Warning" />
<Rule Id="CA2214" Action="Warning" />
<Rule Id="CA2216" Action="Warning" />
<Rule Id="CA2220" Action="Warning" />
<Rule Id="CA2229" Action="Warning" />
<Rule Id="CA2231" Action="Warning" />
<Rule Id="CA2232" Action="Warning" />
<Rule Id="CA2235" Action="Warning" />
<Rule Id="CA2236" Action="Warning" />
<Rule Id="CA2237" Action="Warning" />
<Rule Id="CA2238" Action="Warning" />
<Rule Id="CA2240" Action="Warning" />
<Rule Id="CA2241" Action="Warning" />
<Rule Id="CA2242" Action="Warning" />
</Rules>
</RuleSet>

View File

@ -23,6 +23,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View File

@ -28,6 +28,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>

View File

@ -23,7 +23,7 @@
{
dispatcher.Invoke(action);
}
catch (Exception _)
catch (Exception)
{
}

View File

@ -34,6 +34,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SIRT.PortName" value="COM6"/>
<add key="SIRT.RWTimeout" value="3000"/>
</appSettings>
</configuration>

View File

@ -1,7 +1,6 @@
<Application x:Class="Common.UI.SIRTBroadcaster.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Common.UI.SIRTBroadcaster"
StartupUri="MainWindow.xaml">
<Application.Resources>

View File

@ -1,8 +1,34 @@
namespace Common.UI.SIRTBroadcaster
{
using System;
using System.Windows;
public partial class App : Application
{
private static Boolean activatedForFirstTime;
public static event Action Exited;
public static event Action Started;
public static void Invoke(Action action) => Current?.Dispatcher?.Invoke(action);
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
if (!activatedForFirstTime)
{
activatedForFirstTime = true;
Started?.Invoke();
}
}
protected override void OnExit(ExitEventArgs e)
{
Exited?.Invoke();
base.OnExit(e);
}
}
}

View File

@ -23,6 +23,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -35,6 +36,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
@ -53,6 +55,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Utilities\Appsettings.cs" />
<Compile Include="Utilities\CompilerServices.cs" />
<Compile Include="ViewModels\SIRTBroadcasterViewModel.cs" />
<Compile Include="ViewModels\VM.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -67,6 +73,7 @@
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Models\SIRTBroadcasterModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
@ -84,10 +91,25 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="App.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SIRT\Common.Hardware.Interfaces.Ports.SIRT.csproj">
<Project>{b23bfaf9-08ae-4311-8c08-fb2bb49ea2ad}</Project>
<Name>Common.Hardware.Interfaces.Ports.SIRT</Name>
</ProjectReference>
<ProjectReference Include="..\..\Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports\Common.Hardware.Interfaces.Ports.csproj">
<Project>{9ae071c0-db12-4e09-a3c7-43f6dcd518d6}</Project>
<Name>Common.Hardware.Interfaces.Ports</Name>
</ProjectReference>
<ProjectReference Include="..\..\Hardware\WaterMeter\eRegister\Common.Hardware.WaterMeter.eRegister.Features\Common.Hardware.WaterMeter.eRegister.Features.csproj">
<Project>{E19C1694-132E-477C-86CB-8E146D5F59B0}</Project>
<Name>Common.Hardware.WaterMeter.eRegister.Features</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,12 +1,65 @@
<Window x:Class="Common.UI.SIRTBroadcaster.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Common.UI.SIRTBroadcaster"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
xmlns:VM="clr-namespace:Common.UI.SIRTBroadcaster.ViewModels"
FontFamily="Verdana"
Title="MainWindow"
Height="450"
Width="800">
<Window.DataContext>
<VM:SIRTBroadcasterViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock FontWeight="Black"
Grid.Column="0"
Grid.Row="0"
Padding="10, 5"
Text="{Binding AvailableDevicesCount, StringFormat='Available devices: 0'}" />
<ScrollViewer Background="WhiteSmoke"
Grid.Column="0"
Grid.Row="1"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
HorizontalScrollBarVisibility="Disabled"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding AvailableDevices}">
<ItemsControl.Resources>
<Style x:Key="ItemStyle" TargetType="TextBlock">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Padding" Value="10, 5" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGray" />
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Style="{StaticResource ItemStyle}"
Text="{Binding ., StringFormat='0000000000'}">
<TextBlock.InputBindings>
<MouseBinding Gesture="LeftClick" />
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Window>

View File

@ -0,0 +1,60 @@
namespace Common.UI.SIRTBroadcaster.Models
{
using Common.Hardware.Interfaces.Ports;
using Common.Hardware.Interfaces.Ports.SIRT;
using Common.Hardware.WaterMeter.eRegister.Features;
using System;
public class SIRTBroadcasterModel
{
private readonly SIRTBroadcaster broadcaster;
public SIRTBroadcasterModel(String portName, Int32 timeout)
{
this.broadcaster = new SIRTBroadcaster(new SerialPortSettings
{
BaudRate = SerialPortBaudRate.X115200,
DataBits = SerialPortDataBits.X8,
Parity = SerialPortParity.None,
PortName = portName,
StopBits = SerialPortStopBits.One,
RWTimeout = timeout
});
}
public Int32 Frequency => this.broadcaster?.Frequency ?? 0;
public String Id => this.broadcaster?.SirtId ?? String.Empty;
public Boolean IsConnected => this.broadcaster?.IsOpen ?? false;
public event Action<UInt32> DeviceAvailable
{
add => this.broadcaster.DeviceAvailable += value;
remove => this.broadcaster.DeviceAvailable -= value;
}
public event Action<UInt32> DeviceUnavailable
{
add => this.broadcaster.DeviceUnavailable += value;
remove => this.broadcaster.DeviceUnavailable -= value;
}
public void Activate() => this.broadcaster.Open();
public void Deactivate() => this.broadcaster.Close();
public void WakeUp()
{
var pam = PamBuilder.MultiPamCommand(options =>
{
options.Address = 319020441;
options.DelPamSemi = true;
options.WakeUpCmd = true;
});
var task = this.broadcaster.Send(pam);
}
}
}

View File

@ -0,0 +1,27 @@
namespace Common.UI.SIRTBroadcaster.Utilities
{
using System;
using System.Configuration;
public class Appsettings
{
private static Configuration Configuration => ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
private static AppSettingsSection AppSettings => Configuration.AppSettings;
private static String AppSettingsSectionName => AppSettings.SectionInformation.Name;
public static readonly Appsettings Current = new Appsettings();
public Appsettings() { }
public String this[String key] => GetSetting(key);
private static String GetSetting(String settingKey)
{
ConfigurationManager.RefreshSection(AppSettingsSectionName);
return AppSettings.Settings[settingKey].Value ?? String.Empty;
}
}
}

View File

@ -0,0 +1,17 @@
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class CallerMemberNameAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class CallerFilePathAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class CallerLineNumberAttribute : Attribute
{
}
}

View File

@ -0,0 +1,81 @@
namespace Common.UI.SIRTBroadcaster.ViewModels
{
using Common.UI.SIRTBroadcaster.Models;
using Common.UI.SIRTBroadcaster.Utilities;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
public class SIRTBroadcasterViewModel : VM
{
private readonly SortedDictionary<UInt32, Boolean> devices;
private readonly SIRTBroadcasterModel model;
public SIRTBroadcasterViewModel()
{
App.Started += App_Started;
App.Exited += App_Exited;
this.model = this.CreateSIRTBroadcasterModel();
this.devices = new SortedDictionary<UInt32, Boolean>();
}
private Int32 availableAddressesCount;
public Int32 AvailableDevicesCount
{
get => this.availableAddressesCount;
set => this.Set(() => this.availableAddressesCount = value);
}
public ObservableCollection<UInt32> AvailableDevices { get; private set; }
= new ObservableCollection<UInt32>();
private void App_Exited() => Task.Factory.StartNew(this.model.Deactivate);
private void App_Started() => Task.Factory.StartNew(() =>
{
this.model.Activate();
this.model.WakeUp();
});
private void Model_DeviceAvailable(UInt32 address)
=> App.Invoke(() =>
{
this.devices[address] = true;
this.RefreshAvailableDevices();
});
private void Model_DeviceUnavailable(UInt32 address)
=> App.Invoke(() =>
{
this.devices.Remove(address);
this.RefreshAvailableDevices();
});
private SIRTBroadcasterModel CreateSIRTBroadcasterModel()
{
var portName = Appsettings.Current["SIRT.PortName"];
var _timeout = Appsettings.Current["SIRT.RWTimeout"];
var parsed = Int32.TryParse(_timeout, out var timeout);
var broadcasterModel = new SIRTBroadcasterModel(portName, parsed ? timeout : 3000);
broadcasterModel.DeviceAvailable += Model_DeviceAvailable;
broadcasterModel.DeviceUnavailable += Model_DeviceUnavailable;
return broadcasterModel;
}
private void RefreshAvailableDevices()
{
this.AvailableDevices.Clear();
foreach (var key in this.devices.Keys)
{
this.AvailableDevices.Add(key);
}
this.AvailableDevicesCount = this.AvailableDevices.Count;
}
}
}

View File

@ -0,0 +1,79 @@
namespace Common.UI.SIRTBroadcaster.ViewModels
{
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
public abstract class VM : INotifyPropertyChanged, IDisposable
{
protected VM() => App.Exited += this.Dispose;
public event PropertyChangedEventHandler PropertyChanged;
public virtual void Dispose() => App.Exited -= this.Dispose;
protected void NotifyPropertyChanged([CallerMemberName] string property = "")
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
protected void Set(Action setExpression, [CallerMemberName] string property = "")
{
setExpression?.Invoke();
this.NotifyPropertyChanged(property);
}
protected class Command : ICommand
{
private readonly Action executable;
public Command(Action executable)
{
this.executable = executable;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object _)
{
return this.executable != null;
}
public void Execute(object _)
{
this.executable?.Invoke();
}
}
protected class Command<T> : ICommand
{
private readonly Action<T> executable;
public Command(Action<T> executable)
{
this.executable = executable;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object _)
{
return this.executable != null;
}
public void Execute(object parameter)
{
this.executable?.Invoke(parameter is T t ? t : default(T));
}
}
}
}