Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion RDMSharp/RDM/AsyncRDMRequestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public bool ReceiveMessage(RDMMessage rdmMessage)
return true;
}
//None Queued Parameters
var obj = buffer.Where(b => b.Value.Item1.Parameter != ERDM_Parameter.QUEUED_MESSAGE).FirstOrDefault(b => b.Value.Item2 == null && rdmMessage.Parameter == b.Value.Item1.Parameter && rdmMessage.TransactionCounter == b.Value.Item1.TransactionCounter && b.Value.Item1.DestUID == rdmMessage.SourceUID && b.Value.Item1.SourceUID == rdmMessage.DestUID);
var obj = buffer.Where(b => b.Value.Item1.Parameter != ERDM_Parameter.QUEUED_MESSAGE).FirstOrDefault(b => b.Value.Item2 == null && checkNonQueued(b.Value.Item1, rdmMessage));
if (obj.Value != null)
{
var tuple = new Tuple<RDMMessage, RDMMessage>(obj.Value.Item1, rdmMessage);
Expand All @@ -64,6 +64,22 @@ public bool ReceiveMessage(RDMMessage rdmMessage)
return true;
}
return false;

bool checkNonQueued(RDMMessage request, RDMMessage response)
{
if (request.Parameter != response.Parameter)
return false;
if (request.TransactionCounter != response.TransactionCounter)
return false;
if (request.SubDevice != response.SubDevice)
return false;
if (request.SourceUID != response.DestUID)
return false;
if (request.DestUID != response.SourceUID)
return false;

return true;
}
}


Expand All @@ -72,6 +88,11 @@ public async Task<RequestResult> RequestMessage(RDMMessage requerst)
try
{
int key = random.Next();
if (requerst.SubDevice.IsBroadcast)
{
await _sendMethode.Invoke(requerst);
return new RequestResult(requerst, null); // Broadcasts are not expected to return a response.
}
buffer.TryAdd(key, new Tuple<RDMMessage, RDMMessage>(requerst, null));
RDMMessage response = null;
await _sendMethode.Invoke(requerst);
Expand Down
36 changes: 27 additions & 9 deletions RDMSharp/RDM/Device/AbstractGeneratedRDMDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ public abstract class AbstractGeneratedRDMDevice : AbstractRDMDevice
public sealed override IReadOnlyDictionary<ushort, Slot> Slots { get { return CurrentPersonality.HasValue ? Personalities[CurrentPersonality.Value].Slots : null; } }


private List<IRDMDevice> subDevices = new List<IRDMDevice>();
public sealed override IReadOnlyCollection<IRDMDevice> SubDevices { get { return subDevices.AsReadOnly(); } }


public abstract bool SupportDMXAddress { get; }

private RDMDeviceInfo deviceInfo;
Expand Down Expand Up @@ -131,7 +127,14 @@ private set
}
}

protected AbstractGeneratedRDMDevice(UID uid, ERDM_Parameter[] parameters, string manufacturer = null, Sensor[] sensors = null) : base(uid)

protected AbstractGeneratedRDMDevice(UID uid, ERDM_Parameter[] parameters, string manufacturer = null, Sensor[] sensors = null, IRDMDevice[] subDevices = null) : this(uid, SubDevice.Root, parameters, manufacturer, sensors, subDevices)
{
}
protected AbstractGeneratedRDMDevice(UID uid, SubDevice subDevice, ERDM_Parameter[] parameters, string manufacturer = null, Sensor[] sensors = null) : this(uid, subDevice, parameters, manufacturer, sensors, null)
{
}
private AbstractGeneratedRDMDevice(UID uid, SubDevice subDevice, ERDM_Parameter[] parameters, string manufacturer = null, Sensor[] sensors = null, IRDMDevice[] subDevices = null) : base(uid, subDevice, subDevices)
{
if (!((ushort)ManufacturerID).Equals(uid.ManufacturerID))
throw new Exception($"{uid.ManufacturerID} not match the {ManufacturerID}");
Expand All @@ -156,7 +159,7 @@ protected AbstractGeneratedRDMDevice(UID uid, ERDM_Parameter[] parameters, strin
_params.Add(ERDM_Parameter.SLOT_DESCRIPTION);
_params.Add(ERDM_Parameter.DEFAULT_SLOT_VALUE);
}
if ((Sensors?.Keys.Max() ?? 0) != 0)
if ((Sensors?.Count ?? 0) != 0)
{
_params.Add(ERDM_Parameter.SENSOR_DEFINITION);
_params.Add(ERDM_Parameter.SENSOR_VALUE);
Expand Down Expand Up @@ -288,6 +291,7 @@ private void updateDeviceInfo()
dmx512CurrentPersonality: currentPersonality,
dmx512NumberOfPersonalities: (byte)(Personalities?.Length ?? 0),
dmx512StartAddress: dmxAddress,
subDeviceCount: (ushort)(SubDevices?.Where(sd=>!sd.Subdevice.IsRoot).Count() ?? 0),
sensorCount: (byte)(Sensors?.Count ?? 0));
updateDeviceInfo(info);
}
Expand Down Expand Up @@ -475,8 +479,8 @@ protected sealed override async Task OnReceiveRDMMessage(RDMMessage rdmMessage)
{
if ((rdmMessage.DestUID.IsBroadcast || rdmMessage.DestUID == UID) && !rdmMessage.Command.HasFlag(ERDM_Command.RESPONSE))
{
await SendRDMMessage(processRequestMessage(rdmMessage));
return;
if (rdmMessage.SubDevice.IsBroadcast || rdmMessage.SubDevice == this.Subdevice)
await SendRDMMessage(processRequestMessage(rdmMessage));
}
}

Expand Down Expand Up @@ -525,8 +529,20 @@ protected RDMMessage processRequestMessage(RDMMessage rdmMessage)
return null;
}
}

if (rdmMessage.SubDevice != SubDevice.Broadcast && !(this.SubDevices?.Any(sd => sd.Subdevice == rdmMessage.SubDevice) ?? true))
{
response = new RDMMessage(ERDM_NackReason.SUB_DEVICE_OUT_OF_RANGE) { Parameter = rdmMessage.Parameter, Command = rdmMessage.Command | ERDM_Command.RESPONSE };
goto FAIL;
}
if (rdmMessage.Command == ERDM_Command.GET_COMMAND)
{
if (rdmMessage.SubDevice == SubDevice.Broadcast) // no Response on Broadcast Subdevice, because this cant work on a if there are more then one Device responding on a singel line.
{
response = new RDMMessage(ERDM_NackReason.SUB_DEVICE_OUT_OF_RANGE) { Parameter = rdmMessage.Parameter, Command = rdmMessage.Command | ERDM_Command.RESPONSE };
goto FAIL;
}

parameterValues.TryGetValue(rdmMessage.Parameter, out object responseValue);
try
{
Expand Down Expand Up @@ -598,7 +614,8 @@ protected RDMMessage processRequestMessage(RDMMessage rdmMessage)
Logger?.LogError(e, string.Empty);
}
FAIL:

if (rdmMessage.SubDevice == SubDevice.Broadcast) // no Response on Broadcast Subdevice, because this cant work on a if there are more then one Device responding on a singel line.
return null;
if (rdmMessage.DestUID.IsBroadcast) // no Response on Broadcast
return null;

Expand All @@ -607,6 +624,7 @@ protected RDMMessage processRequestMessage(RDMMessage rdmMessage)
response.TransactionCounter = rdmMessage.TransactionCounter;
response.SourceUID = rdmMessage.DestUID;
response.DestUID = rdmMessage.SourceUID;
response.SubDevice = rdmMessage.SubDevice;
return response;
}
public sealed override IReadOnlyDictionary<ERDM_Parameter, object> GetAllParameterValues()
Expand Down
17 changes: 12 additions & 5 deletions RDMSharp/RDM/Device/AbstractRDMCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,19 @@ protected async Task requestSetParameterWithPayload(ParameterBag parameterBag, M

protected async Task requestGetParameterWithEmptyPayload(ParameterBag parameterBag, MetadataJSONObjectDefine define, UID uid, SubDevice subDevice)
{
PeerToPeerProcess ptpProcess = new PeerToPeerProcess(ERDM_Command.GET_COMMAND, uid, subDevice, parameterBag);
await runPeerToPeerProcess(ptpProcess);
if (!ptpProcess.ResponsePayloadObject.IsUnset)
try
{
updateParameterValuesDependeciePropertyBag(parameterBag.PID, ptpProcess.ResponsePayloadObject);
updateParameterValuesDataTreeBranch(new ParameterDataCacheBag(parameterBag.PID), ptpProcess.ResponsePayloadObject);
PeerToPeerProcess ptpProcess = new PeerToPeerProcess(ERDM_Command.GET_COMMAND, uid, subDevice, parameterBag);
await runPeerToPeerProcess(ptpProcess);
if (!ptpProcess.ResponsePayloadObject.IsUnset)
{
updateParameterValuesDependeciePropertyBag(parameterBag.PID, ptpProcess.ResponsePayloadObject);
updateParameterValuesDataTreeBranch(new ParameterDataCacheBag(parameterBag.PID), ptpProcess.ResponsePayloadObject);
}
}
catch(Exception e)
{

}
}
protected async Task requestGetParameterWithPayload(ParameterBag parameterBag, MetadataJSONObjectDefine define, UID uid, SubDevice subDevice)
Expand Down
84 changes: 70 additions & 14 deletions RDMSharp/RDM/Device/AbstractRDMDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace RDMSharp
Expand All @@ -21,33 +23,64 @@ public abstract class AbstractRDMDevice : AbstractRDMCache, IRDMDevice
public abstract RDMDeviceInfo DeviceInfo { get; }
public abstract IReadOnlyDictionary<byte, Sensor> Sensors { get; }
public abstract IReadOnlyDictionary<ushort, Slot> Slots { get; }
public abstract IReadOnlyCollection<IRDMDevice> SubDevices { get; }

private List<IRDMDevice> subDevices;
protected IList<IRDMDevice> SubDevices_Internal { get => subDevices; }
public IReadOnlyCollection<IRDMDevice> SubDevices => SubDevices_Internal?.AsReadOnly();

public new bool IsDisposing { get; private set; }
public new bool IsDisposed { get; private set; }
public bool IsInitializing { get; private set; }
public bool IsInitialized { get; private set; }
public abstract bool IsGenerated { get; }

protected AbstractRDMDevice(UID uid) : this(uid, SubDevice.Root)

protected AbstractRDMDevice(UID uid, SubDevice? subDevice = null, IRDMDevice[] subDevices = null)
{
}
this.uid = uid;
this.subdevice = subDevice ?? SubDevice.Root;
if (subDevices != null && !this.Subdevice.IsRoot)
throw new NotSupportedException($"A SubDevice {this.Subdevice} cannot have SubDevices.");

if (this.Subdevice.IsBroadcast)
throw new NotSupportedException($"A SubDevice cannot be Broadcast.");


if (this.Subdevice == SubDevice.Root)
{
this.subDevices = new List<IRDMDevice>();
this.subDevices.Add(this);

if (subDevices != null)
this.subDevices.AddRange(subDevices);

protected AbstractRDMDevice(UID uid, SubDevice subDevice)
if (this.subDevices.Distinct().Count() != this.subDevices.Count)
throw new InvalidOperationException($"The SubDevices of {this.UID} are not unique.");

performInitialize();
}
}
protected void performInitialize(RDMDeviceInfo deviceInfo=null)
{
this.IsInitializing = true;
if (this.IsInitialized)
return;

this.uid = uid;
this.subdevice = subDevice;
if (this.Subdevice.IsRoot)
asyncRDMRequestHelper = new AsyncRDMRequestHelper(sendRDMRequestMessage);

asyncRDMRequestHelper = new AsyncRDMRequestHelper(sendRDMRequestMessage);
initialize();
initialize(deviceInfo);
this.IsInitialized = true;
this.IsInitializing = false;
}

protected virtual void initialize()
protected virtual void initialize(RDMDeviceInfo deviceInfo = null)
{
if (this.Subdevice.IsRoot)
foreach (AbstractRDMDevice sd in this.subDevices)
{
if (sd.Subdevice.IsRoot)
continue;
sd.asyncRDMRequestHelper = this.asyncRDMRequestHelper;
sd.performInitialize();
}
}


Expand All @@ -61,15 +94,36 @@ private async Task sendRDMRequestMessage(RDMMessage rdmMessage)

protected async Task ReceiveRDMMessage(RDMMessage rdmMessage)
{
if (!this.Subdevice.IsRoot && !rdmMessage.SubDevice.IsBroadcast)
return;

if (this.IsDisposed || IsDisposing)
return;
try
{
await OnReceiveRDMMessage(rdmMessage);
if (rdmMessage.SubDevice.IsBroadcast)
{
List<Task> tasks = new List<Task>();
foreach (var sd in this.subDevices)
tasks.Add(OnReceiveRDMMessage(rdmMessage));
await Task.WhenAll(tasks);
return;
}
AbstractRDMDevice sds = null;
if (rdmMessage.SubDevice.IsRoot)
sds = this;
else
sds = this.subDevices?.OfType<AbstractRDMDevice>().FirstOrDefault(sd => sd.Subdevice == rdmMessage.SubDevice);

if (sds != null)
await sds.OnReceiveRDMMessage(rdmMessage);
else
this.asyncRDMRequestHelper.ReceiveMessage(rdmMessage);

}
catch (Exception e)
{
Logger.LogError(e, string.Empty);
Logger?.LogError(e, string.Empty);
}
}
protected abstract Task OnReceiveRDMMessage(RDMMessage rdmMessage);
Expand Down Expand Up @@ -109,6 +163,8 @@ public virtual IReadOnlyDictionary<ERDM_Parameter, object> GetAllParameterValues

public override string ToString()
{
if (!this.Subdevice.IsRoot)
return $"[{UID}] ({this.Subdevice})";
return $"[{UID}]";
}
}
Expand Down
Loading
Loading