Files
laatzen/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisConfigReader.cs
T

244 lines
8.1 KiB
C#

namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
{
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json;
using Xylem.Common.Hardware.WaterMeter.WaterMeterRegisters;
/// <summary>
/// JSON filer reader for generation of register lists
/// </summary>
public class GenesisConfigurationReader
{
/// <summary>
/// Registers defined in configuration.json file
/// </summary>
public List<IRegister> ConfigRegistersDefinitions { get; set; }
= new List<IRegister>();
/// <summary>
/// Applications defined in configuration.json file
/// </summary>
public List<ApplicationDefinition> ConfigApplicationDefinitions { get; set; }
= new List<ApplicationDefinition>();
/// <summary>
///
/// </summary>
public IDictionary<string, AppSection> Value { get; private set; }
/// <summary>
/// Ctor
/// </summary>
/// <param name="configFilePath">the file path for configuration.json as interface description to the meter</param>
public GenesisConfigurationReader(String configFilePath)
{
if (string.IsNullOrEmpty(configFilePath))
{
throw new ApplicationException("JsonFileRegisterReader needs at least one file path");
}
if (!File.Exists(configFilePath))
{
throw new ApplicationException($" {configFilePath} doesn't exists");
}
Convert(File.ReadAllText(configFilePath));
}
/// <summary>
/// Convert file content to register list
/// </summary>
/// <param name="configurationJson"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
private void Convert(string configurationJson)
{
var sections = default(IDictionary<string, AppSection>);
try
{
sections = JsonConvert
.DeserializeObject<IDictionary<string, AppSection>>(configurationJson, settings)
?? new Dictionary<string, AppSection>();
}
catch (Exception e)
{
sections = new Dictionary<string, AppSection>();
}
this.Value = sections;
foreach (var sectionKVP in sections)
{
var appId = sectionKVP.Value.Id;
var appName = sectionKVP.Key;
this.ConfigApplicationDefinitions.Add(new ApplicationDefinition
{
AppId = appId,
AppName = appName
});
var section = sectionKVP.Value;
if (section is null)
{
continue;
}
var registers = section.Registers;
if (registers is null)
{
continue;
}
foreach (var registerKVP in registers)
{
var register = registerKVP.Value;
if (register is null)
{
continue;
}
var details = register.Details;
if (details is null)
{
continue;
}
var regId = register.Id;
foreach (var detail in details)
{
var values = detail.Values;
this.ConfigRegistersDefinitions.Add(new RegisterDefinition
{
AppAddress = appId,
AppName = appName,
DataType = this.GetType(detail.Type),
Default = values?.Default is long d ? d : default(long?),
IsAvailable = default(bool),
Maximum = values?.Maximum is long max ? max : default(long?),
Minimum = values?.Minimum is long min ? min : default(long?),
RegAddressInApp = regId,
// RegisterAddress = new byte[] { appId, regId },
RegisterDetail = detail,
RegisterName = registerKVP.Key,
RestoreCapability = new StaticType(detail.StaticType)
});
}
}
}
}
/// <summary>
/// Settings
/// </summary>
public static readonly JsonSerializerSettings settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
AccessConverter.Singleton,
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
private Type GetType(string value)
{
switch (value.ToLower())
{
case "bool_t": return typeof(Boolean);
case "rpc": return typeof(Rpc);
case "string": return typeof(String);
case "uint32_t": return typeof(UInt32);
case "time_t": return typeof(TimeT);
case "status_t": return typeof(StatusT);
case "uint16_t": return typeof(UInt16);
case "uint8_t": return typeof(byte);
case "enum8": return typeof(Enum8);
case "uint64_t": return typeof(UInt64);
case "uint96_t": return typeof(UInt96);
case "int8_t": return typeof(sbyte);
case "int32_t": return typeof(Int32);
case "int64_t": return typeof(Int64);
case "int16_t": return typeof(Int16);
default: throw new Exception($"Type {value} not recognized!");
}
}
}
/// <summary>
///
/// </summary>
public class AccessConverter : JsonConverter
{
/// <summary>
///
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public override bool CanConvert(Type t) => t == typeof(Access) || t == typeof(Access?);
/// <summary>
///
/// </summary>
/// <param name="reader"></param>
/// <param name="t"></param>
/// <param name="existingValue"></param>
/// <param name="serializer"></param>
/// <returns></returns>
public override Object ReadJson(JsonReader reader, Type t, Object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
var value = serializer.Deserialize<String>(reader);
if (Enum.TryParse(value, true, out Access access))
{
return access;
}
throw new Exception("Cannot unmarshal type Lvl");
}
/// <summary>
///
/// </summary>
/// <param name="writer"></param>
/// <param name="untypedValue"></param>
/// <param name="serializer"></param>
public override void WriteJson(JsonWriter writer, Object untypedValue, JsonSerializer serializer)
{
if (untypedValue is Access access)
{
writer.WriteValue(access.ToString());
}
throw new Exception("Cannot marshal type Lvl");
}
/// <summary>
///
/// </summary>
public static readonly AccessConverter Singleton = new AccessConverter();
}
}