using Apache.IoTDB;
using Apache.IoTDB.DataStructure;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.IoTDBProvider
{
///
/// IoTDB数据源
///
public class IoTDBProvider : IIoTDBProvider, IDisposable
{
private readonly IoTDBOptions _options;
private readonly TableSessionPool _sessionPool;
private static readonly ConcurrentDictionary _metadataCache = new();
public IoTDBProvider(IOptions options)
{
_options = options.Value;
_sessionPool = new TableSessionPool.Builder()
.SetNodeUrls(_options.ClusterList)
.SetUsername(_options.UserName)
.SetPassword(_options.Password)
.SetFetchSize(_options.PoolSize)
.Build();
_sessionPool.Open(false).Wait();
}
///
/// 获取设备元数据
///
///
///
private DeviceMetadata GetMetadata() where T : IoTEntity
{
return _metadataCache.GetOrAdd(typeof(T), type =>
{
var metadata = new DeviceMetadata();
foreach (var prop in type.GetProperties())
{
//标签列
var attrTAG = prop.GetCustomAttribute();
if (attrTAG != null)
{
metadata.ColumnCategories.Add(ColumnCategory.TAG);
}
//属性列
var attrATTRIBUTE = prop.GetCustomAttribute();
if (attrATTRIBUTE != null)
{
metadata.ColumnCategories.Add(ColumnCategory.ATTRIBUTE);
}
//数据列
var attrFIELD = prop.GetCustomAttribute();
if (attrFIELD != null)
{
metadata.ColumnCategories.Add(ColumnCategory.FIELD);
metadata.Measurements.Add(prop.Name);
metadata.DataTypes.Add(GetDataTypeFromStr(prop.PropertyType.Name));
}
}
return metadata;
});
}
///
/// 插入数据
///
///
///
///
public async Task InsertAsync(T entity) where T : IoTEntity
{
var metadata = GetMetadata();
var tablet = BuildTablet(new[] { entity }, metadata);
await _sessionPool.InsertAsync(tablet);
}
///
/// 批量插入数据
///
///
///
///
public async Task BatchInsertAsync(IEnumerable entities) where T : IoTEntity
{
var metadata = GetMetadata();
var batchSize = 1000;
var batches = entities.Chunk(batchSize);
foreach (var batch in batches)
{
var tablet = BuildTablet(batch, metadata);
await _sessionPool.InsertAsync(tablet);
}
}
///
/// 构建表模型
///
///
///
///
///
private Tablet BuildTablet(IEnumerable entities, DeviceMetadata metadata) where T : IoTEntity
{
var deviceId = DevicePathBuilder.GetDeviceId(entities.First());
var timestamps = new List();
var values = new List>();
foreach (var entity in entities)
{
timestamps.Add(entity.Timestamps);
var rowValues = new List