Merge pull request 'dev' (#4) from dev into master

Reviewed-on: daizan/JiShe.CollectBus#4
This commit is contained in:
daizan 2025-05-20 05:39:25 +00:00
commit ea81151ca9
301 changed files with 13353 additions and 5525 deletions

View File

@ -1,27 +1,3 @@
# FROM mcr.microsoft.com/dotnet/aspnet:8.0
# # 创建目录
# RUN mkdir /app
# COPY publish /app
# # 设置工作目录
# WORKDIR /app
# # 暴露80端口
# EXPOSE 80
# # 设置时区 .net6 才有这个问题
# ENV TZ=Asia/Shanghai
# # 设置环境变量
# ENV ASPNETCORE_ENVIRONMENT=Production
# ENTRYPOINT ["dotnet", "JiShe.IOT.HttpApi.Host.dll"]
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
@ -30,8 +6,8 @@ ENV TZ=Asia/Shanghai
ENV ASPNETCORE_ENVIRONMENT=Production
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["JiShe.CollectBus.sln", "."]
# WORKDIR /src
COPY ["JiShe.CollectBus.Main.sln", "."]
COPY ["common.props", "."]
COPY ["NuGet.Config", "."]
COPY ["web/", "web/"]
@ -41,10 +17,10 @@ COPY ["shared/", "shared/"]
COPY ["protocols/", "protocols/"]
# 恢复项目依赖
RUN dotnet restore "JiShe.CollectBus.sln"
RUN dotnet restore "JiShe.CollectBus.Main.sln"
# 构建项目
WORKDIR "/src/web/JiShe.CollectBus.Host"
WORKDIR "/web/JiShe.CollectBus.Host"
RUN dotnet build "JiShe.CollectBus.Host.csproj" -c Release -o /app/build
# 发布项目
@ -53,6 +29,7 @@ RUN dotnet publish "JiShe.CollectBus.Host.csproj" -c Release -o /app/publish /p:
# 创建最终镜像
FROM base AS final
WORKDIR /app
# 创建Plugins目录

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.PluginFileWatcher", "external\JiShe.CollectBus.PluginFileWatcher\JiShe.CollectBus.PluginFileWatcher.csproj", "{0F67A493-A4DF-550E-AB4D-95F55144C706}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0F67A493-A4DF-550E-AB4D-95F55144C706}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0F67A493-A4DF-550E-AB4D-95F55144C706}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F67A493-A4DF-550E-AB4D-95F55144C706}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F67A493-A4DF-550E-AB4D-95F55144C706}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD}
EndGlobalSection
EndGlobal

188
JiShe.CollectBus.Main.sln Normal file
View File

@ -0,0 +1,188 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Domain.Shared", "shared\JiShe.CollectBus.Domain.Shared\JiShe.CollectBus.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Domain", "services\JiShe.CollectBus.Domain\JiShe.CollectBus.Domain.csproj", "{F2840BC7-0188-4606-9126-DADD0F5ABF7A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Application.Contracts", "services\JiShe.CollectBus.Application.Contracts\JiShe.CollectBus.Application.Contracts.csproj", "{BD65D04F-08D5-40C1-8C24-77CA0BACB877}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Application", "services\JiShe.CollectBus.Application\JiShe.CollectBus.Application.csproj", "{78040F9E-3501-4A40-82DF-00A597710F35}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.MongoDB", "modules\JiShe.CollectBus.MongoDB\JiShe.CollectBus.MongoDB.csproj", "{F1C58097-4C08-4D88-8976-6B3389391481}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.HttpApi", "web\JiShe.CollectBus.HttpApi\JiShe.CollectBus.HttpApi.csproj", "{077AA5F8-8B61-420C-A6B5-0150A66FDB34}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Host", "web\JiShe.CollectBus.Host\JiShe.CollectBus.Host.csproj", "{35829A15-4127-4F69-8BDE-9405DEAACA9A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Common", "shared\JiShe.CollectBus.Common\JiShe.CollectBus.Common.csproj", "{AD2F1928-4411-4511-B564-5FB996EC08B9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.DbMigrator", "services\JiShe.CollectBus.DbMigrator\JiShe.CollectBus.DbMigrator.csproj", "{8BA01C3D-297D-42DF-BD63-EF07202A0A67}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.FreeSql", "modules\JiShe.CollectBus.FreeSql\JiShe.CollectBus.FreeSql.csproj", "{FE0457D9-4038-4A17-8808-DCAD06CFC0A0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.FreeRedis", "modules\JiShe.CollectBus.FreeRedis\JiShe.CollectBus.FreeRedis.csproj", "{C06C4082-638F-2996-5FED-7784475766C1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Kafka", "modules\JiShe.CollectBus.Kafka\JiShe.CollectBus.Kafka.csproj", "{F0288175-F0EC-48BD-945F-CF1512850943}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.IoTDB", "modules\JiShe.CollectBus.IoTDB\JiShe.CollectBus.IoTDB.csproj", "{A3F3C092-0A25-450B-BF6A-5983163CBEF5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Protocol.Test", "protocols\JiShe.CollectBus.Protocol.Test\JiShe.CollectBus.Protocol.Test.csproj", "{A377955E-7EA1-6F29-8CF7-774569E93925}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Cassandra", "modules\JiShe.CollectBus.Cassandra\JiShe.CollectBus.Cassandra.csproj", "{443B4549-0AC0-4493-8F3E-49C83225DD76}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1.Web", "1.Web", "{A02F7D8A-04DC-44D6-94D4-3F65712D6B94}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4.Modules", "4.Modules", "{2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "5.Protocols", "5.Protocols", "{3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2.Services", "2.Services", "{BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3.Shared", "3.Shared", "{EBF7C01F-9B4F-48E6-8418-2CBFDA51EB0B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T1882018", "protocols\JiShe.CollectBus.Protocol.T1882018\JiShe.CollectBus.Protocol.T1882018.csproj", "{430D298B-377E-49B8-83AA-ADC7C0EBDB0F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T37612012", "protocols\JiShe.CollectBus.Protocol.T37612012\JiShe.CollectBus.Protocol.T37612012.csproj", "{8A61DF78-069B-40B5-8811-614E2960443E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol", "protocols\JiShe.CollectBus.Protocol\JiShe.CollectBus.Protocol.csproj", "{E27377CC-E2D3-4237-060F-96EA214D3129}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T6452007", "protocols\JiShe.CollectBus.Protocol.T6452007\JiShe.CollectBus.Protocol.T6452007.csproj", "{75B7D419-C261-577D-58D6-AA3ACED9129F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0.Docs", "0.Docs", "{D8346C4C-55B8-43E8-A6B8-E59D56FE6D92}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
Dockerfile = Dockerfile
NuGet.Config = NuGet.Config
PackageAndPublish.bat = PackageAndPublish.bat
readme.md = readme.md
Temp.Dockerfile = Temp.Dockerfile
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Analyzers.Shared", "shared\JiShe.CollectBus.Analyzers.Shared\JiShe.CollectBus.Analyzers.Shared.csproj", "{DD68F314-BC66-5601-B094-B1A7BE93F4E0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Analyzers", "modules\JiShe.CollectBus.Analyzers\JiShe.CollectBus.Analyzers.csproj", "{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.Build.0 = Release|Any CPU
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.Build.0 = Release|Any CPU
{BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Release|Any CPU.Build.0 = Release|Any CPU
{78040F9E-3501-4A40-82DF-00A597710F35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78040F9E-3501-4A40-82DF-00A597710F35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78040F9E-3501-4A40-82DF-00A597710F35}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78040F9E-3501-4A40-82DF-00A597710F35}.Release|Any CPU.Build.0 = Release|Any CPU
{F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.Build.0 = Release|Any CPU
{077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Debug|Any CPU.Build.0 = Debug|Any CPU
{077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Release|Any CPU.ActiveCfg = Release|Any CPU
{077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Release|Any CPU.Build.0 = Release|Any CPU
{35829A15-4127-4F69-8BDE-9405DEAACA9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{35829A15-4127-4F69-8BDE-9405DEAACA9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{35829A15-4127-4F69-8BDE-9405DEAACA9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{35829A15-4127-4F69-8BDE-9405DEAACA9A}.Release|Any CPU.Build.0 = Release|Any CPU
{AD2F1928-4411-4511-B564-5FB996EC08B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD2F1928-4411-4511-B564-5FB996EC08B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD2F1928-4411-4511-B564-5FB996EC08B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD2F1928-4411-4511-B564-5FB996EC08B9}.Release|Any CPU.Build.0 = Release|Any CPU
{8BA01C3D-297D-42DF-BD63-EF07202A0A67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8BA01C3D-297D-42DF-BD63-EF07202A0A67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8BA01C3D-297D-42DF-BD63-EF07202A0A67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8BA01C3D-297D-42DF-BD63-EF07202A0A67}.Release|Any CPU.Build.0 = Release|Any CPU
{FE0457D9-4038-4A17-8808-DCAD06CFC0A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE0457D9-4038-4A17-8808-DCAD06CFC0A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE0457D9-4038-4A17-8808-DCAD06CFC0A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE0457D9-4038-4A17-8808-DCAD06CFC0A0}.Release|Any CPU.Build.0 = Release|Any CPU
{C06C4082-638F-2996-5FED-7784475766C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C06C4082-638F-2996-5FED-7784475766C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C06C4082-638F-2996-5FED-7784475766C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C06C4082-638F-2996-5FED-7784475766C1}.Release|Any CPU.Build.0 = Release|Any CPU
{F0288175-F0EC-48BD-945F-CF1512850943}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0288175-F0EC-48BD-945F-CF1512850943}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0288175-F0EC-48BD-945F-CF1512850943}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0288175-F0EC-48BD-945F-CF1512850943}.Release|Any CPU.Build.0 = Release|Any CPU
{A3F3C092-0A25-450B-BF6A-5983163CBEF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3F3C092-0A25-450B-BF6A-5983163CBEF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3F3C092-0A25-450B-BF6A-5983163CBEF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3F3C092-0A25-450B-BF6A-5983163CBEF5}.Release|Any CPU.Build.0 = Release|Any CPU
{A377955E-7EA1-6F29-8CF7-774569E93925}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A377955E-7EA1-6F29-8CF7-774569E93925}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A377955E-7EA1-6F29-8CF7-774569E93925}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A377955E-7EA1-6F29-8CF7-774569E93925}.Release|Any CPU.Build.0 = Release|Any CPU
{443B4549-0AC0-4493-8F3E-49C83225DD76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{443B4549-0AC0-4493-8F3E-49C83225DD76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{443B4549-0AC0-4493-8F3E-49C83225DD76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{443B4549-0AC0-4493-8F3E-49C83225DD76}.Release|Any CPU.Build.0 = Release|Any CPU
{430D298B-377E-49B8-83AA-ADC7C0EBDB0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{430D298B-377E-49B8-83AA-ADC7C0EBDB0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{430D298B-377E-49B8-83AA-ADC7C0EBDB0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{430D298B-377E-49B8-83AA-ADC7C0EBDB0F}.Release|Any CPU.Build.0 = Release|Any CPU
{8A61DF78-069B-40B5-8811-614E2960443E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A61DF78-069B-40B5-8811-614E2960443E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A61DF78-069B-40B5-8811-614E2960443E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A61DF78-069B-40B5-8811-614E2960443E}.Release|Any CPU.Build.0 = Release|Any CPU
{E27377CC-E2D3-4237-060F-96EA214D3129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E27377CC-E2D3-4237-060F-96EA214D3129}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E27377CC-E2D3-4237-060F-96EA214D3129}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E27377CC-E2D3-4237-060F-96EA214D3129}.Release|Any CPU.Build.0 = Release|Any CPU
{75B7D419-C261-577D-58D6-AA3ACED9129F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75B7D419-C261-577D-58D6-AA3ACED9129F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75B7D419-C261-577D-58D6-AA3ACED9129F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75B7D419-C261-577D-58D6-AA3ACED9129F}.Release|Any CPU.Build.0 = Release|Any CPU
{DD68F314-BC66-5601-B094-B1A7BE93F4E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD68F314-BC66-5601-B094-B1A7BE93F4E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD68F314-BC66-5601-B094-B1A7BE93F4E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD68F314-BC66-5601-B094-B1A7BE93F4E0}.Release|Any CPU.Build.0 = Release|Any CPU
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D64C1577-4929-4B60-939E-96DE1534891A} = {EBF7C01F-9B4F-48E6-8418-2CBFDA51EB0B}
{F2840BC7-0188-4606-9126-DADD0F5ABF7A} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}
{BD65D04F-08D5-40C1-8C24-77CA0BACB877} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}
{78040F9E-3501-4A40-82DF-00A597710F35} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}
{F1C58097-4C08-4D88-8976-6B3389391481} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}
{077AA5F8-8B61-420C-A6B5-0150A66FDB34} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94}
{35829A15-4127-4F69-8BDE-9405DEAACA9A} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94}
{AD2F1928-4411-4511-B564-5FB996EC08B9} = {EBF7C01F-9B4F-48E6-8418-2CBFDA51EB0B}
{8BA01C3D-297D-42DF-BD63-EF07202A0A67} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}
{FE0457D9-4038-4A17-8808-DCAD06CFC0A0} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}
{C06C4082-638F-2996-5FED-7784475766C1} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}
{F0288175-F0EC-48BD-945F-CF1512850943} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}
{A3F3C092-0A25-450B-BF6A-5983163CBEF5} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}
{A377955E-7EA1-6F29-8CF7-774569E93925} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}
{443B4549-0AC0-4493-8F3E-49C83225DD76} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}
{430D298B-377E-49B8-83AA-ADC7C0EBDB0F} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}
{8A61DF78-069B-40B5-8811-614E2960443E} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}
{E27377CC-E2D3-4237-060F-96EA214D3129} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}
{75B7D419-C261-577D-58D6-AA3ACED9129F} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}
{DD68F314-BC66-5601-B094-B1A7BE93F4E0} = {EBF7C01F-9B4F-48E6-8418-2CBFDA51EB0B}
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD}
EndGlobalSection
EndGlobal

View File

@ -37,7 +37,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1.Web", "1.Web", "{A02F7D8A
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4.Modules", "4.Modules", "{2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "6.Protocols", "6.Protocols", "{3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "5.Protocols", "5.Protocols", "{3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2.Services", "2.Services", "{BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}"
EndProject
@ -45,8 +45,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3.Shared", "3.Shared", "{EB
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Kafka.Test", "modules\JiShe.CollectBus.Kafka.Test\JiShe.CollectBus.Kafka.Test.csproj", "{6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "5.External", "5.External", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T1882018", "protocols\JiShe.CollectBus.Protocol.T1882018\JiShe.CollectBus.Protocol.T1882018.csproj", "{430D298B-377E-49B8-83AA-ADC7C0EBDB0F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T37612012", "protocols\JiShe.CollectBus.Protocol.T37612012\JiShe.CollectBus.Protocol.T37612012.csproj", "{8A61DF78-069B-40B5-8811-614E2960443E}"
@ -55,8 +53,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T6452007", "protocols\JiShe.CollectBus.Protocol.T6452007\JiShe.CollectBus.Protocol.T6452007.csproj", "{75B7D419-C261-577D-58D6-AA3ACED9129F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.PluginFileWatcher", "external\JiShe.CollectBus.PluginFileWatcher\JiShe.CollectBus.PluginFileWatcher.csproj", "{0F67A493-A4DF-550E-AB4D-95F55144C706}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0.Docs", "0.Docs", "{D8346C4C-55B8-43E8-A6B8-E59D56FE6D92}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
@ -66,6 +62,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0.Docs", "0.Docs", "{D8346C
readme.md = readme.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Analyzers.Shared", "shared\JiShe.CollectBus.Analyzers.Shared\JiShe.CollectBus.Analyzers.Shared.csproj", "{DD68F314-BC66-5601-B094-B1A7BE93F4E0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Analyzers", "modules\JiShe.CollectBus.Analyzers\JiShe.CollectBus.Analyzers.csproj", "{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Migration.Application.Contracts", "services\JiShe.CollectBus.Migration.Application.Contracts\JiShe.CollectBus.Migration.Application.Contracts.csproj", "{E01625B5-B5B7-7A4B-468F-EC12C1BDBA2A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Migration.Application", "services\JiShe.CollectBus.Migration.Application\JiShe.CollectBus.Migration.Application.csproj", "{B955C5DA-3C20-35D2-0770-8FE473C41C44}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Migration.Host", "web\JiShe.CollectBus.Migration.Host\JiShe.CollectBus.Migration.Host.csproj", "{995D3D91-7221-D4A3-A7B2-FEC202328A18}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Migration.HttpApi", "web\JiShe.CollectBus.Migration.HttpApi\JiShe.CollectBus.Migration.HttpApi.csproj", "{8A113DE5-7D50-6E6B-739F-B6EEAD5E13B4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -152,10 +160,30 @@ Global
{75B7D419-C261-577D-58D6-AA3ACED9129F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75B7D419-C261-577D-58D6-AA3ACED9129F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75B7D419-C261-577D-58D6-AA3ACED9129F}.Release|Any CPU.Build.0 = Release|Any CPU
{0F67A493-A4DF-550E-AB4D-95F55144C706}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0F67A493-A4DF-550E-AB4D-95F55144C706}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F67A493-A4DF-550E-AB4D-95F55144C706}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F67A493-A4DF-550E-AB4D-95F55144C706}.Release|Any CPU.Build.0 = Release|Any CPU
{DD68F314-BC66-5601-B094-B1A7BE93F4E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD68F314-BC66-5601-B094-B1A7BE93F4E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD68F314-BC66-5601-B094-B1A7BE93F4E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD68F314-BC66-5601-B094-B1A7BE93F4E0}.Release|Any CPU.Build.0 = Release|Any CPU
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A}.Release|Any CPU.Build.0 = Release|Any CPU
{E01625B5-B5B7-7A4B-468F-EC12C1BDBA2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E01625B5-B5B7-7A4B-468F-EC12C1BDBA2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E01625B5-B5B7-7A4B-468F-EC12C1BDBA2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E01625B5-B5B7-7A4B-468F-EC12C1BDBA2A}.Release|Any CPU.Build.0 = Release|Any CPU
{B955C5DA-3C20-35D2-0770-8FE473C41C44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B955C5DA-3C20-35D2-0770-8FE473C41C44}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B955C5DA-3C20-35D2-0770-8FE473C41C44}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B955C5DA-3C20-35D2-0770-8FE473C41C44}.Release|Any CPU.Build.0 = Release|Any CPU
{995D3D91-7221-D4A3-A7B2-FEC202328A18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{995D3D91-7221-D4A3-A7B2-FEC202328A18}.Debug|Any CPU.Build.0 = Debug|Any CPU
{995D3D91-7221-D4A3-A7B2-FEC202328A18}.Release|Any CPU.ActiveCfg = Release|Any CPU
{995D3D91-7221-D4A3-A7B2-FEC202328A18}.Release|Any CPU.Build.0 = Release|Any CPU
{8A113DE5-7D50-6E6B-739F-B6EEAD5E13B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A113DE5-7D50-6E6B-739F-B6EEAD5E13B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A113DE5-7D50-6E6B-739F-B6EEAD5E13B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A113DE5-7D50-6E6B-739F-B6EEAD5E13B4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -181,7 +209,12 @@ Global
{8A61DF78-069B-40B5-8811-614E2960443E} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}
{E27377CC-E2D3-4237-060F-96EA214D3129} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}
{75B7D419-C261-577D-58D6-AA3ACED9129F} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}
{0F67A493-A4DF-550E-AB4D-95F55144C706} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{DD68F314-BC66-5601-B094-B1A7BE93F4E0} = {EBF7C01F-9B4F-48E6-8418-2CBFDA51EB0B}
{EB97C7BB-1E4A-CBA4-04C1-22DBF48A253A} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59}
{E01625B5-B5B7-7A4B-468F-EC12C1BDBA2A} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}
{B955C5DA-3C20-35D2-0770-8FE473C41C44} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}
{995D3D91-7221-D4A3-A7B2-FEC202328A18} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94}
{8A113DE5-7D50-6E6B-739F-B6EEAD5E13B4} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD}

View File

@ -5,6 +5,7 @@ set VERSION=1.0.0
set CONFIGURATION=Release
set OUTPUT_DIR=%~dp0\nupkgs
set API_KEY=your-nuget-api-key
set SOURCE=https://api.nuget.org/v3/index.json
REM 创建输出目录
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"
@ -22,11 +23,10 @@ echo 开始打包项目...
REM 打包 Protocol 项目
echo 打包 Protocol 项目...
call :PackProject protocols\JiShe.CollectBus.Protocol\JiShe.CollectBus.Protocol.csproj
call :
protocols\JiShe.CollectBus.Protocol\JiShe.CollectBus.Protocol.csproj
call :PackProject protocols\JiShe.CollectBus.Protocol.Contracts\JiShe.CollectBus.Protocol.Contracts.csproj
call :PackProject protocols\JiShe.CollectBus.Protocol.T1882018\JiShe.CollectBus.Protocol.T1882018.csproj
call :PackProject protocols\JiShe.CollectBus.Protocol.T37612012\JiShe.CollectBus.Protocol.T37612012.csproj
call :PackProject protocols\JiShe.CollectBus.Protocol.T6452007\JiShe.CollectBus.Protocol.T6452007.csproj
REM 打包 Modules 项目
echo 打包 Modules 项目...
@ -36,7 +36,6 @@ call :PackProject modules\JiShe.CollectBus.IoTDB\JiShe.CollectBus.IoTDB.csproj
call :PackProject modules\JiShe.CollectBus.MongoDB\JiShe.CollectBus.MongoDB.csproj
call :PackProject modules\JiShe.CollectBus.FreeSql\JiShe.CollectBus.FreeSql.csproj
call :PackProject modules\JiShe.CollectBus.Cassandra\JiShe.CollectBus.Cassandra.csproj
call :PackProject modules\JiShe.CollectBusMultiProcessing\JiShe.CollectBusMultiProcessing.csproj
REM 打包 Shared 项目
echo 打包 Shared 项目...
@ -44,11 +43,11 @@ call :PackProject shared\JiShe.CollectBus.Common\JiShe.CollectBus.Common.csproj
call :PackProject shared\JiShe.CollectBus.Domain.Shared\JiShe.CollectBus.Domain.Shared.csproj
REM 打包 Services 项目
echo 打包 Services 项目...
call :PackProject services\JiShe.CollectBus.Domain\JiShe.CollectBus.Domain.csproj
call :PackProject services\JiShe.CollectBus.Application.Contracts\JiShe.CollectBus.Application.Contracts.csproj
call :PackProject services\JiShe.CollectBus.Application\JiShe.CollectBus.Application.csproj
call :PackProject services\JiShe.CollectBus.EntityFrameworkCore\JiShe.CollectBus.EntityFrameworkCore.csproj
@REM echo 打包 Services 项目...
@REM call :PackProject services\JiShe.CollectBus.Domain\JiShe.CollectBus.Domain.csproj
@REM call :PackProject services\JiShe.CollectBus.Application.Contracts\JiShe.CollectBus.Application.Contracts.csproj
@REM call :PackProject services\JiShe.CollectBus.Application\JiShe.CollectBus.Application.csproj
@REM call :PackProject services\JiShe.CollectBus.EntityFrameworkCore\JiShe.CollectBus.EntityFrameworkCore.csproj
echo.
echo 是否要发布包到 NuGet? (Y/N)
@ -58,7 +57,7 @@ if /i "%PUBLISH_CHOICE%"=="Y" (
echo 开始发布包...
for %%f in ("%OUTPUT_DIR%\*.nupkg") do (
echo 发布: %%f
dotnet nuget push "%%f" --api-key %API_KEY% --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push "%%f" --api-key %API_KEY% --source %SOURCE% --skip-duplicate
)
echo 所有包已发布完成!
) else (
@ -70,7 +69,7 @@ goto :eof
:PackProject
if exist "%~1" (
echo 打包: %~1
dotnet pack "%~1" -c %CONFIGURATION% --no-build --include-symbols -p:SymbolPackageFormat=snupkg -p:PackageVersion=%VERSION% -o "%OUTPUT_DIR%"
dotnet pack "%~1" -c %CONFIGURATION% --include-symbols -p:SymbolPackageFormat=snupkg -p:PackageVersion=%VERSION% -o "%OUTPUT_DIR%"
) else (
echo 警告: 项目不存在 - %~1
)

52
Temp.Dockerfile Normal file
View File

@ -0,0 +1,52 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
ENV TZ=Asia/Shanghai
ENV ASPNETCORE_ENVIRONMENT=Production
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
COPY ["publish/", "/app/publish"]
# # WORKDIR /src
# COPY ["JiShe.CollectBus.Main.sln", "."]
# COPY ["common.props", "."]
# COPY ["NuGet.Config", "."]
# COPY ["web/", "web/"]
# COPY ["modules/", "modules/"]
# COPY ["services/", "services/"]
# COPY ["shared/", "shared/"]
# COPY ["protocols/", "protocols/"]
# # 恢复项目依赖
# RUN dotnet restore "JiShe.CollectBus.Main.sln"
# # 构建项目
# WORKDIR "/web/JiShe.CollectBus.Host"
# RUN dotnet build "JiShe.CollectBus.Host.csproj" -c Release -o /app/build
# 发布项目
FROM build AS publish
# RUN dotnet publish "JiShe.CollectBus.Host.csproj" -c Release -o /app/publish /p:UseAppHost=false
# 创建最终镜像
FROM base AS final
WORKDIR /app
# 创建Plugins目录
RUN mkdir -p /app/Plugins
# 复制发布内容
COPY --from=publish /app/publish .
# 设置入口点
ENTRYPOINT ["dotnet", "JiShe.CollectBus.Host.dll"]
# 启动命令
# 可选:添加命令行参数
# CMD ["--urls", "http://+:80"]

View File

@ -0,0 +1,720 @@
using JiShe.CollectBus.Analyzers.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace JiShe.CollectBus.IncrementalGenerator
{
/// <summary>
/// 复杂类型增量源生成器
/// </summary>
[Generator(LanguageNames.CSharp)]
public class ComplexTypeSourceAnalyzers : IIncrementalGenerator
{
private const string AttributeFullName = "JiShe.CollectBus.Analyzers.Shared.SourceAnalyzersAttribute";
public void Initialize(IncrementalGeneratorInitializationContext context)
{
//Debugger.Launch();
// 步骤1筛选带有 [SourceAnalyzers] 的类
var classDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (s, _) => IsClassWithAttribute(s),
transform: static (ctx, _) => GetClassDeclaration(ctx))
.Where(static c => c is not null);
// 步骤2合并编译信息
var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect());
context.RegisterSourceOutput(compilationAndClasses, (spc, source) =>
GenerateCode(source.Left, source.Right!, spc));
}
private static bool IsClassWithAttribute(SyntaxNode node) => node is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0;
private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
var semanticModel = context.SemanticModel;
// 获取类符号
var classSymbol = semanticModel.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
if (classSymbol == null) return null;
// 检查是否包含 SourceAnalyzers 特性
var sourceAnalyzerAttr = classSymbol.GetAttributes().FirstOrDefault(attr => attr.AttributeClass?.ToDisplayString() == AttributeFullName);
// 必须包含 EntityType 参数
if (sourceAnalyzerAttr == null ||
sourceAnalyzerAttr.ConstructorArguments.Length == 0)
{
return null;
}
return classDecl;
//var classDecl = (ClassDeclarationSyntax)context.Node;
//var attributeType = context.SemanticModel.Compilation.GetTypeByMetadataName(AttributeFullName);
//foreach (var attribute in classDecl.AttributeLists.SelectMany(al => al.Attributes))
//{
// var symbol = context.SemanticModel.GetSymbolInfo(attribute).Symbol;
// if (symbol is IMethodSymbol ctor &&
// SymbolEqualityComparer.Default.Equals(ctor.ContainingType, attributeType))
// {
// return classDecl;
// }
//}
//return null;
}
/// <summary>
/// 递归获取所有层级的属性
/// </summary>
/// <param name="classSymbol"></param>
/// <returns></returns>
private static IEnumerable<IPropertySymbol> GetAllPropertiesInHierarchy(INamedTypeSymbol classSymbol)
{
var currentSymbol = classSymbol;
while (currentSymbol != null)
{
foreach (var prop in currentSymbol.GetMembers().OfType<IPropertySymbol>())
{
yield return prop;
}
currentSymbol = currentSymbol.BaseType; // 向上遍历基类
}
}
/// <summary>
/// 生成代码
/// </summary>
/// <param name="compilation"></param>
/// <param name="classes"></param>
/// <param name="context"></param>
private static void GenerateCode(
Compilation compilation,
IEnumerable<ClassDeclarationSyntax> classes,
SourceProductionContext context)
{
var processedTypes = new HashSet<ITypeSymbol>(SymbolEqualityComparer.Default);
if (!classes.Any())
{
context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor("GEN002", "没有目标类",
"没有找到SourceAnalyzers标记的类", "Debug", DiagnosticSeverity.Warning, true),
Location.None));
}
foreach (var classDecl in classes.Distinct())
{
var model = compilation.GetSemanticModel(classDecl.SyntaxTree);
var classSymbol = model.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
if (classSymbol == null || !processedTypes.Add(classSymbol))
{
context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor("GEN003", "无效符号",
$"类名称为{classDecl.Identifier.Text} 符号为空", "Error", DiagnosticSeverity.Error, true),
Location.None));
continue;
}
var code3 = BuildAccessorsForSourceEntity(classSymbol, compilation, processedTypes);
context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3);
}
// 生成工厂注册代码
context.AddSource("SourceEntityAccessorFactory.g.cs", BuildFactoryCode());
}
/// <summary>
/// 获取泛型参数
/// </summary>
/// <param name="symbol"></param>
/// <returns></returns>
public static string GetGenericParams(INamedTypeSymbol symbol)
{
if (!symbol.IsGenericType) return "";
var parameters = symbol.TypeParameters.Select(t => t.Name);
return $"<{string.Join(", ", parameters)}>";
}
/// <summary>
/// 生成标准属性的访问器
/// </summary>
/// <param name="prop"></param>
/// <param name="propType"></param>
/// <param name="code"></param>
private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code)
{
var parentType = prop.ContainingType.ToDisplayString();
code.AppendLine($" public static {propType.ToDisplayString()} Get{prop.Name}({parentType} obj) => obj.{prop.Name};");
if (prop.SetMethod != null)
{
code.AppendLine($" public static void Set{prop.Name}({parentType} obj, {propType.ToDisplayString()} value) => obj.{prop.Name} = value;");
}
}
/// <summary>
/// 构建实体访问器代码(支持泛型)
/// </summary>
private static string BuildAccessorsForSourceEntity(
INamedTypeSymbol classSymbol,
Compilation compilation,
HashSet<ITypeSymbol> processedTypes)
{
// 获取 SourceAnalyzers 特性的 EntityType 参数
var sourceAnalyzerAttr = classSymbol.GetAttributes()
.FirstOrDefault(attr =>
attr.AttributeClass?.ToDisplayString() == AttributeFullName);
// 解析 EntityType 枚举值
string entityTypeValue = "EntityTypeEnum.Other"; // 默认值
if (sourceAnalyzerAttr != null &&
sourceAnalyzerAttr.ConstructorArguments.Length > 0)
{
var arg = sourceAnalyzerAttr.ConstructorArguments[0];
if (arg.Kind == TypedConstantKind.Enum &&
arg.Type is INamedTypeSymbol enumType)
{
int enumValue = (int)arg.Value!;
entityTypeValue = GetEnumMemberName(enumType, enumValue);
}
}
var code = new StringBuilder();
code.AppendLine("// <auto-generated/>");
code.AppendLine("#nullable enable");
code.AppendLine("using System;");
code.AppendLine("using System.Reflection;");
code.AppendLine("using System.Collections.Generic;");
code.AppendLine("using JiShe.CollectBus.Analyzers.Shared;");
code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};");
code.AppendLine();
// 处理泛型类型名称
var accessibility = classSymbol.DeclaredAccessibility switch
{
Accessibility.Public => "public",
_ => "internal"
};
var genericParams = classSymbol.IsGenericType
? $"<{string.Join(", ", classSymbol.TypeParameters.Select(t => t.Name))}>"
: "";
code.AppendLine(
$"{accessibility} sealed class {classSymbol.Name}Accessor{genericParams} " + // 保留泛型参数
$": ISourceEntityAccessor<{classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>");
code.AppendLine("{");
var propList = GetAllPropertiesInHierarchy(classSymbol);
//类名称
code.AppendLine($" public string EntityName {{get;}} = \"{classSymbol.Name}\";");
// 添加 EntityType 属性
code.AppendLine($" public EntityTypeEnum? EntityType {{ get; }} = {entityTypeValue};");
foreach (var prop in propList)
{
// 安全类型转换
if (prop.Type is not ITypeSymbol propType) continue;
if (propType is INamedTypeSymbol namedType)
{
GenerateStandardAccessors(prop, namedType, code);
}
if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
{
GenerateTupleAccessors(prop, tupleType, code);
}
}
//生成当前类属性名称集合
GeneratePropertyListForSourceEntity(propList, code, compilation, classSymbol);
//生成当前类属性信息集合
GenerateEntityMemberInfoList(propList, code, compilation, classSymbol);
//生成当前类属性访问
GetGeneratePropertyValueForSourceEntity(propList, code, compilation, classSymbol);
//生成当前类属性设置
SetGeneratePropertyValueForSourceEntity(propList, code, compilation, classSymbol);
code.AppendLine("}");
return code.ToString();
}
/// <summary>
/// 生成ValueTuple元组属性访问器
/// </summary>
/// <param name="prop"></param>
/// <param name="tupleType"></param>
/// <param name="code"></param>
private static void GenerateTupleAccessors(
IPropertySymbol prop,
INamedTypeSymbol tupleType,
StringBuilder code)
{
var parentType = prop.ContainingType.ToDisplayString();
var tupleElements = tupleType.TupleElements;
for (int i = 0; i < tupleElements.Length; i++)
{
var element = tupleElements[i];
var elementType = element.Type.ToDisplayString();
var elementName = element.Name;
// Getter
code.AppendLine($"public static {elementType} Get{prop.Name}_{elementName}({parentType} obj) => obj.{prop.Name}.{elementName};");
// Setter
if (prop.SetMethod != null)
{
code.AppendLine($"public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType} value) => obj.{prop.Name} = ({string.Join(", ", GetTupleElements(prop.Name, tupleElements, i))});");
}
}
}
private static IEnumerable<string> GetTupleElements(
string propName,
ImmutableArray<IFieldSymbol> elements,
int targetIndex)
{
for (int i = 0; i < elements.Length; i++)
{
yield return i == targetIndex
? "value"
: $"obj.{propName}.{elements[i].Name}";
}
}
/// <summary>
/// 处理System.Tuple类型的访问器生成
/// </summary>
private static void GenerateSystemTupleAccessors(
IPropertySymbol prop,
INamedTypeSymbol tupleType,
StringBuilder code,
INamedTypeSymbol classSymbol)
{
var parentType = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var elementTypes = tupleType.TypeArguments;
var tupleTypeName = tupleType.ToDisplayString();
for (int i = 0; i < elementTypes.Length; i++)
{
var elementType = elementTypes[i].ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var elementName = $"Item{i + 1}";
// Getter
code.AppendLine(
$" public static {elementType} Get{prop.Name}_{elementName}" +
$"({parentType} obj) => obj.{prop.Name}.{elementName};");
// Setter
if (prop.SetMethod != null)
{
var assignments = elementTypes.Select((_, idx) =>
idx == i ? "value" : $"obj.{prop.Name}.Item{idx + 1}"
).ToList();
code.AppendLine(
$" public static void Set{prop.Name}_{elementName}" +
$"({parentType} obj, {elementType} value) => " +
$"obj.{prop.Name} = new {tupleTypeName}({string.Join(", ", assignments)});");
}
}
}
/// <summary>
/// 增强的工厂类实现
/// </summary>
private static string BuildFactoryCode()
{
return """
using System;
using System.Collections.Concurrent;
using System.Reflection;
namespace JiShe.CollectBus.Analyzers.Shared;
public static class SourceEntityAccessorFactory
{
private static readonly ConcurrentDictionary<Type, object> _accessors = new();
public static ISourceEntityAccessor<T> GetAccessor<T>()
{
return (ISourceEntityAccessor<T>)_accessors.GetOrAdd(typeof(T), t =>
{
// 获取泛型类型定义信息(如果是泛型类型)
var isGeneric = t.IsGenericType;
var genericTypeDef = isGeneric ? t.GetGenericTypeDefinition() : null;
var arity = isGeneric ? genericTypeDef!.GetGenericArguments().Length : 0;
// 构建访问器类名
var typeName = isGeneric
? $"{t.Namespace}.{genericTypeDef!.Name.Split('`')[0]}Accessor`{arity}"
: $"{t.Namespace}.{t.Name}Accessor";
// 尝试从当前程序集加载
var accessorType = Assembly.GetAssembly(t)!.GetType(typeName)
?? throw new InvalidOperationException($"Accessor type {typeName} not found");
// 处理泛型参数
if (isGeneric && accessorType.IsGenericTypeDefinition)
{
accessorType = accessorType.MakeGenericType(t.GetGenericArguments());
}
return Activator.CreateInstance(accessorType)!;
});
}
}
""";
}
/// <summary>
/// 属性访问生成逻辑
/// </summary>
/// <param name="propList">属性集合</param>
/// <param name="code"></param>
/// <param name="compilation"></param>
/// <param name="classSymbol"></param>
private static void GetGeneratePropertyValueForSourceEntity(
IEnumerable<IPropertySymbol> propList,
StringBuilder code,
Compilation compilation,
INamedTypeSymbol classSymbol)
{
code.AppendLine($" public object GetPropertyValue({classSymbol} targetEntity, string propertyName)");
code.AppendLine(" {");
code.AppendLine(" return propertyName switch");
code.AppendLine(" {");
foreach (var prop in propList)
{
code.AppendLine(
$" \"{prop.Name}\" => " +
$"Get{prop.Name}(targetEntity),");
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
{
foreach (var element in tupleType.TupleElements)
{
code.AppendLine(
$" \"{prop.Name}.{element.Name}\" => " +
$"Get{prop.Name}_{element.Name}(targetEntity),");
}
}
}
code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")");
code.AppendLine(" };");
code.AppendLine(" }");
}
/// <summary>
/// 属性设置生成逻辑
/// </summary>
/// <param name="propList">属性集合</param>
/// <param name="code"></param>
/// <param name="compilation"></param>
/// <param name="classSymbol"></param>
private static void SetGeneratePropertyValueForSourceEntity(
IEnumerable<IPropertySymbol> propList,
StringBuilder code,
Compilation compilation,
INamedTypeSymbol classSymbol)
{
code.AppendLine($" public void SetPropertyValue({classSymbol} targetEntity, string propertyName, object value)");
code.AppendLine(" {");
code.AppendLine(" switch (propertyName)");
code.AppendLine(" {");
foreach (var prop in propList)
{
var propType = prop.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
code.AppendLine($" case \"{prop.Name}\":");
code.AppendLine($" Set{prop.Name}(");
code.AppendLine($" targetEntity, ({propType})value);");
code.AppendLine(" break;");
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
{
foreach (var element in tupleType.TupleElements)
{
var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
code.AppendLine($" case \"{prop.Name}.{element.Name}\":");
code.AppendLine($" Set{prop.Name}_{element.Name}(");
code.AppendLine($" targetEntity, ({elementType})value);");
code.AppendLine(" break;");
}
}
}
code.AppendLine(" default:");
code.AppendLine(" throw new ArgumentException($\"Unknown property: {propertyName}\");");
code.AppendLine(" }");
code.AppendLine(" }");
}
/// <summary>
/// 属性名称集合
/// </summary>
/// <param name="propList">属性集合</param>
/// <param name="code"></param>
/// <param name="compilation"></param>
/// <param name="classSymbol"></param>
private static void GeneratePropertyListForSourceEntity(
IEnumerable<IPropertySymbol> propList,
StringBuilder code,
Compilation compilation,
INamedTypeSymbol classSymbol)
{
code.AppendLine(" public List<string> PropertyNameList {get;} = new List<string>()");
code.AppendLine(" {");
List<string> tempPropList = new List<string>();
foreach (var prop in propList)
{
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
{
foreach (var element in tupleType.TupleElements)
{
tempPropList.Add($"\"{prop.Name}.{element.Name}\"");
}
}
else
{
tempPropList.Add($"\"{prop.Name}\"");
}
}
code.Append(string.Join(",", tempPropList));
code.AppendLine(" };");
}
/// <summary>
/// 生成当前类属性信息集合
/// </summary>
private static void GenerateEntityMemberInfoList(
IEnumerable<IPropertySymbol> propList,
StringBuilder code,
Compilation compilation,
INamedTypeSymbol classSymbol)
{
code.AppendLine(" public List<EntityMemberInfo> MemberList { get; } = new()");
code.AppendLine(" {");
var initializerLines = new List<string>();
foreach (var prop in propList)
{
var entityType = prop.ContainingType.ToDisplayString();//entity 实体类型名称
var propType = prop.Type;//实体属性的类型
var propTypeName = propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
// var declaredTypeName = propType.Name; // 直接获取类型名称(如 "Int32"
// 处理可空类型,获取底层具体类型名称
var declaredTypeName = propType switch
{
INamedTypeSymbol { OriginalDefinition.SpecialType: SpecialType.System_Nullable_T } nullableType =>
nullableType.TypeArguments[0].Name, // 提取如 "Int32"
_ => propType.Name
};
// 处理主属性
var propAttributes = prop.GetAttributes()
.Where(a => !IsCompilerGeneratedAttribute(a))
.ToList();
var attributeInitializers = propAttributes
.Select(GenerateAttributeInitializer)
.Where(s => !string.IsNullOrEmpty(s));
var mainMember = new StringBuilder();
mainMember.Append(
$"new EntityMemberInfo(" +
$"\"{prop.Name}\", " +
$"typeof({propTypeName}), " +
$"\"{declaredTypeName}\", " +
$"(e) => Get{prop.Name}(({entityType})e), " +
$"(e, v) => Set{prop.Name}(({entityType})e, ({propTypeName})v))");
if (attributeInitializers.Any())
{
mainMember.AppendLine();
mainMember.Append(" { CustomAttributes = new List<Attribute>");
mainMember.Append($" {{ {string.Join(", ", attributeInitializers)} }} }}");
}
initializerLines.Add(mainMember.ToString());
// 处理元组元素,(暂不需要处理元组元素的特性)
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
{
foreach (var element in tupleType.TupleElements)
{
var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);//元组元素的类型
var elementName = element.Name;//元组元素名称
var elementDeclaredName = element.Type.Name;//元组元素类型名称
initializerLines.Add(
$"new EntityMemberInfo(" +
$"\"{prop.Name}.{elementName}\", " +
$"typeof({elementType}), " +
$"GetValueTupleElementDeclaredTypeName(typeof({elementType})), " +//$"\"{elementDeclaredName}\", " +
$"(e) => Get{prop.Name}_{elementName}(({entityType})e), " +
$"(e, v) => Set{prop.Name}_{elementName}(({entityType})e, ({elementType})v))");
}
}
}
code.AppendLine(string.Join(",\n", initializerLines));
code.AppendLine(" };");
code.AppendLine(GetValueTupleElementName());
}
private static string GetValueTupleElementName()
{
return """
public static string GetValueTupleElementDeclaredTypeName(Type declaredType)
{
string typeName;
// 处理可空类型
if (declaredType.IsGenericType && declaredType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
Type underlyingType = Nullable.GetUnderlyingType(declaredType);
typeName = underlyingType.Name;
}
else
{
typeName = declaredType.Name;
}
return typeName;
}
""";
}
private static string GenerateAttributeInitializer(AttributeData attribute)
{
if (attribute.AttributeClass == null)
return string.Empty;
var attributeClass = attribute.AttributeClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var args = attribute.ConstructorArguments;
var namedArgs = attribute.NamedArguments;
var parameters = new List<string>();
foreach (var arg in args)
{
parameters.Add(ConvertTypedConstantToCode(arg));
}
var constructorArgs = string.Join(", ", parameters);
var initializer = new StringBuilder();
initializer.Append($"new {attributeClass}({constructorArgs})");
if (namedArgs.Any())
{
initializer.Append(" { ");
var namedArgsList = namedArgs.Select(n => $"{n.Key} = {ConvertTypedConstantToCode(n.Value)}");
initializer.Append(string.Join(", ", namedArgsList));
initializer.Append(" }");
}
return initializer.ToString();
}
private static string ConvertTypedConstantToCode(TypedConstant constant)
{
if (constant.IsNull)
return "null";
switch (constant.Kind)
{
case TypedConstantKind.Array:
var elements = constant.Values.Select(ConvertTypedConstantToCode);
return $"new[] {{ {string.Join(", ", elements)} }}";
case TypedConstantKind.Type:
var typeSymbol = (ITypeSymbol)constant.Value!;
return $"typeof({typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)})";
case TypedConstantKind.Enum:
return ConvertEnumTypedConstant(constant);
default:
return ConvertPrimitiveConstant(constant);
}
}
private static string ConvertEnumTypedConstant(TypedConstant constant)
{
var enumType = constant.Type!;
var enumValue = constant.Value!;
var enumTypeName = enumType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
foreach (var member in enumType.GetMembers().OfType<IFieldSymbol>())
{
if (member.ConstantValue != null && member.ConstantValue.Equals(enumValue))
return $"{enumTypeName}.{member.Name}";
}
return $"({enumTypeName})({enumValue})";
}
private static string ConvertPrimitiveConstant(TypedConstant constant)
{
var value = constant.Value!;
return value switch
{
string s => $"\"{s}\"",
char c => $"'{c}'",
bool b => b ? "true" : "false",
_ => value.ToString()
};
}
private static bool IsCompilerGeneratedAttribute(AttributeData attribute)
{
return attribute.AttributeClass?.ToDisplayString() == "System.Runtime.CompilerServices.CompilerGeneratedAttribute";
}
/// <summary>
/// 获取枚举的参数
/// </summary>
/// <param name="enumType"></param>
/// <param name="value"></param>
/// <returns></returns>
private static string GetEnumMemberName(INamedTypeSymbol enumType, int value)
{
foreach (var member in enumType.GetMembers().OfType<IFieldSymbol>())
{
if (member.ConstantValue is int intValue && intValue == value)
{
return $"{enumType.ToDisplayString()}.{member.Name}";
}
}
return $"{enumType.ToDisplayString()}.Other";
}
}
}

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsRoslynComponent>true</IsRoslynComponent>
<NoPackageAnalysis>true</NoPackageAnalysis>
<ImportDirectoryBuildProps>false</ImportDirectoryBuildProps>
<BaseOutputPath>bin</BaseOutputPath>
<IncludeBuildOutput>false</IncludeBuildOutput>
<LangVersion>latest</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\shared\JiShe.CollectBus.Analyzers.Shared\JiShe.CollectBus.Analyzers.Shared.csproj" />
</ItemGroup>
</Project>

View File

@ -37,466 +37,6 @@ namespace JiShe.CollectBus.FreeRedis
Instance.Deserialize = (json, type) => BusJsonSerializer.Deserialize(json, type);
Instance.Notice += (s, e) => Trace.WriteLine(e.Log);
return Instance;
}
///// <summary>
///// 单个添加数据
///// </summary>
///// <typeparam name="T"></typeparam>
///// <param name="redisCacheKey">主数据存储Hash缓存Key</param>
///// <param name="redisCacheFocusIndexKey">集中器索引Set缓存Key</param>
///// <param name="redisCacheScoresIndexKey">集中器排序索引ZSET缓存Key</param>
///// <param name="redisCacheGlobalIndexKey">集中器采集频率分组全局索引ZSet缓存Key</param>
///// <param name="data">表计信息</param>
///// <param name="timestamp">可选时间戳</param>
///// <returns></returns>
//public async Task AddMeterCacheData<T>(
//string redisCacheKey,
//string redisCacheFocusIndexKey,
//string redisCacheScoresIndexKey,
//string redisCacheGlobalIndexKey,
//T data,
//DateTimeOffset? timestamp = null) where T : DeviceCacheBasicModel
//{
// // 参数校验增强
// if (data == null || string.IsNullOrWhiteSpace(redisCacheKey)
// || string.IsNullOrWhiteSpace(redisCacheFocusIndexKey)
// || string.IsNullOrWhiteSpace(redisCacheScoresIndexKey)
// || string.IsNullOrWhiteSpace(redisCacheGlobalIndexKey))
// {
// throw new ArgumentException($"{nameof(AddMeterCacheData)} 参数异常,-101");
// }
// // 计算组合score分类ID + 时间戳)
// var actualTimestamp = timestamp ?? DateTimeOffset.UtcNow;
// long scoreValue = ((long)data.FocusId << 32) | (uint)actualTimestamp.Ticks;
// //全局索引写入
// long globalScore = actualTimestamp.ToUnixTimeMilliseconds();
// // 使用事务保证原子性
// using (var trans = Instance.Multi())
// {
// // 主数据存储Hash
// trans.HSet(redisCacheKey, data.MemberID, data.Serialize());
// // 分类索引
// trans.SAdd(redisCacheFocusIndexKey, data.MemberID);
// // 排序索引使用ZSET
// trans.ZAdd(redisCacheScoresIndexKey, scoreValue, data.MemberID);
// //全局索引
// trans.ZAdd(redisCacheGlobalIndexKey, globalScore, data.MemberID);
// var results = trans.Exec();
// if (results == null || results.Length <= 0)
// throw new Exception($"{nameof(AddMeterCacheData)} 事务提交失败,-102");
// }
// await Task.CompletedTask;
//}
///// <summary>
///// 批量添加数据
///// </summary>
///// <typeparam name="T"></typeparam>
///// <param name="redisCacheKey">主数据存储Hash缓存Key</param>
///// <param name="redisCacheFocusIndexKey">集中器索引Set缓存Key</param>
///// <param name="redisCacheScoresIndexKey">集中器排序索引ZSET缓存Key</param>
///// <param name="redisCacheGlobalIndexKey">集中器采集频率分组全局索引ZSet缓存Key</param>
///// <param name="items">数据集合</param>
///// <param name="timestamp">可选时间戳</param>
///// <returns></returns>
//public async Task BatchAddMeterData<T>(
//string redisCacheKey,
//string redisCacheFocusIndexKey,
//string redisCacheScoresIndexKey,
//string redisCacheGlobalIndexKey,
//IEnumerable<T> items,
//DateTimeOffset? timestamp = null) where T : DeviceCacheBasicModel
//{
// if (items == null
// || items.Count() <=0
// || string.IsNullOrWhiteSpace(redisCacheKey)
// || string.IsNullOrWhiteSpace(redisCacheFocusIndexKey)
// || string.IsNullOrWhiteSpace(redisCacheScoresIndexKey)
// || string.IsNullOrWhiteSpace(redisCacheGlobalIndexKey))
// {
// throw new ArgumentException($"{nameof(BatchAddMeterData)} 参数异常,-101");
// }
// const int BATCH_SIZE = 1000; // 每批1000条
// var semaphore = new SemaphoreSlim(Environment.ProcessorCount * 2);
// foreach (var batch in items.Batch(BATCH_SIZE))
// {
// await semaphore.WaitAsync();
// _ = Task.Run(() =>
// {
// using (var pipe = Instance.StartPipe())
// {
// foreach (var item in batch)
// {
// // 计算组合score分类ID + 时间戳)
// var actualTimestamp = timestamp ?? DateTimeOffset.UtcNow;
// long scoreValue = ((long)item.FocusId << 32) | (uint)actualTimestamp.Ticks;
// //全局索引写入
// long globalScore = actualTimestamp.ToUnixTimeMilliseconds();
// // 主数据存储Hash
// pipe.HSet(redisCacheKey, item.MemberID, item.Serialize());
// // 分类索引Set
// pipe.SAdd(redisCacheFocusIndexKey, item.MemberID);
// // 排序索引使用ZSET
// pipe.ZAdd(redisCacheScoresIndexKey, scoreValue, item.MemberID);
// //全局索引
// pipe.ZAdd(redisCacheGlobalIndexKey, globalScore, item.MemberID);
// }
// pipe.EndPipe();
// }
// semaphore.Release();
// });
// }
// await Task.CompletedTask;
//}
///// <summary>
///// 删除指定redis缓存key的缓存数据
///// </summary>
///// <typeparam name="T"></typeparam>
///// <param name="redisCacheKey">主数据存储Hash缓存Key</param>
///// <param name="redisCacheFocusIndexKey">集中器索引Set缓存Key</param>
///// <param name="redisCacheScoresIndexKey">集中器排序索引ZSET缓存Key</param>
///// <param name="redisCacheGlobalIndexKey">集中器采集频率分组全局索引ZSet缓存Key</param>
///// <param name="data">表计信息</param>
///// <returns></returns>
//public async Task RemoveMeterData<T>(
//string redisCacheKey,
//string redisCacheFocusIndexKey,
//string redisCacheScoresIndexKey,
//string redisCacheGlobalIndexKey,
//T data) where T : DeviceCacheBasicModel
//{
// if (data == null
// || string.IsNullOrWhiteSpace(redisCacheKey)
// || string.IsNullOrWhiteSpace(redisCacheFocusIndexKey)
// || string.IsNullOrWhiteSpace(redisCacheScoresIndexKey)
// || string.IsNullOrWhiteSpace(redisCacheGlobalIndexKey))
// {
// throw new ArgumentException($"{nameof(RemoveMeterData)} 参数异常,-101");
// }
// const string luaScript = @"
// local mainKey = KEYS[1]
// local focusIndexKey = KEYS[2]
// local scoresIndexKey = KEYS[3]
// local globalIndexKey = KEYS[4]
// local member = ARGV[1]
// local deleted = 0
// if redis.call('HDEL', mainKey, member) > 0 then
// deleted = 1
// end
// redis.call('SREM', focusIndexKey, member)
// redis.call('ZREM', scoresIndexKey, member)
// redis.call('ZREM', globalIndexKey, member)
// return deleted
// ";
// var keys = new[]
// {
// redisCacheKey,
// redisCacheFocusIndexKey,
// redisCacheScoresIndexKey,
// redisCacheGlobalIndexKey
// };
// var result = await Instance.EvalAsync(luaScript, keys, new[] { data.MemberID });
// if ((int)result == 0)
// throw new KeyNotFoundException("指定数据不存在");
//}
///// <summary>
///// 修改表计缓存信息
///// </summary>
///// <typeparam name="T"></typeparam>
///// <param name="redisCacheKey">主数据存储Hash缓存Key</param>
///// <param name="oldRedisCacheFocusIndexKey">旧集中器索引Set缓存Key</param>
///// <param name="newRedisCacheFocusIndexKey">新集中器索引Set缓存Key</param>
///// <param name="redisCacheScoresIndexKey">集中器排序索引ZSET缓存Key</param>
///// <param name="redisCacheGlobalIndexKey">集中器采集频率分组全局索引ZSet缓存Key</param>
///// <param name="newData">表计信息</param>
///// <param name="newTimestamp">可选时间戳</param>
///// <returns></returns>
//public async Task UpdateMeterData<T>(
//string redisCacheKey,
//string oldRedisCacheFocusIndexKey,
//string newRedisCacheFocusIndexKey,
//string redisCacheScoresIndexKey,
//string redisCacheGlobalIndexKey,
//T newData,
//DateTimeOffset? newTimestamp = null) where T : DeviceCacheBasicModel
//{
// if (newData == null
// || string.IsNullOrWhiteSpace(redisCacheKey)
// || string.IsNullOrWhiteSpace(oldRedisCacheFocusIndexKey)
// || string.IsNullOrWhiteSpace(newRedisCacheFocusIndexKey)
// || string.IsNullOrWhiteSpace(redisCacheScoresIndexKey)
// || string.IsNullOrWhiteSpace(redisCacheGlobalIndexKey))
// {
// throw new ArgumentException($"{nameof(UpdateMeterData)} 参数异常,-101");
// }
// var luaScript = @"
// local mainKey = KEYS[1]
// local oldFocusIndexKey = KEYS[2]
// local newFocusIndexKey = KEYS[3]
// local scoresIndexKey = KEYS[4]
// local globalIndexKey = KEYS[5]
// local member = ARGV[1]
// local newData = ARGV[2]
// local newScore = ARGV[3]
// local newGlobalScore = ARGV[4]
// -- 校验存在性
// if redis.call('HEXISTS', mainKey, member) == 0 then
// return 0
// end
// -- 更新主数据
// redis.call('HSET', mainKey, member, newData)
// -- 处理变更
// if newScore ~= '' then
// -- 删除旧索引
// redis.call('SREM', oldFocusIndexKey, member)
// redis.call('ZREM', scoresIndexKey, member)
// -- 添加新索引
// redis.call('SADD', newFocusIndexKey, member)
// redis.call('ZADD', scoresIndexKey, newScore, member)
// end
// -- 更新全局索引
// if newGlobalScore ~= '' then
// -- 删除旧索引
// redis.call('ZREM', globalIndexKey, member)
// -- 添加新索引
// redis.call('ZADD', globalIndexKey, newGlobalScore, member)
// end
// return 1
// ";
// var actualTimestamp = newTimestamp ?? DateTimeOffset.UtcNow;
// var newGlobalScore = actualTimestamp.ToUnixTimeMilliseconds();
// var newScoreValue = ((long)newData.FocusId << 32) | (uint)actualTimestamp.Ticks;
// var result = await Instance.EvalAsync(luaScript,
// new[]
// {
// redisCacheKey,
// oldRedisCacheFocusIndexKey,
// newRedisCacheFocusIndexKey,
// redisCacheScoresIndexKey,
// redisCacheGlobalIndexKey
// },
// new object[]
// {
// newData.MemberID,
// newData.Serialize(),
// newScoreValue.ToString() ?? "",
// newGlobalScore.ToString() ?? ""
// });
// if ((int)result == 0)
// {
// throw new KeyNotFoundException($"{nameof(UpdateMeterData)}指定Key{redisCacheKey}的数据不存在");
// }
//}
//public async Task<BusPagedResult<T>> SingleGetMeterPagedData<T>(
//string redisCacheKey,
//string redisCacheScoresIndexKey,
//int focusId,
//int pageSize = 10,
//int pageIndex = 1,
//bool descending = true)
//{
// // 计算score范围
// long minScore = (long)focusId << 32;
// long maxScore = ((long)focusId + 1) << 32;
// // 分页参数计算
// int start = (pageIndex - 1) * pageSize;
// // 获取排序后的member列表
// var members = descending
// ? await Instance.ZRevRangeByScoreAsync(
// redisCacheScoresIndexKey,
// maxScore,
// minScore,
// start,
// pageSize)
// : await Instance.ZRangeByScoreAsync(
// redisCacheScoresIndexKey,
// minScore,
// maxScore,
// start,
// pageSize);
// // 批量获取实际数据
// var dataTasks = members.Select(m =>
// Instance.HGetAsync<T>(redisCacheKey, m)).ToArray();
// await Task.WhenAll(dataTasks);
// // 总数统计优化
// var total = await Instance.ZCountAsync(
// redisCacheScoresIndexKey,
// minScore,
// maxScore);
// return new BusPagedResult<T>
// {
// Items = dataTasks.Select(t => t.Result).ToList(),
// TotalCount = total,
// PageIndex = pageIndex,
// PageSize = pageSize
// };
//}
//public async Task<BusPagedResult<T>> GetFocusPagedData<T>(
//string redisCacheKey,
//string redisCacheScoresIndexKey,
//int focusId,
//int pageSize = 10,
//long? lastScore = null,
//string lastMember = null,
//bool descending = true) where T : DeviceCacheBasicModel
//{
// // 计算分数范围
// long minScore = (long)focusId << 32;
// long maxScore = ((long)focusId + 1) << 32;
// // 获取成员列表
// var members = await GetSortedMembers(
// redisCacheScoresIndexKey,
// minScore,
// maxScore,
// pageSize,
// lastScore,
// lastMember,
// descending);
// // 批量获取数据
// var dataDict = await Instance.HMGetAsync<T>(redisCacheKey, members.CurrentItems);
// return new BusPagedResult<T>
// {
// Items = dataDict,
// TotalCount = await GetTotalCount(redisCacheScoresIndexKey, minScore, maxScore),
// HasNext = members.HasNext,
// NextScore = members.NextScore,
// NextMember = members.NextMember
// };
//}
//private async Task<(string[] CurrentItems, bool HasNext, decimal? NextScore, string NextMember)>
// GetSortedMembers(
// string zsetKey,
// long minScore,
// long maxScore,
// int pageSize,
// long? lastScore,
// string lastMember,
// bool descending)
//{
// var querySize = pageSize + 1;
// var (startScore, exclude) = descending
// ? (lastScore ?? maxScore, lastMember)
// : (lastScore ?? minScore, lastMember);
// var members = descending
// ? await Instance.ZRevRangeByScoreAsync(
// zsetKey,
// max: startScore,
// min: minScore,
// offset: 0,
// count: querySize)
// : await Instance.ZRangeByScoreAsync(
// zsetKey,
// min: startScore,
// max: maxScore,
// offset: 0,
// count: querySize);
// var hasNext = members.Length > pageSize;
// var currentItems = members.Take(pageSize).ToArray();
// var nextCursor = currentItems.Any()
// ? await GetNextCursor(zsetKey, currentItems.Last(), descending)
// : (null, null);
// return (currentItems, hasNext, nextCursor.score, nextCursor.member);
//}
//private async Task<long> GetTotalCount(string zsetKey, long min, long max)
//{
// // 缓存计数优化
// var cacheKey = $"{zsetKey}_count_{min}_{max}";
// var cached = await Instance.GetAsync<long?>(cacheKey);
// if (cached.HasValue)
// return cached.Value;
// var count = await Instance.ZCountAsync(zsetKey, min, max);
// await Instance.SetExAsync(cacheKey, 60, count); // 缓存60秒
// return count;
//}
//public async Task<Dictionary<int, BusPagedResult<T>>> BatchGetMeterPagedData<T>(
//string redisCacheKey,
//string redisCacheScoresIndexKey,
//IEnumerable<int> focusIds,
//int pageSizePerFocus = 10) where T : DeviceCacheBasicModel
//{
// var results = new ConcurrentDictionary<int, BusPagedResult<T>>();
// var parallelOptions = new ParallelOptions
// {
// MaxDegreeOfParallelism = Environment.ProcessorCount * 2
// };
// await Parallel.ForEachAsync(focusIds, parallelOptions, async (focusId, _) =>
// {
// var data = await SingleGetMeterPagedData<T>(
// redisCacheKey,
// redisCacheScoresIndexKey,
// focusId,
// pageSizePerFocus);
// results.TryAdd(focusId, data);
// });
// return new Dictionary<int, BusPagedResult<T>>(results);
//}
}
}
}

View File

@ -1,19 +0,0 @@
using JiShe.CollectBus.IoTDB.Enums;
namespace JiShe.CollectBus.IoTDB.Attribute
{
/// <summary>
/// IoTDB实体类型特性
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class EntityTypeAttribute : System.Attribute
{
public EntityTypeEnum EntityType { get; }
public EntityTypeAttribute(EntityTypeEnum entityType)
{
EntityType = entityType;
}
}
}

View File

@ -1,4 +1,4 @@
namespace JiShe.CollectBus.IoTDB.Attribute
namespace JiShe.CollectBus.IoTDB.Attributes
{
/// <summary>
/// Column分类标记特性ATTRIBUTE字段,也就是属性字段

View File

@ -1,4 +1,4 @@
namespace JiShe.CollectBus.IoTDB.Attribute
namespace JiShe.CollectBus.IoTDB.Attributes
{
/// <summary>
/// Column分类标记特性FIELD字段数据列字段

View File

@ -1,4 +1,4 @@
namespace JiShe.CollectBus.IoTDB.Attribute
namespace JiShe.CollectBus.IoTDB.Attributes
{
/// <summary>
/// 用于标识当前实体为单侧点模式单侧点模式只有一个Filed标识字段,类型是Tuple<string,T>,Item1=>测点名称Item2=>测点值,泛型

View File

@ -1,4 +1,4 @@
namespace JiShe.CollectBus.IoTDB.Attribute
namespace JiShe.CollectBus.IoTDB.Attributes
{
/// <summary>
/// Column分类标记特性TAG字段标签字段

View File

@ -1,6 +1,5 @@
using JiShe.CollectBus.IoTDB.Enums;
namespace JiShe.CollectBus.IoTDB.Attribute

namespace JiShe.CollectBus.IoTDB.Attributes
{
/// <summary>
/// IoTDB实体存储路径或表名称一般用于已经明确的存储路径或表名称例如日志存储

View File

@ -7,7 +7,7 @@ namespace JiShe.CollectBus.IoTDB.Context
/// <summary>
/// IoTDB SessionPool 运行时上下文
/// </summary>
public class IoTDBRuntimeContext: IScopedDependency
public class IoTDBRuntimeContext: IScopedDependency//ITransientDependency
{
private readonly bool _defaultValue;

View 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;
}
}
}

View File

@ -16,6 +16,8 @@ namespace JiShe.CollectBus.IoTDB.Interface
///// <param name="useTableSession">是否使用表模型</param>
//void SwitchSessionPool(bool useTableSession);
IIoTDbProvider GetSessionPool(bool sessionpolType);
/// <summary>
/// 插入数据
/// </summary>

View File

@ -1,15 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Apache.IoTDB" Version="2.0.2" />
<PackageReference Include="Volo.Abp" Version="8.3.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\shared\JiShe.CollectBus.Common\JiShe.CollectBus.Common.csproj" />
<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" />
</ItemGroup>
</Project>

View File

@ -1,9 +1,12 @@
using JiShe.CollectBus.IoTDB.Attribute;
using JiShe.CollectBus.Common.Attributes;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.IoTDB.Attributes;
using Volo.Abp.Domain.Entities;
namespace JiShe.CollectBus.IoTDB.Model
{
/// <summary>
/// IoT实体基类此类适用于多个数据测点记录场景单个测点请使用子类 SingleMeasuring
/// IoT实体基类此类适用于多个数据测点记录场景单个测点请使用子类 SingleMeasuring,新增字段只能现有字段末尾添加,否则会导致数据写入失败。
/// </summary>
public abstract class IoTEntity
{
@ -19,6 +22,12 @@ namespace JiShe.CollectBus.IoTDB.Model
[TAGColumn]
public string ProjectId { get; set; }
/// <summary>
/// 数据类型
/// </summary>
[TAGColumn]
public string DataType { get; set; } = IOTDBDataTypeConst.Data;
/// <summary>
/// 设备类型集中器、电表、水表、流量计、传感器等
/// </summary>
@ -35,5 +44,29 @@ namespace JiShe.CollectBus.IoTDB.Model
/// 时标,也就是业务时间戳,单位毫秒,必须通过DateTimeOffset获取
/// </summary>
public long Timestamps { get; set; } = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
/// <summary>
/// 设备路径
/// </summary>
private string _devicePath;
/// <summary>
/// 设备路径
/// </summary>
public virtual string DevicePath
{
get
{
// 如果未手动设置路径,则自动生成
if (string.IsNullOrWhiteSpace(_devicePath))
{
return $"root.{SystemName.ToLower()}.`{ProjectId}`.`{DeviceType}`.{DataType}.`{DeviceId}`";
}
return _devicePath;
}
set
{
_devicePath = value; // 直接赋值给支持字段,避免递归
}
}
}
}

View File

@ -1,24 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JiShe.CollectBus.IoTDB.Attribute;
using JiShe.CollectBus.IoTDB.Enums;
using JiShe.CollectBus.IoTDB.Provider;
using JiShe.CollectBus.Analyzers.Shared;
using JiShe.CollectBus.IoTDB.Attributes;
namespace JiShe.CollectBus.IoTDB.Model
{
/// <summary>
/// Table模型单项数据实体
/// </summary>
[EntityType(EntityTypeEnum.TableModel)]
/// </summary>
[SourceAnalyzers(EntityTypeEnum.TableModel)]
public class TableModelSingleMeasuringEntity<T> : IoTEntity
{
/// <summary>
/// 单项数据键值对
/// </summary>
[SingleMeasuring(nameof(SingleColumn))]
public required Tuple<string, T> SingleColumn { get; set; }
public required ValueTuple<string, T> SingleColumn { get; set; }
}
}

View File

@ -1,24 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JiShe.CollectBus.IoTDB.Attribute;
using JiShe.CollectBus.IoTDB.Enums;
using JiShe.CollectBus.IoTDB.Provider;
using JiShe.CollectBus.Analyzers.Shared;
using JiShe.CollectBus.IoTDB.Attributes;
namespace JiShe.CollectBus.IoTDB.Model
{
/// <summary>
/// Tree模型单项数据实体
/// </summary>
[EntityType(EntityTypeEnum.TreeModel)]
[SourceAnalyzers(EntityTypeEnum.TreeModel)]
public class TreeModelSingleMeasuringEntity<T> : IoTEntity
{
/// <summary>
/// 单项数据键值对
/// </summary>
[SingleMeasuring(nameof(SingleMeasuring))]
public required Tuple<string, T> SingleMeasuring { get; set; }
public required ValueTuple<string, T> SingleMeasuring { get; set; }
}
}

View File

@ -26,7 +26,7 @@
/// <summary>
/// 连接池大小
/// </summary>
public int PoolSize { get; set; } = 2;
public int PoolSize { get; set; } = 8;
/// <summary>
/// 查询时每次查询的数据量默认1024

View File

@ -1,4 +1,7 @@
namespace JiShe.CollectBus.IoTDB.Options
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
namespace JiShe.CollectBus.IoTDB.Options
{
/// <summary>
/// 查询条件
@ -19,10 +22,43 @@
/// 是否数值,如果是数值,则进行数值比较,否则进行字符串比较
/// </summary>
public bool IsNumber { get; set; } = false;
private object _rawValue;
/// <summary>
/// 值
/// </summary>
public object Value { get; set; }
public object Value
{
get => ApplyValueConversion(_rawValue);
set => _rawValue = value;
}
/// <summary>
/// 值转换
/// </summary>
/// <param name="rawValue"></param>
/// <returns></returns>
private object ApplyValueConversion(object rawValue)
{
string declaredTypeName = rawValue.GetType().Name;
Func<object, object> converter = GetQueryConditionValue(declaredTypeName);
return converter(rawValue);
}
/// <summary>
/// 查询条件值转换委托
/// </summary>
/// <param name="declaredTypeName"></param>
/// <returns></returns>
private Func<object, object> GetQueryConditionValue(string declaredTypeName)
{
return declaredTypeName?.ToUpper() switch
{
"DATETIME" => v => v != null ? ((DateTime)v).ToUniversalTime().Ticks : null,
"STRING" => v => v != null ? $"'{v}'" : "''",
_ => v => v
};
}
}
}

View File

@ -1,17 +1,27 @@
using Apache.IoTDB;
using JiShe.CollectBus.IoTDB.Enums;
using JiShe.CollectBus.Analyzers.Shared;
namespace JiShe.CollectBus.IoTDB.Provider
{
/// <summary>
/// 设备元数据
/// </summary>
public class DeviceMetadata
public sealed class DeviceMetadata
{
/// <summary>
/// IoTDB实体类型枚举
/// 实体类名称
/// </summary>
public EntityTypeEnum EntityType { get; set; }
public string EntityName { get; set; }
/// <summary>
/// 设备表名或树路径如果实体没有添加TableNameOrTreePath,此处为空
/// </summary>
public string TableNameOrTreePath { get; set; }
/// <summary>
/// 实体类型枚举
/// </summary>
public EntityTypeEnum? EntityType { get; set; }
/// <summary>
/// 是否有单测量值
@ -31,6 +41,57 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// <summary>
/// 值类型集合用于构建Table的值类型也就是dataTypes参数
/// </summary>
public List<TSDataType> DataTypes { get; } = new();
public List<TSDataType> DataTypes { get; set; } = new();
/// <summary>
/// 列处理信息集合
/// </summary>
public List<ColumnProcessor> Processors { get; } = new List<ColumnProcessor>();
}
/// <summary>
/// 列处理信息结构
/// </summary>
public struct ColumnProcessor
{
/// <summary>
/// 列名
/// </summary>
public string ColumnName;
/// <summary>
/// 数据类型
/// </summary>
public TSDataType TSDataType { get; set;}
/// <summary>
/// 值获取委托(参数:实体对象)
/// </summary>
public Func<object, object> ValueGetter;
/// <summary>
/// 值设置委托(参数:实体对象,新值)
/// </summary>
public Action<object, object> ValueSetter;
/// <summary>
/// 类型转换委托
/// </summary>
public Func<object, object> GetConverter;
/// <summary>
/// 类型转换委托
/// </summary>
public Func<object, object> SetConverter;
/// <summary>
/// 是否单测点
/// </summary>
public bool IsSingleMeasuring;
/// <summary>
/// 单测点名称委托
/// </summary>
public Func<object, object> SingleMeasuringNameGetter;
}
}

View File

@ -15,7 +15,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// <returns></returns>
public static string GetDevicePath<T>(T entity) where T : IoTEntity
{
return $"root.{entity.SystemName.ToLower()}.`{entity.ProjectId}`.`{entity.DeviceType}`.`{entity.DeviceId}`";
return $"root.{entity.SystemName.ToLower()}.`{entity.ProjectId}`.`{entity.DeviceType}`.{entity.DataType}.`{entity.DeviceId}`";
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Text;
@ -11,7 +12,7 @@ using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Common.Models;
using JiShe.CollectBus.IoTDB.Attribute;
using JiShe.CollectBus.IoTDB.Attributes;
using JiShe.CollectBus.IoTDB.Context;
using JiShe.CollectBus.IoTDB.Interface;
using JiShe.CollectBus.IoTDB.Model;
@ -19,6 +20,12 @@ using JiShe.CollectBus.IoTDB.Options;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
using JiShe.CollectBus.Analyzers.Shared;
using JiShe.CollectBus.IoTDB.Exceptions;
using System.Diagnostics.Metrics;
using Newtonsoft.Json.Linq;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Text.RegularExpressions;
namespace JiShe.CollectBus.IoTDB.Provider
{
@ -29,11 +36,22 @@ namespace JiShe.CollectBus.IoTDB.Provider
{
private static readonly ConcurrentDictionary<Type, DeviceMetadata> MetadataCache = new();
private readonly ILogger<IoTDbProvider> _logger;
private readonly IIoTDbSessionFactory _sessionFactory;
private readonly IoTDBRuntimeContext _runtimeContext;
private readonly IIoTDbSessionFactory _sessionFactory;
/// <summary>
/// 存储模型切换标识是否使用table模型存储, 默认为false标识tree模型存储
/// </summary>
public bool UseTableSessionPool { get; set; }
private IIoTDbSessionPool CurrentSession { get; set; }
public IIoTDbProvider GetSessionPool(bool useTableSessionPool)
{
CurrentSession = _sessionFactory.GetSessionPool(useTableSessionPool);
UseTableSessionPool = useTableSessionPool;
return this;
}
private IIoTDbSessionPool CurrentSession =>
_sessionFactory.GetSessionPool(_runtimeContext.UseTableSessionPool);
/// <summary>
/// IoTDbProvider
@ -43,12 +61,10 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// <param name="runtimeContext"></param>
public IoTDbProvider(
ILogger<IoTDbProvider> logger,
IIoTDbSessionFactory sessionFactory,
IoTDBRuntimeContext runtimeContext)
IIoTDbSessionFactory sessionFactory)
{
_logger = logger;
_sessionFactory = sessionFactory;
_runtimeContext = runtimeContext;
}
@ -65,12 +81,18 @@ namespace JiShe.CollectBus.IoTDB.Provider
var metadata = await GetMetadata<T>();
var tablet = BuildTablet(new[] { entity }, metadata);
if (tablet == null || tablet.Count <= 0)
{
_logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 tablet 为null");
return;
}
_logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 路径为 {tablet.First().InsertTargetName}");
await CurrentSession.InsertAsync(tablet);
await CurrentSession.InsertAsync(tablet.First());
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(InsertAsync)} 插入数据时发生异常");
_logger.LogError(ex, $"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时发生异常");
throw;
}
}
@ -84,6 +106,11 @@ namespace JiShe.CollectBus.IoTDB.Provider
{
try
{
if (entities == null || entities.Count() <= 0)
{
_logger.LogError($"{nameof(BatchInsertAsync)} 参数异常,-101");
return;
}
var metadata = await GetMetadata<T>();
var batchSize = 1000;
@ -92,12 +119,23 @@ namespace JiShe.CollectBus.IoTDB.Provider
foreach (var batch in batches)
{
var tablet = BuildTablet(batch, metadata);
await CurrentSession.InsertAsync(tablet);
if (tablet == null || tablet.Count <= 0)
{
_logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 tablet 为null");
return;
}
foreach (var item in tablet)
{
_logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 路径为 {item.InsertTargetName}");
await CurrentSession.InsertAsync(item);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(BatchInsertAsync)} 批量插入数据时发生异常");
_logger.LogError(ex, $"{nameof(BatchInsertAsync)} IoTDB批量插入{typeof(T).Name}的数据时发生异常");
throw;
}
}
@ -112,20 +150,27 @@ namespace JiShe.CollectBus.IoTDB.Provider
public async Task BatchInsertAsync<T>(DeviceMetadata deviceMetadata, IEnumerable<T> entities) where T : IoTEntity
{
try
{
{
var batchSize = 1000;
var batches = entities.Chunk(batchSize);
foreach (var batch in batches)
{
var tablet = BuildTablet(batch, deviceMetadata);
await CurrentSession.InsertAsync(tablet);
if (tablet == null || tablet.Count <= 0)
{
_logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 tablet 为null");
return;
}
foreach (var item in tablet)
{
await CurrentSession.InsertAsync(item);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(BatchInsertAsync)} 批量插入数据时发生异常");
_logger.LogError(ex, $"{nameof(BatchInsertAsync)} IoTDB批量插入{typeof(T).Name}的数据时发生异常");
throw;
}
}
@ -142,21 +187,28 @@ namespace JiShe.CollectBus.IoTDB.Provider
try
{
var query = await BuildDeleteSQL<T>(options);
var sessionDataSet = await CurrentSession.ExecuteQueryStatementAsync(query);
var result = await CurrentSession.ExecuteQueryStatementAsync(query);
if (!sessionDataSet.HasNext())
if (result == null)
{
_logger.LogWarning($"{typeof(T).Name} 删除数据时,没有返回受影响记录数量。");
return 0;
}
if (!result.HasNext())
{
_logger.LogWarning($"{typeof(T).Name} IoTDB删除{typeof(T).Name}的数据时,没有返回受影响记录数量。");
return 0;
}
//获取唯一结果行
var row = sessionDataSet.Next();
return row.Values[0];
var row = result.Next();
await result.Close();
var dataResult = row.Values[0];
return dataResult;
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(DeleteAsync)} 删除数据时发生异常");
_logger.LogError(ex, $"{nameof(DeleteAsync)} IoTDB删除{typeof(T).Name}的数据时发生异常");
throw;
}
}
@ -168,22 +220,58 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// <returns></returns>
public async Task<DeviceMetadata> GetMetadata<T>() where T : IoTEntity
{
var columns = CollectColumnMetadata(typeof(T));
var metadata = BuildDeviceMetadata<T>(columns);
var accessor = SourceEntityAccessorFactory.GetAccessor<T>();
var columns = CollectColumnMetadata<T>(accessor);
var tmpMetadata = BuildDeviceMetadata<T>(columns, accessor);
string tableNameOrTreePath = string.Empty;
var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute<TableNameOrTreePathAttribute>();
if (tableNameOrTreePathAttribute != null)
{
tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath;
}
tmpMetadata.EntityName = accessor.EntityName;
tmpMetadata.EntityType = accessor.EntityType;
tmpMetadata.TableNameOrTreePath = tableNameOrTreePath;
var metaData = MetadataCache.AddOrUpdate(
typeof(T),
addValueFactory: t => metadata, // 如果键不存在,用此值添加
addValueFactory: t => tmpMetadata, // 如果键不存在,用此值添加
updateValueFactory: (t, existingValue) =>
{
var columns = CollectColumnMetadata(t);
var metadata = BuildDeviceMetadata<T>(columns);
var columns = CollectColumnMetadata(accessor);
var metadata = BuildDeviceMetadata(columns, accessor);
//对现有值 existingValue 进行修改,返回新值
string tableNameOrTreePath = string.Empty;
var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute<TableNameOrTreePathAttribute>();
if (tableNameOrTreePathAttribute != null)
{
tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath;
}
existingValue.ColumnNames = metadata.ColumnNames;
existingValue.DataTypes = metadata.DataTypes;
return existingValue;
}
);
//var metaData = MetadataCache.GetOrAdd(typeof(T), type =>
//{
// var columns = CollectColumnMetadata(accessor);
// var metadata = BuildDeviceMetadata(columns, accessor);
// string tableNameOrTreePath = string.Empty;
// var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute<TableNameOrTreePathAttribute>();
// if (tableNameOrTreePathAttribute != null)
// {
// tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath;
// }
// metadata.EntityName = accessor.EntityName;
// metadata.EntityType = accessor.EntityType;
// metadata.TableNameOrTreePath = tableNameOrTreePath;
// return metadata;
//});
return await Task.FromResult(metaData);
}
@ -197,6 +285,8 @@ namespace JiShe.CollectBus.IoTDB.Provider
{
try
{
var stopwatch2 = Stopwatch.StartNew();
var query = await BuildQuerySQL<T>(options);
var sessionDataSet = await CurrentSession.ExecuteQueryStatementAsync(query);
@ -209,15 +299,27 @@ namespace JiShe.CollectBus.IoTDB.Provider
PageSize = options.PageSize,
};
stopwatch2.Stop();
result.HasNext = result.TotalCount > 0 ? result.TotalCount < result.PageSize : false;
//int totalPageCount = (int)Math.Ceiling((double)result.TotalCount / options.PageSize);
if (result.Items.Count() < result.PageSize)
{
result.HasNext = false;
}
else
{
result.HasNext = true;
}
//result.HasNext = result.Items.Count() > 0 ? result.Items.Count() < result.PageSize : false;
return result;
}
catch (Exception ex)
{
CurrentSession.Dispose();
_logger.LogError(ex, $"{nameof(QueryAsync)} IoTDB查询数据时发生异常");
_logger.LogError(ex, $"{nameof(QueryAsync)} IoTDB查询{typeof(T).Name}的数据时发生异常");
throw;
}
}
@ -229,157 +331,117 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// <param name="entities">表实体</param>
/// <param name="metadata">设备元数据</param></param>
/// <returns></returns>
private Tablet BuildTablet<T>(IEnumerable<T> entities, DeviceMetadata metadata) where T : IoTEntity
private List<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 entitiyList = entities.ToList();
if (entitiyList == null || entitiyList.Count <= 0)
{
return null;
}
var entityTypeAttribute = typeof(T).GetCustomAttribute<EntityTypeAttribute>();
if (entityTypeAttribute == null)
if (metadata.EntityType == null)
{
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 没有指定,属于异常情况,-101");
}
if (metadata.EntityType != entityTypeAttribute.EntityType)
if (metadata.EntityType == EntityTypeEnum.Other)
{
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 和{nameof(DeviceMetadata)}的 EntityType 不一致,属于异常情况,-102");
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 不属于IoTDB数据模型实体,属于异常情况,-102");
}
if (metadata.EntityType == Enums.EntityTypeEnum.TreeModel && _runtimeContext.UseTableSessionPool == true)
if (metadata.EntityType == EntityTypeEnum.TreeModel && UseTableSessionPool == true)
{
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 tree模型不能使用table模型Session连接属于异常情况-103");
}
else if (metadata.EntityType == Enums.EntityTypeEnum.TableModel && _runtimeContext.UseTableSessionPool == false)
else if (metadata.EntityType == EntityTypeEnum.TableModel && UseTableSessionPool == false)
{
throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接属于异常情况-104");
throw new Exception($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接属于异常情况-104");
}
string tableNameOrTreePath = string.Empty;
var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute<TableNameOrTreePathAttribute>();
if (tableNameOrTreePathAttribute != null)
if ( UseTableSessionPool)//表模型
{
tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath;
}
foreach (var entity in entities)
{
timestamps.Add(entity.Timestamps);
var rowValues = new List<object>();
foreach (var measurement in tempColumnNames)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(measurement);
if (propertyInfo == null)
{
throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,没有找到{measurement}属性,属于异常情况,-101。");
}
var value = propertyInfo.GetValue(entity);
if (propertyInfo.IsDefined(typeof(SingleMeasuringAttribute), false) && metadata.IsSingleMeasuring == true)//表示当前对象是单测点模式
{
if (value != null)
{
Type tupleType = value.GetType();
Type[] tupleArgs = tupleType.GetGenericArguments();
Type item2Type = tupleArgs[1]; // T 的实际类型
var item1 = tupleType.GetProperty("Item1")!.GetValue(value);
var item2 = tupleType.GetProperty("Item2")!.GetValue(value);
if (item1 == null || item2 == null)
{
throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,单测点模式构建失败,没有获取测点名称或者测点值,-102。");
}
var indexOf = metadata.ColumnNames.IndexOf(measurement);
metadata.ColumnNames[indexOf] = (string)item1!;
rowValues.Add(item2);
}
else
{
rowValues.Add(null);
}
//同时如果是单测点模式且是table模型存储路径只能通过DevicePathBuilder.GetDeviceTableName(entity)获取
if (_runtimeContext.UseTableSessionPool)
{
tableNameOrTreePath = DevicePathBuilder.GetDeviceTableName(entity);
}
}
else
{
//需要根据value的类型进行相应的值映射转换例如datetime转换为long的时间戳值
if (value != null)
{
Type tupleType = value.GetType();
var tempValue = tupleType.Name.ToUpper() switch
{
"DATETIME" => Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds(),
_ => value
};
rowValues.Add(tempValue);
}
else
{
rowValues.Add(value);
}
}
}
values.Add(rowValues);
//如果指定了路径
if (!string.IsNullOrWhiteSpace(tableNameOrTreePath))
if (!string.IsNullOrWhiteSpace(metadata.TableNameOrTreePath))
{
devicePaths.Add(tableNameOrTreePath);
tableNameOrTreePath = metadata.TableNameOrTreePath;
}
else
{
if (!_runtimeContext.UseTableSessionPool)//树模型
{
devicePaths.Add(DevicePathBuilder.GetDevicePath(entity));
}
else
{
devicePaths.Add(DevicePathBuilder.GetTableName<T>());
}
tableNameOrTreePath = DevicePathBuilder.GetTableName<T>();
}
return new List<Tablet>() { BuildTablet(entitiyList, metadata, tableNameOrTreePath) };
}
if (devicePaths.Count > 1)
else
{
throw new Exception($"{nameof(BuildTablet)} 构建Tablet《{typeof(T).Name}》时,批量插入的设备路径不一致。");
//树模型的时候实体的设备Id可能会不同因此需要根据不同路径进行存储。
var tabletList = new List<Tablet>();
var groupEntities = entitiyList.GroupBy(d => d.DevicePath).ToList();
foreach (var group in groupEntities)
{
tabletList.Add(BuildTablet(group.ToList(), metadata, group.Key));
}
return tabletList;
}
}
private Tablet BuildTablet<T>(List<T> entities, DeviceMetadata metadata, string tableNameOrTreePath) where T : IoTEntity
{
// 预分配内存结构
var rowCount = entities.Count;
var timestamps = new long[rowCount];
var values = new object[rowCount][];
for (var i = 0; i < values.Length; i++)
{
values[i] = new object[metadata.ColumnNames.Count];
}
return _runtimeContext.UseTableSessionPool
? BuildTableSessionTablet(metadata, devicePaths.First(), values, timestamps)
: BuildSessionTablet(metadata, devicePaths.First(), values, timestamps);
List<string> tempColumnNames = new List<string>();
tempColumnNames.AddRange(metadata.ColumnNames);
// 顺序处理数据(保证线程安全)
for (var row = 0; row < rowCount; row++)
{
var entity = entities[row];
timestamps[row] = entity.Timestamps;
for (int i = 0; i < metadata.ColumnNames.Count; i++)
{
var processor = metadata.Processors[i];
if (processor.IsSingleMeasuring)
{
tempColumnNames[i] = (string)processor.SingleMeasuringNameGetter(entity);
}
// 获取并转换值
values[row][i] = processor.ValueGetter(entity);
}
}
return UseTableSessionPool
? BuildTableSessionTablet(metadata, tableNameOrTreePath, tempColumnNames, values.Select(d => d.ToList()).ToList(), timestamps.ToList())
: BuildSessionTablet(metadata, tableNameOrTreePath, tempColumnNames, values.Select(d => d.ToList()).ToList(), timestamps.ToList());
}
/// <summary>
/// 构建tree模型的Tablet
/// </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
@ -391,14 +453,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,
@ -417,7 +480,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
private async Task<string> BuildQuerySQL<T>(IoTDBQueryOptions options) where T : IoTEntity
{
var metadata = await GetMetadata<T>();
var sb = new StringBuilder("SELECT TIME as Timestamps,");
var sb = new StringBuilder("SELECT ");
sb.AppendJoin(", ", metadata.ColumnNames);
sb.Append($" FROM {options.TableNameOrTreePath}");
@ -442,7 +505,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
var metadata = await GetMetadata<T>();
var sb = new StringBuilder();
if (!_runtimeContext.UseTableSessionPool)
if (!UseTableSessionPool)
{
sb.Append("DELETE ");
}
@ -471,16 +534,16 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// <returns></returns>
/// <exception cref="NotSupportedException"></exception>
private string TranslateCondition(QueryCondition condition)
{
{
return condition.Operator switch
{
">" => condition.IsNumber ? $"{condition.Field} > {condition.Value}" : $"{condition.Field} > '{condition.Value}'",
"<" => condition.IsNumber ? $"{condition.Field} < {condition.Value}" : $"{condition.Field} < '{condition.Value}'",
"=" => condition.IsNumber ? $"{condition.Field} = {condition.Value}" : $"{condition.Field} = '{condition.Value}'",
">" => $"{condition.Field} > {condition.Value}",
"<" => $"{condition.Field} < {condition.Value}",
"=" => $"{condition.Field} = {condition.Value}",
_ => throw new NotSupportedException($"{nameof(TranslateCondition)} 将查询条件转换为SQL语句时操作符 {condition.Operator} 属于异常情况")
};
}
/// <summary>
/// 获取查询条件的总数量
/// </summary>
@ -496,12 +559,17 @@ namespace JiShe.CollectBus.IoTDB.Provider
}
var result = await CurrentSession.ExecuteQueryStatementAsync(countQuery);
if (result.HasNext())
if (result == null)
{
await result.Close();
return 0;
}
if (!result.HasNext())
{
return 0;
}
var count = Convert.ToInt32(result.Next().Values[0]);
await result.Close();
@ -520,14 +588,9 @@ namespace JiShe.CollectBus.IoTDB.Provider
var results = new List<T>();
var metadata = await GetMetadata<T>();
var properties = typeof(T).GetProperties();
var accessor = SourceEntityAccessorFactory.GetAccessor<T>();
var memberCache = BuildMemberCache(accessor);
var columns = new List<string>() { "Timestamps" };
var dataTypes = new List<TSDataType>() { TSDataType.TIMESTAMP };
columns.AddRange(metadata.ColumnNames);
dataTypes.AddRange(metadata.DataTypes);
//metadata.ColumnNames.Insert(0, "Timestamps");
//metadata.DataTypes.Insert(0, TSDataType.TIMESTAMP);
while (dataSet.HasNext() && results.Count < pageSize)
{
@ -537,28 +600,13 @@ namespace JiShe.CollectBus.IoTDB.Provider
Timestamps = record.Timestamps
};
foreach (var measurement in columns)
for (int i = 0; i < metadata.Processors.Count; i++)
{
int indexOf = columns.IndexOf(measurement);
var value = record.Values[indexOf];
TSDataType tSDataType = dataTypes[indexOf];
var prop = properties.FirstOrDefault(p =>
p.Name.Equals(measurement, StringComparison.OrdinalIgnoreCase));
if (prop != null && !(value is System.DBNull))
var value = record.Values[i];
if (!(value is System.DBNull))
{
dynamic tempValue = GetTSDataValue(tSDataType, value);
if (measurement.ToLower().EndsWith("time"))
{
typeof(T).GetProperty(measurement)?.SetValue(entity, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds));
}
else
{
typeof(T).GetProperty(measurement)?.SetValue(entity, tempValue);
}
metadata.Processors[i].ValueSetter(entity, value);
}
}
results.Add(entity);
@ -571,72 +619,55 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// <summary>
/// 获取设备元数据的列
/// </summary>
/// <param name="type"></param>
/// <param name="accessor"></param>
/// <returns></returns>
private List<ColumnInfo> CollectColumnMetadata(Type type)
private List<ColumnInfo> CollectColumnMetadata<T>(ISourceEntityAccessor<T> accessor)
{
var columns = new List<ColumnInfo>();
var memberCache = BuildMemberCache(accessor);
foreach (var prop in type.GetProperties())
foreach (var member in accessor.MemberList)
{
// 过滤元组子项
if (member.NameOrPath.Contains(".Item")) continue;
string typeName = string.Empty;
// 类型名称处理
string declaredTypeName = member.DeclaredTypeName;
Type declaredType = prop.PropertyType;
// 处理可空类型
if (declaredType.IsGenericType && declaredType.GetGenericTypeDefinition() == typeof(Nullable<>))
// 特性查询优化
var attributes = member.CustomAttributes ?? Enumerable.Empty<Attribute>();
var tagAttr = attributes.OfType<TAGColumnAttribute>().FirstOrDefault();
var attrColumn = attributes.OfType<ATTRIBUTEColumnAttribute>().FirstOrDefault();
var fieldColumn = attributes.OfType<FIELDColumnAttribute>().FirstOrDefault();
var singleMeasuringAttr = attributes.OfType<SingleMeasuringAttribute>().FirstOrDefault();
// 构建ColumnInfo
ColumnInfo? column = null;
if (tagAttr != null)
{
Type underlyingType = Nullable.GetUnderlyingType(declaredType);
typeName = underlyingType.Name;
column = new ColumnInfo(member.NameOrPath, ColumnCategory.TAG, GetDataTypeFromTypeName(member.DeclaredTypeName), false, member.DeclaredTypeName);
}
else
else if (attrColumn != null)
{
typeName = declaredType.Name;
column = new ColumnInfo(member.NameOrPath, ColumnCategory.ATTRIBUTE, GetDataTypeFromTypeName(member.DeclaredTypeName), false, member.DeclaredTypeName);
}
else if (fieldColumn != null)
{
column = new ColumnInfo(member.NameOrPath, ColumnCategory.FIELD, GetDataTypeFromTypeName(member.DeclaredTypeName), false, member.DeclaredTypeName);
}
//先获取Tag标签和属性标签
ColumnInfo? column = prop.GetCustomAttribute<TAGColumnAttribute>() is not null ? new ColumnInfo(
name: prop.Name,
category: ColumnCategory.TAG,
dataType: GetDataTypeFromTypeName(typeName),
false
) : prop.GetCustomAttribute<ATTRIBUTEColumnAttribute>() is not null ? new ColumnInfo(
prop.Name,
ColumnCategory.ATTRIBUTE,
GetDataTypeFromTypeName(typeName),
false
) : prop.GetCustomAttribute<FIELDColumnAttribute>() is not null ? new ColumnInfo(
prop.Name,
ColumnCategory.FIELD,
GetDataTypeFromTypeName(typeName),
false)
: null;
//最先检查是不是单侧点模式
SingleMeasuringAttribute singleMeasuringAttribute = prop.GetCustomAttribute<SingleMeasuringAttribute>();
if (singleMeasuringAttribute != null && column == null)
// 单测模式处理
if (singleMeasuringAttr != null && column == null)
{
//warning: 单侧点模式注意事项
//Entity实体 字段类型是 Tuple<string,T>,Item1=>测点名称Item2=>测点值,泛型
//只有一个Filed字段。
//MeasuringName 默认为 SingleMeasuringAttribute.FieldName以便于在获取对应的Value的时候重置为 Item1 的值。
Type tupleType = prop.PropertyType;
Type[] tupleArgs = tupleType.GetGenericArguments();
column = new ColumnInfo(
singleMeasuringAttribute.FieldName,
ColumnCategory.FIELD,
GetDataTypeFromTypeName(tupleArgs[1].Name),
true
);
var tupleItemKey = $"{member.NameOrPath}.Item2";
if (!memberCache.TryGetValue(tupleItemKey, out var tupleMember))
{
throw new Exception($"{nameof(CollectColumnMetadata)} {accessor.EntityName} {member.NameOrPath} 单侧点属性解析异常");
}
column = new ColumnInfo(member.NameOrPath, ColumnCategory.FIELD, GetDataTypeFromTypeName(tupleMember.DeclaredTypeName), true, tupleMember.DeclaredTypeName);
}
if (column.HasValue)
{
columns.Add(column.Value);
}
if (column.HasValue) columns.Add(column.Value);
}
return columns;
}
@ -647,7 +678,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// <param name="typeInfo">待解析的类</param>
/// <param name="columns">已处理好的数据列</param>
/// <returns></returns>
private DeviceMetadata BuildDeviceMetadata<T>(List<ColumnInfo> columns) where T : IoTEntity
private DeviceMetadata BuildDeviceMetadata<T>(List<ColumnInfo> columns, ISourceEntityAccessor<T> accessor) where T : IoTEntity
{
var metadata = new DeviceMetadata();
@ -666,18 +697,135 @@ namespace JiShe.CollectBus.IoTDB.Provider
ProcessCategory(groupedColumns, ColumnCategory.ATTRIBUTE, metadata);
ProcessCategory(groupedColumns, ColumnCategory.FIELD, metadata);
var entityTypeAttribute = typeof(T).GetCustomAttribute<EntityTypeAttribute>();
if (entityTypeAttribute == null)
// 新增处理器初始化
foreach (var item in metadata.ColumnNames)
{
throw new ArgumentException($"{nameof(BuildDeviceMetadata)} 构建设备元数据时 {nameof(IoTEntity)} 的EntityType 没有指定,属于异常情况,-101");
}
ColumnInfo column = columns.FirstOrDefault(d => d.Name == item);
metadata.EntityType = entityTypeAttribute.EntityType;
var processor = new ColumnProcessor
{
ColumnName = column.Name,
IsSingleMeasuring = column.IsSingleMeasuring,
GetConverter = GetterConverter(column.DeclaredTypeName.ToUpper()),
SetConverter = SetterConverter(column.Name.ToUpper()),
TSDataType = column.DataType,
};
// 处理单测点
if (column.IsSingleMeasuring)
{
var item1Member = accessor.MemberList
.First(m => m.NameOrPath == $"{column.Name}.Item1");
processor.SingleMeasuringNameGetter = (obj) =>
{
// 获取原始值并转为字符串
object rawValue = item1Member.Getter(obj);
string value = rawValue?.ToString();
ValidateSingleMeasuringName(value);
return value;
};
var item2Member = accessor.MemberList
.First(m => m.NameOrPath == $"{column.Name}.Item2");
processor.ValueGetter = (obj) =>
{
object rawValue = item2Member.Getter(obj);
return processor.GetConverter(rawValue);
};
}
else
{
// 获取对应的成员访问器
var member = accessor.MemberList.First(m => m.NameOrPath == column.Name);
processor.ValueGetter = (obj) =>
{
object rawValue = member.Getter(obj);
return processor.GetConverter(rawValue);
};
//对应的属性成员进行赋值
processor.ValueSetter = (obj, value) =>
{
dynamic tempValue = GetTSDataValue(processor.TSDataType, value);
var rawValue = processor.SetConverter(value);
member.Setter(obj, rawValue);
};
}
metadata.Processors.Add(processor);
}
return metadata;
}
/// <summary>
/// 验证单测点名称格式
/// </summary>
private void ValidateSingleMeasuringName(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return;
}
// 规则1: 严格检查ASCII字母和数字0-9, A-Z, a-z
bool hasInvalidChars = value.Any(c =>
!((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9')));
// 规则2: 首字符不能是数字
bool startsWithDigit = value[0] >= '0' && value[0] <= '9';
// 规则3: 全字符串不能都是数字
bool allDigits = value.All(c => c >= '0' && c <= '9');
// 按优先级抛出具体异常
if (hasInvalidChars)
{
throw new InvalidOperationException(
$"SingleMeasuring name '{value}' 包含非法字符,只允许字母和数字");
}
else if (startsWithDigit)
{
throw new InvalidOperationException(
$"SingleMeasuring name '{value}' 不能以数字开头");
}
else if (allDigits)
{
throw new InvalidOperationException(
$"SingleMeasuring name '{value}' 不能全为数字");
}
}
/// <summary>
/// 取值的处理器
/// </summary>
/// <param name="declaredTypeName"></param>
/// <returns></returns>
private Func<object, object> GetterConverter(string declaredTypeName)
{
return declaredTypeName switch
{
"DATETIME" => value => value != null ? Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds() : null,
"DECIMAL" => value => value != null ? Convert.ToDouble( value) : null,
_ => value => value
};
}
/// <summary>
/// 设置值的处理
/// </summary>
/// <param name="columnName"></param>
/// <returns></returns>
private Func<object, object> SetterConverter(string columnName) =>
columnName.ToLower().EndsWith("time")
? value => value != null ? TimestampHelper.ConvertToDateTime(Convert.ToInt64(value), TimestampUnit.Nanoseconds) : null
: value => value;
/// <summary>
/// 处理不同列类型的逻辑
/// </summary>
@ -704,6 +852,11 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// </summary>
public string Name { get; }
/// <summary>
/// 声明的类型的名称
/// </summary>
public string DeclaredTypeName { get; }
/// <summary>
/// 是否是单测点
/// </summary>
@ -719,12 +872,13 @@ namespace JiShe.CollectBus.IoTDB.Provider
/// </summary>
public TSDataType DataType { get; }
public ColumnInfo(string name, ColumnCategory category, TSDataType dataType, bool isSingleMeasuring)
public ColumnInfo(string name, ColumnCategory category, TSDataType dataType, bool isSingleMeasuring, string declaredTypeName)
{
Name = name;
Category = category;
DataType = dataType;
IsSingleMeasuring = isSingleMeasuring;
DeclaredTypeName = declaredTypeName;
}
}
@ -759,7 +913,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
["DATETIME"] = TSDataType.TIMESTAMP,
["DATE"] = TSDataType.DATE,
["BLOB"] = TSDataType.BLOB,
["DECIMAL"] = TSDataType.STRING,
["DECIMAL"] = TSDataType.DOUBLE,
["STRING"] = TSDataType.STRING
};
@ -795,7 +949,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
TSDataType.BOOLEAN => Convert.ToBoolean(value),
TSDataType.INT32 => Convert.ToInt32(value),
TSDataType.INT64 => Convert.ToInt64(value),
TSDataType.FLOAT => Convert.ToDouble(value),
TSDataType.FLOAT => Convert.ToSingle(value),
TSDataType.DOUBLE => Convert.ToDouble(value),
TSDataType.TEXT => Convert.ToString(value),
TSDataType.NONE => null,
@ -805,5 +959,23 @@ 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;
}
private static readonly Regex _asciiAlphanumericRegex = new Regex(@"^[a-zA-Z0-9]*$", RegexOptions.Compiled);
}
}

View File

@ -70,7 +70,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
var result = await _sessionPool.InsertAlignedTabletAsync(tablet);
if (result != 0)
{
throw new Exception($"{nameof(SessionPoolAdapter)} Tree模型数据入库没有成功返回结果为{result}");
throw new Exception($"{nameof(SessionPoolAdapter)} Tree模型数据入库没有成功返回结果为{result}请检查IoTEntity继承子类属性索引是否有变动。");
}
//await CloseAsync();
return result;

View File

@ -68,7 +68,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
var result = await _sessionPool.InsertAsync(tablet);
if (result != 0)
{
throw new Exception($"{nameof(TableSessionPoolAdapter)} table模型数据入库没有成功返回结果为{result}");
throw new Exception($"{nameof(TableSessionPoolAdapter)} table模型数据入库没有成功返回结果为{result}请检查IoTEntity继承子类属性索引是否有变动。");
}
//await CloseAsync();

View File

@ -31,10 +31,14 @@
<ProjectReference Include="..\JiShe.CollectBus.Kafka\JiShe.CollectBus.Kafka.csproj" />
</ItemGroup>
<!--<ItemGroup>
<Reference Include="JiShe.CollectBus.Kafka">
<HintPath>Lib\JiShe.CollectBus.Kafka.dll</HintPath>
</Reference>
</ItemGroup>-->
<!--注意基准测试需要引用dll测试-->
<!--<ItemGroup>
<Reference Include="JiShe.CollectBus.Common">
<HintPath>Lib\JiShe.CollectBus.Common.dll</HintPath>
</Reference>
<Reference Include="JiShe.CollectBus.Kafka">
<HintPath>Lib\JiShe.CollectBus.Kafka.dll</HintPath>
</Reference>
</ItemGroup>-->
</Project>

View File

@ -1,8 +1,10 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using Confluent.Kafka;
using JiShe.CollectBus.Common;
using JiShe.CollectBus.Kafka.AdminClient;
using JiShe.CollectBus.Kafka.Consumer;
using JiShe.CollectBus.Kafka.Internal;
using JiShe.CollectBus.Kafka.Producer;
using Microsoft.Extensions.Configuration;
@ -24,11 +26,11 @@ namespace JiShe.CollectBus.Kafka.Test
{
// 每批消息数量
[Params(1000, 10000, 100000)]
[Params(1000, 10000, 100000, 1000000)]
public int N;
public ServiceProvider _serviceProvider;
public IConsumerService _consumerService;
public IProducerService _producerService;
public IConsumerService _consumerService;
public IProducerService _producerService;
public string topic = "test-topic1";
[GlobalSetup]
@ -40,13 +42,22 @@ namespace JiShe.CollectBus.Kafka.Test
.AddJsonFile("appsettings.json")
.Build();
// 直接读取配置项
var greeting = config["ServerTagName"];
var greeting = config["Kafka:ServerTagName"];
Console.WriteLine(greeting); // 输出: Hello, World!
// 创建服务容器
var services = new ServiceCollection();
// 注册 IConfiguration 实例
services.AddSingleton<IConfiguration>(config);
services.Configure<KafkaOptionConfig>(options =>
{
config.GetSection("Kafka").Bind(options);
});
services.Configure<ServerApplicationOptions>(options =>
{
config.GetSection(nameof(ServerApplicationOptions)).Bind(options);
});
// 初始化日志
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config) // 从 appsettings.json 读取配置
@ -61,6 +72,8 @@ namespace JiShe.CollectBus.Kafka.Test
services.AddSingleton<IAdminClientService, AdminClientService>();
services.AddSingleton<IProducerService, ProducerService>();
services.AddSingleton<IConsumerService, ConsumerService>();
services.AddSingleton<KafkaPollyPipeline>();
services.AddTransient<KafkaSubscribeTest>();
// 构建ServiceProvider
_serviceProvider = services.BuildServiceProvider();
@ -72,10 +85,10 @@ namespace JiShe.CollectBus.Kafka.Test
var adminClientService = _serviceProvider.GetRequiredService<IAdminClientService>();
//await adminClientService.DeleteTopicAsync(topic);
// 创建 topic
adminClientService.CreateTopicAsync(topic, 3, 3).ConfigureAwait(false).GetAwaiter();
//adminClientService.CreateTopicAsync(topic, 3, 3).ConfigureAwait(false).GetAwaiter();
_consumerService = _serviceProvider.GetRequiredService<IConsumerService>();
@ -100,9 +113,9 @@ namespace JiShe.CollectBus.Kafka.Test
List<Task> tasks = new();
for (int i = 0; i < N; ++i)
{
var task = _producerService.ProduceAsync<string>(topic, i.ToString(),null);
var task = _producerService.ProduceAsync<string>(topic, i.ToString(), null);
}
await Task.WhenAll(tasks);
}
}
}
}

View File

@ -1,8 +1,5 @@
// See https://aka.ms/new-console-template for more information
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using Confluent.Kafka;
using DeviceDetectorNET.Parser.Device;
using JiShe.CollectBus.Common;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Kafka;
using JiShe.CollectBus.Kafka.AdminClient;
@ -17,10 +14,6 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.PortableExecutable;
using System.Text.Json;
#region
//var summary = BenchmarkRunner.Run<KafkaProduceBenchmark>();
@ -38,7 +31,7 @@ var host = Host.CreateDefaultBuilder(args)
.AddJsonFile("appsettings.json")
.Build();
// 直接读取配置项
var greeting = config["Kafka:ServerTagName"];
var greeting = config["ServerApplicationOptions:ServerTagName"];
Console.WriteLine(greeting); // 输出: Hello, World!
@ -58,7 +51,18 @@ var host = Host.CreateDefaultBuilder(args)
logging.ClearProviders();
logging.AddSerilog();
});
services.Configure<KafkaOptionConfig>(config.GetSection("Kafka"));
//services.Configure<KafkaOptionConfig>(config.GetSection("Kafka"));
//services.Configure<ServerApplicationOptions>(config.GetSection("ServerApplicationOptions"));
var dss = config.GetSection("Kafka");
services.Configure<KafkaOptionConfig>(options =>
{
config.GetSection("Kafka").Bind(options);
});
services.Configure<ServerApplicationOptions>(options =>
{
config.GetSection(nameof(ServerApplicationOptions)).Bind(options);
});
services.AddSingleton<IAdminClientService, AdminClientService>();
services.AddSingleton<IProducerService, ProducerService>();
@ -86,8 +90,20 @@ var host = Host.CreateDefaultBuilder(args)
var loggerFactory = host.Services.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("程序启动");
var _kafkaPollyPipeline = host.Services.GetRequiredService<KafkaPollyPipeline>();
if (_kafkaPollyPipeline == null)
{
logger.LogInformation("KafkaPollyPipeline未注册");
}
var adminClientService = host.Services.GetRequiredService<IAdminClientService>();
var configuration = host.Services.GetRequiredService<IConfiguration>();
var kafkaOptionConfig=host.Services.GetRequiredService<IOptions<ServerApplicationOptions>>();
string topic = ProtocolConst.TESTTOPIC;
//await adminClientService.DeleteTopicAsync(topic);
// 创建 topic

View File

@ -0,0 +1,8 @@
{
"profiles": {
"WSL": {
"commandName": "WSL2",
"distributionName": ""
}
}
}

View File

@ -13,7 +13,8 @@
"DotNetCore.CAP": "Warning",
"Serilog.AspNetCore": "Information",
"Microsoft.EntityFrameworkCore": "Warning",
"Microsoft.AspNetCore": "Warning"
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.Diagnostics.HealthChecks": "Warning"
}
},
"WriteTo": [
@ -34,7 +35,7 @@
"CorsOrigins": "http://localhost:4200,http://localhost:3100"
},
"ConnectionStrings": {
"Default": "mongodb://admin:admin02023@118.190.144.92:37117,118.190.144.92:37119,118.190.144.92:37120/JiSheCollectBus?authSource=admin&maxPoolSize=400&minPoolSize=10&waitQueueTimeoutMS=5000",
"Default": "mongodb://mongo_PmEeF3:lixiao1980@192.168.1.9:27017/JiSheCollectBus?authSource=admin&maxPoolSize=400&minPoolSize=10&waitQueueTimeoutMS=5000",
"Kafka": "192.168.1.9:29092,192.168.1.9:39092,192.168.1.9:49092",
"PrepayDB": "server=118.190.144.92;database=jishe.sysdb;uid=sa;pwd=admin@2023;Encrypt=False;Trust Server Certificate=False",
"EnergyDB": "server=118.190.144.92;database=db_energy;uid=sa;pwd=admin@2023;Encrypt=False;Trust Server Certificate=False"
@ -43,7 +44,7 @@
"Configuration": "192.168.1.9:6380,password=1q2w3e!@#,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true",
"MaxPoolSize": "50",
"DefaultDB": "14",
"HangfireDB": "15"
"HangfireDB": "13"
},
"Jwt": {
"Audience": "JiShe.CollectBus",
@ -51,16 +52,11 @@
"Issuer": "JiShe.CollectBus",
"ExpirationTime": 2
},
"HealthCheck": {
"HealthChecks": {
"IsEnable": true,
"MySql": {
"IsEnable": true
},
"Pings": {
"IsEnable": true,
"Host": "https://www.baidu.com/",
"TimeOut": 5000
}
"HealthCheckDatabaseName": "HealthChecks",
"EvaluationTimeInSeconds": 10,
"MinimumSecondsBetweenFailureNotifications": 60
},
"SwaggerConfig": [
{
@ -74,14 +70,6 @@
"Version": "V1"
}
],
"Cap": {
"RabbitMq": {
"HostName": "118.190.144.92",
"UserName": "collectbus",
"Password": "123456",
"Port": 5672
}
},
"Kafka": {
"BootstrapServers": "192.168.1.9:29092,192.168.1.9:39092,192.168.1.9:49092",
"EnableFilter": true,
@ -92,48 +80,17 @@
"SaslPassword": "lixiao1980",
"KafkaReplicationFactor": 3,
"NumPartitions": 30,
"ServerTagName": "JiSheCollectBus99"
//"Topic": {
// "ReplicationFactor": 3,
// "NumPartitions": 1000
//}
"FirstCollectionTime": "2025-04-22 16:07:00"
},
//"Kafka": {
// "Connections": {
// "Default": {
// "BootstrapServers": "192.168.1.9:29092,192.168.1.9:39092,192.168.1.9:49092"
// // "SecurityProtocol": "SASL_PLAINTEXT",
// // "SaslMechanism": "PLAIN",
// // "SaslUserName": "lixiao",
// // "SaslPassword": "lixiao1980",
// }
// },
// "Consumer": {
// "GroupId": "JiShe.CollectBus"
// },
// "Producer": {
// "MessageTimeoutMs": 6000,
// "Acks": -1
// },
// "Topic": {
// "ReplicationFactor": 3,
// "NumPartitions": 1000
// },
// "EventBus": {
// "GroupId": "JiShe.CollectBus",
// "TopicName": "DefaultTopicName"
// }
//},
"IoTDBOptions": {
"UserName": "root",
"Password": "root",
"ClusterList": [ "192.168.1.9:6667" ],
"PoolSize": 2,
"PoolSize": 32,
"DataBaseName": "energy",
"OpenDebugMode": true,
"UseTableSessionPoolByDefault": false
},
"ServerTagName": "JiSheCollectBus3",
"Cassandra": {
"ReplicationStrategy": {
"Class": "NetworkTopologyStrategy", //NetworkTopologyStrategySimpleStrategy
@ -156,6 +113,12 @@
"Port": 9043,
"DataCenter": "dc1",
"Rack": "RAC2"
},
{
"Host": "192.168.1.9",
"Port": 9044,
"DataCenter": "dc1",
"Rack": "RAC2"
}
],
"Username": "admin",
@ -176,5 +139,17 @@
"SerialConsistencyLevel": "Serial",
"DefaultIdempotence": true
}
}
},
"ServerApplicationOptions": {
"ServerTagName": "JiSheCollectBus4",
"SystemType": "Energy",
"FirstCollectionTime": "2025-04-28 15:07:00",
"AutomaticVerificationTime": "16:07:00",
"AutomaticTerminalVersionTime": "17:07:00",
"AutomaticTelematicsModuleTime": "17:30:00",
"AutomaticDayFreezeTime": "02:30:00",
"AutomaticMonthFreezeTime": "03:30:00",
"DefaultProtocolPlugin": "T37612012ProtocolPlugin"
},
"PlugInFolder": ""
}

View File

@ -1,7 +1,9 @@
using Confluent.Kafka;
using Confluent.Kafka.Admin;
using JiShe.CollectBus.Kafka.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace JiShe.CollectBus.Kafka.AdminClient;
@ -9,16 +11,17 @@ namespace JiShe.CollectBus.Kafka.AdminClient;
public class AdminClientService : IAdminClientService, IDisposable, ISingletonDependency
{
private readonly ILogger<AdminClientService> _logger;
private readonly KafkaOptionConfig _kafkaOptionConfig;
/// <summary>
/// Initializes a new instance of the <see cref="AdminClientService" /> class.
/// </summary>
/// <param name="configuration"></param>
/// <param name="logger"></param>
public AdminClientService(IConfiguration configuration, ILogger<AdminClientService> logger)
public AdminClientService(IConfiguration configuration, ILogger<AdminClientService> logger, IOptions<KafkaOptionConfig> kafkaOptionConfig)
{
_logger = logger;
Instance = GetInstance(configuration);
_kafkaOptionConfig = kafkaOptionConfig.Value;
Instance = GetInstance();
}
/// <summary>
@ -142,22 +145,19 @@ public class AdminClientService : IAdminClientService, IDisposable, ISingletonDe
/// <summary>
/// Gets the instance.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <returns></returns>
public IAdminClient GetInstance(IConfiguration configuration)
public IAdminClient GetInstance()
{
ArgumentException.ThrowIfNullOrWhiteSpace(configuration["Kafka:EnableAuthorization"]);
var enableAuthorization = bool.Parse(configuration["Kafka:EnableAuthorization"]!);
var adminClientConfig = new AdminClientConfig
{
BootstrapServers = configuration["Kafka:BootstrapServers"]
BootstrapServers = _kafkaOptionConfig.BootstrapServers
};
if (enableAuthorization)
if (_kafkaOptionConfig.EnableAuthorization)
{
adminClientConfig.SecurityProtocol = SecurityProtocol.SaslPlaintext;
adminClientConfig.SaslMechanism = SaslMechanism.Plain;
adminClientConfig.SaslUsername = configuration["Kafka:SaslUserName"];
adminClientConfig.SaslPassword = configuration["Kafka:SaslPassword"];
adminClientConfig.SecurityProtocol = _kafkaOptionConfig.SecurityProtocol;
adminClientConfig.SaslMechanism = _kafkaOptionConfig.SaslMechanism;
adminClientConfig.SaslUsername = _kafkaOptionConfig.SaslUserName;
adminClientConfig.SaslPassword = _kafkaOptionConfig.SaslPassword;
}
return new AdminClientBuilder(adminClientConfig).Build();
}

View File

@ -1,6 +1,7 @@
using Confluent.Kafka;
using JiShe.CollectBus.Common;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Kafka.Internal;
using JiShe.CollectBus.Kafka.Serialization;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
@ -27,7 +28,7 @@ namespace JiShe.CollectBus.Kafka.Consumer
/// <summary>
/// 消费完或者无数据时的延迟时间
/// </summary>
private TimeSpan DelayTime => TimeSpan.FromMilliseconds(100);
private static TimeSpan DelayTime => TimeSpan.FromMilliseconds(100);
private readonly KafkaOptionConfig _kafkaOptionConfig;
@ -127,75 +128,88 @@ namespace JiShe.CollectBus.Kafka.Consumer
/// <returns></returns>
public async Task SubscribeAsync<TKey, TValue>(string[] topics, Func<TKey, TValue, Task<bool>> messageHandler, string? groupId = null) where TKey : notnull where TValue : class
{
await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token =>
try
{
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}";
var cts = new CancellationTokenSource();
var consumer = _consumerStore.GetOrAdd(consumerKey, _ =>
(
CreateConsumer<TKey, TValue>(groupId),
cts
)).Consumer as IConsumer<TKey, TValue>;
consumer!.Subscribe(topics);
_ = Task.Run(async () =>
await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token =>
{
while (!cts.IsCancellationRequested)
{
try
{
//_logger.LogInformation($"Kafka消费: {string.Join("", topics)} 开始拉取消息....");
var result = consumer.Consume(cts.Token);
if (result == null || result.Message == null || result.Message.Value == null)
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}";
var cts = new CancellationTokenSource();
var consumer = _consumerStore.GetOrAdd(consumerKey, _ =>
(
CreateConsumer<TKey, TValue>(groupId),
cts
)).Consumer as IConsumer<TKey, TValue>;
consumer!.Subscribe(topics);
_ = Task.Run(async () =>
{
while (!cts.IsCancellationRequested)
{
try
{
await Task.Delay(DelayTime, cts.Token);
continue;
}
if (result.IsPartitionEOF)
{
#if DEBUG
_logger.LogInformation("Kafka消费: {Topic} 分区 {Partition} 已消费完", result.Topic, result.Partition);
#endif
await Task.Delay(DelayTime, cts.Token);
continue;
}
if (_kafkaOptionConfig.EnableFilter)
{
var headersFilter = new HeadersFilter { { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } };
// 检查 Header 是否符合条件
if (!headersFilter.Match(result.Message.Headers))
//_logger.LogInformation($"Kafka消费: {string.Join("", topics)} 开始拉取消息....");
var result = consumer.Consume(cts.Token);
if (result == null || result.Message == null || result.Message.Value == null)
{
consumer.Commit(result); // 提交偏移量
// 跳过消息
await Task.Delay(DelayTime, cts.Token);
continue;
}
if (result.IsPartitionEOF)
{
#if DEBUG
_logger.LogInformation("Kafka消费: {Topic} 分区 {Partition} 已消费完", result.Topic, result.Partition);
#endif
await Task.Delay(DelayTime, cts.Token);
continue;
}
if (_kafkaOptionConfig.EnableFilter)
{
var headersFilter = new HeadersFilter { { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } };
// 检查 Header 是否符合条件
if (!headersFilter.Match(result.Message.Headers))
{
consumer.Commit(result); // 提交偏移量
// 跳过消息
continue;
}
}
bool sucess = await messageHandler(result.Message.Key, result.Message.Value);
if (sucess)
consumer.Commit(result); // 手动提交
}
catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"{string.Join("", topics)}消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (KafkaException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"{string.Join("", topics)} 消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (OperationCanceledException)
{
//ignore
}
catch (Exception ex)
{
_logger.LogError(ex, "处理消息时发生未知错误");
}
bool sucess = await messageHandler(result.Message.Key, result.Message.Value);
if (sucess)
consumer.Commit(result); // 手动提交
}
catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"{string.Join("", topics)}消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (OperationCanceledException)
{
//ignore
}
catch (Exception ex)
{
_logger.LogError(ex, "处理消息时发生未知错误");
}
}
}, cts.Token);
await Task.CompletedTask;
});
}, cts.Token);
await Task.CompletedTask;
});
}
catch (Exception ex)
{
throw;
}
}
@ -210,76 +224,84 @@ namespace JiShe.CollectBus.Kafka.Consumer
/// <returns></returns>
public async Task SubscribeAsync<TValue>(string[] topics, Func<TValue, Task<bool>> messageHandler, string? groupId) where TValue : class
{
await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token =>
try
{
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(Ignore).Name}_{typeof(TValue).Name}";
var cts = new CancellationTokenSource();
var consumer = _consumerStore.GetOrAdd(consumerKey, _ =>
(
CreateConsumer<Ignore, TValue>(groupId),
cts
)).Consumer as IConsumer<Ignore, TValue>;
consumer!.Subscribe(topics);
_ = Task.Run(async () =>
await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token =>
{
int count = 0;
while (!cts.IsCancellationRequested)
{
try
{
//_logger.LogInformation($"Kafka消费: {string.Join("", topics)}_{count} 开始拉取消息....");
count++;
var result = consumer.Consume(cts.Token);
if (result == null || result.Message == null || result.Message.Value == null)
{
await Task.Delay(DelayTime, cts.Token);
continue;
}
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(Ignore).Name}_{typeof(TValue).Name}";
var cts = new CancellationTokenSource();
var consumer = _consumerStore.GetOrAdd(consumerKey, _ =>
(
CreateConsumer<Ignore, TValue>(groupId),
cts
)).Consumer as IConsumer<Ignore, TValue>;
if (result.IsPartitionEOF)
consumer!.Subscribe(topics);
_ = Task.Run(async () =>
{
int count = 0;
while (!cts.IsCancellationRequested)
{
try
{
#if DEBUG
_logger.LogInformation("Kafka消费: {Topic} 分区 {Partition} 已消费完", result.Topic, result.Partition);
#endif
await Task.Delay(DelayTime, cts.Token);
continue;
}
if (_kafkaOptionConfig.EnableFilter)
{
var headersFilter = new HeadersFilter { { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } };
// 检查 Header 是否符合条件
if (!headersFilter.Match(result.Message.Headers))
//_logger.LogInformation($"Kafka消费: {string.Join("", topics)}_{count} 开始拉取消息....");
count++;
var result = consumer.Consume(cts.Token);
if (result == null || result.Message == null || result.Message.Value == null)
{
consumer.Commit(result); // 提交偏移量
// 跳过消息
await Task.Delay(DelayTime, cts.Token);
continue;
}
if (result.IsPartitionEOF)
{
#if DEBUG
_logger.LogInformation("Kafka消费: {Topic} 分区 {Partition} 已消费完", result.Topic, result.Partition);
#endif
await Task.Delay(DelayTime, cts.Token);
continue;
}
if (_kafkaOptionConfig.EnableFilter)
{
var headersFilter = new HeadersFilter { { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } };
// 检查 Header 是否符合条件
if (!headersFilter.Match(result.Message.Headers))
{
consumer.Commit(result); // 提交偏移量
// 跳过消息
continue;
}
}
bool sucess = await messageHandler(result.Message.Value);
if (sucess)
consumer.Commit(result); // 手动提交
//else
// consumer.StoreOffset(result);
}
catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"{string.Join("", topics)}消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (OperationCanceledException)
{
//ignore
}
catch (Exception ex)
{
_logger.LogError(ex, "处理消息时发生未知错误");
}
bool sucess = await messageHandler(result.Message.Value);
if (sucess)
consumer.Commit(result); // 手动提交
//else
// consumer.StoreOffset(result);
}
catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"{string.Join("", topics)}消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (OperationCanceledException)
{
//ignore
}
catch (Exception ex)
{
_logger.LogError(ex, "处理消息时发生未知错误");
}
}
}, cts.Token);
await Task.CompletedTask;
});
}, cts.Token);
await Task.CompletedTask;
});
}
catch (Exception ex)
{
throw;
}
}
@ -295,7 +317,15 @@ namespace JiShe.CollectBus.Kafka.Consumer
/// <param name="batchTimeout">批次超时时间</param>
public async Task SubscribeBatchAsync<TKey, TValue>(string topic, Func<List<TValue>, Task<bool>> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null) where TKey : notnull where TValue : class
{
await SubscribeBatchAsync<TKey, TValue>(new[] { topic }, messageBatchHandler, groupId, batchSize, batchTimeout);
try
{
await SubscribeBatchAsync<TKey, TValue>(new[] { topic }, messageBatchHandler, groupId, batchSize, batchTimeout);
}
catch (Exception ex)
{
throw;
}
}
/// <summary>
@ -310,112 +340,125 @@ namespace JiShe.CollectBus.Kafka.Consumer
/// <param name="batchTimeout">批次超时时间</param>
public async Task SubscribeBatchAsync<TKey, TValue>(string[] topics, Func<List<TValue>, Task<bool>> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null) where TKey : notnull where TValue : class
{
await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token =>
try
{
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}";
var cts = new CancellationTokenSource();
var consumer = _consumerStore.GetOrAdd(consumerKey, _ =>
(
CreateConsumer<TKey, TValue>(groupId),
cts
)).Consumer as IConsumer<TKey, TValue>;
consumer!.Subscribe(topics);
var timeout = batchTimeout ?? TimeSpan.FromSeconds(5); // 默认超时时间调整为5秒
_ = Task.Run(async () =>
await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token =>
{
var messages = new List<(TValue Value, TopicPartitionOffset Offset)>();
var startTime = DateTime.UtcNow;
while (!cts.IsCancellationRequested)
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}";
var cts = new CancellationTokenSource();
var consumer = _consumerStore.GetOrAdd(consumerKey, _ =>
(
CreateConsumer<TKey, TValue>(groupId),
cts
)).Consumer as IConsumer<TKey, TValue>;
consumer!.Subscribe(topics);
var timeout = batchTimeout ?? TimeSpan.FromSeconds(5); // 默认超时时间调整为5秒
_ = Task.Run(async () =>
{
try
{
// 非阻塞快速累积消息
while (messages.Count < batchSize && (DateTime.UtcNow - startTime) < timeout)
{
var result = consumer.Consume(TimeSpan.Zero); // 非阻塞调用
var messages = new List<(TValue Value, TopicPartitionOffset Offset)>();
var startTime = DateTime.UtcNow;
if (result != null)
while (!cts.IsCancellationRequested)
{
try
{
// 非阻塞快速累积消息
while (messages.Count < batchSize && (DateTime.UtcNow - startTime) < timeout)
{
if (result.IsPartitionEOF)
var result = consumer.Consume(TimeSpan.Zero); // 非阻塞调用
if (result != null)
{
if (result.IsPartitionEOF)
{
#if DEBUG
_logger.LogInformation("Kafka消费: {Topic} 分区 {Partition} 已消费完", result.Topic, result.Partition);
_logger.LogInformation("Kafka消费: {Topic} 分区 {Partition} 已消费完", result.Topic, result.Partition);
#endif
await Task.Delay(DelayTime, cts.Token);
}
else if (result.Message.Value != null)
{
if (_kafkaOptionConfig.EnableFilter)
{
var headersFilter = new HeadersFilter { { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } };
// 检查 Header 是否符合条件
if (!headersFilter.Match(result.Message.Headers))
{
consumer.Commit(result); // 提交偏移量
// 跳过消息
continue;
}
}
messages.Add((result.Message.Value, result.TopicPartitionOffset));
}
}
else
{
// 无消息时短暂等待
await Task.Delay(DelayTime, cts.Token);
}
else if (result.Message.Value != null)
}
// 处理批次
if (messages.Count > 0)
{
bool success = await messageBatchHandler(messages.Select(m => m.Value).ToList());
if (success)
{
if (_kafkaOptionConfig.EnableFilter)
var offsetsByPartition = new Dictionary<TopicPartition, long>();
foreach (var msg in messages)
{
var headersFilter = new HeadersFilter { { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } };
// 检查 Header 是否符合条件
if (!headersFilter.Match(result.Message.Headers))
var tp = msg.Offset.TopicPartition;
var offset = msg.Offset.Offset;
if (!offsetsByPartition.TryGetValue(tp, out var currentMax) || offset > currentMax)
{
consumer.Commit(result); // 提交偏移量
// 跳过消息
continue;
offsetsByPartition[tp] = offset;
}
}
messages.Add((result.Message.Value, result.TopicPartitionOffset));
}
}
else
{
// 无消息时短暂等待
await Task.Delay(DelayTime, cts.Token);
}
}
// 处理批次
if (messages.Count > 0)
var offsetsToCommit = offsetsByPartition
.Select(kv => new TopicPartitionOffset(kv.Key, new Offset(kv.Value + 1)))
.ToList();
consumer.Commit(offsetsToCommit);
}
messages.Clear();
}
startTime = DateTime.UtcNow;
}
catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
bool success = await messageBatchHandler(messages.Select(m => m.Value).ToList());
if (success)
{
var offsetsByPartition = new Dictionary<TopicPartition, long>();
foreach (var msg in messages)
{
var tp = msg.Offset.TopicPartition;
var offset = msg.Offset.Offset;
if (!offsetsByPartition.TryGetValue(tp, out var currentMax) || offset > currentMax)
{
offsetsByPartition[tp] = offset;
}
}
var offsetsToCommit = offsetsByPartition
.Select(kv => new TopicPartitionOffset(kv.Key, new Offset(kv.Value + 1)))
.ToList();
consumer.Commit(offsetsToCommit);
}
messages.Clear();
_logger.LogError(ex, $"{string.Join("", topics)} 消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (KafkaException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"{string.Join("", topics)} 消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (OperationCanceledException)
{
//ignore
}
catch (Exception ex)
{
_logger.LogError(ex, "处理批量消息时发生未知错误");
}
}
}, cts.Token);
startTime = DateTime.UtcNow;
}
catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"{string.Join("", topics)} 消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (OperationCanceledException)
{
//ignore
}
catch (Exception ex)
{
_logger.LogError(ex, "处理批量消息时发生未知错误");
}
}
}, cts.Token);
await Task.CompletedTask;
});
}
catch (Exception ex)
{
await Task.CompletedTask;
});
throw;
}
}
@ -431,7 +474,15 @@ namespace JiShe.CollectBus.Kafka.Consumer
/// <param name="consumeTimeout">消费等待时间</param>
public async Task SubscribeBatchAsync<TValue>(string topic, Func<List<TValue>, Task<bool>> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null, TimeSpan? consumeTimeout = null) where TValue : class
{
await SubscribeBatchAsync(new[] { topic }, messageBatchHandler, groupId, batchSize, batchTimeout, consumeTimeout);
try
{
await SubscribeBatchAsync(new[] { topic }, messageBatchHandler, groupId, batchSize, batchTimeout, consumeTimeout);
}
catch (Exception ex)
{
throw;
}
}
@ -448,111 +499,124 @@ namespace JiShe.CollectBus.Kafka.Consumer
/// <param name="consumeTimeout">消费等待时间</param>
public async Task SubscribeBatchAsync<TValue>(string[] topics, Func<List<TValue>, Task<bool>> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null, TimeSpan? consumeTimeout = null) where TValue : class
{
await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token =>
try
{
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(Ignore).Name}_{typeof(TValue).Name}";
var cts = new CancellationTokenSource();
var consumer = _consumerStore.GetOrAdd(consumerKey, _ =>
(
CreateConsumer<Ignore, TValue>(groupId),
cts
)).Consumer as IConsumer<Ignore, TValue>;
consumer!.Subscribe(topics);
var timeout = batchTimeout ?? TimeSpan.FromSeconds(5); // 默认超时时间调整为5秒
_ = Task.Run(async () =>
await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token =>
{
var messages = new List<(TValue Value, TopicPartitionOffset Offset)>();
var startTime = DateTime.UtcNow;
while (!cts.IsCancellationRequested)
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(Ignore).Name}_{typeof(TValue).Name}";
var cts = new CancellationTokenSource();
var consumer = _consumerStore.GetOrAdd(consumerKey, _ =>
(
CreateConsumer<Ignore, TValue>(groupId),
cts
)).Consumer as IConsumer<Ignore, TValue>;
consumer!.Subscribe(topics);
var timeout = batchTimeout ?? TimeSpan.FromSeconds(5); // 默认超时时间调整为5秒
_ = Task.Run(async () =>
{
try
{
// 非阻塞快速累积消息
while (messages.Count < batchSize && (DateTime.UtcNow - startTime) < timeout)
{
var result = consumer.Consume(TimeSpan.Zero); // 非阻塞调用
var messages = new List<(TValue Value, TopicPartitionOffset Offset)>();
var startTime = DateTime.UtcNow;
if (result != null)
while (!cts.IsCancellationRequested)
{
try
{
// 非阻塞快速累积消息
while (messages.Count < batchSize && (DateTime.UtcNow - startTime) < timeout)
{
if (result.IsPartitionEOF)
var result = consumer.Consume(TimeSpan.Zero); // 非阻塞调用
if (result != null)
{
//_logger.LogInformation("Kafka消费: {Topic} 分区 {Partition} 已消费完", result.Topic, result.Partition);
if (result.IsPartitionEOF)
{
//_logger.LogInformation("Kafka消费: {Topic} 分区 {Partition} 已消费完", result.Topic, result.Partition);
await Task.Delay(DelayTime, cts.Token);
}
else if (result.Message.Value != null)
{
if (_kafkaOptionConfig.EnableFilter)
{
var headersFilter = new HeadersFilter { { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } };
// 检查 Header 是否符合条件
if (!headersFilter.Match(result.Message.Headers))
{
consumer.Commit(result); // 提交偏移量
// 跳过消息
continue;
}
}
messages.Add((result.Message.Value, result.TopicPartitionOffset));
}
}
else
{
// 无消息时短暂等待
await Task.Delay(DelayTime, cts.Token);
}
else if (result.Message.Value != null)
}
// 处理批次
if (messages.Count > 0)
{
bool success = await messageBatchHandler(messages.Select(m => m.Value).ToList());
if (success)
{
if (_kafkaOptionConfig.EnableFilter)
var offsetsByPartition = new Dictionary<TopicPartition, long>();
foreach (var msg in messages)
{
var headersFilter = new HeadersFilter { { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } };
// 检查 Header 是否符合条件
if (!headersFilter.Match(result.Message.Headers))
var tp = msg.Offset.TopicPartition;
var offset = msg.Offset.Offset;
if (!offsetsByPartition.TryGetValue(tp, out var currentMax) || offset > currentMax)
{
consumer.Commit(result); // 提交偏移量
// 跳过消息
continue;
offsetsByPartition[tp] = offset;
}
}
messages.Add((result.Message.Value, result.TopicPartitionOffset));
}
}
else
{
// 无消息时短暂等待
await Task.Delay(DelayTime, cts.Token);
}
}
// 处理批次
if (messages.Count > 0)
var offsetsToCommit = offsetsByPartition
.Select(kv => new TopicPartitionOffset(kv.Key, new Offset(kv.Value + 1)))
.ToList();
consumer.Commit(offsetsToCommit);
}
messages.Clear();
}
startTime = DateTime.UtcNow;
}
catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
bool success = await messageBatchHandler(messages.Select(m => m.Value).ToList());
if (success)
{
var offsetsByPartition = new Dictionary<TopicPartition, long>();
foreach (var msg in messages)
{
var tp = msg.Offset.TopicPartition;
var offset = msg.Offset.Offset;
if (!offsetsByPartition.TryGetValue(tp, out var currentMax) || offset > currentMax)
{
offsetsByPartition[tp] = offset;
}
}
var offsetsToCommit = offsetsByPartition
.Select(kv => new TopicPartitionOffset(kv.Key, new Offset(kv.Value + 1)))
.ToList();
consumer.Commit(offsetsToCommit);
}
messages.Clear();
_logger.LogError(ex, $"消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (KafkaException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"{string.Join("", topics)} 消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (OperationCanceledException)
{
//ignore
}
catch (Exception ex)
{
_logger.LogError(ex, "处理批量消息时发生未知错误");
}
}
}, cts.Token);
startTime = DateTime.UtcNow;
}
catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex))
{
_logger.LogError(ex, $"消息消费失败: {ex.Error.Reason}");
throw; // 抛出异常,以便重试
}
catch (OperationCanceledException)
{
//ignore
}
catch (Exception ex)
{
_logger.LogError(ex, "处理批量消息时发生未知错误");
}
}
}, cts.Token);
await Task.CompletedTask;
});
}
catch (Exception ex)
{
await Task.CompletedTask;
});
throw;
}
}
@ -563,12 +627,20 @@ namespace JiShe.CollectBus.Kafka.Consumer
/// <typeparam name="TValue"></typeparam>
public void Unsubscribe<TKey, TValue>(string[] topics, string? groupId) where TKey : notnull where TValue : class
{
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}";
if (_consumerStore.TryRemove(consumerKey, out var entry))
try
{
entry.CTS.Cancel();
(entry.Consumer as IDisposable)?.Dispose();
entry.CTS.Dispose();
var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}";
if (_consumerStore.TryRemove(consumerKey, out var entry))
{
entry.CTS.Cancel();
(entry.Consumer as IDisposable)?.Dispose();
entry.CTS.Dispose();
}
}
catch (Exception ex)
{
throw;
}
}

View File

@ -1,16 +1,8 @@
using Confluent.Kafka;
using Microsoft.Extensions.Logging;
using Polly;
using Polly.CircuitBreaker;
using Polly.Retry;
using Polly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Polly.Contrib.WaitAndRetry;
using Volo.Abp.DependencyInjection;
using Microsoft.Extensions.Logging;
using JiShe.CollectBus.Kafka.Producer;
namespace JiShe.CollectBus.Kafka.Internal
{
@ -41,7 +33,9 @@ namespace JiShe.CollectBus.Kafka.Internal
ErrorCode.RebalanceInProgress,
ErrorCode.NotCoordinatorForGroup,
ErrorCode.NetworkException,
ErrorCode.GroupCoordinatorNotAvailable
ErrorCode.GroupCoordinatorNotAvailable,
ErrorCode.InvalidGroupId,
ErrorCode.IllegalGeneration
};
return ex switch
{

View File

@ -21,6 +21,10 @@ namespace JiShe.CollectBus.Kafka
public static class KafkaSubscribeExtensions
{
private static long _threadCount = 0;
private static long _topicSubscribeCount = 0;
private static long _threadStartCount = 0;
public static void UseInitKafkaTopic(this IServiceProvider provider)
{
//初始化主题信息
@ -46,12 +50,12 @@ namespace JiShe.CollectBus.Kafka
lifetime.ApplicationStarted.Register(() =>
{
var logger = provider.GetRequiredService<ILogger<CollectBusKafkaModule>>();
var threadCount = 0;
var topicCount = 0;
//var threadCount = 0;
//var topicCount = 0;
var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
if (string.IsNullOrWhiteSpace(assemblyPath))
{
logger.LogInformation($"kafka订阅未能找到程序路径");
logger.LogWarning($"kafka订阅未能找到程序路径");
return;
}
var dllFiles = Directory.GetFiles(assemblyPath, "*.dll");
@ -69,21 +73,35 @@ namespace JiShe.CollectBus.Kafka
if (subscribeTypes.Count == 0)
continue;
foreach (var subscribeType in subscribeTypes)
// 并行处理
Parallel.ForEach(subscribeTypes, subscribeType =>
{
var subscribes = provider.GetServices(subscribeType).ToList();
subscribes.ForEach(subscribe =>
Parallel.ForEach(subscribes,subscribe =>
{
if (subscribe != null)
{
Tuple<int, int> tuple = BuildKafkaSubscribe(subscribe, provider, logger, kafkaOptions.Value);
threadCount += tuple.Item1;
topicCount += tuple.Item2;
//threadCount += tuple.Item1;
//topicCount += tuple.Item2;
}
});
}
});
//foreach (var subscribeType in subscribeTypes)
//{
// var subscribes = provider.GetServices(subscribeType).ToList();
// subscribes.ForEach(subscribe =>
// {
// if (subscribe != null)
// {
// Tuple<int, int> tuple = BuildKafkaSubscribe(subscribe, provider, logger, kafkaOptions.Value);
// threadCount += tuple.Item1;
// topicCount += tuple.Item2;
// }
// });
//}
}
logger.LogInformation($"kafka订阅主题:{topicCount}数,共启动:{threadCount}线程");
logger.LogWarning($"kafka订阅主题:{_topicSubscribeCount}数,共启动:{_threadCount}线程");
});
}
@ -135,24 +153,50 @@ namespace JiShe.CollectBus.Kafka
//var configuration = provider.GetRequiredService<IConfiguration>();
int threadCount = 0;
foreach (var sub in subscribedMethods)
Parallel.ForEach(subscribedMethods, sub =>
{
int partitionCount = 3;// kafkaOptionConfig.NumPartitions;
#if DEBUG
Interlocked.Increment(ref _topicSubscribeCount);
int partitionCount = sub.Attribute!.TaskCount == -1 ? 3 : sub.Attribute!.TaskCount;// kafkaOptionConfig.NumPartitions;
var adminClientService = provider.GetRequiredService<IAdminClientService>();
int topicCount = adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic);
//int partitionCount = sub.Attribute!.TaskCount == -1 ? topicCount : sub.Attribute!.TaskCount;// kafkaOptionConfig.NumPartitions;
partitionCount = partitionCount > topicCount ? topicCount : partitionCount;
#endif
//int partitionCount = sub.Attribute!.TaskCount==-1?adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic) : sub.Attribute!.TaskCount;
//partitionCount = sub.Attribute!.TaskCount == -1 ? adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic) : sub.Attribute!.TaskCount;
if (partitionCount <= 0)
partitionCount = 1;
for (int i = 0; i < partitionCount; i++)
Parallel.For(0,partitionCount, async (partition) =>
{
//if (sub.Attribute!.Topic == ProtocolConst.SubscriberLoginReceivedEventName)
Task.Run(() => StartConsumerAsync(provider, sub.Attribute!, sub.Method, subscribe, logger));
threadCount++;
}
}
Interlocked.Increment(ref _threadCount);
//Task.Run(() => StartConsumerAsync(provider, sub.Attribute!, sub.Method, subscribe, logger));
//threadCount++;
await StartConsumerAsync(provider, sub.Attribute!, sub.Method, subscribe, logger);
});
});
//foreach (var sub in subscribedMethods)
//{
// //int partitionCount = sub.Attribute!.TaskCount==-1?3: sub.Attribute!.TaskCount;// kafkaOptionConfig.NumPartitions;
// var adminClientService = provider.GetRequiredService<IAdminClientService>();
// int topicCount = adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic);
// int partitionCount = sub.Attribute!.TaskCount == -1 ? topicCount : sub.Attribute!.TaskCount;// kafkaOptionConfig.NumPartitions;
// partitionCount = partitionCount > topicCount ? topicCount : partitionCount;
// //partitionCount = sub.Attribute!.TaskCount == -1 ? adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic) : sub.Attribute!.TaskCount;
// if (partitionCount <= 0)
// partitionCount = 1;
// for (int i = 0; i < partitionCount; i++)
// {
// //if (sub.Attribute!.Topic == ProtocolConst.SubscriberLoginReceivedEventName)
// Task.Run(() => StartConsumerAsync(provider, sub.Attribute!, sub.Method, subscribe, logger));
// threadCount++;
// }
//}
return Tuple.Create(threadCount, subscribedMethods.Length);
}
@ -165,6 +209,8 @@ namespace JiShe.CollectBus.Kafka
if (attr.EnableBatch)
{
Interlocked.Increment(ref _threadStartCount);
logger.LogInformation($"kafka开启线程消费:{_threadStartCount}");
await consumerService.SubscribeBatchAsync<dynamic>(attr.Topic, async (message) =>
{
try
@ -180,11 +226,18 @@ namespace JiShe.CollectBus.Kafka
// 处理消费错误
logger.LogError($"kafka批量消费异常:{ex.Message}");
}
catch (Exception ex)
{
// 处理消费错误
logger.LogError($"kafka批量消费异常:{ex.Message}");
}
return await Task.FromResult(false);
}, attr.GroupId, attr.BatchSize, attr.BatchTimeout);
}
else
{
Interlocked.Increment(ref _threadStartCount);
logger.LogInformation($"kafka开启线程消费:{_threadStartCount}");
await consumerService.SubscribeAsync<dynamic>(attr.Topic, async (message) =>
{
try
@ -200,6 +253,11 @@ namespace JiShe.CollectBus.Kafka
// 处理消费错误
logger.LogError($"kafka消费异常:{ex.Message}");
}
catch (Exception ex)
{
// 处理消费错误
logger.LogError($"kafka批量消费异常:{ex.Message}");
}
return await Task.FromResult(false);
}, attr.GroupId);
}
@ -212,125 +270,133 @@ namespace JiShe.CollectBus.Kafka
/// </summary>
private static async Task<bool> ProcessMessageAsync(List<dynamic> messages, MethodInfo method, object subscribe)
{
var parameters = method.GetParameters();
bool isGenericTask = method.ReturnType.IsGenericType
&& method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>);
bool existParameters = parameters.Length > 0;
object[]? executeParameters = null;
if (existParameters)
try
{
IList? list = null;
Tuple<Type, Type?> tuple = method.GetParameterTypeInfo();
bool isEnumerable = false;
if (tuple.Item2 != null)
{
Type listType = typeof(List<>).MakeGenericType(tuple.Item2);
list = (IList)Activator.CreateInstance(listType)!;
isEnumerable = tuple.Item2.IsConvertType();
}
else
{
isEnumerable = tuple.Item1.IsConvertType();
}
#region
//foreach (var msg in messages)
//{
// if (tuple.Item2 != null)
// {
// if (isEnumerable)
// {
// var parameterType = parameters[0].ParameterType;
// var data=messages?.Serialize().Deserialize(parameterType);
// messageObj = data!=null? new[] { data }:null;
// break;
// }
// else
// {
// // 集合类型
// var data = msg?.Serialize().Deserialize(tuple.Item2) /*isEnumerable ? Convert.ChangeType(msg, tuple.Item2) : msg?.Serialize().Deserialize(tuple.Item2)*/;
// if (data != null)
// list?.Add(data);
// }
var parameters = method.GetParameters();
bool isGenericTask = method.ReturnType.IsGenericType
&& method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>);
bool existParameters = parameters.Length > 0;
object[]? executeParameters = null;
// }
// else
// {
// // (dynamic)Convert.ChangeType(msg, tuple.Item1)
// using (var stream = new MemoryStream(msg))
// {
// var data1= System.Text.Json.JsonSerializer.Deserialize(stream, tuple.Item1);
// }
// var data = isEnumerable ? System.Text.Json.JsonSerializer.Deserialize(msg, tuple.Item1): msg?.ToString()?.Deserialize(tuple.Item1);
// if (data != null)
// messageObj = new[] { data };
// }
//}
//if (tuple.Item2 != null && list != null && list.Count > 0)
//{
// messageObj = new[] { list };
//}
#endregion
var parameterDescriptors = method.GetParameters();
executeParameters = new object?[parameterDescriptors.Length];
for (var i = 0; i < parameterDescriptors.Length; i++)
if (existParameters)
{
foreach (var item in messages)
{
object? tempParameter=null;
var parameterDescriptor = parameterDescriptors[i];
if (KafkaSerialization.IsJsonType(item))
IList? list = null;
Tuple<Type, Type?> tuple = method.GetParameterTypeInfo();
bool isEnumerable = false;
if (tuple.Item2 != null)
{
Type listType = typeof(List<>).MakeGenericType(tuple.Item2);
list = (IList)Activator.CreateInstance(listType)!;
isEnumerable = tuple.Item2.IsConvertType();
}
else
{
isEnumerable = tuple.Item1.IsConvertType();
}
#region
//foreach (var msg in messages)
//{
// if (tuple.Item2 != null)
// {
// if (isEnumerable)
// {
// var parameterType = parameters[0].ParameterType;
// var data=messages?.Serialize().Deserialize(parameterType);
// messageObj = data!=null? new[] { data }:null;
// break;
// }
// else
// {
// // 集合类型
// var data = msg?.Serialize().Deserialize(tuple.Item2) /*isEnumerable ? Convert.ChangeType(msg, tuple.Item2) : msg?.Serialize().Deserialize(tuple.Item2)*/;
// if (data != null)
// list?.Add(data);
// }
// }
// else
// {
// // (dynamic)Convert.ChangeType(msg, tuple.Item1)
// using (var stream = new MemoryStream(msg))
// {
// var data1= System.Text.Json.JsonSerializer.Deserialize(stream, tuple.Item1);
// }
// var data = isEnumerable ? System.Text.Json.JsonSerializer.Deserialize(msg, tuple.Item1): msg?.ToString()?.Deserialize(tuple.Item1);
// if (data != null)
// messageObj = new[] { data };
// }
//}
//if (tuple.Item2 != null && list != null && list.Count > 0)
//{
// messageObj = new[] { list };
//}
#endregion
var parameterDescriptors = method.GetParameters();
executeParameters = new object?[parameterDescriptors.Length];
for (var i = 0; i < parameterDescriptors.Length; i++)
{
foreach (var item in messages)
{
tempParameter = KafkaSerialization.Deserialize(item, tuple.Item2 != null? tuple.Item2: parameterDescriptor.ParameterType);
}
else
{
var converter = TypeDescriptor.GetConverter(parameterDescriptor.ParameterType);
if (converter.CanConvertFrom(item.GetType()))
object? tempParameter = null;
var parameterDescriptor = parameterDescriptors[i];
if (KafkaSerialization.IsJsonType(item))
{
tempParameter = converter.ConvertFrom(item);
tempParameter = KafkaSerialization.Deserialize(item, tuple.Item2 != null ? tuple.Item2 : parameterDescriptor.ParameterType);
}
else
{
if (parameterDescriptor.ParameterType.IsInstanceOfType(item))
tempParameter = item;
else
tempParameter =Convert.ChangeType(item, parameterDescriptor.ParameterType);
}
}
if (tuple.Item2 == null)
{
executeParameters[i] = tempParameter;
}
else
{
list.Add(tempParameter);
}
}
if(list!=null && list.Count>0)
executeParameters[i] = list;
}
}
var result = method.Invoke(subscribe, executeParameters);
if (result is Task<ISubscribeAck> genericTask)
{
await genericTask.ConfigureAwait(false);
return genericTask.Result.Ack;
var converter = TypeDescriptor.GetConverter(parameterDescriptor.ParameterType);
if (converter.CanConvertFrom(item.GetType()))
{
tempParameter = converter.ConvertFrom(item);
}
else
{
if (parameterDescriptor.ParameterType.IsInstanceOfType(item))
tempParameter = item;
else
tempParameter = Convert.ChangeType(item, parameterDescriptor.ParameterType);
}
}
if (tuple.Item2 == null)
{
executeParameters[i] = tempParameter;
}
else
{
list.Add(tempParameter);
}
}
if (list != null && list.Count > 0)
executeParameters[i] = list;
}
}
var result = method.Invoke(subscribe, executeParameters);
if (result is Task<ISubscribeAck> genericTask)
{
await genericTask.ConfigureAwait(false);
return genericTask.Result.Ack;
}
else if (result is Task nonGenericTask)
{
await nonGenericTask.ConfigureAwait(false);
return true;
}
else if (result is ISubscribeAck ackResult)
{
return ackResult.Ack;
}
return false;
}
else if (result is Task nonGenericTask)
catch (Exception ex)
{
await nonGenericTask.ConfigureAwait(false);
return true;
throw;
}
else if (result is ISubscribeAck ackResult)
{
return ackResult.Ack;
}
return false;
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@ -6,6 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using Confluent.Kafka;
using JiShe.CollectBus.Common;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Kafka.Consumer;
using JiShe.CollectBus.Kafka.Internal;
using JiShe.CollectBus.Kafka.Serialization;
@ -68,15 +70,16 @@ namespace JiShe.CollectBus.Kafka.Producer
{
BootstrapServers = _kafkaOptionConfig.BootstrapServers,
//AllowAutoCreateTopics = true,
QueueBufferingMaxKbytes = 2_097_151, // 修改缓冲区最大为2GB默认为1GB
QueueBufferingMaxKbytes = 4_194_304, // 4_194_304 2_097_151 // 修改缓冲区最大为2GB默认为1GB
QueueBufferingMaxMessages = int.MaxValue, // 缓冲区消息条
CompressionType = CompressionType.Lz4, // 配置使用压缩算法LZ4其他gzip/snappy/zstd
BatchSize = 32_768, // 修改批次大小为32K
LingerMs = 20, // 修改等待时间为20ms
LingerMs = 20, // 修改等待时间为20ms默认为5ms
Acks = Acks.All, // 表明只有所有副本Broker都收到消息才算提交成功, 可以 Acks.Leader
MessageSendMaxRetries = 50, // 消息发送失败最大重试50次
MessageTimeoutMs = 120000, // 消息发送超时时间为2分钟,设置值MessageTimeoutMs > LingerMs
};
if (_kafkaOptionConfig.EnableAuthorization)
{
config.SecurityProtocol = _kafkaOptionConfig.SecurityProtocol;
@ -114,17 +117,25 @@ namespace JiShe.CollectBus.Kafka.Producer
/// <returns></returns>
public async Task ProduceAsync<TKey, TValue>(string topic, TKey key, TValue value)where TKey : notnull where TValue : class
{
var typeKey = typeof(KafkaProducer<TKey, TValue>);
var producer = GetProducer<TKey, TValue>(typeKey);
var message = new Message<TKey, TValue>
try
{
Key = key,
Value = value,
Headers = new Headers{
var typeKey = typeof(KafkaProducer<TKey, TValue>);
var producer = GetProducer<TKey, TValue>(typeKey);
var message = new Message<TKey, TValue>
{
Key = key,
Value = value,
Headers = new Headers{
{ "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) }
}
};
await producer.ProduceAsync(topic, message);
};
await producer.ProduceAsync(topic, message);
}
catch (Exception ex)
{
throw;
}
}
/// <summary>
@ -136,17 +147,24 @@ namespace JiShe.CollectBus.Kafka.Producer
/// <returns></returns>
public async Task ProduceAsync<TValue>(string topic, TValue value) where TValue : class
{
var typeKey = typeof(KafkaProducer<string, TValue>);
var producer = GetProducer<Null, TValue>(typeKey);
var message = new Message<Null, TValue>
try
{
//Key= _kafkaOptionConfig.ServerTagName,
Value = value,
Headers = new Headers{
var typeKey = typeof(KafkaProducer<string, TValue>);
var producer = GetProducer<Null, TValue>(typeKey);
var message = new Message<Null, TValue>
{
Value = value,
Headers = new Headers{
{ "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) }
}
};
await producer.ProduceAsync(topic, message);
};
await producer.ProduceAsync(topic, message);
}
catch (Exception ex)
{
throw;
}
}
/// <summary>
@ -162,26 +180,34 @@ namespace JiShe.CollectBus.Kafka.Producer
/// <returns></returns>
public async Task ProduceAsync<TKey, TValue>(string topic,TKey key,TValue value,int? partition=null, Action<DeliveryReport<TKey, TValue>>? deliveryHandler = null)where TKey : notnull where TValue : class
{
var message = new Message<TKey, TValue>
try
{
Key = key,
Value = value,
Headers = new Headers{
var message = new Message<TKey, TValue>
{
Key = key,
Value = value,
Headers = new Headers{
{ "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) }
}
};
var typeKey = typeof(KafkaProducer<TKey, TValue>);
var producer = GetProducer<TKey, TValue>(typeKey);
if (partition.HasValue)
{
var topicPartition = new TopicPartition(topic, partition.Value);
producer.Produce(topicPartition, message, deliveryHandler);
};
var typeKey = typeof(KafkaProducer<TKey, TValue>);
var producer = GetProducer<TKey, TValue>(typeKey);
if (partition.HasValue)
{
var topicPartition = new TopicPartition(topic, new Partition(partition.Value));
producer.Produce(topicPartition, message, deliveryHandler);
}
else
{
producer.Produce(topic, message, deliveryHandler);
}
await Task.CompletedTask;
}
else
catch (Exception ex)
{
producer.Produce(topic, message, deliveryHandler);
throw;
}
await Task.CompletedTask;
}
@ -197,26 +223,34 @@ namespace JiShe.CollectBus.Kafka.Producer
/// <returns></returns>
public async Task ProduceAsync<TValue>(string topic, TValue value, int? partition=null, Action<DeliveryReport<Null, TValue>>? deliveryHandler = null) where TValue : class
{
var message = new Message<Null, TValue>
try
{
//Key = _kafkaOptionConfig.ServerTagName,
Value = value,
Headers = new Headers{
var message = new Message<Null, TValue>
{
Value = value,
Headers = new Headers{
{ "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) }
}
};
var typeKey = typeof(KafkaProducer<Null, TValue>);
var producer = GetProducer<Null, TValue>(typeKey);
if (partition.HasValue)
{
var topicPartition = new TopicPartition(topic, partition.Value);
producer.Produce(topicPartition, message, deliveryHandler);
};
var typeKey = typeof(KafkaProducer<Null, TValue>);
var producer = GetProducer<Null, TValue>(typeKey);
if (partition.HasValue)
{
var topicPartition = new TopicPartition(topic, new Partition(partition.Value));
//_logger.LogError($"push消息{topic}-{partition.Value}");
producer.Produce(topicPartition, message, deliveryHandler);
}
else
{
producer.Produce(topic, message, deliveryHandler);
}
await Task.CompletedTask;
}
else
catch (Exception ex)
{
producer.Produce(topic, message, deliveryHandler);
throw;
}
await Task.CompletedTask;
}
public void Dispose()

View File

@ -19,6 +19,7 @@ namespace JiShe.CollectBus.Kafka.Serialization
{
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
WriteIndented = false,// 设置格式化输出
IncludeFields = true,// 允许反序列化到非公共 setter 和字段
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,// 允许特殊字符
IgnoreReadOnlyFields = true,
IgnoreReadOnlyProperties = true,
@ -53,7 +54,7 @@ namespace JiShe.CollectBus.Kafka.Serialization
{
if (data.IsEmpty)
return default;
return JsonSerializer.Deserialize<T>(data, _options)!;
return JsonSerializer.Deserialize<T>(data, _options)!;
}
catch (Exception ex)
{
@ -102,24 +103,37 @@ namespace JiShe.CollectBus.Kafka.Serialization
}
public static object? Deserialize(object value, Type valueType)
{
var _jsonSerializerOptions = new JsonSerializerOptions
try
{
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
WriteIndented = false,// 设置格式化输出
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,// 允许特殊字符
IgnoreReadOnlyFields = true,
IgnoreReadOnlyProperties = true,
NumberHandling = JsonNumberHandling.AllowReadingFromString, // 允许数字字符串
AllowTrailingCommas = true, // 忽略尾随逗号
ReadCommentHandling = JsonCommentHandling.Skip, // 忽略注释
PropertyNameCaseInsensitive = true, // 属性名称大小写不敏感
PropertyNamingPolicy = JsonNamingPolicy.CamelCase, // 属性名称使用驼峰命名规则
Converters = { new DateTimeJsonConverter() } // 注册你的自定义转换器,
};
var _jsonSerializerOptions = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
WriteIndented = false,// 设置格式化输出
IncludeFields = true,// 允许反序列化到非公共 setter 和字段
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,// 允许特殊字符
IgnoreReadOnlyFields = true,
IgnoreReadOnlyProperties = true,
NumberHandling = JsonNumberHandling.AllowReadingFromString, // 允许数字字符串
AllowTrailingCommas = true, // 忽略尾随逗号
ReadCommentHandling = JsonCommentHandling.Skip, // 忽略注释
PropertyNameCaseInsensitive = true, // 属性名称大小写不敏感
PropertyNamingPolicy = JsonNamingPolicy.CamelCase, // 属性名称使用驼峰命名规则
Converters = { new DateTimeJsonConverter() } // 注册你的自定义转换器,
};
if (value is JsonElement jsonElement) return jsonElement.Deserialize(valueType, _jsonSerializerOptions);
if (value is JsonElement jsonElement)
{
//return jsonElement.Deserialize(valueType, _jsonSerializerOptions);
return JsonSerializer.Deserialize(jsonElement, valueType, _jsonSerializerOptions);
}
throw new NotSupportedException("Type is not of type JsonElement");
return null;
}
catch (Exception ex)
{
throw;
}
}
}
}

View File

@ -13,6 +13,7 @@ using JiShe.CollectBus.IotSystems.MessageIssueds;
using Volo.Abp.Data;
using Volo.Abp.MongoDB;
using Volo.Abp.MultiTenancy;
using JiShe.CollectBus.IotSystems.LogRecord;
namespace JiShe.CollectBus.MongoDB;
@ -32,7 +33,6 @@ public class CollectBusMongoDbContext : AbpMongoDbContext, ICollectBusMongoDbCon
public IMongoCollection<MessageIssued> MessageIssueds => Collection<MessageIssued>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{

View File

@ -1,5 +1,7 @@
using JiShe.CollectBus.IotSystems.MeterReadingRecords;
using JiShe.CollectBus.IotSystems.LogRecord;
using JiShe.CollectBus.IotSystems.MeterReadingRecords;
using JiShe.CollectBus.Repository;
using JiShe.CollectBus.Repository.LogRecord;
using JiShe.CollectBus.Repository.MeterReadingRecord;
using JiShe.CollectBus.ShardingStrategy;
using Microsoft.Extensions.DependencyInjection;
@ -35,10 +37,14 @@ public class CollectBusMongoDbModule : AbpModule
typeof(IShardingStrategy<>),
typeof(DayShardingStrategy<>));
context.Services.AddTransient(typeof(HourShardingStrategy<>));
//// 分表策略仓储 替换默认仓储
//options.AddRepository<MeterReadingRecords, MeterReadingRecordRepository>();
});
options.AddRepository<LogRecords, LogRecordRepository>();
});
context.Services.AddAlwaysDisableUnitOfWorkTransaction();
Configure<AbpUnitOfWorkDefaultOptions>(options =>
{

View File

@ -0,0 +1,57 @@
using JiShe.CollectBus.IotSystems.LogRecord;
using JiShe.CollectBus.IotSystems.MeterReadingRecords;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace JiShe.CollectBus.Repository.LogRecord
{
public interface ILogRecordRepository : IRepository<LogRecords, Guid>
{
/// <summary>
/// 批量插入
/// </summary>
/// <param name="entities"></param>
/// <param name="dateTime"></param>
/// <returns></returns>
Task InsertManyAsync(List<LogRecords> entities,
DateTime? dateTime);
/// <summary>
/// 单个插入
/// </summary>
/// <param name="entity"></param>
/// <param name="dateTime"></param>
/// <returns></returns>
Task<LogRecords> InsertAsync(LogRecords entity, DateTime? dateTime);
/// <summary>
/// 单条更新
/// </summary>
/// <param name="filter">过滤条件示例Builders<LogRecords>.Filter.Eq(x => x.Id, filter.Id)</param>
/// <param name="update">包含待更新的内容示例Builders<LogRecords>.Update.Set(x => x.SendHexMessage, SendHexMessage).Set(x => x.MessageId, MessageId)</param>
/// <param name="entity">数据实体,用于获取对应的分片库</param>
/// <returns></returns>
Task<LogRecords> UpdateOneAsync(FilterDefinition<LogRecords> filter, UpdateDefinition<LogRecords> update, LogRecords entity);
/// <summary>
/// 单个获取
/// </summary>
/// <param name="entity"></param>
/// <param name="dateTime"></param>
/// <returns></returns>
Task<LogRecords> FirOrDefaultAsync(LogRecords entity, DateTime dateTime);
/// <summary>
/// 多集合数据查询
/// </summary>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <returns></returns>
Task<List<LogRecords>> ParallelQueryAsync(DateTime startTime, DateTime endTime);
}
}

View File

@ -0,0 +1,166 @@
using JiShe.CollectBus.IotSystems.LogRecord;
using JiShe.CollectBus.IotSystems.MeterReadingRecords;
using JiShe.CollectBus.MongoDB;
using JiShe.CollectBus.Repository.MeterReadingRecord;
using JiShe.CollectBus.ShardingStrategy;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
namespace JiShe.CollectBus.Repository.LogRecord
{
public class LogRecordRepository : MongoDbRepository<CollectBusMongoDbContext, LogRecords, Guid>, ILogRecordRepository
{
private readonly HourShardingStrategy<LogRecords> _hourShardingStrategy;
private readonly IMongoDbContextProvider<CollectBusMongoDbContext> _dbContextProvider;
public LogRecordRepository(
IMongoDbContextProvider<CollectBusMongoDbContext> dbContextProvider,
HourShardingStrategy<LogRecords> hourShardingStrategy
)
: base(dbContextProvider)
{
_dbContextProvider = dbContextProvider;
_hourShardingStrategy = hourShardingStrategy;
}
/// <summary>
/// 批量插入
/// </summary>
/// <param name="entities"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override async Task<IEnumerable<LogRecords>> InsertManyAsync(IEnumerable<LogRecords> entities, bool autoSave = false, CancellationToken cancellationToken = default(CancellationToken))
{
var collection = await GetShardedCollection(DateTime.Now);
await collection.InsertManyAsync(entities);
return entities;
}
/// <summary>
/// 批量插入
/// </summary>
/// <param name="entities"></param>
/// <param name="dateTime"></param>
/// <returns></returns>
public async Task InsertManyAsync(List<LogRecords> entities, DateTime? dateTime)
{
var collection = await GetShardedCollection(dateTime);
await collection.InsertManyAsync(entities);
}
/// <summary>
/// 单条插入
/// </summary>
/// <param name="entity"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override async Task<LogRecords> InsertAsync(LogRecords entity, bool autoSave = false, CancellationToken cancellationToken = default(CancellationToken))
{
var collection = await GetShardedCollection(DateTime.Now);
await collection.InsertOneAsync(entity);
return entity;
}
/// <summary>
/// 单条插入
/// </summary>
/// <param name="entity"></param>
/// <param name="dateTime"></param>
/// <returns></returns>
public async Task<LogRecords> InsertAsync(LogRecords entity, DateTime? dateTime)
{
var collection = await GetShardedCollection(dateTime);
await collection.InsertOneAsync(entity);
return entity;
}
/// <summary>
/// 单条更新
/// </summary>
/// <param name="filter">过滤条件示例Builders<LogRecords>.Filter.Eq(x => x.Id, filter.Id)</param>
/// <param name="update">包含待更新的内容示例Builders<LogRecords>.Update.Set(x => x.SendHexMessage, SendHexMessage).Set(x => x.MessageId, MessageId)</param>
/// <param name="entity">数据实体,用于获取对应的分片库</param>
/// <returns></returns>
public async Task<LogRecords> UpdateOneAsync(FilterDefinition<LogRecords> filter, UpdateDefinition<LogRecords> update, LogRecords entity)
{
var collection = await GetShardedCollection(entity.CreationTime);
await collection.UpdateOneAsync(filter, update);
return entity;
}
/// <summary>
/// 单个获取
/// </summary>
/// <param name="entity"></param>
/// <param name="dateTime"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<LogRecords> FirOrDefaultAsync(LogRecords entity, DateTime dateTime)
{
var collection = await GetShardedCollection(dateTime);
var query = await collection.FindAsync(d => d.CreationTime == dateTime && d.AFN == entity.AFN && d.Fn == entity.Fn && d.Code == entity.Code);
return await query.FirstOrDefaultAsync();
}
/// <summary>
/// 多集合数据查询
/// </summary>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <returns></returns>
public async Task<List<LogRecords>> ParallelQueryAsync(DateTime startTime, DateTime endTime)
{
var collectionNames = _hourShardingStrategy.GetQueryCollectionNames(startTime, endTime);
var dbContext = await DbContextProvider.GetDbContextAsync();
var tasks = collectionNames.Select(async name =>
{
var collection = dbContext.Database.GetCollection<LogRecords>(name);
var filter = Builders<LogRecords>.Filter.And(
Builders<LogRecords>.Filter.Gte(x => x.CreationTime, startTime),
Builders<LogRecords>.Filter.Lte(x => x.CreationTime, endTime)
);
return await collection.Find(filter).ToListAsync();
});
var results = await Task.WhenAll(tasks);
return results.SelectMany(r => r).ToList();
}
/// <summary>
/// 获得分片集合
/// </summary>
/// <returns></returns>
private async Task<IMongoCollection<LogRecords>> GetShardedCollection(DateTime? dateTime)
{
var dbContext = await DbContextProvider.GetDbContextAsync();
string collectionName = string.Empty;
if (dateTime != null)
{
collectionName = _hourShardingStrategy.GetCollectionName(dateTime.Value);
}
else
{
collectionName = _hourShardingStrategy.GetCurrentCollectionName();
}
return dbContext.Database.GetCollection<LogRecords>(collectionName);
}
}
}

View File

@ -1,4 +1,5 @@
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
@ -22,7 +23,7 @@ namespace JiShe.CollectBus.ShardingStrategy
public string GetCollectionName(DateTime dateTime)
{
var baseName = typeof(TEntity).Name;
return $"{baseName}_{dateTime.GetDataTableShardingStrategy()}";
return $"{baseName}_{dateTime.GetDataTableShardingStrategy(TableTimeStrategyEnum.DayShardingStrategy)}";
}
/// <summary>
@ -32,7 +33,7 @@ namespace JiShe.CollectBus.ShardingStrategy
public string GetCurrentCollectionName()
{
var baseName = typeof(TEntity).Name;
return $"{baseName}_{DateTime.Now.GetDataTableShardingStrategy()}";
return $"{baseName}_{DateTime.Now.GetDataTableShardingStrategy(TableTimeStrategyEnum.DayShardingStrategy)}";
}
/// <summary>
@ -50,7 +51,7 @@ namespace JiShe.CollectBus.ShardingStrategy
while (current <= end)
{
months.Add($"{baseName}_{current.GetDataTableShardingStrategy()}");
months.Add($"{baseName}_{current.GetDataTableShardingStrategy(TableTimeStrategyEnum.DayShardingStrategy)}");
current = current.AddMonths(1);
}

View File

@ -0,0 +1,58 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
namespace JiShe.CollectBus.ShardingStrategy
{
/// <summary>
/// 按小时分表
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class HourShardingStrategy<TEntity>
{
/// <summary>
/// 获取指定时间对应的集合名
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public string GetCollectionName(DateTime dateTime)
{
var baseName = typeof(TEntity).Name;
return $"{baseName}_{dateTime.GetDataTableShardingStrategy(TableTimeStrategyEnum.HourShardingStrategy)}";
}
/// <summary>
/// 获取当前时间对应的集合名
/// </summary>
/// <returns></returns>
public string GetCurrentCollectionName()
{
var baseName = typeof(TEntity).Name;
return $"{baseName}_{DateTime.Now.GetDataTableShardingStrategy(TableTimeStrategyEnum.HourShardingStrategy)}";
}
/// <summary>
/// 用于查询时确定目标集合
/// </summary>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <returns></returns>
public IEnumerable<string> GetQueryCollectionNames(DateTime? startTime, DateTime? endTime)
{
var list = new List<string>();
var current = startTime ?? DateTime.MinValue;
var end = endTime ?? DateTime.MaxValue;
var baseName = typeof(TEntity).Name;
while (current <= end)
{
list.Add($"{baseName}_{current.GetDataTableShardingStrategy(TableTimeStrategyEnum.HourShardingStrategy)}");
current = current.AddHours(1);
}
return list.Distinct();
}
}
}

View File

@ -4,9 +4,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto
namespace JiShe.CollectBus.ShardingStrategy
{
public class AFN12_F188_AnalysisDto : AnalysisBaseDto<decimal>
public interface IHourShardingStrategy<TEntity> : IShardingStrategy<TEntity>
{
}
}

View File

@ -46,7 +46,7 @@ namespace JiShe.CollectBus.Protocol.T1882018.SendData
{
var itemCodeArr = request.ItemCode.Split('_');
var c_data = itemCodeArr[0];//01
var d_data = itemCodeArr[1];//91 或者 90
var d_data = itemCodeArr[2];//91 或者 90
var dataUnit = new List<string>() { "1F", d_data, "00" };
var dataList = Build188SendData.Build188SendCommand(request.MeterAddress, c_data, dataUnit);
@ -64,7 +64,7 @@ namespace JiShe.CollectBus.Protocol.T1882018.SendData
{
var itemCodeArr = request.ItemCode.Split('_');
var c_data = itemCodeArr[0];//01
var d_data = itemCodeArr[1];//55 或者 99
var d_data = itemCodeArr[2];//55 或者 99
var dataUnit = new List<string>() { "A0", "17", "00", d_data };
var dataList = Build188SendData.Build188SendCommand(request.MeterAddress, c_data, dataUnit);

View File

@ -91,8 +91,10 @@ namespace JiShe.CollectBus.Protocol.T1882018
List<string> dataUnit = new List<string>();
//数据转发场景 10H_F1
if (aFNStr == "10" && request.SubProtocolRequest != null && string.IsNullOrWhiteSpace(request.SubProtocolRequest.ItemCode) == false)
{
if (request.ItemCode == T37612012PacketItemCodeConst.AFN10HFN01H && request.SubProtocolRequest != null && string.IsNullOrWhiteSpace(request.SubProtocolRequest.ItemCode) == false)
{
//var subItemCodeArr = request.SubProtocolRequest.ItemCode.Split("_");
var t188PacketHandlerName = $"{T1882018PacketItemCodeConst.BasicT1882018}_{request.SubProtocolRequest.ItemCode}_Send";
Telemetry1882018PacketResponse t645PacketResponse = null;

View File

@ -1,4 +1,11 @@
using JiShe.CollectBus.Protocol.Dto;
using Apache.IoTDB;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
@ -8,35 +15,63 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_00H
/// <summary>
/// 5.1.3.1 F1全部确认对收到报文中的全部数据单元标识进行确认
/// </summary>
public class AFN0_F1_Analysis: IAnalysisStrategy<TB3761, UnitDataAnalysis<bool>>
public class AFN0_F1_Analysis: IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN0_F1_Analysis> _logger;
private readonly DataStorage _dataStorage;
public AFN0_F1_Analysis(ILogger<AFN0_F1_Analysis> logger)
public AFN0_F1_Analysis(ILogger<AFN0_F1_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage= dataStorage;
}
public Task<UnitDataAnalysis<bool>> ExecuteAsync(TB3761 tB3761)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(nameof(tB3761));
UnitDataAnalysis<bool> dto = new UnitDataAnalysis<bool>
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
var data = new AnalysisBaseDto<bool?>()
{
Code = tB3761.A.Code,
AFN = tB3761.AFN_FC.AFN,
Fn = tB3761.DT.Fn,
Pn = tB3761.DA.Pn,
Data= true
FiledDesc = "全部确认",
DataValue = true,
ItemType= $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
return Task.FromResult(dto);
// 查询电表信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId= deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<bool?>> dto = new UnitDataAnalysis<AnalysisBaseDto<bool?>>
{
Code = input.A.Code,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType= IOTDBDataTypeConst.Log
};
result?.Invoke(dto);
await _dataStorage.SaveDataToIotDbAsync<bool?>(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"00_1解析失败:{tB3761.A.Code}-{tB3761.DT.Fn}-{tB3761.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
_logger.LogError(ex, $"00_1解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
}
return await Task.FromResult(false);
}
}

View File

@ -1,4 +1,10 @@
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
@ -8,34 +14,66 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_00H
/// <summary>
/// 5.1.3.2 F2全部否认
/// </summary>
public class AFN0_F2_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<bool>>
public class AFN0_F2_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN0_F2_Analysis> _logger;
public AFN0_F2_Analysis(ILogger<AFN0_F2_Analysis> logger)
private readonly DataStorage _dataStorage;
public AFN0_F2_Analysis(ILogger<AFN0_F2_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage = dataStorage;
}
public Task<UnitDataAnalysis<bool>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
UnitDataAnalysis<bool> dto = new UnitDataAnalysis<bool>
ArgumentNullException.ThrowIfNull(input.A.Code);
var data = new AnalysisBaseDto<bool?>()
{
FiledDesc = "全部否认",
DataValue = false,
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询电表信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<bool?>> dto = new UnitDataAnalysis<AnalysisBaseDto<bool?>>
{
Code = input.A.Code,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = false,
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime =input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType = IOTDBDataTypeConst.Log
};
return Task.FromResult(dto);
result?.Invoke(dto);
#if DEBUG
_logger.LogWarning($"全部否认:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString}");
#endif
await _dataStorage.SaveDataToIotDbAsync<bool?>(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"00_2解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
}
}

View File

@ -0,0 +1,77 @@
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_02H
{
/// <summary>
/// 5.3.3.1 F1登录
/// </summary>
public class AFN2_F1_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN2_F1_Analysis> _logger;
private readonly DataStorage _dataStorage;
public AFN2_F1_Analysis(ILogger<AFN2_F1_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage= dataStorage;
}
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
var data = new AnalysisBaseDto<string>()
{
FiledDesc = "登录",
FiledName = "Type",
DataValue = "Login",
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<string>> dto = new UnitDataAnalysis<AnalysisBaseDto<string>>
{
Code = input.A.Code,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType = IOTDBDataTypeConst.Status
};
result?.Invoke(dto);
await _dataStorage.SaveStatusToIotDbAsync<string>(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"02_1解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
}
return await Task.FromResult(false);
}
}
}

View File

@ -0,0 +1,76 @@
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_02H
{
/// <summary>
/// 5.3.3.2 F2退出登录
/// </summary>
public class AFN2_F2_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN2_F2_Analysis> _logger;
private readonly DataStorage _dataStorage;
public AFN2_F2_Analysis(ILogger<AFN2_F2_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage = dataStorage;
}
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
var data = new AnalysisBaseDto<string>()
{
FiledDesc = "退出登录",
FiledName = "Type",
DataValue = "LogOut",
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<string>> dto = new UnitDataAnalysis<AnalysisBaseDto<string>>
{
Code = input.A.Code,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType = IOTDBDataTypeConst.Status
};
result?.Invoke(dto);
await _dataStorage.SaveStatusToIotDbAsync<string>(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"02_2解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
}
return await Task.FromResult(false);
}
}
}

View File

@ -0,0 +1,76 @@
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_02H
{
/// <summary>
/// 5.3.3.3 F3心跳
/// </summary>
public class AFN2_F3_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN2_F3_Analysis> _logger;
private readonly DataStorage _dataStorage;
public AFN2_F3_Analysis(ILogger<AFN2_F3_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage = dataStorage;
}
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
var data = new AnalysisBaseDto<string>()
{
FiledDesc = "心跳",
FiledName = "Type",
DataValue = "Heartbeat",
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<string>> dto = new UnitDataAnalysis<AnalysisBaseDto<string>>
{
Code = input.A.Code,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType = IOTDBDataTypeConst.Status
};
result?.Invoke(dto);
await _dataStorage.SaveStatusToIotDbAsync<string>(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"02_3解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
}
return await Task.FromResult(false);
}
}
}

View File

@ -1,8 +1,13 @@
using System.Text;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.AnalysisData;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
@ -11,39 +16,68 @@ namespace JiShe.CollectBus.Protocol.AnalysisData.AFN_09H
/// <summary>
/// 5.9.1.2 F1:终端版本信息
/// </summary>
public class AFN9_F1_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<AFN9_F1_AnalysisDto>>
public class AFN9_F1_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN9_F1_Analysis> _logger;
public AFN9_F1_Analysis(ILogger<AFN9_F1_Analysis> logger)
private readonly DataStorage _dataStorage;
public AFN9_F1_Analysis(ILogger<AFN9_F1_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage = dataStorage;
}
public Task<UnitDataAnalysis<AFN9_F1_AnalysisDto>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList);
var data = AnalysisDataUnit(input.UnitData.HexMessageList);
data.AreaCode = input.A.Code?.Substring(0, 4);
data.Address = input.A.Code?.Substring(4, 5);
UnitDataAnalysis<AFN9_F1_AnalysisDto> dto = new UnitDataAnalysis<AFN9_F1_AnalysisDto>
var version = AnalysisDataUnit(input.UnitData.HexMessageList);
version.AreaCode = input.A.Code?.Substring(0, 4);
version.Address = input.A.Code?.Substring(4, 5);
var data = new AnalysisBaseDto<AFN9_F1_AnalysisDto?>()
{
Code = input.A.Code,
FiledDesc = "终端版本信息",
DataValue = version,
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<AFN9_F1_AnalysisDto?>> dto = new UnitDataAnalysis<AnalysisBaseDto<AFN9_F1_AnalysisDto?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data= data
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType=IOTDBDataTypeConst.Data
};
return Task.FromResult(dto);
result?.Invoke(dto);
await _dataStorage.SaveDataToIotDbAsync(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"09_1解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
private AFN9_F1_AnalysisDto AnalysisDataUnit(List<string> hexMessageList)

View File

@ -1,5 +1,10 @@
using System.Text;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol3761;
@ -10,36 +15,64 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_09H
/// <summary>
/// 5.9.2.4.9 F9远程通信模块版本信息(只读解析SIM卡号)
/// </summary>
public class AFN9_F9_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<string>>
public class AFN9_F9_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN9_F9_Analysis> _logger;
public AFN9_F9_Analysis(ILogger<AFN9_F9_Analysis> logger)
private readonly DataStorage _dataStorage;
public AFN9_F9_Analysis(ILogger<AFN9_F9_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage = dataStorage;
}
public Task<UnitDataAnalysis<string>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList);
UnitDataAnalysis<string> dto = new UnitDataAnalysis<string>
var data = new AnalysisBaseDto<string?>()
{
Code = input.A.Code,
FiledDesc = "远程通信模块版本信息",
DataValue = Encoding.ASCII.GetString(string.Join("", input.UnitData.HexMessageList.Skip(30).Take(20).ToList()).HexToByte()).Replace("\0", ""),
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<string?>> dto = new UnitDataAnalysis<AnalysisBaseDto<string?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = Encoding.ASCII.GetString(string.Join("", input.UnitData.HexMessageList.Skip(30).Take(20).ToList()).HexToByte()).Replace("\0", "") //SIM卡
Data = data, //SIM卡
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType= IOTDBDataTypeConst.Data
};
return Task.FromResult(dto);
result?.Invoke(dto);
await _dataStorage.SaveDataToIotDbAsync(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"00_1解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
}
}

View File

@ -1,4 +1,8 @@
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
@ -10,45 +14,71 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH
/// <summary>
/// 5.10.1.3.1 F10终端电能表/交流采样装置配置参数
/// </summary>
internal class AFN10_F10_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<AFN10_F10_AnalysisDto>>
internal class AFN10_F10_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN10_F10_Analysis> _logger;
public AFN10_F10_Analysis(ILogger<AFN10_F10_Analysis> logger)
private readonly DataStorage _dataStorage;
public AFN10_F10_Analysis(ILogger<AFN10_F10_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage = dataStorage;
}
public Task<UnitDataAnalysis<AFN10_F10_AnalysisDto>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList);
Tuple<int, List<AFN10F10Entity>> tuple = AFN10F10EntityAnalysis(input.UnitData.HexMessageList);
UnitDataAnalysis<AFN10_F10_AnalysisDto> dto = new UnitDataAnalysis<AFN10_F10_AnalysisDto>
var data = new AnalysisBaseDto<AFN10_F10_AnalysisDto?>()
{
Code = input.A.Code,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data=new AFN10_F10_AnalysisDto()
FiledDesc = "终端电能表/交流采样装置配置参数",
DataValue = new AFN10_F10_AnalysisDto()
{
AFN10F10Entitys = tuple.Item2,
ConfigNum = tuple.Item1
}
},
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
return Task.FromResult(dto);
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<AFN10_F10_AnalysisDto?>> dto = new UnitDataAnalysis<AnalysisBaseDto<AFN10_F10_AnalysisDto?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType=IOTDBDataTypeConst.Param
};
result?.Invoke(dto);
await _dataStorage.SaveDataToIotDbAsync<AFN10_F10_AnalysisDto?>(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0A_10解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
public Tuple<int, List<AFN10F10Entity>> AFN10F10EntityAnalysis(List<string> hexMessageList)
{
List<Dictionary<string, string>> meterList = new List<Dictionary<string, string>>();
@ -62,22 +92,25 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH
SerialNum = $"{sArray[1]}{sArray[0]}".HexToDec(),
Point = $"{sArray[3]}{sArray[2]}".HexToDec(),
RuleType= GetProtocol(sArray[5]),
ComAddress= $"{sArray[11]}{sArray[10]}{sArray[9]}{sArray[8]}{sArray[7]}{sArray[6]}",
ComPwd= $"{sArray[17]}{sArray[16]}{sArray[15]}{sArray[14]}{sArray[13]}{sArray[12]}".Substring(6, 6),
ElectricityRatesNum= sArray[18].HexToBin().Substring(2, 6).BinToDec(),
CollectorAddress = $"{sArray[25]}{sArray[24]}{sArray[23]}{sArray[22]}{sArray[21]}{sArray[20]}",
//ComAddress= $"{sArray[11]}{sArray[10]}{sArray[9]}{sArray[8]}{sArray[7]}{sArray[6]}"
//ComPwd= $"{sArray[17]}{sArray[16]}{sArray[15]}{sArray[14]}{sArray[13]}{sArray[12]}".Substring(6, 6),
//ElectricityRatesNum= sArray[18].HexToBin().Substring(2, 6).BinToDec(),
//CollectorAddress = $"{sArray[25]}{sArray[24]}{sArray[23]}{sArray[22]}{sArray[21]}{sArray[20]}",
};
string baudPort = sArray[4].HexToBin().PadLeft(8, '0'); //波特率和端口号放在一个字节内
aFN10F10Entity.ComAddress = $"{sArray[11]}{sArray[10]}{sArray[9]}{sArray[8]}{sArray[7]}{sArray[6]}";
aFN10F10Entity.ComPwd = $"{sArray[17]}{sArray[16]}{sArray[15]}{sArray[14]}{sArray[13]}{sArray[12]}".Substring(6, 6);
aFN10F10Entity.ElectricityRatesNum = sArray[18].HexTo4BinZero().Substring(2, 6).BinToDec();
aFN10F10Entity.CollectorAddress = $"{sArray[25]}{sArray[24]}{sArray[23]}{sArray[22]}{sArray[21]}{sArray[20]}";
string baudPort = sArray[4].HexTo4BinZero().PadLeft(8, '0'); //波特率和端口号放在一个字节内
aFN10F10Entity.BaudRate = GetBaudrate(baudPort.Substring(0, 3));
aFN10F10Entity.Port = baudPort.Substring(3, 5).BinToDec();
string dataDigit = sArray[19].HexToBin().PadLeft(8, '0'); //有功电能示值整数位及小数位个数
string dataDigit = sArray[19].HexTo4BinZero().PadLeft(8, '0'); //有功电能示值整数位及小数位个数
aFN10F10Entity.IntegerBitsNum = dataDigit.Substring(4, 2).BinToDec() + 4;
aFN10F10Entity.DecimalPlacesNum = dataDigit.Substring(6, 2).BinToDec() + 1;
string classNo = sArray[26].HexToBin().PadLeft(8, '0');//用户大类号及用户小类号
string classNo = sArray[26].HexTo4BinZero().PadLeft(8, '0');//用户大类号及用户小类号
aFN10F10Entity.UserCategoryNum = classNo.Substring(0, 4).BinToDec() + 1;
aFN10F10Entity.UserCategoryNum = classNo.Substring(4, 4).BinToDec() + 1;
aFN10F10Entitys.Add(aFN10F10Entity);
@ -154,5 +187,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH
}
return "其他协议";
}
}
}

View File

@ -1,55 +1,88 @@
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH
{
/// <summary>
/// 5.5.1.3.53 F66定时上报 2 类数据任务设置
/// </summary>
public class AFN10_F66_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<AFN10_F66_AnalysisDto>>
public class AFN10_F66_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN10_F66_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN10_F66_Analysis(ILogger<AFN10_F66_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN10_F66_Analysis(ILogger<AFN10_F66_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext= analysisStrategyContext;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<AFN10_F66_AnalysisDto>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList);
var data = await GenerateFinalResult(input.UnitData.HexMessageList);
data.Pn = input.DA.Pn;
UnitDataAnalysis<AFN10_F66_AnalysisDto> dto = new UnitDataAnalysis<AFN10_F66_AnalysisDto>
var data = new AnalysisBaseDto<AFN10_F66_AnalysisDto?>()
{
Code = input.A.Code,
FiledDesc = "终端电能表/交流采样装置配置参数",
DataValue = await GenerateFinalResult(input.UnitData.HexMessageList),
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<AFN10_F66_AnalysisDto?>> dto = new UnitDataAnalysis<AnalysisBaseDto<AFN10_F66_AnalysisDto?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data= data
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType = IOTDBDataTypeConst.Param
};
return await Task.FromResult(dto);
result?.Invoke(dto);
await _dataStorage.SaveDataToIotDbAsync<AFN10_F66_AnalysisDto?>(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0A_66解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
public async Task<AFN10_F66_AnalysisDto> GenerateFinalResult(List<string> hexMessageList)
{
AFN10_F66_AnalysisDto entity = new AFN10_F66_AnalysisDto();
var cycleBin = hexMessageList[4].HexToBin().PadLeft(8, '0');
var cycleBin = hexMessageList[4].HexTo4BinZero().PadLeft(8, '0');
var cycleUnitBin = cycleBin.Substring(0, 2);
var cycleValueBin = cycleBin.Substring(2, 6);
@ -58,11 +91,14 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH
//TODO:发送基准时间
var arrBaseTime = hexMessageList.GetRange(5, 6);
var baseTimeArrStr = await _analysisStrategyContext.ExecuteAsync<List<string>, string>("Appendix_A1", arrBaseTime);
var baseTimeArr= baseTimeArrStr.Split('_');
//entity.BaseTime = DateTime.Parse($"{DateTime.Now.Year.ToString().Substring(0, 2)}{arrBaseTime[0]}-{arrBaseTime[1]}-{arrBaseTime[2]} {arrBaseTime[3]}:{arrBaseTime[4]}:{arrBaseTime[5]}");
entity.BaseTime = Convert.ToDateTime(baseTimeArr[0]);
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A1), arrBaseTime, (value) =>
{
var baseTimeArrStr = (string)value;
var baseTimeArr = baseTimeArrStr.Split('_');
//entity.BaseTime = DateTime.Parse($"{DateTime.Now.Year.ToString().Substring(0, 2)}{arrBaseTime[0]}-{arrBaseTime[1]}-{arrBaseTime[2]} {arrBaseTime[3]}:{arrBaseTime[4]}:{arrBaseTime[5]}");
entity.BaseTime = Convert.ToDateTime(baseTimeArr[0]);
});
entity.CurveRatio = hexMessageList[11].HexToDec();
var count = hexMessageList[12].HexToDec();
var dataArr = hexMessageList.GetRange(13, 4 * count);

View File

@ -1,4 +1,10 @@
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
@ -8,36 +14,64 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH
/// <summary>
/// 5.5.1.3.55 F68定时上报 2 类数据任务启动/停止设置
/// </summary>
public class AFN10_F68_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<bool>>
public class AFN10_F68_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN10_F68_Analysis> _logger;
public AFN10_F68_Analysis(ILogger<AFN10_F68_Analysis> logger)
private readonly DataStorage _dataStorage;
public AFN10_F68_Analysis(ILogger<AFN10_F68_Analysis> logger, DataStorage dataStorage)
{
_logger = logger;
_dataStorage = dataStorage;
}
public Task<UnitDataAnalysis<bool>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList);
UnitDataAnalysis<bool> dto = new UnitDataAnalysis<bool>
var data = new AnalysisBaseDto<bool?>()
{
Code = input.A.Code,
FiledDesc = "终端电能表/交流采样装置配置参数",
DataValue = input.UnitData.HexMessageList[4].Equals("55"),
ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.FocusId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.FocusAddress;
data.DeviceType = MeterTypeEnum.Focus;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<bool?>> dto = new UnitDataAnalysis<AnalysisBaseDto<bool?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = input.UnitData.HexMessageList[4].Equals("55")
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.None,
TimeDensity = -1,
DataType = IOTDBDataTypeConst.Param
};
result?.Invoke(dto);
await _dataStorage.SaveDataToIotDbAsync<bool?>(dto);
return Task.FromResult(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0A_68解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
}
}

View File

@ -1,56 +1,87 @@
using JiShe.CollectBus.IoTDB.Interface;
using Apache.IoTDB;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IoTDB.Interface;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
{
/// <summary>
/// 5.12.2.4.85 F129当前正向有功电能示值总、费率1M
/// </summary>
public class AFN12_F129_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AFN12_F129_AnalysisDto>>>
public class AFN12_F129_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F129_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
private readonly IIoTDbProvider _dbProvider;
public AFN12_F129_Analysis(ILogger<AFN12_F129_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, IIoTDbProvider dbProvider)
private readonly DataStorage _dataStorage;
public AFN12_F129_Analysis(ILogger<AFN12_F129_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dbProvider= dbProvider;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AFN12_F129_AnalysisDto>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
ArgumentNullException.ThrowIfNull(input.A.A3?.D1_D7);
UnitDataAnalysis<List<AFN12_F129_AnalysisDto>> unitDataAnalysis = new UnitDataAnalysis<List<AFN12_F129_AnalysisDto>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
MSA= input.A.A3.D1_D7,
PSEQ= input.SEQ.PSEQ,
MSA = input.A.A3.D1_D7,
PSEQ = input.SEQ.PSEQ,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
List<AFN12_F129_AnalysisDto> list = GenerateFinalResult(2, datas, "正向有功电能示值", input.AFN_FC.AFN, input.DT.Fn);
List<AnalysisBaseDto<decimal?>> list = GenerateFinalResult(2, datas, "正向有功电能示值", input.AFN_FC.AFN, input.DT.Fn);
if (list.Count > 0)
{
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code,input.DA.Pn);
if (deviceInfo != null)
{
list.ForEach(item =>
{
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
unitDataAnalysis.Data= list;
return await Task.FromResult(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_129解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
#region
@ -72,31 +103,44 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A14), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A14), arr, (value) =>
{
values.Add(value.ToString());
}); //从第10个开始每加5个字节为下一个值的开始
}
}
return values;
}
#endregion
public List<AFN12_F129_AnalysisDto> GenerateFinalResult(int index, List<string> data, string remark = "", int afn = 0, int fn = 0)
public List<AnalysisBaseDto<decimal?>> GenerateFinalResult(int index, List<string> data, string filedDesc = "", int afn = 0, int fn = 0)
{
List<AFN12_F129_AnalysisDto> list = new List<AFN12_F129_AnalysisDto>();
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = index; i < data.Count; i++)
{
AFN12_F129_AnalysisDto meter = new AFN12_F129_AnalysisDto();
decimal value = 0;
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ErrorCodeMsg= errorCode.Item2;
meter.ValidData = false;
}
else
decimal.TryParse(data[i], out value);
meter.DataValue = value;
meter.DataType = $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
meter.ReadTime = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
{
if(decimal.TryParse(data[i], out decimal value))
meter.DataValue = value;
}
meter.ItemType = i - index == 0 ? $"{afn.ToString().PadLeft(2, '0')}_{fn}": $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
string timeSpan = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00";
if (DateTime.TryParse(timeSpan, out DateTime readingDate))
{
meter.TimeSpan = readingDate;
}
meter.FiledDesc = filedDesc;
meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
}
return list;

View File

@ -1,51 +1,83 @@
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
{
/// <summary>
/// 5.12.2.4.86 F130当前正向无功组合无功 1电能示值总、费率 1M
/// </summary>
public class AFN12_F130_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AFN12_F130_AnalysisDto>>>
public class AFN12_F130_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F130_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F130_Analysis(ILogger<AFN12_F130_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F130_Analysis(ILogger<AFN12_F130_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AFN12_F130_AnalysisDto>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
List<AFN12_F130_AnalysisDto> list = GenerateFinalResult(2, datas, "正向无功电能示值", input.AFN_FC.AFN, input.DT.Fn);
UnitDataAnalysis<List<AFN12_F130_AnalysisDto>> unitDataAnalysis = new UnitDataAnalysis<List<AFN12_F130_AnalysisDto>>
List<AnalysisBaseDto<decimal?>> list = GenerateFinalResult(2, datas, "正向无功电能示值", input.AFN_FC.AFN, input.DT.Fn);
if (list.Count > 0)
{
Code = input.A.Code,
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
list.ForEach(item =>
{
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = list
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
return await Task.FromResult(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_130解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
private async Task<List<string>> AnalysisDataUnitAsync(List<string> hexMessageList)
@ -62,27 +94,40 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
}); //从第10个开始每加5个字节为下一个值的开始
}
}
return values;
}
public List<AFN12_F130_AnalysisDto> GenerateFinalResult(int index, List<string> data, string remark = "", int afn = 0, int fn = 0)
public List<AnalysisBaseDto<decimal?>> GenerateFinalResult(int index, List<string> data, string filedDesc = "", int afn = 0, int fn = 0)
{
List<AFN12_F130_AnalysisDto> list = new List<AFN12_F130_AnalysisDto>();
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = index; i < data.Count; i++)
{
AFN12_F130_AnalysisDto meter = new AFN12_F130_AnalysisDto();
decimal value = 0;
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ErrorCodeMsg = errorCode.Item2;
meter.ValidData = false;
}
else
decimal.TryParse(data[i], out value);
meter.DataValue = value;
meter.DataType = $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
meter.ReadTime = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
{
if(decimal.TryParse(data[i], out decimal value))
meter.DataValue = value;
}
meter.ItemType = i - index==0 ? $"{afn.ToString().PadLeft(2, '0')}_{fn}": $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
string timeSpan = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00";
if(DateTime.TryParse(timeSpan, out DateTime readingDate))
meter.TimeSpan = readingDate;
meter.FiledDesc = filedDesc;
meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
}
return list;

View File

@ -1,50 +1,84 @@
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using YamlDotNet.Core.Tokens;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
{
/// <summary>
/// 5.12.2.4.87 F131当前反向有功电能示值总、费率 1M
/// </summary>
public class AFN12_F131_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AFN12_F131_AnalysisDto>>>
public class AFN12_F131_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F131_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F131_Analysis(ILogger<AFN12_F131_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F131_Analysis(ILogger<AFN12_F131_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AFN12_F131_AnalysisDto>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
List<AFN12_F131_AnalysisDto> list = GenerateFinalResult(2, datas, "反向有功总电能示值", input.AFN_FC.AFN, input.DT.Fn);
UnitDataAnalysis<List<AFN12_F131_AnalysisDto>> unitDataAnalysis = new UnitDataAnalysis<List<AFN12_F131_AnalysisDto>>
List<AnalysisBaseDto<decimal?>> list = GenerateFinalResult(2, datas, "反向有功总电能示值", input.AFN_FC.AFN, input.DT.Fn);
if (list.Count > 0)
{
Code = input.A.Code,
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
list.ForEach(item =>
{
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = list
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
return await Task.FromResult(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_131解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
@ -62,27 +96,40 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A14), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A14), arr, (value) =>
{
values.Add(value.ToString());
}); //从第10个开始每加5个字节为下一个值的开始
}
}
return values;
}
public List<AFN12_F131_AnalysisDto> GenerateFinalResult(int index, List<string> data, string remark = "", int afn = 0, int fn = 0)
public List<AnalysisBaseDto<decimal?>> GenerateFinalResult(int index, List<string> data, string filedDesc = "", int afn = 0, int fn = 0)
{
List<AFN12_F131_AnalysisDto> list = new List<AFN12_F131_AnalysisDto>();
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = index; i < data.Count; i++)
{
AFN12_F131_AnalysisDto meter = new AFN12_F131_AnalysisDto();
decimal value = 0;
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ErrorCodeMsg = errorCode.Item2;
meter.ValidData = false;
}
else
decimal.TryParse(data[i], out value);
meter.DataValue = value;
meter.DataType = $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
meter.ReadTime = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
{
if(decimal.TryParse(data[i], out decimal value))
meter.DataValue = value;
}
meter.ItemType = i - index==0? $"{afn.ToString().PadLeft(2, '0')}_{fn}" : $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
string timeSpan = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00";
if(DateTime.TryParse(timeSpan, out DateTime readTime))
meter.TimeSpan = readTime;
meter.FiledDesc = filedDesc;
meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
}
return list;

View File

@ -1,52 +1,86 @@
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
{
/// <summary>
/// 5.12.2.4.88 F132当前反向无功组合无功 2电能示值总、费率 1M
/// </summary>
public class AFN12_F132_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AFN12_F132_AnalysisDto>>>
public class AFN12_F132_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F132_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F132_Analysis(ILogger<AFN12_F132_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F132_Analysis(ILogger<AFN12_F132_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AFN12_F132_AnalysisDto>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
List<AFN12_F132_AnalysisDto> list = GenerateFinalResult(2, datas, "反向无功电能示值", (int)input.AFN_FC.AFN!, (int)input.DT.Fn!);
UnitDataAnalysis<List<AFN12_F132_AnalysisDto>> unitDataAnalysis = new UnitDataAnalysis<List<AFN12_F132_AnalysisDto>>
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal?>> list = GenerateFinalResult(2, datas, "反向无功电能示值", dataType);
if (list.Count > 0)
{
Code = input.A.Code,
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
list.ForEach(item =>
{
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn ,
Pn = input.DA.Pn,
Data = list
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
return await Task.FromResult(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_132解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
private async Task<List<string>> AnalysisDataUnitAsync(List<string> hexMessageList)
@ -63,27 +97,43 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加4个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
}); //从第10个开始每加5个字节为下一个值的开始
}
}
return values;
}
public List<AFN12_F132_AnalysisDto> GenerateFinalResult(int index, List<string> data, string remark = "",int afn=0,int fn=0)
public List<AnalysisBaseDto<decimal?>> GenerateFinalResult(int index, List<string> data, string itemType, string filedDesc = "")
{
List<AFN12_F132_AnalysisDto> list = new List<AFN12_F132_AnalysisDto>();
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = index; i < data.Count; i++)
{
AFN12_F132_AnalysisDto meter = new AFN12_F132_AnalysisDto();
decimal value = 0;
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ErrorCodeMsg = errorCode.Item2;
meter.ValidData = false;
}
else
decimal.TryParse(data[i], out value);
meter.DataValue = value;
meter.DataType = $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
meter.ReadTime = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
{
if(decimal.TryParse(data[i], out decimal value))
meter.DataValue = value;
}
meter.ItemType = i - index==0?itemType:$"{itemType}_{i - index}";
string timeSpan = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00";
if (DateTime.TryParse(timeSpan,out DateTime readingDate))
{
meter.TimeSpan = readingDate;
}
meter.FiledDesc = filedDesc;
meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
}
return list;

View File

@ -1,53 +1,83 @@
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using static FreeSql.Internal.GlobalFilter;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
{
/// <summary>
/// 5.12.2.4.101 F145当月正向有功最大需量及发生时间总、费率 1M
/// </summary>
public class AFN12_F145_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<AFN12_F145_AnalysisDto>>
public class AFN12_F145_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F145_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F145_Analysis(ILogger<AFN12_F145_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F145_Analysis(ILogger<AFN12_F145_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<AFN12_F145_AnalysisDto>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
AFN12_F145_AnalysisDto data = GenerateFinalResult(2, datas, "当月正向有功最大需量及发生时间");
data.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
UnitDataAnalysis<AFN12_F145_AnalysisDto> unitDataAnalysis = new UnitDataAnalysis<AFN12_F145_AnalysisDto>
string itemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
AnalysisBaseDto<decimal?> data = GenerateFinalResult(datas, "当月正向有功最大需量及发生时间", itemType);
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
Code = input.A.Code,
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.MeterId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.MeterAddress;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<decimal?>> unitDataAnalysis = new UnitDataAnalysis<AnalysisBaseDto<decimal?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = data
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
return await Task.FromResult(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_145解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
@ -65,8 +95,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A23), arr);
values.Add(value.ToString());//正向有功总最大需量
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A23), arr, (value) =>
{
values.Add(value.ToString());
}); //正向有功总最大需量
}
arr = hexMessageList.GetRange(10 + i * 7 + 3, 4);
@ -75,30 +107,41 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, string>(nameof(Appendix_A17), arr);
values.Add(value.ToString());//正向有功总最大需量发生时间
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A17), arr, (value) =>
{
values.Add(value.ToString());
});//正向有功总最大需量发生时间
}
}
return values;
}
public AFN12_F145_AnalysisDto GenerateFinalResult(int index, List<string> data, string remark = "")
public AnalysisBaseDto<decimal?> GenerateFinalResult(List<string> data, string filedDesc,string itemType)
{
AFN12_F145_AnalysisDto dto = new AFN12_F145_AnalysisDto();
decimal value = 0;
AnalysisBaseDto<decimal?> dto = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCode = data[2].CheckErrorCode();
if (errorCode != null)
dto.ValidData = false;
else
decimal.TryParse(data[2], out value);
dto.DataValue = value;
dto.TimeSpan = $"{DateTime.Now.Year}-{data[3].Substring(0, 2)}-{data[3].Substring(2, 2)} {data[3].Substring(4, 2)}:{data[3].Substring(6, 2)}:00";//$"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)}";
if (DateTime.TryParse(dto.TimeSpan, out DateTime readingDate))
{
dto.ReadingDate = readingDate;
dto.ErrorCodeMsg = errorCode.Item2;
dto.ValidData = false;
}
else
{
if(decimal.TryParse(data[2], out decimal value))
dto.DataValue = value;
}
string timeSpan = $"{DateTime.Now.Year}-{data[3].Substring(0, 2)}-{data[3].Substring(2, 2)} {data[3].Substring(4, 2)}:{data[3].Substring(6, 2)}:00";
if (DateTime.TryParse(timeSpan, out DateTime readingDate))
{
dto.TimeSpan = readingDate;
}
dto.ItemType = itemType;
dto.FiledDesc = filedDesc;
dto.FiledName = dto.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
return dto;
}

View File

@ -1,7 +1,9 @@
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
@ -9,13 +11,14 @@ using JiShe.CollectBus.Protocol.T37612012.AnalysisData;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using static FreeSql.Internal.GlobalFilter;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
/// <summary>
/// 5.12.2.4.105 F149上月上一结算日正向有功最大需量及发生时间总、费率 1M
/// </summary>
public class AFN12_F149_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<AnalysisBaseDto<decimal>>>
public class AFN12_F149_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F149_Analysis> _logger;
@ -29,26 +32,29 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
}
public async Task<UnitDataAnalysis<AnalysisBaseDto<decimal>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnit(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
string itemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
AnalysisBaseDto<decimal> data = GenerateFinalResult(datas, dataType,"上月(上一结算日)正向有功最大需量及发生时间");
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data.MeterType.ToString(), "15");
if (ammeterInfo != null)
AnalysisBaseDto<decimal?> data = GenerateFinalResult(datas, itemType,"上月(上一结算日)正向有功最大需量及发生时间");
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ProjectId = ammeterInfo.ProjectID;
data.MeterId = ammeterInfo.MeterId;
data.DatabaseBusiID=ammeterInfo.DatabaseBusiID;
data.MeterAddress= ammeterInfo.AmmerterAddress;
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.MeterId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.MeterAddress;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<decimal>> unitDataAnalysis = new UnitDataAnalysis<AnalysisBaseDto<decimal>>
UnitDataAnalysis<AnalysisBaseDto<decimal?>> unitDataAnalysis = new UnitDataAnalysis<AnalysisBaseDto<decimal?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -57,19 +63,23 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
MSA=input.A.A3!.D1_D7!,
PSEQ=input.SEQ.PSEQ,
Data = data,
HexMessage=input.BaseHexMessage.HexMessageString,
ReceivedHexMessage=input.BaseHexMessage.HexMessageString,
MessageId=input.MessageId,
TimeDensity=1,
DensityUnit = DensityUnit.Month
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_149解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
private async Task<List<string>> AnalysisDataUnit(List<string> hexMessageList)
@ -86,8 +96,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A23), arr);
values.Add(value.ToString());//正向有功总最大需量
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A23), arr, (value) =>
{
values.Add(value.ToString());
});//正向有功总最大需量
}
arr = hexMessageList.GetRange(13 + i * 7, 4);
@ -97,16 +109,20 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, string>(nameof(Appendix_A17), arr);//正向有功总最大需量发生时间
values.Add(value);//正向有功总最大需量
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A17), arr, (value) =>
{
values.Add(value.ToString());
});//正向有功总最大需量
}
}
return values;
}
public AnalysisBaseDto<decimal> GenerateFinalResult(List<string> data,string dataType, string filedDesc = "")
public AnalysisBaseDto<decimal?> GenerateFinalResult(List<string> data,string itemType, string filedDesc = "")
{
AnalysisBaseDto<decimal> dto = new AnalysisBaseDto<decimal>();
AnalysisBaseDto<decimal?> dto = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCodeInfo = data[2].CheckErrorCode();
if (errorCodeInfo != null)
{
@ -115,7 +131,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
}
decimal.TryParse(data[2], out decimal value);
dto.DataValue = value;
dto.MeterType= MeterTypeEnum.Ammeter;
dto.DeviceType= MeterTypeEnum.Ammeter;
//TODO:最大需量发生时间
errorCodeInfo = data[3].CheckErrorCode();
if (data[3].Length != 8 && errorCodeInfo != null)
@ -126,20 +142,19 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
else
{
string timeSpan = $"{DateTime.Now.Year}-{data[3].Substring(0, 2)}-{data[3].Substring(2, 2)} {data[3].Substring(4, 2)}:{data[3].Substring(6, 2)}:00";
//TODO:时间标
if (!DateTime.TryParse(timeSpan, out DateTime dataTime))
dto.ValidData = false;
dto.DataTime = dataTime;
dto.TimeSpan = dataTime;
}
if (DateTime.Now.Month.Equals(1))//如果为1月份则日期减去1年
if (DateTime.Now.Month.Equals(1) && dto.TimeSpan.HasValue)//如果为1月份则日期减去1年
{
dto.DataTime = dto.DataTime.AddYears(-1);
dto.TimeSpan= dto.DataTime;
dto.TimeSpan= dto.TimeSpan.Value.AddYears(-1);
}
dto.ItemType = itemType;
dto.FiledDesc = "上月(上一结算日)正向有功最大需量及发生时间";
dto.FiledName = dataType.GetDataFieldByGatherDataType() ?? string.Empty;
dto.FiledName = dto.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
return dto;
}

View File

@ -1,58 +1,90 @@
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.AnalysisData;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using YamlDotNet.Core.Tokens;
using static FreeSql.Internal.GlobalFilter;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
/// <summary>
/// 水表抄读取
/// </summary>
public class AFN12_F188_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<AFN12_F149_AnalysisDto>>
public class AFN12_F188_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F188_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F188_Analysis(ILogger<AFN12_F188_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F188_Analysis(ILogger<AFN12_F188_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<AFN12_F149_AnalysisDto>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
ArgumentNullException.ThrowIfNull(input.AFN_FC.AFN);
ArgumentNullException.ThrowIfNull(input.DT.Fn);
var data = GenerateFinalResult(input.UnitData.HexMessageList);
data.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
UnitDataAnalysis<AFN12_F149_AnalysisDto> dto = new UnitDataAnalysis<AFN12_F149_AnalysisDto>
string itemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
AnalysisBaseDto<decimal?> data = GenerateFinalResult(input.UnitData.HexMessageList, itemType);
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
Code = input.A.Code,
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.MeterId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.MeterAddress;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<decimal?>> dto = new UnitDataAnalysis<AnalysisBaseDto<decimal?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = data
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
return await Task.FromResult(dto);
result?.Invoke(dto);
await _dataStorage.SaveDataToIotDbAsync(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_188解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
public AFN12_F149_AnalysisDto GenerateFinalResult(List<string> hexMessageList)
public AnalysisBaseDto<decimal?> GenerateFinalResult(List<string> hexMessageList,string itemType)
{
AFN12_F149_AnalysisDto dto = new AFN12_F149_AnalysisDto();
decimal value = 0;
AnalysisBaseDto<decimal?> dto = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.WaterMeter
};
var arr = hexMessageList.GetRange(11, 4);
var errorCodeInfo = arr.CheckErrorCode();
if (errorCodeInfo != null)
@ -61,10 +93,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
dto.ErrorCodeMsg = errorCodeInfo.Item2;
}
else
decimal.TryParse($"{arr[11]}{arr[12]}{arr[13]}.{arr[14]}", out value);
dto.DataValue = value;
//dto.ReadTime = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
{
if (decimal.TryParse($"{arr[11]}{arr[12]}{arr[13]}.{arr[14]}", out decimal value))
dto.DataValue = value;
}
dto.ItemType = itemType;
dto.FiledDesc = "水示值";
dto.FiledName = dto.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
return dto;
}

View File

@ -1,43 +1,55 @@
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.AnalysisData;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
/// <summary>
/// 5.12.2.4.22 F25当前三相及总有/无功功率、功率因数,三相电压、电流、零序电流、视在功率
/// </summary>
public class AFN12_F25_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AFN12_F25_AnalysisDto>>>
public class AFN12_F25_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F25_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F25_Analysis(ILogger<AFN12_F25_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F25_Analysis(ILogger<AFN12_F25_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public List<string> DataType { get; set; } = new List<string>() { "YGGL", "YGGL_A", "YGGL_B", "YGGL_C", "WGGL", "WGGL_A", "WGGL_B", "WGGL_C", "GLYS", "GLYS_A", "GLYS_B", "GLYS_C", "DY_A", "DY_B", "DY_C", "DL_A", "DL_B", "DL_C", "LXDL", "SZGL", "SZGL_A", "SZGL_B", "SZGL_C" };
public List<string> ItemType { get; set; } = new List<string>() { "YGGL", "AYGGL", "BYGGL", "CYGGL", "WGGL", "AWGGL", "BWGGL", "CWGGL", "GLYS", "AGLYS", "BGLYS", "CGLYS", "ADY", "BDY", "CDY", "ADL", "BDL", "CDL", "LXDL", "SZGL", "ASZGL", "BSZGL", "CSZGL" };
public async Task<UnitDataAnalysis<List<AFN12_F25_AnalysisDto>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> remarks = new List<string>() { "当前总有功功率", "当前A相有功功率", "当前B相有功功率", "当前C相有功功率", "当前总无功功率", "当前A相无功功率", "当前B相无功功率", "当前C相无功功率", "当前总功率因数", "当前A相功率因数", "当前B相功率因数", "当前C相功率因数", "当前A相电压", "当前B相电压", "当前C相电压", "当前A相电流", "当前C相电流", "当前 C相电流", "当前零序电流", "当前总视在功率", "当前A相视在功率", "当前B相视在功率", "当前C相视在功率" };
List<AFN12_F25_AnalysisDto> list = new List<AFN12_F25_AnalysisDto>();
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
List<string> data = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
for (int i = 1; i < data.Count; i++)
{
AFN12_F25_AnalysisDto dto = new AFN12_F25_AnalysisDto();
decimal value = 0;
AnalysisBaseDto<decimal?> dto = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCodeInfo = data[i].CheckErrorCode();
if (errorCodeInfo != null)
{
@ -45,30 +57,58 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
dto.ErrorCodeMsg = errorCodeInfo.Item2;
}
else
decimal.TryParse(data[i], out value);
dto.DataValue = value;
dto.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}_{DataType[i-1]}";
dto.FiledName = DataType[i - 1];
dto.ReadTime = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
{
if(decimal.TryParse(data[i], out decimal value))
dto.DataValue = value;
}
dto.ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}_{ItemType[i-1]}";
dto.FiledName = ItemType[i - 1].GetDataFieldByGatherDataType() ?? string.Empty;
dto.TimeSpan = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
dto.FiledDesc = remarks[i - 1];
list.Add(dto);
}
UnitDataAnalysis<List<AFN12_F25_AnalysisDto>> unitDataAnalysis = new UnitDataAnalysis<List<AFN12_F25_AnalysisDto>>
if (list.Count > 0)
{
Code = input.A.Code,
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
list.ForEach(item =>
{
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = list
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
return await Task.FromResult(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_25解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
private async Task<List<string>> AnalysisDataUnitAsync(List<string> hexMessageList)
@ -102,8 +142,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(appendixName, arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(appendixName, arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,56 +1,86 @@
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Diagnostics.Metrics;
using JiShe.CollectBus.Protocol.T37612012.AnalysisData;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.Common.Consts;
using static FreeSql.Internal.GlobalFilter;
using JiShe.CollectBus.IotSystems.Devices;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
/// <summary>
/// 5.12.2.4.1 F2终端日历时钟
/// </summary>
public class AFN12_F2_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<AFN12_F2_AnalysisDto>>
public class AFN12_F2_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F2_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F2_Analysis(ILogger<AFN12_F2_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F2_Analysis(ILogger<AFN12_F2_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<AFN12_F2_AnalysisDto>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
var data= await GenerateFinalResultAsync(input.UnitData.HexMessageList);
data.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
UnitDataAnalysis<AFN12_F2_AnalysisDto> dto = new UnitDataAnalysis<AFN12_F2_AnalysisDto>
string itemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
var data = await GenerateFinalResultAsync(input.UnitData.HexMessageList, itemType);
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
Code = input.A.Code,
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.MeterId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.MeterAddress;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<string>> dto = new UnitDataAnalysis<AnalysisBaseDto<string>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = data
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Param,
};
return await Task.FromResult(dto);
result?.Invoke(dto);
await _dataStorage.SaveDataToIotDbAsync(dto);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_2解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
public async Task<AFN12_F2_AnalysisDto> GenerateFinalResultAsync(List<string> hexMessageList)
public async Task<AnalysisBaseDto<string>> GenerateFinalResultAsync(List<string> hexMessageList,string itemType)
{
AFN12_F2_AnalysisDto dto = new AFN12_F2_AnalysisDto();
AnalysisBaseDto<string> dto = new AnalysisBaseDto<string>();
var arr = hexMessageList.GetRange(4, 6);
var errorCodeInfo = arr.CheckErrorCode();
if (errorCodeInfo != null)
@ -59,8 +89,14 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
dto.ErrorCodeMsg = errorCodeInfo.Item2;
}
else
dto.DataValue = await _analysisStrategyContext.ExecuteAsync<List<string>, string>(nameof(Appendix_A1), arr);
{
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A1), arr, (value) =>
{
var data = (Tuple<string, string>)value;
dto.DataValue = $"{data.Item1} {data.Item2}";
});
}
dto.ItemType = itemType;
dto.FiledName = "TerminalTime";
dto.FiledDesc = "召读终端时间";
return await Task.FromResult(dto);

View File

@ -1,54 +1,87 @@
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.AnalysisData;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System;
using static FreeSql.Internal.GlobalFilter;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
/// <summary>
/// 5.12.2.4.30 F33当前正向有/无功电能示值、一/四象限无功电能示值(总、费率 1M1≤M≤12
/// </summary>
public class AFN12_F33_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<AFN12_F33_AnalysisDto>>
public class AFN12_F33_Analysis : IAnalysisStrategy<TB3761>
{
private List<string> DataUnitHexList { get; set; }=new List<string>();
private readonly ILogger<AFN12_F33_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F33_Analysis(ILogger<AFN12_F33_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F33_Analysis(ILogger<AFN12_F33_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<AFN12_F33_AnalysisDto>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList);
int rationgCount = input.UnitData.HexMessageList!.GetRatingCount(23, 1);
DataUnitHexList = input.UnitData.HexMessageList.GetRange(24, (5 * (rationgCount + 1)) + (4 * (rationgCount + 1)) * 3);
GetDataUnitHexString(input.UnitData.HexMessageList, rationgCount);
UnitDataAnalysis<AFN12_F33_AnalysisDto> unitDataAnalysis = new UnitDataAnalysis<AFN12_F33_AnalysisDto>
var data = new AnalysisBaseDto<AFN12_F33_AnalysisDto?>()
{
Code = input.A.Code,
FiledDesc = "当前正向有/无功电能示值、一/四象限无功电能示值",
DataValue = await AnalysisDataUnit(input.UnitData.HexMessageList, rationgCount),
ItemType= $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"
};
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ProjectId = deviceInfo.ProjectID;
data.DeviceId = deviceInfo.MeterId;
data.DatabaseBusiID = deviceInfo.DatabaseBusiID;
data.DeviceAddress = deviceInfo.MeterAddress;
data.FocusId = deviceInfo.FocusId;
}
UnitDataAnalysis<AnalysisBaseDto<AFN12_F33_AnalysisDto?>> unitDataAnalysis = new UnitDataAnalysis<AnalysisBaseDto<AFN12_F33_AnalysisDto?>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data = await AnalysisDataUnit(input.UnitData.HexMessageList, rationgCount)
Data = data,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
return await Task.FromResult(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_33解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
#region / private void GetDataUnitHexString(int rationgCount)
@ -83,8 +116,11 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
private async Task<ParentNodes> GetDataAsync(int ratingCount, int startIndex, int len, string appendxName)
{
ParentNodes parent = new ParentNodes();
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(appendxName, DataUnitHexList.GetRange(startIndex, len));
parent.Total_Value = value;
var arr = DataUnitHexList.GetRange(startIndex, len);
await _analysisStrategyContext.ExecuteAsync<List<string>>(appendxName, arr, (value) =>
{
parent.Total_Value = value;
});
parent.childNodes = await GetChildDataAsync(ratingCount, startIndex, len, appendxName);
return parent;
}
@ -102,11 +138,15 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
List<ChildNodes> children = new List<ChildNodes>();
for (int i = 0; i < RatingCount; i++)
{
ChildNodes model = new ChildNodes()
var arr = DataUnitHexList.GetRange((i * len) + (startIndex + len), len);
await _analysisStrategyContext.ExecuteAsync<List<string>>(appendxName, arr, (value) =>
{
Value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(appendxName, DataUnitHexList.GetRange((i * len) + (startIndex + len), len)) //29,4 33,4 37,4 41,4
};
children.Add(model);
ChildNodes model = new ChildNodes()
{
Value = value
};
children.Add(model);
});
}
return children;
}

View File

@ -1,73 +1,108 @@
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.AnalysisData;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
/// <summary>
/// 5.12.2.4.46 F49当前电压、电流相位角
/// </summary>
public class AFN12_F49_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AFN12_F49_AnalysisDto>>>
public class AFN12_F49_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN12_F49_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
public AFN12_F49_Analysis(ILogger<AFN12_F49_Analysis> logger, AnalysisStrategyContext analysisStrategyContext)
private readonly DataStorage _dataStorage;
public AFN12_F49_Analysis(ILogger<AFN12_F49_Analysis> logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage)
{
_logger = logger;
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public List<string> DataType { get; set; } = new List<string>() { "Uab_Ua", "Ub", "Ucb_Uc", "Ia", "Ib", "Ic" };
public List<string> ItemType { get; set; } = new List<string>() { "Uab_Ua", "Ub", "Ucb_Uc", "Ia", "Ib", "Ic" };
public async Task<UnitDataAnalysis<List<AFN12_F49_AnalysisDto>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
List<string> data = await AnalysisDataUnitAsync(input.UnitData?.HexMessageList!);
List<string> remarks = new List<string>() { "Uab/Ua 相位角", "Ub 相位角", "Ucb/Uc 相位角", "Ia 相位角", "Ib 相位角", "Ic 相位角" };
List<AFN12_F49_AnalysisDto> list = new List<AFN12_F49_AnalysisDto>();
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = 0; i < data.Count; i++)
{
AFN12_F49_AnalysisDto dto = new AFN12_F49_AnalysisDto();
decimal value = 0;
AnalysisBaseDto<decimal?> dto = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCodeInfo = data[i].CheckErrorCode();
if (errorCodeInfo != null)
{
dto.ValidData = false;
dto.ErrorCodeMsg = errorCodeInfo.Item2;
}
}
else
decimal.TryParse(data[i], out value);
dto.DataValue = value;
dto.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}_{DataType[i]}";
dto.FiledName = DataType[i];
{
if(decimal.TryParse(data[i], out decimal value))
dto.DataValue = value;
}
dto.ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}_{ItemType[i]}";
dto.FiledName = dto.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
dto.FiledDesc= remarks[i];
list.Add(dto);
}
UnitDataAnalysis<List<AFN12_F49_AnalysisDto>> unitDataAnalysis = new UnitDataAnalysis<List<AFN12_F49_AnalysisDto>>
if (list.Count > 0)
{
Code = input.A.Code,
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
list.ForEach(item =>
{
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
Fn = input.DT.Fn,
Pn = input.DA.Pn,
Data= list
Data= list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
ReceivedTime = input.ReceivedTime,
DensityUnit = DensityUnit.Second,
TimeDensity = 0,
DataType = IOTDBDataTypeConst.Data,
};
return await Task.FromResult(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0C_49解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
}
return await Task.FromResult(false);
}
private async Task<List<string>> AnalysisDataUnitAsync(List<string> hexMessageList)
{
@ -80,8 +115,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
values.Add(errorCode.Item1);
else
{
var value= await _analysisStrategyContext.ExecuteAsync<List<string>,decimal>(nameof(Appendix_A5), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A5), arr, (value) =>
{
values.Add(value.ToString());
});
}
}

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.78 F100测量点反向无功总电能量曲线
/// </summary>
public class AFN13_F100_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F100_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F100_Analysis> _logger;
@ -26,36 +30,38 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向无功总电能量");
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "反向无功总电能量");
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -63,19 +69,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
TimeDensity = density,//密度,注意这里会兼容存储做判断
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_100解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -92,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A13), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A13), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.79 F101测量点正向有功总电能示值曲线
/// </summary>
public class AFN13_F101_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F101_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F101_Analysis> _logger;
@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_analysisStrategyContext = analysisStrategyContext;
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向有功总电能示值");
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "正向有功总电能示值");
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +66,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
TimeDensity = density,//密度,注意这里会兼容存储做判断
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_101解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -89,8 +98,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.80 F102测量点正向无功总电能示值曲线
/// </summary>
public class AFN13_F102_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F102_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F102_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +28,38 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向无功总电能示值");
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "正向无功总电能示值");
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +67,21 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
TimeDensity = density,//密度,注意这里会兼容存储做判断
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_102解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -90,8 +98,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.81 F103测量点反向有功总电能示值曲线
/// </summary>
public class AFN13_F103_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F103_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F103_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +29,38 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向有功总电能示值");
string itemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, itemType, "反向有功总电能示值");
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +68,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
TimeDensity = density,//密度,注意这里会兼容存储做判断
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_103解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -90,8 +100,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.82 F104测量点反向无功总电能示值曲线
/// </summary>
public class AFN13_F104_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F104_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F104_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向无功总电能示值");
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "反向无功总电能示值");
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +67,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
TimeDensity = density,//密度,注意这里会兼容存储做判断
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_104解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -90,8 +99,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.83 F105测量点功率因数曲线
/// </summary>
public class AFN13_F105_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F105_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F105_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "功率因数");
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "功率因数");
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +67,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
TimeDensity = density,//密度,注意这里会兼容存储做判断
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_105解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -91,8 +100,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A5), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A5), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.84 F106测量点 A相功率因数曲线
/// </summary>
public class AFN13_F106_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F106_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F106_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "A相功率因数");
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "A相功率因数");
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +67,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
TimeDensity = density,//密度,注意这里会兼容存储做判断
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_106解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -92,8 +101,11 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A5), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A5), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.84 F107测量点 B相功率因数曲线
/// </summary>
public class AFN13_F107_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F107_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F107_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "B相功率因数");
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "B相功率因数");
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +66,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
TimeDensity = density,//密度,注意这里会兼容存储做判断
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_107解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -90,8 +99,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A5), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A5), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.84 F108测量点 C相功率因数曲线
/// </summary>
public class AFN13_F108_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F108_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F108_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "C相功率因数");
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "C相功率因数");
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +67,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_107解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
private async Task<List<string>> AnalysisDataUnitAsync(List<string> hexMessageList)
@ -89,8 +98,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A5), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A5), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,20 +1,24 @@
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.11 F11抄表日冻结电能表正向有/无功最大需量及发生时间(总、费率 1M1≤M≤12
/// </summary>
public class AFN13_F11_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F11_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F11_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -26,33 +30,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = GenerateFinalResult(datas,3, dataType, "抄表日冻结电能表正向有功最大需量及发生时间");
List<AnalysisBaseDto<decimal?>> list = GenerateFinalResult(datas,3, dataType, "抄表日冻结电能表正向有功最大需量及发生时间");
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +66,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_11解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -84,18 +93,18 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
int ratingCount = hexMessageList.GetRatingCount(12, 1);//费率数 M1≤M≤12
values.Add(ratingCount.ToString());
int handlerNum = 13;
values.AddRange(await GetDataAsync<decimal>(hexMessageList.GetRange(handlerNum, 3 * (ratingCount + 1)), ratingCount, 3, nameof(Appendix_A23)));//正向有功总最大需量
values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 3 * (ratingCount + 1)), ratingCount, 3, nameof(Appendix_A23)));//正向有功总最大需量
handlerNum += 3 * (ratingCount + 1);//12
values.AddRange(await GetDataAsync<string>(hexMessageList.GetRange(handlerNum, 4 * (ratingCount + 1)), ratingCount, 4, nameof(Appendix_A17)));//正向有功总最大需量发生时间
values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 4 * (ratingCount + 1)), ratingCount, 4, nameof(Appendix_A17)));//正向有功总最大需量发生时间
handlerNum += 4 * (ratingCount + 1);//28
values.AddRange(await GetDataAsync<decimal>(hexMessageList.GetRange(handlerNum, 3 * (ratingCount + 1)), ratingCount, 3, nameof(Appendix_A23)));//正向无功总最大需量
values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 3 * (ratingCount + 1)), ratingCount, 3, nameof(Appendix_A23)));//正向无功总最大需量
handlerNum += 3 * (ratingCount + 1);//48
values.AddRange(await GetDataAsync<string>(hexMessageList.GetRange(handlerNum, 4 * (ratingCount + 1)), ratingCount, 4, nameof(Appendix_A17)));//正向无功总最大需量发生时间
values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 4 * (ratingCount + 1)), ratingCount, 4, nameof(Appendix_A17)));//正向无功总最大需量发生时间
handlerNum += 4 * (ratingCount + 1);
return values;
}
private async Task<List<string>> GetDataAsync<T>(List<string> data, int ratingCount, int len, string appendixName)
private async Task<List<string>> GetDataAsync(List<string> data, int ratingCount, int len, string appendixName)
{
List<string> values = new List<string>();
for (int i = 0; i < ratingCount + 1; i++)
@ -106,26 +115,27 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, T>(nameof(Appendix_A5), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(appendixName, arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;
}
public List<AnalysisBaseDto<decimal>> GenerateFinalResult(List<string> data, int index, string dataType, string filedDesc = "")
public List<AnalysisBaseDto<decimal?>> GenerateFinalResult(List<string> data, int index, string dataType, string filedDesc = "")
{
List<AnalysisBaseDto<decimal>> list = new List<AnalysisBaseDto<decimal>>();
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
int fCount = Convert.ToInt32(data[2]) + 1;
for (int i = 1; i <= 2; i++)
{
AnalysisBaseDto<decimal> meter = new AnalysisBaseDto<decimal>
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>
{
MeterType = MeterTypeEnum.Ammeter
DeviceType = MeterTypeEnum.Ammeter
};
int startIndex = i == 1 ? 3 : (3 + i * fCount);
decimal value = 0;
var errorCode = data[startIndex].CheckErrorCode();
if (errorCode != null)
{
@ -133,19 +143,21 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
meter.ErrorCodeMsg = errorCode.Item2;
}
else
decimal.TryParse(data[startIndex], out value);
meter.DataValue = value;
{
if(decimal.TryParse(data[startIndex], out decimal value))
{
meter.DataValue = value;
}
}
string timeSpan = $"{DateTime.Now.Year}-{data[startIndex + fCount].Substring(0, 2)}-{data[startIndex + fCount].Substring(2, 2)} {data[startIndex + fCount].Substring(4, 2)}:{data[startIndex + fCount].Substring(6, 2)}:00";
DateTime readingDate = DateTime.Now;
if (DateTime.TryParse(timeSpan, out readingDate))
if (DateTime.TryParse(timeSpan, out DateTime readingDate))
{
meter.TimeSpan = readingDate;
}
meter.DataType = i == 1 ? dataType : $"{dataType}_{ i - 1}";
meter.ItemType = i == 1 ? dataType : $"{dataType}_{ i - 1}";
filedDesc = i == 1 ? filedDesc : filedDesc.Replace("有功", "无功");
meter.FiledDesc = filedDesc;
meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
}

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.104 F145测量点一象限无功总电能示值曲线
/// </summary>
public class AFN13_F145_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F145_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F145_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "一象限无功电能示值");
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "一象限无功电能示值");
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +66,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_145解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -90,8 +99,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.105 F146测量点四象限无功总电能示值曲线
/// </summary>
public class AFN13_F146_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F146_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F146_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "四象限无功电能示值");
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "四象限无功电能示值");
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +66,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_146解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -90,8 +99,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.106 F147测量点二象限无功总电能示值曲线
/// </summary>
public class AFN13_F147_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F147_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F147_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "二象限无功电能示值");
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "二象限无功电能示值");
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +66,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_147解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -90,8 +99,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,23 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.107 F148测量点三象限无功总电能示值曲线
/// </summary>
public class AFN13_F148_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F148_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F148_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
int density = Convert.ToInt32(Enum.GetName(typeof(DensityEnums), Convert.ToInt32(datas[1]))!.Split('_')[1]);//密度-间隔分钟数,
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_c(3, density, dataType, "三象限无功电能示值");
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_c(3, density, dataType, "三象限无功电能示值");
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +67,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = density,//密度-间隔分钟数,
DensityUnit = DensityUnit.Minute
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_148解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -90,8 +99,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr);
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.116 F161日冻结正向有功电能示值总、费率 1M
/// </summary>
public class AFN13_F161_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F161_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F161_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +28,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00";
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_d(3, dataType,timeSpan, "正向有功总电能示值").IsValidData(new List<string>() { "0D_161", "0D_161_1", "0D_161_2", "0D_161_3", "0D_161_4" });
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_d(3, dataType,timeSpan, "正向有功总电能示值").IsValidData(new List<string>() { "0D_161", "0D_161_1", "0D_161_2", "0D_161_3", "0D_161_4" });
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +66,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_161解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -95,8 +103,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A14), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A14), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.117 F162日冻结正向无功组合无功 1电能示值总、费率 1M
/// </summary>
public class AFN13_F162_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F162_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F162_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00";
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "正向无功(组合无功 1电能示值").IsValidData(new List<string>() { "0D_162", "0D_162_1", "0D_162_2", "0D_162_3", "0D_162_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "正向无功(组合无功 1电能示值").IsValidData(new List<string>() { "0D_162", "0D_162_1", "0D_162_2", "0D_162_3", "0D_162_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_162解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
private async Task<List<string>> AnalysisDataUnitAsync(List<string> hexMessageList)
@ -92,8 +100,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.118 F163日冻结反向有功电能示值总、费率 1M
/// </summary>
public class AFN13_F163_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F163_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F163_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,35 +28,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00";
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "反向有功总电能示值").IsValidData(new List<string>() { "0D_163", "0D_163_1", "0D_163_2", "0D_163_3", "0D_163_4" });
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "反向有功总电能示值").IsValidData(new List<string>() { "0D_163", "0D_163_1", "0D_163_2", "0D_163_3", "0D_163_4" });
if (data.Count > 0)
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -61,19 +66,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_163解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
private async Task<List<string>> AnalysisDataUnitAsync(List<string> hexMessageList)
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A14), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A14), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.119 F164日冻结反向无功组合无功 1电能示值总、费率 1M
/// </summary>
public class AFN13_F164_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F164_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F164_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00";
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结反向无功(组合无功 1电能示值").IsValidData(new List<string>() { "0D_164", "0D_164_1", "0D_164_2", "0D_164_3", "0D_164_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结反向无功(组合无功 1电能示值").IsValidData(new List<string>() { "0D_164", "0D_164_1", "0D_164_2", "0D_164_3", "0D_164_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_164解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.120 F165日冻结一象限无功电能示值总、费率 1M
/// </summary>
public class AFN13_F165_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F165_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F165_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00";
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结一象限无功电能示值").IsValidData(new List<string>() { "0D_165", "0D_165_1", "0D_165_2", "0D_165_3", "0D_165_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结一象限无功电能示值").IsValidData(new List<string>() { "0D_165", "0D_165_1", "0D_165_2", "0D_165_3", "0D_165_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_165解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.121 F166日冻结二象限无功电能示值总、费率 1M
/// </summary>
public class AFN13_F166_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F166_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F166_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00";
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结二象限无功电能示值").IsValidData(new List<string>() { "0D_166", "0D_166_1", "0D_166_2", "0D_166_3", "0D_166_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结二象限无功电能示值").IsValidData(new List<string>() { "0D_166", "0D_166_1", "0D_166_2", "0D_166_3", "0D_166_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_166解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.122 F167日冻结三象限无功电能示值总、费率 1M
/// </summary>
public class AFN13_F167_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F167_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F167_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00";
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结三象限无功电能示值").IsValidData(new List<string>() { "0D_167", "0D_167_1", "0D_167_2", "0D_167_3", "0D_167_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结三象限无功电能示值").IsValidData(new List<string>() { "0D_167", "0D_167_1", "0D_167_2", "0D_167_3", "0D_167_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_167解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.123 F168日冻结四象限无功电能示值总、费率 1M
/// </summary>
public class AFN13_F168_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F168_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F168_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00";
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结四象限无功电能示值").IsValidData(new List<string>() { "0D_168", "0D_168_1", "0D_168_2", "0D_168_3", "0D_168_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结四象限无功电能示值").IsValidData(new List<string>() { "0D_168", "0D_168_1", "0D_168_2", "0D_168_3", "0D_168_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Day
DensityUnit = DensityUnit.Day,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_168解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.132 F177月冻结正向有功电能示值总、费率 1M
/// </summary>
public class AFN13_F177_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F177_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F177_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,33 +28,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-01 00:00:00";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结正向有功电能示值").IsValidData(new List<string>() { "0D_177", "0D_177_1", "0D_177_2", "0D_177_3", "0D_177_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结正向有功电能示值").IsValidData(new List<string>() { "0D_177", "0D_177_1", "0D_177_2", "0D_177_3", "0D_177_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -59,19 +64,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Month
DensityUnit = DensityUnit.Month,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_177解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A14), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A14), arr, (value) =>
{
values.Add(value.ToString());
});
}
}

View File

@ -8,13 +8,16 @@ using Microsoft.Extensions.Logging;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.IotSystems.Devices;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// F178月冻结正向无功组合无功 1电能示值总、费率 1M
/// </summary>
public class AFN13_F178_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F178_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F178_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-01 00:00:00";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结正向无功(组合无功 1电能示值").IsValidData(new List<string>() { "0D_178", "0D_178_1", "0D_178_2", "0D_178_3", "0D_178_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结正向无功(组合无功 1电能示值").IsValidData(new List<string>() { "0D_178", "0D_178_1", "0D_178_2", "0D_178_3", "0D_178_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Month
DensityUnit = DensityUnit.Month,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_178解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}

View File

@ -8,13 +8,16 @@ using Microsoft.Extensions.Logging;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.IotSystems.Devices;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.134 F179月冻结反向有功电能示值总、费率 1M
/// </summary>
public class AFN13_F179_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F179_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F179_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-01 00:00:00";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "反向有功总电能示值").IsValidData(new List<string>() { "0D_179", "0D_179_1", "0D_179_2", "0D_179_3", "0D_179_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "反向有功总电能示值").IsValidData(new List<string>() { "0D_179", "0D_179_1", "0D_179_2", "0D_179_3", "0D_179_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Month
DensityUnit = DensityUnit.Month,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_179解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A14), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A14), arr, (value) =>
{
values.Add(value.ToString());
});
}
}

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.135 F180月冻结反向无功组合无功 1电能示值总、费率 1M
/// </summary>
public class AFN13_F180_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F180_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F180_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,33 +28,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-01 00:00:00";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结反向无功(组合无功 1电能示值").IsValidData(new List<string>() { "0D_180", "0D_180_1", "0D_180_2", "0D_180_3", "0D_180_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结反向无功(组合无功 1电能示值").IsValidData(new List<string>() { "0D_180", "0D_180_1", "0D_180_2", "0D_180_3", "0D_180_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -59,19 +64,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Month
DensityUnit = DensityUnit.Month,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_180解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -92,8 +100,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}

View File

@ -8,13 +8,16 @@ using Microsoft.Extensions.Logging;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.IotSystems.Devices;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.136 F181月冻结一象限无功电能示值总、费率 1M
/// </summary>
public class AFN13_F181_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F181_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F181_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-01 00:00:00";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结一象限无功电能示值(总、费率 1M").IsValidData(new List<string>() { "0D_181", "0D_181_1", "0D_181_2", "0D_181_3", "0D_181_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结一象限无功电能示值(总、费率 1M").IsValidData(new List<string>() { "0D_181", "0D_181_1", "0D_181_2", "0D_181_3", "0D_181_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Month
DensityUnit = DensityUnit.Month,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_181解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}

View File

@ -8,13 +8,16 @@ using Microsoft.Extensions.Logging;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.IotSystems.Devices;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.137 F182月冻结二象限无功电能示值总、费率 1M
/// </summary>
public class AFN13_F182_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F182_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F182_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-01 00:00:00";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结二象限无功电能示值(总、费率 1M").IsValidData(new List<string>() { "0D_182", "0D_182_1", "0D_182_2", "0D_182_3", "0D_182_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结二象限无功电能示值(总、费率 1M").IsValidData(new List<string>() { "0D_182", "0D_182_1", "0D_182_2", "0D_182_3", "0D_182_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -60,19 +65,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Month
DensityUnit = DensityUnit.Month,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_182解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

View File

@ -1,19 +1,22 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.IotSystems.Ammeters;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
{
/// <summary>
/// 5.13.2.4.138 F183月冻结三象限无功电能示值总、费率 1M
/// </summary>
public class AFN13_F183_Analysis : IAnalysisStrategy<TB3761, UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>>
public class AFN13_F183_Analysis : IAnalysisStrategy<TB3761>
{
private readonly ILogger<AFN13_F183_Analysis> _logger;
private readonly AnalysisStrategyContext _analysisStrategyContext;
@ -25,33 +28,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
_dataStorage = dataStorage;
}
public async Task<UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>> ExecuteAsync(TB3761 input)
public async Task<bool> ExecuteAsync(TB3761 input, Action<dynamic>? result = null)
{
try
{
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.A.Code);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List<string> datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
string timeSpan = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-01 00:00:00";
List<AnalysisBaseDto<decimal>> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结三象限无功电能示值(总、费率 1M").IsValidData(new List<string>() { "0D_183", "0D_183_1", "0D_183_2", "0D_183_3", "0D_183_4" });
if (data.Count > 0)
List<AnalysisBaseDto<decimal?>> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结三象限无功电能示值(总、费率 1M").IsValidData(new List<string>() { "0D_183", "0D_183_1", "0D_183_2", "0D_183_3", "0D_183_4" });
if (list.Count > 0)
{
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data[0].MeterType.ToString(), "15");
if (ammeterInfo != null)
// 查询设备信息
DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn);
if (deviceInfo != null)
{
data.ForEach(item =>
list.ForEach(item =>
{
item.ProjectId = ammeterInfo.ProjectID;
item.MeterId = ammeterInfo.MeterId;
item.DatabaseBusiID = ammeterInfo.DatabaseBusiID;
item.MeterAddress = ammeterInfo.AmmerterAddress;
item.ProjectId = deviceInfo.ProjectID;
item.DeviceId = deviceInfo.MeterId;
item.DatabaseBusiID = deviceInfo.DatabaseBusiID;
item.DeviceAddress = deviceInfo.MeterAddress;
item.FocusId = deviceInfo.FocusId;
});
}
}
UnitDataAnalysis<List<AnalysisBaseDto<decimal>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal>>>
UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>> unitDataAnalysis = new UnitDataAnalysis<List<AnalysisBaseDto<decimal?>>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@ -59,19 +64,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
Pn = input.DA.Pn,
MSA = input.A.A3!.D1_D7!,
PSEQ = input.SEQ.PSEQ,
Data = data,
HexMessage = input.BaseHexMessage.HexMessageString,
Data = list,
ReceivedHexMessage = input.BaseHexMessage.HexMessageString,
MessageId = input.MessageId,
TimeDensity = 1,//密度-间隔,
DensityUnit = DensityUnit.Month
DensityUnit = DensityUnit.Month,
ReceivedTime = input.ReceivedTime,
DataType = IOTDBDataTypeConst.Data,
};
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal>(unitDataAnalysis);
return await Task.FromResult(unitDataAnalysis);
await _dataStorage.SaveMultipleDataToIotDbAsync<decimal?>(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, $"0D_183解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}");
return null;
return await Task.FromResult(false);
}
}
@ -92,8 +100,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
values.Add(errorCode.Item1);
else
{
var value = await _analysisStrategyContext.ExecuteAsync<List<string>, decimal>(nameof(Appendix_A11), arr); //从第10个开始每加5个字节为下一个值的开始
values.Add(value.ToString());
await _analysisStrategyContext.ExecuteAsync<List<string>>(nameof(Appendix_A11), arr, (value) =>
{
values.Add(value.ToString());
});
}
}
return values;

Some files were not shown because too many files have changed in this diff Show More