Innovenergy_trunk/csharp/Lib/Victron/VeDBus/VeProperties.cs

96 lines
3.2 KiB
C#

using System.Collections;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reactive.Subjects;
using InnovEnergy.Lib.Protocols.DBus.Protocol.DataTypes;
namespace InnovEnergy.Lib.Victron.VeDBus;
public class VeProperties : IEnumerable<VeProperty>
{
// Thread safe
private ImmutableDictionary<ObjectPath, VeProperty> _Dict = ImmutableDictionary<ObjectPath, VeProperty>.Empty;
private readonly Subject<VeProperty> _PropertyChanged = new();
private readonly Subject<ImmutableDictionary<ObjectPath, VeProperty>> _PropertiesChanged = new();
public IObservable<VeProperty> PropertyChanged => _PropertyChanged;
public IObservable<ImmutableDictionary<ObjectPath, VeProperty>> PropertiesChanged => _PropertiesChanged;
public Variant GetValueOfAllProperties(String prefix = "")
{
return _Dict
.Where(p => p.Key.Path.StartsWith(prefix))
.ToDictionary(p => p.Key.Path, p => p.Value.Value.Variant())
.Variant();
}
public Dictionary<String, String> GetTextOfAllProperties(String prefix = "")
{
return _Dict
.Where(p => p.Key.Path.StartsWith(prefix))
.ToDictionary(p => p.Key.Path, p => p.Value.Text);
}
public Dictionary<String, Dictionary<String, Variant>> GetAllItems(String prefix = "")
{
return _Dict
.Where(p => p.Key.Path.StartsWith(prefix))
.ToDictionary(p => p.Key.Path, p => p.Value.GetItem());
}
public VeProperty? Get(ObjectPath path)
{
return _Dict.TryGetValue(path, out var v) ? v : null;
}
public Boolean Set(ObjectPath path, Object value, String? text = null)
{
var txt = text ?? (value is Variant v ? v.Value.ToString() : value.ToString());
var p = new VeProperty(path, value, txt!);
return Set(p);
}
public Boolean Set(ObjectPath path, Object value, Boolean writable, String? text = null)
{
var txt = text ?? (value is Variant v ? v.Value.ToString() : value.ToString());
var p = new VeProperty(path, value, Text:txt!, writable);
return Set(p);
}
public Boolean Set(VeProperty prop)
{
// TODO: reenable optimization?
// var p = Get(prop.ObjectPath);
//
// if (p.HasValue && p.Value == prop)
// return false;
Debug.WriteLine($"Property changed: {prop.ObjectPath} {prop.Value} {prop.Text}");
_Dict = _Dict.SetItem(prop.ObjectPath, prop); // thread safe
_PropertiesChanged.OnNext(_Dict);
_PropertyChanged.OnNext(prop);
return true;
}
#region Collection initializer
public Boolean Add(ObjectPath path, Object value, String? text = null) => Set(path, value, text:text);
public Boolean Add(VeProperty prop) => Set(prop);
public IEnumerator<VeProperty> GetEnumerator() => _Dict.Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
#endregion Collection initializer
}