修复IoTDB驱动适配增量源码生成器以后,单侧点模式失效的问题
This commit is contained in:
parent
8d1fc46e8f
commit
541c118dbb
22
modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs
Normal file
22
modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace JiShe.CollectBus.IoTDB.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// IoTDB异常
|
||||
/// </summary>
|
||||
public class IoTException : Exception
|
||||
{
|
||||
public int ErrorCode { get; }
|
||||
|
||||
public IoTException(string message, int errorCode)
|
||||
: base($"{message} (Code: {errorCode})")
|
||||
{
|
||||
ErrorCode = errorCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,7 +14,6 @@
|
||||
<ProjectReference Include="..\..\shared\JiShe.CollectBus.Analyzers.Shared\JiShe.CollectBus.Analyzers.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\shared\JiShe.CollectBus.Common\JiShe.CollectBus.Common.csproj" />
|
||||
|
||||
<ProjectReference Include="..\..\modules\JiShe.CollectBus.Analyzers\JiShe.CollectBus.Analyzers.csproj"
|
||||
OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||
<ProjectReference Include="..\..\modules\JiShe.CollectBus.Analyzers\JiShe.CollectBus.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@ -21,6 +21,7 @@ using Microsoft.Extensions.Logging;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using JiShe.CollectBus.Analyzers.Shared;
|
||||
using JiShe.CollectBus.IoTDB.Exceptions;
|
||||
|
||||
namespace JiShe.CollectBus.IoTDB.Provider
|
||||
{
|
||||
@ -250,128 +251,337 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
}
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// 构建Tablet
|
||||
///// </summary>
|
||||
///// <typeparam name="T"></typeparam>
|
||||
///// <param name="entities">表实体</param>
|
||||
///// <param name="metadata">设备元数据</param></param>
|
||||
///// <returns></returns>
|
||||
//private Tablet BuildTablet<T>(IEnumerable<T> entities, DeviceMetadata metadata) where T : IoTEntity
|
||||
//{
|
||||
// var timestamps = new List<long>();
|
||||
// var values = new List<List<object>>();
|
||||
// var devicePaths = new HashSet<string>();
|
||||
// List<string> tempColumnNames = new List<string>();
|
||||
// tempColumnNames.AddRange(metadata.ColumnNames);
|
||||
|
||||
// var accessor = SourceEntityAccessorFactory.GetAccessor<T>();
|
||||
|
||||
// var memberCache = new Dictionary<string, EntityMemberInfo>(); // 缓存优化查询
|
||||
// // 预构建成员缓存(Key: NameOrPath)
|
||||
// foreach (var member in accessor.MemberList)
|
||||
// {
|
||||
// memberCache[member.NameOrPath] = member;
|
||||
// }
|
||||
|
||||
// if (accessor.EntityType == null || metadata.EntityType == null)
|
||||
// {
|
||||
// throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 没有指定,属于异常情况,-101");
|
||||
// }
|
||||
|
||||
// if (metadata.EntityType != accessor.EntityType)
|
||||
// {
|
||||
// throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 和{nameof(DeviceMetadata)}的 EntityType 不一致,属于异常情况,-102");
|
||||
// }
|
||||
|
||||
// if (metadata.EntityType == EntityTypeEnum.TreeModel && _runtimeContext.UseTableSessionPool == true)
|
||||
// {
|
||||
// throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 tree模型不能使用table模型Session连接,属于异常情况,-103");
|
||||
// }
|
||||
// else if (metadata.EntityType == EntityTypeEnum.TableModel && _runtimeContext.UseTableSessionPool == false)
|
||||
// {
|
||||
// throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接,属于异常情况,-104");
|
||||
// }
|
||||
|
||||
// string tableNameOrTreePath = string.Empty;
|
||||
// var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute<TableNameOrTreePathAttribute>();
|
||||
// if (tableNameOrTreePathAttribute != null)
|
||||
// {
|
||||
// tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath;
|
||||
// }
|
||||
|
||||
// foreach (var entity in entities)
|
||||
// {
|
||||
// timestamps.Add(entity.Timestamps);
|
||||
// var rowValues = new List<object>();
|
||||
|
||||
// foreach (var measurement in metadata.ColumnNames)
|
||||
// {
|
||||
// if (!memberCache.TryGetValue(measurement, out var member))
|
||||
// {
|
||||
// throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构时{accessor.EntityName}没有找到{measurement}对应的member信息,-105");
|
||||
// }
|
||||
|
||||
// var value = member.GetValue(entity);
|
||||
|
||||
// // 特性查询优化
|
||||
// var attributes = member.CustomAttributes ?? Enumerable.Empty<Attribute>();
|
||||
// var singleMeasuringAttr = attributes.OfType<SingleMeasuringAttribute>().FirstOrDefault();
|
||||
// if (singleMeasuringAttr != null)//如果是单侧点
|
||||
// {
|
||||
|
||||
// var tupleItem1Key = $"{member.NameOrPath}.Item1";
|
||||
// if (!memberCache.TryGetValue(tupleItem1Key, out var tuple1Member))
|
||||
// {
|
||||
// throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构时{accessor.EntityName} 没有找到{measurement}对应的member Item1 信息,-106");
|
||||
// }
|
||||
// int indexOf = metadata.ColumnNames.IndexOf(measurement);
|
||||
// tempColumnNames[indexOf] = (string)tuple1Member.GetValue(entity);
|
||||
|
||||
// var tupleItem2Key = $"{member.NameOrPath}.Item2";
|
||||
// if (!memberCache.TryGetValue(tupleItem2Key, out var tuple2Member))
|
||||
// {
|
||||
// throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构时{accessor.EntityName} 没有找到{measurement}对应的member Item2 信息,-107");
|
||||
// }
|
||||
|
||||
// value = tuple2Member.GetValue(entity);
|
||||
// }
|
||||
|
||||
// if (value != null)
|
||||
// {
|
||||
// var tempValue = member.DeclaredTypeName.ToUpper() switch
|
||||
// {
|
||||
// "DATETIME" => Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds(),
|
||||
// _ => value
|
||||
// };
|
||||
|
||||
// rowValues.Add(tempValue);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// rowValues.Add(value);
|
||||
// }
|
||||
// }
|
||||
|
||||
// values.Add(rowValues);
|
||||
|
||||
// //如果指定了路径
|
||||
// if (!string.IsNullOrWhiteSpace(tableNameOrTreePath))
|
||||
// {
|
||||
// devicePaths.Add(tableNameOrTreePath);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (!_runtimeContext.UseTableSessionPool)//树模型
|
||||
// {
|
||||
// devicePaths.Add(DevicePathBuilder.GetDevicePath(entity));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// devicePaths.Add(DevicePathBuilder.GetTableName<T>());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (devicePaths.Count > 1)
|
||||
// {
|
||||
// throw new Exception($"{nameof(BuildTablet)} 构建Tablet《{typeof(T).Name}》时,批量插入的设备路径不一致。");
|
||||
// }
|
||||
|
||||
// return _runtimeContext.UseTableSessionPool
|
||||
// ? BuildTableSessionTablet(metadata, devicePaths.First(), tempColumnNames, values, timestamps)
|
||||
// : BuildSessionTablet(metadata, devicePaths.First(), tempColumnNames,values, timestamps);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 构建Tablet
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entities">表实体</param>
|
||||
/// <param name="entities">表实体集合</param>
|
||||
/// <param name="metadata">设备元数据</param></param>
|
||||
/// <returns></returns>
|
||||
private Tablet BuildTablet<T>(IEnumerable<T> entities, DeviceMetadata metadata) where T : IoTEntity
|
||||
{
|
||||
var timestamps = new List<long>();
|
||||
var values = new List<List<object>>();
|
||||
var devicePaths = new HashSet<string>();
|
||||
List<string> tempColumnNames = new List<string>();
|
||||
tempColumnNames.AddRange(metadata.ColumnNames);
|
||||
// 前置校验
|
||||
ValidateMetadataAndAccessor<T>(metadata, out var accessor);
|
||||
|
||||
var accessor = SourceEntityAccessorFactory.GetAccessor<T>();
|
||||
// 初始化数据结构
|
||||
var (timestamps, values, devicePaths) = (new List<long>(), new List<List<object>>(), new HashSet<string>());
|
||||
var tempColumnNames = new List<string>(metadata.ColumnNames);
|
||||
var memberCache = BuildMemberCache(accessor);
|
||||
var tableNameOrTreePath = GetTableNameOrTreePath<T>();
|
||||
|
||||
var memberCache = new Dictionary<string, EntityMemberInfo>(); // 缓存优化查询
|
||||
// 预构建成员缓存(Key: NameOrPath)
|
||||
foreach (var member in accessor.MemberList)
|
||||
// 处理每个实体
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
memberCache[member.NameOrPath] = member;
|
||||
ProcessEntity(entity, accessor, metadata, memberCache, tempColumnNames, timestamps, values);
|
||||
UpdateDevicePaths(entity, tableNameOrTreePath, devicePaths);
|
||||
}
|
||||
|
||||
// 后置校验与返回
|
||||
ValidateDevicePaths(devicePaths);
|
||||
// return CreateFinalTablet(metadata, devicePaths.First(), tempColumnNames, values, timestamps);
|
||||
return _runtimeContext.UseTableSessionPool
|
||||
? BuildTableSessionTablet(metadata, devicePaths.First(), tempColumnNames, values, timestamps)
|
||||
: BuildSessionTablet(metadata, devicePaths.First(), tempColumnNames, values, timestamps);
|
||||
}
|
||||
|
||||
private void ValidateMetadataAndAccessor<T>(DeviceMetadata metadata, out ISourceEntityAccessor<T> accessor) where T : IoTEntity
|
||||
{
|
||||
accessor = SourceEntityAccessorFactory.GetAccessor<T>();
|
||||
|
||||
if (accessor.EntityType == null || metadata.EntityType == null)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 没有指定,属于异常情况,-101");
|
||||
throw new IoTException($"{nameof(BuildTablet)} 构建IoTDB数据结构时,EntityType未指定", -101);
|
||||
}
|
||||
|
||||
if (metadata.EntityType != accessor.EntityType)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 和{nameof(DeviceMetadata)}的 EntityType 不一致,属于异常情况,-102");
|
||||
throw new IoTException($"{nameof(BuildTablet)} 构建IoTDB数据结构时,EntityType不一致", -102);
|
||||
}
|
||||
|
||||
if (metadata.EntityType == EntityTypeEnum.TreeModel && _runtimeContext.UseTableSessionPool == true)
|
||||
bool isTableModel = accessor.EntityType == EntityTypeEnum.TableModel;
|
||||
if (_runtimeContext.UseTableSessionPool != isTableModel)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 tree模型不能使用table模型Session连接,属于异常情况,-103");
|
||||
}
|
||||
else if (metadata.EntityType == EntityTypeEnum.TableModel && _runtimeContext.UseTableSessionPool == false)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接,属于异常情况,-104");
|
||||
throw new IoTException($"{nameof(BuildTablet)} 构建IoTDB数据结构时,Session类型不匹配: 预期{(isTableModel ? "Table" : "Tree")}模型", isTableModel ? -104 : -103);
|
||||
}
|
||||
}
|
||||
|
||||
string tableNameOrTreePath = string.Empty;
|
||||
var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute<TableNameOrTreePathAttribute>();
|
||||
if (tableNameOrTreePathAttribute != null)
|
||||
{
|
||||
tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath;
|
||||
}
|
||||
/// <summary>
|
||||
/// 处理实体并获取值
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="accessor"></param>
|
||||
/// <param name="metadata"></param>
|
||||
/// <param name="memberCache"></param>
|
||||
/// <param name="tempColumnNames"></param>
|
||||
/// <param name="timestamps"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <exception cref="IoTException"></exception>
|
||||
private void ProcessEntity<T>(
|
||||
T entity,
|
||||
ISourceEntityAccessor<T> accessor,
|
||||
DeviceMetadata metadata,
|
||||
Dictionary<string, EntityMemberInfo> memberCache,
|
||||
List<string> tempColumnNames,
|
||||
List<long> timestamps,
|
||||
List<List<object>> values) where T : IoTEntity
|
||||
{
|
||||
timestamps.Add(entity.Timestamps);
|
||||
var rowValues = new object[metadata.ColumnNames.Count];
|
||||
|
||||
foreach (var entity in entities)
|
||||
Parallel.ForEach(metadata.ColumnNames, (measurement, state, index) =>
|
||||
{
|
||||
timestamps.Add(entity.Timestamps);
|
||||
var rowValues = new List<object>();
|
||||
|
||||
foreach (var measurement in tempColumnNames)
|
||||
if (!memberCache.TryGetValue(measurement, out var member))
|
||||
{
|
||||
if (!memberCache.TryGetValue(measurement, out var member))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构时{accessor.EntityName}没有找到{measurement}对应的member信息,-105");
|
||||
}
|
||||
|
||||
var value = member.GetValue(entity);
|
||||
|
||||
// 特性查询优化
|
||||
var attributes = member.CustomAttributes ?? Enumerable.Empty<Attribute>();
|
||||
var singleMeasuringAttr = attributes.OfType<SingleMeasuringAttribute>().FirstOrDefault();
|
||||
if (singleMeasuringAttr != null)//如果是单侧点
|
||||
{
|
||||
var tupleItemKey = $"{member.NameOrPath}.Item2";
|
||||
if (!memberCache.TryGetValue(tupleItemKey, out var tupleMember))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构时{accessor.EntityName} 没有找到{measurement}对应的member Item2 信息,-106");
|
||||
}
|
||||
|
||||
value = tupleMember.GetValue(entity);
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
var tempValue = member.DeclaredTypeName.ToUpper() switch
|
||||
{
|
||||
"DATETIME" => Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds(),
|
||||
_ => value
|
||||
};
|
||||
|
||||
rowValues.Add(tempValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
rowValues.Add(value);
|
||||
}
|
||||
throw new IoTException($"{nameof(BuildTablet)} 构建IoTDB数据结构时,找不到成员: {measurement}", -105);
|
||||
}
|
||||
|
||||
values.Add(rowValues);
|
||||
object value = ResolveMemberValue(entity, member, memberCache, tempColumnNames, (int)index);
|
||||
rowValues[index] = ConvertValueByType(member, value);
|
||||
});
|
||||
|
||||
//如果指定了路径
|
||||
if (!string.IsNullOrWhiteSpace(tableNameOrTreePath))
|
||||
values.Add(rowValues.ToList());
|
||||
}
|
||||
|
||||
private object ResolveMemberValue<T>(
|
||||
T entity,
|
||||
EntityMemberInfo member,
|
||||
Dictionary<string, EntityMemberInfo> memberCache,
|
||||
List<string> tempColumnNames,
|
||||
int columnIndex) where T : IoTEntity
|
||||
{
|
||||
// 单测点逻辑
|
||||
if (member.CustomAttributes?.OfType<SingleMeasuringAttribute>().FirstOrDefault() is { } attr)
|
||||
{
|
||||
var tuple1Key = $"{member.NameOrPath}.Item1";
|
||||
var tuple2Key = $"{member.NameOrPath}.Item2";
|
||||
|
||||
if (!memberCache.TryGetValue(tuple1Key, out var tuple1) || !memberCache.TryGetValue(tuple2Key, out var tuple2))
|
||||
{
|
||||
devicePaths.Add(tableNameOrTreePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_runtimeContext.UseTableSessionPool)//树模型
|
||||
{
|
||||
devicePaths.Add(DevicePathBuilder.GetDevicePath(entity));
|
||||
}
|
||||
else
|
||||
{
|
||||
devicePaths.Add(DevicePathBuilder.GetTableName<T>());
|
||||
}
|
||||
throw new IoTException($"{nameof(BuildTablet)} 构建IoTDB数据结构时,单侧点元组成员缺失", -106);
|
||||
}
|
||||
|
||||
tempColumnNames[columnIndex] = (string)tuple1.GetValue(entity);
|
||||
return tuple2.GetValue(entity);
|
||||
}
|
||||
return member.GetValue(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置实体的成员值
|
||||
/// </summary>
|
||||
/// <param name="member"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
private object ConvertValueByType(EntityMemberInfo member, object value)
|
||||
{
|
||||
return member.DeclaredTypeName switch
|
||||
{
|
||||
"DATETIME" => Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds(),
|
||||
_ => value
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理设备路径
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="tableNameOrTreePath"></param>
|
||||
/// <param name="devicePaths"></param>
|
||||
private void UpdateDevicePaths<T>(
|
||||
T entity,
|
||||
string tableNameOrTreePath,
|
||||
HashSet<string> devicePaths) where T : IoTEntity
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tableNameOrTreePath))
|
||||
{
|
||||
devicePaths.Add(tableNameOrTreePath);
|
||||
return;
|
||||
}
|
||||
|
||||
var path = _runtimeContext.UseTableSessionPool
|
||||
? DevicePathBuilder.GetTableName<T>()
|
||||
: DevicePathBuilder.GetDevicePath(entity);
|
||||
devicePaths.Add(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证设备路径
|
||||
/// </summary>
|
||||
/// <param name="devicePaths"></param>
|
||||
private void ValidateDevicePaths(HashSet<string> devicePaths)
|
||||
{
|
||||
if (devicePaths.Count == 0)
|
||||
{
|
||||
throw new IoTException($"{nameof(BuildTablet)} 构建IoTDB数据结构时,设备路径集合为空", -108);
|
||||
}
|
||||
|
||||
if (devicePaths.Count > 1)
|
||||
{
|
||||
throw new Exception($"{nameof(BuildTablet)} 构建Tablet《{typeof(T).Name}》时,批量插入的设备路径不一致。");
|
||||
var paths = string.Join(", ", devicePaths.Take(3));
|
||||
{
|
||||
throw new IoTException($"{nameof(BuildTablet)} 构建IoTDB数据结构时,设备路径不一致。检测到路径: {paths}...", -109);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _runtimeContext.UseTableSessionPool
|
||||
? BuildTableSessionTablet(metadata, devicePaths.First(), values, timestamps)
|
||||
: BuildSessionTablet(metadata, devicePaths.First(), values, timestamps);
|
||||
/// <summary>
|
||||
/// 缓存优化:避免重复反射
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
private string GetTableNameOrTreePath<T>()
|
||||
{
|
||||
return AttributeCache<T>.TableNameOrTreePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 特性缓存辅助类
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
private static class AttributeCache<T>
|
||||
{
|
||||
public static readonly string TableNameOrTreePath;
|
||||
|
||||
static AttributeCache()
|
||||
{
|
||||
var attr = typeof(T).GetCustomAttribute<TableNameOrTreePathAttribute>();
|
||||
TableNameOrTreePath = attr?.TableNameOrTreePath ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -379,16 +589,17 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
/// </summary>
|
||||
/// <param name="metadata">已解析的设备数据元数据</param>
|
||||
/// <param name="devicePath">设备路径</param>
|
||||
/// <param name="columns">数据列集合</param>
|
||||
/// <param name="values">数据集合</param>
|
||||
/// <param name="timestamps">时间戳集合</param>
|
||||
/// <returns></returns>
|
||||
private Tablet BuildSessionTablet(DeviceMetadata metadata, string devicePath, List<List<object>> values, List<long> timestamps)
|
||||
private Tablet BuildSessionTablet(DeviceMetadata metadata, string devicePath, List<string> columns, List<List<object>> values, List<long> timestamps)
|
||||
{
|
||||
//todo 树模型需要去掉TAG类型和ATTRIBUTE类型的字段,只需要保留FIELD类型字段即可
|
||||
|
||||
return new Tablet(
|
||||
devicePath,
|
||||
metadata.ColumnNames,
|
||||
columns,
|
||||
metadata.DataTypes,
|
||||
values,
|
||||
timestamps
|
||||
@ -400,14 +611,15 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
/// </summary>
|
||||
/// <param name="metadata">已解析的设备数据元数据</param>
|
||||
/// <param name="tableName">表名称</param>
|
||||
/// <param name="columns">数据列集合</param>
|
||||
/// <param name="values">数据集合</param>
|
||||
/// <param name="timestamps">时间戳集合</param>
|
||||
/// <returns></returns>
|
||||
private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List<List<object>> values, List<long> timestamps)
|
||||
private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List<string> columns,List<List<object>> values, List<long> timestamps)
|
||||
{
|
||||
var tablet = new Tablet(
|
||||
tableName,
|
||||
metadata.ColumnNames,
|
||||
columns,
|
||||
metadata.ColumnCategories,
|
||||
metadata.DataTypes,
|
||||
values,
|
||||
@ -535,13 +747,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
var metadata = await GetMetadata<T>();
|
||||
|
||||
var accessor = SourceEntityAccessorFactory.GetAccessor<T>();
|
||||
var memberCache = new Dictionary<string, EntityMemberInfo>(); // 缓存优化查询
|
||||
|
||||
// 预构建成员缓存(Key: NameOrPath)
|
||||
foreach (var member in accessor.MemberList)
|
||||
{
|
||||
memberCache[member.NameOrPath] = member;
|
||||
}
|
||||
var memberCache = BuildMemberCache(accessor);
|
||||
|
||||
var columns = new List<string>() { "Timestamps" };
|
||||
var dataTypes = new List<TSDataType>() { TSDataType.TIMESTAMP };
|
||||
@ -596,13 +802,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
private List<ColumnInfo> CollectColumnMetadata<T>(ISourceEntityAccessor<T> accessor)
|
||||
{
|
||||
var columns = new List<ColumnInfo>();
|
||||
var memberCache = new Dictionary<string, EntityMemberInfo>(); // 缓存优化查询
|
||||
|
||||
// 预构建成员缓存(Key: NameOrPath)
|
||||
foreach (var member in accessor.MemberList)
|
||||
{
|
||||
memberCache[member.NameOrPath] = member;
|
||||
}
|
||||
var memberCache = BuildMemberCache(accessor);
|
||||
|
||||
foreach (var member in accessor.MemberList)
|
||||
{
|
||||
@ -807,5 +1007,21 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
TSDataType.STRING => Convert.ToString(value),
|
||||
_ => Convert.ToString(value)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 缓存实体属性信息
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="accessor"></param>
|
||||
/// <returns></returns>
|
||||
private Dictionary<string, EntityMemberInfo> BuildMemberCache<T>(ISourceEntityAccessor<T> accessor)
|
||||
{
|
||||
var cache = new Dictionary<string, EntityMemberInfo>(StringComparer.Ordinal);
|
||||
foreach (var member in accessor.MemberList)
|
||||
{
|
||||
cache[member.NameOrPath] = member;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,8 +7,9 @@ using JiShe.CollectBus.Common.Enums;
|
||||
using JiShe.CollectBus.Common.Extensions;
|
||||
using JiShe.CollectBus.Common.Helpers;
|
||||
using JiShe.CollectBus.Common.Models;
|
||||
using JiShe.CollectBus.DataChannels;
|
||||
using JiShe.CollectBus.DataMigration.Options;
|
||||
using JiShe.CollectBus.GatherItem;
|
||||
using JiShe.CollectBus.IoTDB.Context;
|
||||
using JiShe.CollectBus.IoTDB.Interface;
|
||||
using JiShe.CollectBus.IoTDB.Model;
|
||||
using JiShe.CollectBus.IoTDB.Options;
|
||||
@ -17,8 +18,8 @@ using JiShe.CollectBus.IotSystems.Ammeters;
|
||||
using JiShe.CollectBus.IotSystems.MeterReadingRecords;
|
||||
using JiShe.CollectBus.IotSystems.Watermeter;
|
||||
using JiShe.CollectBus.Kafka.Internal;
|
||||
using JiShe.CollectBus.Kafka.Producer;
|
||||
using JiShe.CollectBus.Protocol.Interfaces;
|
||||
using JiShe.CollectBus.Protocol.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
@ -26,14 +27,6 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using JiShe.CollectBus.Protocol.Models;
|
||||
using System.Threading.Channels;
|
||||
using static IdentityModel.ClaimComparer;
|
||||
using JiShe.CollectBus.DataChannels;
|
||||
using JiShe.CollectBus.DataMigration.Options;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
using static System.Formats.Asn1.AsnWriter;
|
||||
using System.Threading;
|
||||
|
||||
namespace JiShe.CollectBus.ScheduledMeterReading
|
||||
{
|
||||
@ -329,7 +322,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
||||
/// <returns></returns>
|
||||
public virtual async Task InitAmmeterCacheData(string gatherCode = "")
|
||||
{
|
||||
return;
|
||||
//return;
|
||||
|
||||
// 创建取消令牌源
|
||||
//var cts = new CancellationTokenSource();
|
||||
@ -744,7 +737,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
||||
ItemCode = tempItem,
|
||||
DataTimeMark = new Protocol.DataTimeMark()
|
||||
{
|
||||
Density = ammeterInfo.TimeDensity,//todo 转换成协议的值
|
||||
Density = ammeterInfo.TimeDensity.GetDensity(),//转换成协议的值
|
||||
Point = 1,
|
||||
DataTime = timestamps,
|
||||
}
|
||||
@ -1354,7 +1347,6 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
||||
}
|
||||
|
||||
List<MeterReadingTelemetryPacketInfo> taskList = new List<MeterReadingTelemetryPacketInfo>();
|
||||
var metadata = await _dbProvider.GetMetadata<MeterReadingTelemetryPacketInfo>();
|
||||
|
||||
var itemCode = T37612012PacketItemCodeConst.AFN09HFN01H;
|
||||
//var subItemCode = T6452007PacketItemCodeConst.C08;
|
||||
|
||||
@ -859,6 +859,21 @@ namespace JiShe.CollectBus.Common.Helpers
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 采集频率转换为集中器采集密度
|
||||
/// </summary>
|
||||
/// <param name="timeDensity"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetDensity(this int timeDensity) =>
|
||||
timeDensity switch
|
||||
{
|
||||
0 => 0,//无
|
||||
1 => 255,//1分钟
|
||||
5 => 245,//5分钟
|
||||
15 => 1,//15分钟
|
||||
30 => 2,//30分钟
|
||||
60 => 3,//60分钟
|
||||
_ => -1//采集项本身无密度位
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<title>后端服务</title>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@ -141,7 +141,7 @@
|
||||
}
|
||||
},
|
||||
"ServerApplicationOptions": {
|
||||
"ServerTagName": "JiSheCollectBus99",
|
||||
"ServerTagName": "JiSheCollectBus4",
|
||||
"SystemType": "Energy",
|
||||
"FirstCollectionTime": "2025-04-28 15:07:00",
|
||||
"AutomaticVerificationTime": "16:07:00",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user