diff --git a/HealthMonitor.Model/HealthMonitor.Model.csproj b/HealthMonitor.Model/HealthMonitor.Model.csproj
index f958b97..f4f1bf1 100644
--- a/HealthMonitor.Model/HealthMonitor.Model.csproj
+++ b/HealthMonitor.Model/HealthMonitor.Model.csproj
@@ -8,6 +8,8 @@
+
+
diff --git a/HealthMonitor.Model/Service/Mapper/FetalHeartRateModel.cs b/HealthMonitor.Model/Service/Mapper/FetalHeartRateModel.cs
new file mode 100644
index 0000000..2bd2745
--- /dev/null
+++ b/HealthMonitor.Model/Service/Mapper/FetalHeartRateModel.cs
@@ -0,0 +1,65 @@
+using Newtonsoft.Json;
+using SqlSugar;
+using SqlSugar.TDengine;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HealthMonitor.Model.Service.Mapper
+{
+ [STableAttribute(STableName = "stb_hm_fetal_heart_rate_test")]
+
+ public class FetalHeartRateModel
+ {
+ [JsonProperty("ts")]
+ [SqlSugar.SugarColumn(IsPrimaryKey = true, ColumnName = "ts", SqlParameterDbType = typeof(DateTime19))]
+ public DateTime Timestamp { get; set; }
+
+ [JsonProperty("fetal_heart_rate_id")]
+ [SqlSugar.SugarColumn(ColumnName= "fetal_heart_rate_id")]
+ public string FetalHeartRateId { get; set; } = default!;
+
+ [JsonProperty("message_id")]
+ [SqlSugar.SugarColumn(ColumnName = "message_id")]
+ public string MessageId { get; set; } = default!;
+
+
+ [JsonProperty("person_id")]
+ [SqlSugar.SugarColumn(ColumnName = "person_id")]
+ public string PersonId { get; set; } = default!;
+
+ [JsonProperty("serialno")]
+ [SqlSugar.SugarColumn(ColumnName = "serialno")]
+ public string SerialNumber { get; set; } = default!;
+
+ [JsonProperty("fetal_heart_rate")]
+ [SqlSugar.SugarColumn(ColumnName = "fetal_heart_rate")]
+ public int FetalHeartRate { get; set; }
+
+ [JsonProperty("create_time")]
+ [SqlSugar.SugarColumn(ColumnName = "create_time")]
+ public DateTime CreateTime { get; set; }
+
+ [JsonProperty("last_update")]
+ [SqlSugar.SugarColumn(ColumnName = "last_update")]
+ public DateTime LastUpdate { get; set; }
+
+ [JsonProperty("method")]
+ [SqlSugar.SugarColumn(ColumnName = "method")]
+ public byte Method { get; set; }
+
+ [JsonProperty("is_display")]
+ [SqlSugar.SugarColumn(ColumnName = "is_display")]
+ public bool IsDisplay { get; set; }
+
+ [JsonProperty("device_key")]
+ [SqlSugar.SugarColumn(ColumnName = "device_key")]
+ public string DeviceKey { get; set; } = default!;
+
+ [JsonProperty("serial_tail_no")]
+ [SqlSugar.SugarColumn(IsIgnore = true, ColumnName = "serial_tail_no")]
+ public string SerialTailNumber { get; set; } = default!;
+ }
+}
diff --git a/HealthMonitor.Model/Service/Mapper/PregnancyHeartRateModel.cs b/HealthMonitor.Model/Service/Mapper/PregnancyHeartRateModel.cs
new file mode 100644
index 0000000..3fc749e
--- /dev/null
+++ b/HealthMonitor.Model/Service/Mapper/PregnancyHeartRateModel.cs
@@ -0,0 +1,64 @@
+using Newtonsoft.Json;
+using SqlSugar;
+using SqlSugar.TDengine;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HealthMonitor.Model.Service.Mapper
+{
+ [STableAttribute(STableName = "stb_hm_pregnancy_heart_rate")]
+ public class PregnancyHeartRateModel
+ {
+ [JsonProperty("ts")]
+ [SqlSugar.SugarColumn(IsPrimaryKey = true, ColumnName = "ts", SqlParameterDbType = typeof(DateTime19))]
+ public DateTime Timestamp { get; set; }
+
+ [JsonProperty("pregnancy_heart_rate_id")]
+ [SqlSugar.SugarColumn(ColumnName = "pregnancy_heart_rate_id")]
+ public string PregnancyHeartRateId { get; set; } = default!;
+
+ [JsonProperty("message_id")]
+ [SqlSugar.SugarColumn(ColumnName = "message_id")]
+ public string MessageId { get; set; } = default!;
+
+
+ [JsonProperty("person_id")]
+ [SqlSugar.SugarColumn(ColumnName = "person_id")]
+ public string PersonId { get; set; } = default!;
+
+ [JsonProperty("serialno")]
+ [SqlSugar.SugarColumn(ColumnName = "serialno")]
+ public string SerialNumber { get; set; } = default!;
+
+ [JsonProperty("pregnancy_heart_rate")]
+ [SqlSugar.SugarColumn(ColumnName = "pregnancy_heart_rate")]
+ public int PregnancyHeartRate { get; set; }
+
+ [JsonProperty("create_time")]
+ [SqlSugar.SugarColumn(ColumnName = "create_time")]
+ public DateTime CreateTime { get; set; }
+
+ [JsonProperty("last_update")]
+ [SqlSugar.SugarColumn(ColumnName = "last_update")]
+ public DateTime LastUpdate { get; set; }
+
+ [JsonProperty("method")]
+ [SqlSugar.SugarColumn(ColumnName = "method")]
+ public byte Method { get; set; }
+
+ [JsonProperty("is_display")]
+ [SqlSugar.SugarColumn(ColumnName = "is_display")]
+ public bool IsDisplay { get; set; }
+
+ [JsonProperty("device_key")]
+ [SqlSugar.SugarColumn(ColumnName = "device_key")]
+ public string DeviceKey { get; set; } = default!;
+
+ [JsonProperty("serial_tail_no")]
+ [SqlSugar.SugarColumn(IsIgnore = true, ColumnName = "serial_tail_no")]
+ public string SerialTailNumber { get; set; } = default!;
+ }
+}
diff --git a/HealthMonitor.Service/Biz/db/TDengineService.cs b/HealthMonitor.Service/Biz/db/TDengineService.cs
index bfc7062..e39bee1 100644
--- a/HealthMonitor.Service/Biz/db/TDengineService.cs
+++ b/HealthMonitor.Service/Biz/db/TDengineService.cs
@@ -9,14 +9,21 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using SqlSugar;
+using SqlSugar.DbConvert;
+using SqlSugar.TDengine;
using System;
using System.Collections.Generic;
+using System.Data;
using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using TDengineDriver;
using TDengineDriver.Impl;
+using TDengineTMQ;
namespace HealthMonitor.Service.Biz.db
{
@@ -26,14 +33,46 @@ namespace HealthMonitor.Service.Biz.db
private readonly ILogger _logger;
private readonly HttpHelper _httpHelper=default!;
private readonly TDengineServiceConfig _configTDengineService;
+ private readonly SqlSugarClient _clientSqlSugar;
public TDengineService(ILogger logger,
IOptions configTDengineService,
HttpHelper httpHelper
+
)
{
_logger = logger;
_configTDengineService = configTDengineService.Value;
_httpHelper = httpHelper;
+ _clientSqlSugar = new SqlSugarClient(new ConnectionConfig()
+ {
+ DbType = SqlSugar.DbType.TDengine,
+ ConnectionString = $"Host={_configTDengineService.Host};Port={_configTDengineService.Port};Username={_configTDengineService.UserName};Password={_configTDengineService.Password};Database={_configTDengineService.DB};TsType=config_ns",
+ IsAutoCloseConnection = true,
+ AopEvents = new AopEvents
+ {
+ OnLogExecuting = (sql, p) =>
+ {
+ Console.WriteLine(SqlSugar.UtilMethods.GetNativeSql(sql, p));
+ }
+ },
+ ConfigureExternalServices = new ConfigureExternalServices()
+ {
+ EntityService = (property, column) =>
+ {
+ if (column.SqlParameterDbType == null)
+ {
+ column.SqlParameterDbType = typeof(CommonPropertyConvert);
+ }
+ }
+ },
+ MoreSettings=new ConnMoreSettings()
+ {
+ PgSqlIsAutoToLower = false,
+ PgSqlIsAutoToLowerCodeFirst = false,
+ }
+
+ });
+
}
public IntPtr Connection()
{
@@ -596,5 +635,178 @@ namespace HealthMonitor.Service.Biz.db
return new decimal[] { (decimal)systolicAvg!, (decimal)diastolicAvg! };
}
+
+ #region SqlSugarClient
+ public async Task InsertFetalHeartRateAsync()
+ {
+ var tableName = typeof(FetalHeartRateModel)
+ .GetCustomAttribute()?
+ .STableName;
+
+ if (tableName == null)
+ {
+ throw new InvalidOperationException("STableAttribute not found on FetalHeartRateModel class.");
+ }
+
+ await _clientSqlSugar.Ado.ExecuteCommandAsync($"create table IF NOT EXISTS hm_fhr_00 using {tableName} tags('00')");
+
+ _clientSqlSugar.Insertable(new FetalHeartRateModel()
+ {
+ Timestamp = DateTime.Now,
+ CreateTime = DateTime.Now,
+ FetalHeartRate = 90,
+ FetalHeartRateId = Guid.NewGuid().ToString("D"),
+ IsDisplay = false,
+ Method = 1,
+ PersonId = Guid.NewGuid().ToString("D"),
+ MessageId = Guid.NewGuid().ToString("D"),
+ SerialNumber = Guid.NewGuid().ToString("D"),
+ DeviceKey = Guid.NewGuid().ToString("D"),
+ SerialTailNumber = "00",
+ LastUpdate = DateTime.Now,
+ }).AS("hm_fhr_00").ExecuteCommand();
+
+ }
+
+ public Task GetFirst()
+ {
+ var tableName = typeof(FetalHeartRateModel)
+ .GetCustomAttribute()?
+ .STableName;
+
+ var first = _clientSqlSugar
+ .Queryable()
+ .AS(tableName)
+ .OrderByDescending(x => x.Timestamp).FirstAsync();
+ return first;
+ }
+ public void InsertFetalHeartRate2()
+ {
+ //var insrtSql = "";
+ //_clientSqlSugar.Ado.ExecuteCommand(insrtSql);
+ // 通过反射获取STableAttribute的STableName值
+ var tableName = typeof(FetalHeartRateModel)
+ .GetCustomAttribute()?
+ .STableName;
+
+ if (tableName == null)
+ {
+ throw new InvalidOperationException("STableAttribute not found on FetalHeartRateModel class.");
+ }
+
+ _clientSqlSugar.Ado.ExecuteCommand($"create table IF NOT EXISTS hm_fhr_00 using {tableName} tags('00')");
+
+ //_clientSqlSugar.Ado.ExecuteCommand($"create table IF NOT EXISTS hm_fhr_00 using `stb_hm_fetal_heart_rate_test` tags('00')");
+ _clientSqlSugar.Insertable(new FetalHeartRateModel()
+ {
+ Timestamp = DateTime.Now,
+ CreateTime = DateTime.Now,
+ FetalHeartRate = 90,
+ FetalHeartRateId = Guid.NewGuid().ToString("D"),
+ IsDisplay = false,
+ Method = 1,
+ PersonId = Guid.NewGuid().ToString("D"),
+ MessageId = Guid.NewGuid().ToString("D"),
+ SerialNumber = Guid.NewGuid().ToString("D"),
+ DeviceKey = Guid.NewGuid().ToString("D"),
+ SerialTailNumber = "00",
+ LastUpdate = DateTime.Now,
+ }).AS("hm_fhr_00").ExecuteCommand();
+
+
+ //List rows = new();
+
+ //rows.Add(new FetalHeartRateModel() {
+ // Timestamp = new DateTime(2024, 1, 1),
+ // CreateTime = DateTime.Now,
+ // FetalHeartRate = 90,
+ // FetalHeartRateId = Guid.NewGuid().ToString("D"),
+ // IsDisplay = false,
+ // Method = 1,
+ // PersonId = Guid.NewGuid().ToString("D"),
+ // MessageId = Guid.NewGuid().ToString("D"),
+ // SerialNumber = Guid.NewGuid().ToString("D"),
+ // DeviceKey = Guid.NewGuid().ToString("D"),
+ // SerialTailNumber = "00",
+ // LastUpdate = DateTime.Now,
+
+ //});
+
+ //_clientSqlSugar.Insertable(rows).AS("hm_fhr_00").ExecuteCommand();
+ }
+
+ ///
+ /// 插入记录
+ ///
+ ///
+ ///
+ /// 子表名称
+ ///
+ ///
+ public async Task InsertAsync(string tbName, T model)
+ {
+ var stbName = typeof(T)
+ .GetCustomAttribute()?
+ .STableName;
+
+ if (stbName == null)
+ {
+ throw new InvalidOperationException($"STableAttribute not found on {nameof(T)} class.");
+ }
+ var tailNo = typeof(T).GetProperty("SerialTailNumber")?.GetValue(model)?.ToString();
+
+ if (string.IsNullOrEmpty(tailNo))
+ {
+ throw new InvalidOperationException($"SerialNumberAttribute not found on {nameof(T)} class.");
+ }
+ var tbFullName = $"{tbName}_{tailNo}";
+ await _clientSqlSugar.Ado.ExecuteCommandAsync($"create table IF NOT EXISTS {tbFullName} using {stbName} tags('{tailNo}')");
+
+ //_clientSqlSugar.InsertableByDynamic(model).AS(tbFullName).ExecuteCommand();
+ _clientSqlSugar.InsertableByObject(model).AS(tbFullName).ExecuteCommand();
+ }
+
+ public Task GetFirstAsync() where T : class
+ {
+ var tableName = typeof(T)
+ .GetCustomAttribute()?
+ .STableName;
+ // 创建一个表示 Timestamp 属性的表达式
+ var parameter = Expression.Parameter(typeof(T), "x");
+ var property = Expression.Property(parameter, "Timestamp");
+ var lambda = Expression.Lambda>(Expression.Convert(property, typeof(object)), parameter);
+
+
+ var first = _clientSqlSugar
+ .Queryable()
+ .AS(tableName)
+ .OrderByDescending(lambda).FirstAsync();
+ return first;
+ }
+
+ public async Task> GetBySerialNoAsync(string serialNo) where T : class
+ {
+ var tableName = typeof(T)
+ .GetCustomAttribute()?
+ .STableName;
+ // 创建表示 Timestamp 属性的表达式
+ var parameter = Expression.Parameter(typeof(T), "x");
+ var timestampProperty = Expression.Property(parameter, "Timestamp");
+ var timestampLambda = Expression.Lambda>(Expression.Convert(timestampProperty, typeof(object)), parameter);
+
+ // 创建表示 SerialNo 属性的表达式
+ var serialNoProperty = Expression.Property(parameter, "SerialNumber");
+ var serialNoConstant = Expression.Constant(serialNo);
+ var equalExpression = Expression.Equal(serialNoProperty, serialNoConstant);
+ var serialNoLambda = Expression.Lambda>(equalExpression, parameter);
+
+ var res = await _clientSqlSugar
+ .Queryable()
+ .AS(tableName)
+ .Where(serialNoLambda)
+ .OrderByDescending(timestampLambda).ToListAsync();
+ return res;
+ }
+ #endregion
}
}
diff --git a/HealthMonitor.Service/HealthMonitor.Service.csproj b/HealthMonitor.Service/HealthMonitor.Service.csproj
index fa312cb..af17312 100644
--- a/HealthMonitor.Service/HealthMonitor.Service.csproj
+++ b/HealthMonitor.Service/HealthMonitor.Service.csproj
@@ -11,6 +11,8 @@
+
+
diff --git a/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs b/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs
index 17b0ede..c5b3db4 100644
--- a/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs
+++ b/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs
@@ -57,63 +57,25 @@ namespace HealthMonitor.Service.Sub
}
public void BeginListen(CancellationToken stoppingToken)
{
- //var cfg = new ConsumerConfig
- //{
- // GourpId = "group_1",
- // TDConnectUser = "root",
- // TDConnectPasswd = "taosdata",
- // MsgWithTableName = "true",
- // TDConnectIp = "47.116.142.20",
- //};
- //var conn = GetConnection();
-
-
- //ProcessMsg(consumer);
-
- //防止造成多线程运行
+
_tokenSource?.Cancel();
-
_tokenSource = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
DoTDengineConnect();
}
public void DoTDengineConnect()
{
- // string host = _configTDengineService.Host;
- // short port = 6030;
- // string username = _configTDengineService.UserName;
- // string password = _configTDengineService.Password;
- // string dbname = _configTDengineService.DB;
- ////#if DEBUG
- //// //string configDir = "C:/TDengine/cfg";
- //// //TDengine.Options((int)TDengineInitOption.TSDB_OPTION_CONFIGDIR, configDir);
- //// TDengine.Options((int)TDengineInitOption.TSDB_OPTION_TIMEZONE, "Asia/Beijing");
- ////#endif
- // var conn = TDengine.Connect(host, username, password, dbname, port);
-
- // if (conn == IntPtr.Zero)
- // {
- // _logger.LogError("reason:{TDengine.Error(conn)}", TDengine.Error(conn));
-
- // }
- // else
- // {
- // _logger.LogInformation($"连接 TDengine 成功....");
-
- // }
-
var conn = _serviceTDengine.Connection();
DoReceive(conn);
}
public void DoReceive(IntPtr Connection)
{
-
- // string topic = "topic_hm_bp_stats";
+ #region topichmbpstats 订阅
+ // string topic = "topichmbpstats";
string topic = nameof(TopicHmBloodPress).ToLower();
TopicHmBloodPress fields = new();
PropertyInfo[] props = fields.GetType().GetProperties();
-
// 获取 fields
string attributes = "";
foreach (PropertyInfo prop in props)
@@ -126,9 +88,16 @@ namespace HealthMonitor.Service.Sub
}
attributes = attributes.TrimEnd(',');
- //create topic
+ //创建 topichmbpstats
IntPtr res = TDengine.Query(Connection, $"create topic if not exists {topic} as select {attributes} from health_monitor.stb_hm_bloodpress");
+ //创建 topichmfetalheartrate
+ //var fetalHeartRateTopic = "topichmfetalheartrate";
+ //var fetalHeartRateFields = "ts,fetal_heart_rate_id,message_id,person_id,serialno,fetal_heart_rate,create_time,method,last_update,is_display,device_key";
+ //res = TDengine.Query(Connection, $"create topic if not exists {fetalHeartRateTopic} as select {fetalHeartRateFields} from health_monitor.stb_hm_fetal_heart_rate_test");
+ #endregion
+
+
if (TDengine.ErrorNo(res) != 0)
{
_logger.LogError($"create topic failed, reason:{TDengine.Error(res)}");
@@ -160,12 +129,10 @@ namespace HealthMonitor.Service.Sub
{
try
{
-
IDictionary row = new Dictionary();
foreach (var meta in kv.Value.Metas)
{
int index = i - (kv.Value.Metas.Count - kv.Value.Metas.IndexOf(meta) - 1);
- //var value = kv.Value.Datas[index];
row.Add(meta.name, kv.Value.Datas[index]);
}
diff --git a/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressController.cs b/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressController.cs
index 3d0f2f6..de805ee 100644
--- a/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressController.cs
+++ b/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressController.cs
@@ -1,4 +1,5 @@
using HealthMonitor.Model.Config;
+using HealthMonitor.Model.Service.Mapper;
using HealthMonitor.Service.Biz.db;
using HealthMonitor.WebApi.Configs;
using HealthMonitor.WebApi.Controllers.Api;
@@ -72,5 +73,32 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor
return ApiResponse