Skip to content

Commit

Permalink
ignore system-config-response and always add all devices (#73)
Browse files Browse the repository at this point in the history
* ignore system-config-response and always add all devices from the parameter.json

* fallback to default readBusAddress - 5 if no writeBusAddress was given

* sort devices & parameters for parameter.json (to make diffing easier)

* clone parameter templates to support multiple instances of parameters or devices

* add missing Clone(...) implementations
  • Loading branch information
zivillian committed Oct 20, 2023
1 parent 081a227 commit 453787f
Show file tree
Hide file tree
Showing 22 changed files with 157 additions and 47 deletions.
2 changes: 2 additions & 0 deletions src/ism7config/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class Device

public string ReadBusAddress { get; set; }

public string WriteBusAddress { get; set; }

public int DeviceTemplateId { get; set; }

[JsonIgnore]
Expand Down
9 changes: 6 additions & 3 deletions src/ism7config/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,20 @@ static async Task Main(string[] args)
{
Devices = new List<Device>()
};
foreach (var device in gc.Devices)
foreach (var device in gc.Devices.OrderBy(x => x.ReadBusAddress))
{
if (device.DeviceTemplateId == 0) continue; //skip devices with invalid template id as seen in #64
config.Devices.Add(new Device
{
Id = device.Id,
ReadBusAddress = device.ReadBusAddress,
WriteBusAddress = device.WriteBusAddress,
DeviceTemplateId = device.DeviceTemplateId,
Parameters = parameterStore.Parameters
.Where(x=>x.Value.DeviceId == device.Id)
.Select(x=>new Parameter{ParameterId = x.Value.ParameterId / 100_000}).ToList()
.Where(x => x.Value.DeviceId == device.Id)
.Select(x => new Parameter { ParameterId = x.Value.ParameterId / 100_000 })
.OrderBy(x => x.ParameterId)
.ToList()
});
}
await File.WriteAllTextAsync(file, JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true }));
Expand Down
2 changes: 2 additions & 0 deletions src/ism7mqtt/ISM7/Config/ParameterConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class ConfigDevice
{
public string ReadBusAddress { get; set; }

public string WriteBusAddress { get; set; }

public int DeviceTemplateId { get; set; }

public List<int> Parameter { get; set; }
Expand Down
36 changes: 8 additions & 28 deletions src/ism7mqtt/ISM7/Ism7Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public class Ism7Client
private readonly Func<Ism7Config, CancellationToken, Task> _messageHandler;
private readonly IPAddress _ipAddress;
private readonly ConcurrentDictionary<Type, XmlSerializer> _serializers = new ConcurrentDictionary<Type, XmlSerializer>();
private readonly ConcurrentDictionary<string, SystemconfigResp.BusDevice> _devices = new ConcurrentDictionary<string, SystemconfigResp.BusDevice>();
private readonly Ism7Config _config;
private readonly Pipe _pipe;
private readonly ResponseDispatcher _dispatcher = new ResponseDispatcher();
Expand Down Expand Up @@ -240,13 +239,12 @@ private static string HexEncode(ReadOnlySpan<byte> data)

private async Task SubscribeAsync(string busAddress, CancellationToken cancellationToken)
{
var device = _devices[busAddress];
var infoReads = _config.GetInfoReadForDevice(device.Ba).ToList();
var infoReads = _config.GetInfoReadForDevice(busAddress).ToList();
var bundleId = NextBundleId();
_dispatcher.Subscribe(x => x.MessageType == PayloadType.TgrBundleResp && ((TelegramBundleResp) x).BundleId == bundleId, OnPushResponseAsync);
foreach (var infoRead in infoReads)
{
infoRead.BusAddress = device.Ba;
infoRead.BusAddress = busAddress;
infoRead.Intervall = Interval;
}
await SendAsync(new TelegramBundleReq
Expand Down Expand Up @@ -276,10 +274,9 @@ private async Task OnPushResponseAsync(IResponse response, CancellationToken can

private async Task LoadInitialValuesAsync(CancellationToken cancellationToken)
{
foreach (var device in _devices.Values)
foreach (var busAddress in _config.AddAllDevices(_ipAddress.ToString()))
{
if (!_config.AddDevice(_ipAddress.ToString(), device.Ba)) continue;
var infoReads = _config.GetInfoReadForDevice(device.Ba).ToList();
var infoReads = _config.GetInfoReadForDevice(busAddress).ToList();
var bundleId = NextBundleId();
_dispatcher.SubscribeOnce(
x => x.MessageType == PayloadType.TgrBundleResp && ((TelegramBundleResp) x).BundleId == bundleId,
Expand All @@ -291,7 +288,7 @@ private async Task LoadInitialValuesAsync(CancellationToken cancellationToken)
}
foreach (var infoRead in infoReads)
{
infoRead.BusAddress = device.Ba;
infoRead.BusAddress = busAddress;
}
await SendAsync(new TelegramBundleReq
{
Expand Down Expand Up @@ -321,29 +318,12 @@ private async Task OnInitialValuesAsync(IResponse response, CancellationToken ca
if (hasDatapoints)
{
await _messageHandler(_config, cancellationToken);
var busAddress = resp.Telegrams.Select(x => x.BusAddress).First();
await SubscribeAsync(busAddress, cancellationToken);
}
var busAddress = resp.Telegrams.Select(x => x.BusAddress).First();
await SubscribeAsync(busAddress, cancellationToken);
}
}

private async Task GetConfigAsync(LoginResp session, CancellationToken cancellationToken)
{
_dispatcher.SubscribeOnce(x => x.MessageType == PayloadType.SystemconfigResp,
OnSystemConfigAsync);
await SendAsync(new SystemconfigReq {Sid = session.Sid}, cancellationToken);
}

private Task OnSystemConfigAsync(IResponse response, CancellationToken cancellationToken)
{
var resp = (SystemconfigResp)response;
foreach (var device in resp.BusConfig.Devices)
{
_devices.AddOrUpdate(device.Ba, device, (k, o) => device);
}
return LoadInitialValuesAsync(cancellationToken);
}

private ValueTask AuthenticateAsync(string password, CancellationToken cancellationToken)
{
_dispatcher.SubscribeOnce(x => x.MessageType == PayloadType.DirectLogonResp,
Expand All @@ -356,7 +336,7 @@ private Task OnAuthenticateAsync(IResponse response, CancellationToken cancellat
var resp = (LoginResp)response;
if (resp.State != LoginState.ok)
throw new InvalidDataException("invalid login state");
return GetConfigAsync(resp, cancellationToken);
return LoadInitialValuesAsync(cancellationToken);
}

private async Task KeepAliveAsync(CancellationToken cancellationToken)
Expand Down
24 changes: 16 additions & 8 deletions src/ism7mqtt/ISM7/Ism7Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,16 @@ private List<ParameterDescriptor> LoadParameterTemplates()
}
}

public bool AddDevice(string ip, string ba)
public IEnumerable<string> AddAllDevices(string ip)
{
foreach (var ba in _config.Devices.Select(x=>x.ReadBusAddress).Distinct())
{
AddDevice(ip, ba);
yield return ba;
}
}

public void AddDevice(string ip, string ba)
{
if (!_devices.TryGetValue(Converter.FromHex(ba), out var devices))
{
Expand All @@ -75,9 +84,8 @@ public bool AddDevice(string ip, string ba)
{
var device = _deviceTemplates.First(x => x.DTID == configDevice.DeviceTemplateId);
var tids = configDevice.Parameter.ToHashSet();
devices.Add(new RunningDevice(device.Name, ip, ba, _parameterTemplates.Where(x => tids.Contains(x.PTID)), _converterTemplates.Where(x => tids.Contains(x.CTID))));
devices.Add(new RunningDevice(device.Name, ip, configDevice.ReadBusAddress, configDevice.WriteBusAddress, _parameterTemplates.Where(x => tids.Contains(x.PTID)), _converterTemplates.Where(x => tids.Contains(x.CTID))));
}
return true;
}

public IEnumerable<InfoRead> GetInfoReadForDevice(string ba)
Expand Down Expand Up @@ -154,13 +162,13 @@ public class RunningDevice
{
private readonly List<RunningParameter> _parameter;

public RunningDevice(string name, string ip, string ba, IEnumerable<ParameterDescriptor> parameter, IEnumerable<ConverterTemplateBase> converter)
public RunningDevice(string name, string ip, string readBusAddress, string writeBusAddress, IEnumerable<ParameterDescriptor> parameter, IEnumerable<ConverterTemplateBase> converter)
{
Name = name;
IP = ip;

WriteAddress = $"0x{(Converter.FromHex(ba) - 5):X2}";
MqttTopic = $"Wolf/{ip}/{name}_{ba}";
WriteAddress = writeBusAddress ?? $"0x{(Converter.FromHex(readBusAddress) - 5):X2}";
MqttTopic = $"Wolf/{ip}/{name}_{readBusAddress}";

_parameter = new List<RunningParameter>();
foreach (var descriptor in parameter)
Expand Down Expand Up @@ -305,10 +313,10 @@ public class RunningParameter
private readonly ParameterDescriptor _descriptor;
private readonly ConverterTemplateBase _converter;

public RunningParameter( ParameterDescriptor descriptor, ConverterTemplateBase converter)
public RunningParameter(ParameterDescriptor descriptor, ConverterTemplateBase converter)
{
_descriptor = descriptor;
_converter = converter;
_converter = converter.Clone();
}

public string Name => _descriptor.Name;
Expand Down
5 changes: 5 additions & 0 deletions src/ism7mqtt/ISM7/Xml/BM2DateConverterTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,10 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
var high = (byte)(bytes >> 8);
yield return new InfoWrite{InfoNumber = TelegramNr, DBLow = $"0x{low:X2}", DBHigh = $"0x{high:X2}"};
}

public override ConverterTemplateBase Clone()
{
return Clone(new BM2DateConverterTemplate());
}
}
}
5 changes: 5 additions & 0 deletions src/ism7mqtt/ISM7/Xml/BM2TimeConverterTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,10 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
var low = time.Minutes;
yield return new InfoWrite{InfoNumber = TelegramNr, DBLow = $"0x{low:X2}", DBHigh = $"0x{high:X2}"};
}

public override ConverterTemplateBase Clone()
{
return Clone(new BM2TimeConverterTemplate());
}
}
}
9 changes: 9 additions & 0 deletions src/ism7mqtt/ISM7/Xml/BinaryReadOnlyConverterTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,14 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
{
throw new NotImplementedException($"CTID '{CTID}' is not yet implemented");
}

public override ConverterTemplateBase Clone()
{
return Clone(new BinaryReadOnlyConverterTemplate
{
OnValue = OnValue,
Bitnumber = Bitnumber,
});
}
}
}
5 changes: 5 additions & 0 deletions src/ism7mqtt/ISM7/Xml/Bit0to3ConverterTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
{
throw new NotImplementedException($"CTID '{CTID}' is not yet implemented");
}

public override ConverterTemplateBase Clone()
{
return Clone(new Bit0to3ConverterTemplate());
}
}
}
5 changes: 5 additions & 0 deletions src/ism7mqtt/ISM7/Xml/Bit4to7ConverterTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
{
throw new NotImplementedException($"CTID '{CTID}' is not yet implemented");
}

public override ConverterTemplateBase Clone()
{
return Clone(new Bit4to7ConverterTemplate());
}
}
}
11 changes: 11 additions & 0 deletions src/ism7mqtt/ISM7/Xml/ConverterTemplateBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,16 @@ public abstract class ConverterTemplateBase
public abstract JsonValue GetValue();

public abstract IEnumerable<InfoWrite> GetWrite(string value);

public abstract ConverterTemplateBase Clone();

protected virtual ConverterTemplateBase Clone(ConverterTemplateBase clone)
{
clone.CTID = CTID;
clone.Type = Type;
clone.ServiceReadNumber = ServiceReadNumber;
clone.ServiceWriteNumber = ServiceWriteNumber;
return clone;
}
}
}
5 changes: 5 additions & 0 deletions src/ism7mqtt/ISM7/Xml/DateTimeConverterTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,10 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
{
throw new NotImplementedException($"CTID '{CTID}' is not yet implemented");
}

public override ConverterTemplateBase Clone()
{
return Clone(new DateTimeConverterTemplate());
}
}
}
9 changes: 9 additions & 0 deletions src/ism7mqtt/ISM7/Xml/MixerStateConverterTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,14 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
{
throw new NotImplementedException($"CTID '{CTID}' is not yet implemented");
}

public override ConverterTemplateBase Clone()
{
return Clone(new MixerStateConverterTemplate
{
TelegramNrOpen = TelegramNrOpen,
TelegramNrClose = TelegramNrClose,
});
}
}
}
10 changes: 10 additions & 0 deletions src/ism7mqtt/ISM7/Xml/MultiTelegramConverterTemplateBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,15 @@ public override bool CanProcess(ushort telegram)
{
return TelegramNumbers.Any(x => x == telegram);
}

protected override ConverterTemplateBase Clone(ConverterTemplateBase clone)
{
base.Clone(clone);
if (clone is MultiTelegramConverterTemplateBase multi)
{
multi.TelegramNumbers = TelegramNumbers;
}
return clone;
}
}
}
9 changes: 9 additions & 0 deletions src/ism7mqtt/ISM7/Xml/NullConverterTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,14 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
{
throw new NotImplementedException($"CTID '{CTID}' is not yet implemented");
}

public override ConverterTemplateBase Clone()
{
return Clone(new NullConverterTemplate
{
XMLName = XMLName,
IntervalSec = IntervalSec,
});
}
}
}
5 changes: 5 additions & 0 deletions src/ism7mqtt/ISM7/Xml/NumericConverter16Template.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,10 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
}
yield return new InfoWrite{InfoNumber = TelegramNr, DBLow = $"0x{(data & 0xff):X2}", DBHigh = $"0x{(data >> 8):X2}"};
}

public override ConverterTemplateBase Clone()
{
return Clone(new NumericConverter16Template());
}
}
}
9 changes: 9 additions & 0 deletions src/ism7mqtt/ISM7/Xml/NumericConverter32Template.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,14 @@ public override IEnumerable<InfoWrite> GetWrite(string value)
yield return new InfoWrite{InfoNumber = TelegramNrLow, DBLow = $"0x{(low & 0xff):X2}", DBHigh = $"0x{(low >> 8):X2}"};
yield return new InfoWrite{InfoNumber = TelegramNrHigh, DBLow = $"0x{(high & 0xff):X2}", DBHigh = $"0x{(high >> 8):X2}"};
}

public override ConverterTemplateBase Clone()
{
return Clone(new NumericConverter32Template
{
TelegramNrHigh = TelegramNrHigh,
TelegramNrLow = TelegramNrLow,
});
}
}
}
9 changes: 9 additions & 0 deletions src/ism7mqtt/ISM7/Xml/SingleTelegramConverterTemplateBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,14 @@ public override bool CanProcess(ushort telegram)
}

protected abstract void AddTelegram(byte low, byte high);

protected override ConverterTemplateBase Clone(ConverterTemplateBase clone)
{
if (clone is SingleTelegramConverterTemplateBase single)
{
single.TelegramNr = TelegramNr;
}
return base.Clone(clone);
}
}
}
Loading

0 comments on commit 453787f

Please sign in to comment.