Skip to content

Commit

Permalink
move the implementation for loading object specs to SpecificationMaster
Browse files Browse the repository at this point in the history
  • Loading branch information
smdn committed Apr 2, 2024
1 parent 93a4d1a commit 430fa80
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;

namespace Smdn.Net.EchonetLite.Appendix
{
Expand All @@ -18,73 +17,41 @@ public sealed class EchonetObjectSpecification
/// </summary>
internal static EchonetObjectSpecification CreateUnknown(byte classGroupCode, byte classCode)
=> new(
classGroup: new(
code: classGroupCode,
name: "Unknown",
propertyName: "Unknown",
classes: Array.Empty<EchonetClassSpecification>(),
superClassName: null
),
@class: new(
isDefined: false,
code: classCode,
name: "Unknown",
propertyName: "Unknown"
),
properties: Array.Empty<EchonetPropertySpecification>()
(
ClassGroup: new(
code: classGroupCode,
name: "Unknown",
propertyName: "Unknown",
classes: Array.Empty<EchonetClassSpecification>(),
superClassName: null
),
Class: new(
isDefined: false,
code: classCode,
name: "Unknown",
propertyName: "Unknown"
),
Properties: Array.Empty<EchonetPropertySpecification>()
)
);

internal EchonetObjectSpecification(byte classGroupCode, byte classCode)
internal EchonetObjectSpecification(
byte classGroupCode,
byte classCode
)
: this(SpecificationMaster.LoadObjectSpecification(classGroupCode, classCode))
{
ClassGroup =
SpecificationMaster.GetInstance().Profiles.FirstOrDefault(p => p.Code == classGroupCode) ??
SpecificationMaster.GetInstance().DeviceClasses.FirstOrDefault(p => p.Code == classGroupCode) ??
throw new ArgumentException($"unknown class group: 0x{classGroupCode:X2}");

const int MaxNumberOfProperty = 0x80; // EPC: 0b_1XXX_XXXX (0x80~0xFF)

var properties = new List<EchonetPropertySpecification>(capacity: MaxNumberOfProperty);

//スーパークラスのプロパティを列挙
using (var stream = SpecificationMaster.GetSpecificationMasterDataStream($"{ClassGroup.SuperClassName}.json"))
{
var superClassProperties = JsonSerializer.Deserialize<PropertyMaster>(stream) ?? throw new InvalidOperationException($"{nameof(PropertyMaster)} can not be null");
properties.AddRange(superClassProperties.Properties);
}

Class = ClassGroup.Classes?.FirstOrDefault(c => c.IsDefined && c.Code == classCode)
?? throw new ArgumentException($"unknown class: 0x{classCode:X2}");

if (Class.IsDefined)
{
var classGroupDirectoryName = $"0x{ClassGroup.Code:X2}-{ClassGroup.PropertyName}";
var classFileName = $"0x{Class.Code:X2}-{Class.PropertyName}.json";

//クラスのプロパティを列挙
using (var stream = SpecificationMaster.GetSpecificationMasterDataStream(classGroupDirectoryName, classFileName))
{
if (stream is not null)
{
var classProperties = JsonSerializer.Deserialize<PropertyMaster>(stream) ?? throw new InvalidOperationException($"{nameof(PropertyMaster)} can not be null");
properties.AddRange(classProperties.Properties);
}
}
}

properties.TrimExcess(); // reduce capacity

Properties = properties;
}

private EchonetObjectSpecification(
EchonetClassGroupSpecification classGroup,
EchonetClassSpecification @class,
IReadOnlyList<EchonetPropertySpecification> properties
(
EchonetClassGroupSpecification ClassGroup,
EchonetClassSpecification Class,
IReadOnlyList<EchonetPropertySpecification> Properties
) objectSpecification
)
{
ClassGroup = classGroup;
Class = @class;
Properties = properties;
(ClassGroup, Class, Properties) = objectSpecification;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
Expand Down Expand Up @@ -64,9 +65,9 @@ public static SpecificationMaster GetInstance()
return _Instance;
}

internal static readonly string SpecificationMasterDataLogicalRootName = "MasterData/";
private static readonly string SpecificationMasterDataLogicalRootName = "MasterData/";

internal static Stream GetSpecificationMasterDataStream(string file)
private static Stream GetSpecificationMasterDataStream(string file)
{
var logicalName = SpecificationMasterDataLogicalRootName + file;

Expand All @@ -78,13 +79,67 @@ internal static Stream GetSpecificationMasterDataStream(string file)
return stream;
}

internal static Stream? GetSpecificationMasterDataStream(string classGroupDirectoryName, string classFileName)
private static Stream? GetSpecificationMasterDataStream(string classGroupDirectoryName, string classFileName)
{
var logicalName = string.Concat(SpecificationMasterDataLogicalRootName, classGroupDirectoryName, "/", classFileName);

return Assembly.GetExecutingAssembly().GetManifestResourceStream(logicalName);
}

internal static (
EchonetClassGroupSpecification ClassGroup,
EchonetClassSpecification Class,
IReadOnlyList<EchonetPropertySpecification> Properties
)
LoadObjectSpecification(
byte classGroupCode,
byte classCode
)
{
var classGroupSpec =
GetInstance().Profiles.FirstOrDefault(p => p.Code == classGroupCode) ??
GetInstance().DeviceClasses.FirstOrDefault(p => p.Code == classGroupCode) ??
throw new ArgumentException($"unknown class group: 0x{classGroupCode:X2}");

const int MaxNumberOfProperty = 0x80; // EPC: 0b_1XXX_XXXX (0x80~0xFF)

var properties = new List<EchonetPropertySpecification>(capacity: MaxNumberOfProperty);

//スーパークラスのプロパティを列挙
using (var stream = GetSpecificationMasterDataStream($"{classGroupSpec.SuperClassName}.json"))
{
var superClassProperties = JsonSerializer.Deserialize<PropertyMaster>(stream) ?? throw new InvalidOperationException($"{nameof(PropertyMaster)} can not be null");
properties.AddRange(superClassProperties.Properties);
}

var classSpec = classGroupSpec.Classes?.FirstOrDefault(c => c.IsDefined && c.Code == classCode)
?? throw new ArgumentException($"unknown class: 0x{classCode:X2}");

if (classSpec.IsDefined)
{
var classGroupDirectoryName = $"0x{classGroupSpec.Code:X2}-{classGroupSpec.PropertyName}";
var classFileName = $"0x{classSpec.Code:X2}-{classSpec.PropertyName}.json";

//クラスのプロパティを列挙
using (var stream = GetSpecificationMasterDataStream(classGroupDirectoryName, classFileName))
{
if (stream is not null)
{
var classProperties = JsonSerializer.Deserialize<PropertyMaster>(stream) ?? throw new InvalidOperationException($"{nameof(PropertyMaster)} can not be null");
properties.AddRange(classProperties.Properties);
}
}
}

properties.TrimExcess(); // reduce capacity

return (
classGroupSpec,
classSpec,
properties
);
}

/// <summary>
/// ECHONET Lite SPECIFICATIONのバージョン
/// </summary>
Expand Down

0 comments on commit 430fa80

Please sign in to comment.