diff --git a/Dockerfile b/Dockerfile index d4999c8..a8f5003 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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目录 diff --git a/JiShe.CollectBus.External.sln b/JiShe.CollectBus.External.sln new file mode 100644 index 0000000..a1344ff --- /dev/null +++ b/JiShe.CollectBus.External.sln @@ -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 diff --git a/JiShe.CollectBus.Main.sln b/JiShe.CollectBus.Main.sln new file mode 100644 index 0000000..46d2db3 --- /dev/null +++ b/JiShe.CollectBus.Main.sln @@ -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 diff --git a/JiShe.CollectBus.sln b/JiShe.CollectBus.sln index 03bd207..272514c 100644 --- a/JiShe.CollectBus.sln +++ b/JiShe.CollectBus.sln @@ -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} diff --git a/PackageAndPublish.bat b/PackageAndPublish.bat index 0bb73cd..24ce317 100644 --- a/PackageAndPublish.bat +++ b/PackageAndPublish.bat @@ -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 ) diff --git a/Temp.Dockerfile b/Temp.Dockerfile new file mode 100644 index 0000000..e63b6e0 --- /dev/null +++ b/Temp.Dockerfile @@ -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"] + + diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs new file mode 100644 index 0000000..00a7129 --- /dev/null +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -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 +{ + /// + /// 复杂类型增量源生成器 + /// + [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; + } + + /// + /// 递归获取所有层级的属性 + /// + /// + /// + private static IEnumerable GetAllPropertiesInHierarchy(INamedTypeSymbol classSymbol) + { + var currentSymbol = classSymbol; + while (currentSymbol != null) + { + foreach (var prop in currentSymbol.GetMembers().OfType()) + { + yield return prop; + } + currentSymbol = currentSymbol.BaseType; // 向上遍历基类 + } + } + + /// + /// 生成代码 + /// + /// + /// + /// + private static void GenerateCode( + Compilation compilation, + IEnumerable classes, + SourceProductionContext context) + { + var processedTypes = new HashSet(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()); + } + + /// + /// 获取泛型参数 + /// + /// + /// + public static string GetGenericParams(INamedTypeSymbol symbol) + { + if (!symbol.IsGenericType) return ""; + var parameters = symbol.TypeParameters.Select(t => t.Name); + return $"<{string.Join(", ", parameters)}>"; + } + + + /// + /// 生成标准属性的访问器 + /// + /// + /// + /// + 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;"); + } + } + + + /// + /// 构建实体访问器代码(支持泛型) + /// + private static string BuildAccessorsForSourceEntity( + INamedTypeSymbol classSymbol, + Compilation compilation, + HashSet 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("// "); + 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(); + } + + /// + /// 生成ValueTuple元组属性访问器 + /// + /// + /// + /// + 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 GetTupleElements( + string propName, + ImmutableArray elements, + int targetIndex) + { + for (int i = 0; i < elements.Length; i++) + { + yield return i == targetIndex + ? "value" + : $"obj.{propName}.{elements[i].Name}"; + } + } + + /// + /// 处理System.Tuple类型的访问器生成 + /// + 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)});"); + } + } + } + + /// + /// 增强的工厂类实现 + /// + 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 _accessors = new(); + + public static ISourceEntityAccessor GetAccessor() + { + return (ISourceEntityAccessor)_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)!; + }); + } + } + """; + } + + /// + /// 属性访问生成逻辑 + /// + /// 属性集合 + /// + /// + /// + private static void GetGeneratePropertyValueForSourceEntity( + IEnumerable 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(" }"); + } + + /// + /// 属性设置生成逻辑 + /// + /// 属性集合 + /// + /// + /// + private static void SetGeneratePropertyValueForSourceEntity( + IEnumerable 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(" }"); + } + + /// + /// 属性名称集合 + /// + /// 属性集合 + /// + /// + /// + private static void GeneratePropertyListForSourceEntity( + IEnumerable propList, + StringBuilder code, + Compilation compilation, + INamedTypeSymbol classSymbol) + { + code.AppendLine(" public List PropertyNameList {get;} = new List()"); + code.AppendLine(" {"); + List tempPropList = new List(); + 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(" };"); + } + + + /// + /// 生成当前类属性信息集合 + /// + private static void GenerateEntityMemberInfoList( + IEnumerable propList, + StringBuilder code, + Compilation compilation, + INamedTypeSymbol classSymbol) + { + code.AppendLine(" public List MemberList { get; } = new()"); + code.AppendLine(" {"); + + var initializerLines = new List(); + + 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"); + 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(); + 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()) + { + 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"; + } + + /// + /// 获取枚举的参数 + /// + /// + /// + /// + private static string GetEnumMemberName(INamedTypeSymbol enumType, int value) + { + foreach (var member in enumType.GetMembers().OfType()) + { + if (member.ConstantValue is int intValue && intValue == value) + { + return $"{enumType.ToDisplayString()}.{member.Name}"; + } + } + return $"{enumType.ToDisplayString()}.Other"; + } + } +} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Analyzers/JiShe.CollectBus.Analyzers.csproj b/modules/JiShe.CollectBus.Analyzers/JiShe.CollectBus.Analyzers.csproj new file mode 100644 index 0000000..66b1fcf --- /dev/null +++ b/modules/JiShe.CollectBus.Analyzers/JiShe.CollectBus.Analyzers.csproj @@ -0,0 +1,21 @@ + + + + netstandard2.0 + true + true + false + bin + false + latest + true + true + + + + + + + + + diff --git a/modules/JiShe.CollectBus.FreeRedis/FreeRedisProvider.cs b/modules/JiShe.CollectBus.FreeRedis/FreeRedisProvider.cs index 4c81d02..b2cf9e5 100644 --- a/modules/JiShe.CollectBus.FreeRedis/FreeRedisProvider.cs +++ b/modules/JiShe.CollectBus.FreeRedis/FreeRedisProvider.cs @@ -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; - } - - ///// - ///// 单个添加数据 - ///// - ///// - ///// 主数据存储Hash缓存Key - ///// 集中器索引Set缓存Key - ///// 集中器排序索引ZSET缓存Key - ///// 集中器采集频率分组全局索引ZSet缓存Key - ///// 表计信息 - ///// 可选时间戳 - ///// - //public async Task AddMeterCacheData( - //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; - //} - - ///// - ///// 批量添加数据 - ///// - ///// - ///// 主数据存储Hash缓存Key - ///// 集中器索引Set缓存Key - ///// 集中器排序索引ZSET缓存Key - ///// 集中器采集频率分组全局索引ZSet缓存Key - ///// 数据集合 - ///// 可选时间戳 - ///// - //public async Task BatchAddMeterData( - //string redisCacheKey, - //string redisCacheFocusIndexKey, - //string redisCacheScoresIndexKey, - //string redisCacheGlobalIndexKey, - //IEnumerable 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; - //} - - ///// - ///// 删除指定redis缓存key的缓存数据 - ///// - ///// - ///// 主数据存储Hash缓存Key - ///// 集中器索引Set缓存Key - ///// 集中器排序索引ZSET缓存Key - ///// 集中器采集频率分组全局索引ZSet缓存Key - ///// 表计信息 - ///// - //public async Task RemoveMeterData( - //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("指定数据不存在"); - //} - - ///// - ///// 修改表计缓存信息 - ///// - ///// - ///// 主数据存储Hash缓存Key - ///// 旧集中器索引Set缓存Key - ///// 新集中器索引Set缓存Key - ///// 集中器排序索引ZSET缓存Key - ///// 集中器采集频率分组全局索引ZSet缓存Key - ///// 表计信息 - ///// 可选时间戳 - ///// - //public async Task UpdateMeterData( - //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> SingleGetMeterPagedData( - //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(redisCacheKey, m)).ToArray(); - // await Task.WhenAll(dataTasks); - - // // 总数统计优化 - // var total = await Instance.ZCountAsync( - // redisCacheScoresIndexKey, - // minScore, - // maxScore); - - // return new BusPagedResult - // { - // Items = dataTasks.Select(t => t.Result).ToList(), - // TotalCount = total, - // PageIndex = pageIndex, - // PageSize = pageSize - // }; - //} - - - //public async Task> GetFocusPagedData( - //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(redisCacheKey, members.CurrentItems); - - // return new BusPagedResult - // { - // 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 GetTotalCount(string zsetKey, long min, long max) - //{ - // // 缓存计数优化 - // var cacheKey = $"{zsetKey}_count_{min}_{max}"; - // var cached = await Instance.GetAsync(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>> BatchGetMeterPagedData( - //string redisCacheKey, - //string redisCacheScoresIndexKey, - //IEnumerable focusIds, - //int pageSizePerFocus = 10) where T : DeviceCacheBasicModel - //{ - // var results = new ConcurrentDictionary>(); - // var parallelOptions = new ParallelOptions - // { - // MaxDegreeOfParallelism = Environment.ProcessorCount * 2 - // }; - - // await Parallel.ForEachAsync(focusIds, parallelOptions, async (focusId, _) => - // { - // var data = await SingleGetMeterPagedData( - // redisCacheKey, - // redisCacheScoresIndexKey, - // focusId, - // pageSizePerFocus); - - // results.TryAdd(focusId, data); - // }); - - // return new Dictionary>(results); - //} - - - + } } } \ No newline at end of file diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/EntityTypeAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attribute/EntityTypeAttribute.cs deleted file mode 100644 index 3610c00..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Attribute/EntityTypeAttribute.cs +++ /dev/null @@ -1,19 +0,0 @@ -using JiShe.CollectBus.IoTDB.Enums; - -namespace JiShe.CollectBus.IoTDB.Attribute -{ - /// - /// IoTDB实体类型特性 - /// - [AttributeUsage(AttributeTargets.Class)] - public class EntityTypeAttribute : System.Attribute - { - public EntityTypeEnum EntityType { get; } - - - public EntityTypeAttribute(EntityTypeEnum entityType) - { - EntityType = entityType; - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/ATTRIBUTEColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs similarity index 83% rename from modules/JiShe.CollectBus.IoTDB/Attribute/ATTRIBUTEColumnAttribute.cs rename to modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs index d188c36..7ef13f3 100644 --- a/modules/JiShe.CollectBus.IoTDB/Attribute/ATTRIBUTEColumnAttribute.cs +++ b/modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs @@ -1,4 +1,4 @@ -namespace JiShe.CollectBus.IoTDB.Attribute +namespace JiShe.CollectBus.IoTDB.Attributes { /// /// Column分类标记特性(ATTRIBUTE字段),也就是属性字段 diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/FIELDColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs similarity index 82% rename from modules/JiShe.CollectBus.IoTDB/Attribute/FIELDColumnAttribute.cs rename to modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs index 7cabdf4..43d699f 100644 --- a/modules/JiShe.CollectBus.IoTDB/Attribute/FIELDColumnAttribute.cs +++ b/modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs @@ -1,4 +1,4 @@ -namespace JiShe.CollectBus.IoTDB.Attribute +namespace JiShe.CollectBus.IoTDB.Attributes { /// /// Column分类标记特性(FIELD字段),数据列字段 diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/SingleMeasuringAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs similarity index 91% rename from modules/JiShe.CollectBus.IoTDB/Attribute/SingleMeasuringAttribute.cs rename to modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs index 5f0ca07..481bfa2 100644 --- a/modules/JiShe.CollectBus.IoTDB/Attribute/SingleMeasuringAttribute.cs +++ b/modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs @@ -1,4 +1,4 @@ -namespace JiShe.CollectBus.IoTDB.Attribute +namespace JiShe.CollectBus.IoTDB.Attributes { /// /// 用于标识当前实体为单侧点模式,单侧点模式只有一个Filed标识字段,类型是Tuple,Item1=>测点名称,Item2=>测点值,泛型 diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/TAGColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs similarity index 82% rename from modules/JiShe.CollectBus.IoTDB/Attribute/TAGColumnAttribute.cs rename to modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs index 6f40a47..48a3830 100644 --- a/modules/JiShe.CollectBus.IoTDB/Attribute/TAGColumnAttribute.cs +++ b/modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs @@ -1,4 +1,4 @@ -namespace JiShe.CollectBus.IoTDB.Attribute +namespace JiShe.CollectBus.IoTDB.Attributes { /// /// Column分类标记特性(TAG字段),标签字段 diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/TableNameOrTreePathAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs similarity index 85% rename from modules/JiShe.CollectBus.IoTDB/Attribute/TableNameOrTreePathAttribute.cs rename to modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs index 1b4f4f0..5f986b5 100644 --- a/modules/JiShe.CollectBus.IoTDB/Attribute/TableNameOrTreePathAttribute.cs +++ b/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs @@ -1,6 +1,5 @@ -using JiShe.CollectBus.IoTDB.Enums; - -namespace JiShe.CollectBus.IoTDB.Attribute + +namespace JiShe.CollectBus.IoTDB.Attributes { /// /// IoTDB实体存储路径或表名称,一般用于已经明确的存储路径或表名称,例如日志存储 diff --git a/modules/JiShe.CollectBus.IoTDB/Context/IoTDBRuntimeContext.cs b/modules/JiShe.CollectBus.IoTDB/Context/IoTDBRuntimeContext.cs index ef68325..7384716 100644 --- a/modules/JiShe.CollectBus.IoTDB/Context/IoTDBRuntimeContext.cs +++ b/modules/JiShe.CollectBus.IoTDB/Context/IoTDBRuntimeContext.cs @@ -7,7 +7,7 @@ namespace JiShe.CollectBus.IoTDB.Context /// /// IoTDB SessionPool 运行时上下文 /// - public class IoTDBRuntimeContext: IScopedDependency + public class IoTDBRuntimeContext: IScopedDependency//ITransientDependency { private readonly bool _defaultValue; diff --git a/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs b/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs new file mode 100644 index 0000000..93bed4f --- /dev/null +++ b/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs @@ -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 +{ + /// + /// IoTDB异常 + /// + public class IoTException : Exception + { + public int ErrorCode { get; } + + public IoTException(string message, int errorCode) + : base($"{message} (Code: {errorCode})") + { + ErrorCode = errorCode; + } + } +} diff --git a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs b/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs index 82a0d47..a5d885d 100644 --- a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs +++ b/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs @@ -16,6 +16,8 @@ namespace JiShe.CollectBus.IoTDB.Interface ///// 是否使用表模型 //void SwitchSessionPool(bool useTableSession); + IIoTDbProvider GetSessionPool(bool sessionpolType); + /// /// 插入数据 /// diff --git a/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj b/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj index 8cc4b33..78b81e3 100644 --- a/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj +++ b/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj @@ -1,15 +1,19 @@  - - net8.0 - enable - enable - + + net8.0 + enable + enable + - + + + + + diff --git a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs index a079bd4..da14d20 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs @@ -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 { /// - /// IoT实体基类,此类适用于多个数据测点记录场景,单个测点请使用子类 SingleMeasuring + /// IoT实体基类,此类适用于多个数据测点记录场景,单个测点请使用子类 SingleMeasuring,新增字段只能现有字段末尾添加,否则会导致数据写入失败。 /// public abstract class IoTEntity { @@ -19,6 +22,12 @@ namespace JiShe.CollectBus.IoTDB.Model [TAGColumn] public string ProjectId { get; set; } + /// + /// 数据类型 + /// + [TAGColumn] + public string DataType { get; set; } = IOTDBDataTypeConst.Data; + /// /// 设备类型集中器、电表、水表、流量计、传感器等 /// @@ -35,5 +44,29 @@ namespace JiShe.CollectBus.IoTDB.Model /// 时标,也就是业务时间戳,单位毫秒,必须通过DateTimeOffset获取 /// public long Timestamps { get; set; } = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + + /// + /// 设备路径 + /// + private string _devicePath; + /// + /// 设备路径 + /// + public virtual string DevicePath + { + get + { + // 如果未手动设置路径,则自动生成 + if (string.IsNullOrWhiteSpace(_devicePath)) + { + return $"root.{SystemName.ToLower()}.`{ProjectId}`.`{DeviceType}`.{DataType}.`{DeviceId}`"; + } + return _devicePath; + } + set + { + _devicePath = value; // 直接赋值给支持字段,避免递归 + } + } } } diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs index 4308dae..376b677 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs @@ -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 { /// /// Table模型单项数据实体 - /// - [EntityType(EntityTypeEnum.TableModel)] + /// + [SourceAnalyzers(EntityTypeEnum.TableModel)] public class TableModelSingleMeasuringEntity : IoTEntity { /// /// 单项数据键值对 /// [SingleMeasuring(nameof(SingleColumn))] - public required Tuple SingleColumn { get; set; } + public required ValueTuple SingleColumn { get; set; } } } diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs index 9b3609c..56a6c54 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs @@ -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 { /// /// Tree模型单项数据实体 /// - [EntityType(EntityTypeEnum.TreeModel)] + [SourceAnalyzers(EntityTypeEnum.TreeModel)] public class TreeModelSingleMeasuringEntity : IoTEntity { /// /// 单项数据键值对 /// [SingleMeasuring(nameof(SingleMeasuring))] - public required Tuple SingleMeasuring { get; set; } + public required ValueTuple SingleMeasuring { get; set; } } } diff --git a/modules/JiShe.CollectBus.IoTDB/Options/IoTDBOptions.cs b/modules/JiShe.CollectBus.IoTDB/Options/IoTDBOptions.cs index 251e48b..68b2770 100644 --- a/modules/JiShe.CollectBus.IoTDB/Options/IoTDBOptions.cs +++ b/modules/JiShe.CollectBus.IoTDB/Options/IoTDBOptions.cs @@ -26,7 +26,7 @@ /// /// 连接池大小 /// - public int PoolSize { get; set; } = 2; + public int PoolSize { get; set; } = 8; /// /// 查询时,每次查询的数据量,默认1024 diff --git a/modules/JiShe.CollectBus.IoTDB/Options/QueryCondition.cs b/modules/JiShe.CollectBus.IoTDB/Options/QueryCondition.cs index 40dd443..bccf017 100644 --- a/modules/JiShe.CollectBus.IoTDB/Options/QueryCondition.cs +++ b/modules/JiShe.CollectBus.IoTDB/Options/QueryCondition.cs @@ -1,4 +1,7 @@ -namespace JiShe.CollectBus.IoTDB.Options +using JiShe.CollectBus.Common.Extensions; +using JiShe.CollectBus.Common.Helpers; + +namespace JiShe.CollectBus.IoTDB.Options { /// /// 查询条件 @@ -19,10 +22,43 @@ /// 是否数值,如果是数值,则进行数值比较,否则进行字符串比较 /// public bool IsNumber { get; set; } = false; - + + private object _rawValue; /// /// 值 /// - public object Value { get; set; } + public object Value + { + get => ApplyValueConversion(_rawValue); + set => _rawValue = value; + } + + /// + /// 值转换 + /// + /// + /// + private object ApplyValueConversion(object rawValue) + { + string declaredTypeName = rawValue.GetType().Name; + + Func converter = GetQueryConditionValue(declaredTypeName); + return converter(rawValue); + } + + /// + /// 查询条件值转换委托 + /// + /// + /// + private Func GetQueryConditionValue(string declaredTypeName) + { + return declaredTypeName?.ToUpper() switch + { + "DATETIME" => v => v != null ? ((DateTime)v).ToUniversalTime().Ticks : null, + "STRING" => v => v != null ? $"'{v}'" : "''", + _ => v => v + }; + } } } diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs b/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs index a093bb7..a93ba35 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs @@ -1,17 +1,27 @@ using Apache.IoTDB; -using JiShe.CollectBus.IoTDB.Enums; +using JiShe.CollectBus.Analyzers.Shared; namespace JiShe.CollectBus.IoTDB.Provider { /// /// 设备元数据 /// - public class DeviceMetadata + public sealed class DeviceMetadata { /// - /// IoTDB实体类型枚举 + /// 实体类名称 /// - public EntityTypeEnum EntityType { get; set; } + public string EntityName { get; set; } + + /// + /// 设备表名或树路径,如果实体没有添加TableNameOrTreePath,此处为空 + /// + public string TableNameOrTreePath { get; set; } + + /// + /// 实体类型枚举 + /// + public EntityTypeEnum? EntityType { get; set; } /// /// 是否有单测量值 @@ -31,6 +41,57 @@ namespace JiShe.CollectBus.IoTDB.Provider /// /// 值类型集合,用于构建Table的值类型,也就是dataTypes参数 /// - public List DataTypes { get; } = new(); + public List DataTypes { get; set; } = new(); + + /// + /// 列处理信息集合 + /// + public List Processors { get; } = new List(); + } + + /// + /// 列处理信息结构 + /// + public struct ColumnProcessor + { + /// + /// 列名 + /// + public string ColumnName; + + /// + /// 数据类型 + /// + public TSDataType TSDataType { get; set;} + + /// + /// 值获取委托(参数:实体对象) + /// + public Func ValueGetter; + + /// + /// 值设置委托(参数:实体对象,新值) + /// + public Action ValueSetter; + + /// + /// 类型转换委托 + /// + public Func GetConverter; + + /// + /// 类型转换委托 + /// + public Func SetConverter; + + /// + /// 是否单测点 + /// + public bool IsSingleMeasuring; + + /// + /// 单测点名称委托 + /// + public Func SingleMeasuringNameGetter; } } diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs b/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs index 6a1a596..57e1b09 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs @@ -15,7 +15,7 @@ namespace JiShe.CollectBus.IoTDB.Provider /// public static string GetDevicePath(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}`"; } diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs index 9c7c602..cd57ea9 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs @@ -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 MetadataCache = new(); private readonly ILogger _logger; - private readonly IIoTDbSessionFactory _sessionFactory; - private readonly IoTDBRuntimeContext _runtimeContext; + private readonly IIoTDbSessionFactory _sessionFactory; + + /// + /// 存储模型切换标识,是否使用table模型存储, 默认为false,标识tree模型存储 + /// + 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); /// /// IoTDbProvider @@ -43,12 +61,10 @@ namespace JiShe.CollectBus.IoTDB.Provider /// public IoTDbProvider( ILogger 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(); 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(); 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(DeviceMetadata deviceMetadata, IEnumerable 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(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 /// public async Task GetMetadata() where T : IoTEntity { - var columns = CollectColumnMetadata(typeof(T)); - var metadata = BuildDeviceMetadata(columns); + var accessor = SourceEntityAccessorFactory.GetAccessor(); + + var columns = CollectColumnMetadata(accessor); + var tmpMetadata = BuildDeviceMetadata(columns, accessor); + + string tableNameOrTreePath = string.Empty; + var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute(); + 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(columns); + var columns = CollectColumnMetadata(accessor); + var metadata = BuildDeviceMetadata(columns, accessor); //对现有值 existingValue 进行修改,返回新值 + string tableNameOrTreePath = string.Empty; + var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute(); + 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(); + // 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(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 /// 表实体 /// 设备元数据 /// - private Tablet BuildTablet(IEnumerable entities, DeviceMetadata metadata) where T : IoTEntity + private List BuildTablet(IEnumerable entities, DeviceMetadata metadata) where T : IoTEntity { - var timestamps = new List(); - var values = new List>(); - var devicePaths = new HashSet(); - List tempColumnNames = new List(); - tempColumnNames.AddRange(metadata.ColumnNames); + var entitiyList = entities.ToList(); + if (entitiyList == null || entitiyList.Count <= 0) + { + return null; + } + - var entityTypeAttribute = typeof(T).GetCustomAttribute(); - - 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(); - if (tableNameOrTreePathAttribute != null) + if ( UseTableSessionPool)//表模型 { - tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath; - } - - foreach (var entity in entities) - { - timestamps.Add(entity.Timestamps); - var rowValues = new List(); - - 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()); - } + tableNameOrTreePath = DevicePathBuilder.GetTableName(); } + return new List() { BuildTablet(entitiyList, metadata, tableNameOrTreePath) }; } - - if (devicePaths.Count > 1) + else { - throw new Exception($"{nameof(BuildTablet)} 构建Tablet《{typeof(T).Name}》时,批量插入的设备路径不一致。"); + //树模型的时候,实体的设备Id可能会不同,因此需要根据不同路径进行存储。 + var tabletList = new List(); + 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(List 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 tempColumnNames = new List(); + 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()); } + /// /// 构建tree模型的Tablet /// /// 已解析的设备数据元数据 /// 设备路径 + /// 数据列集合 /// 数据集合 /// 时间戳集合 /// - private Tablet BuildSessionTablet(DeviceMetadata metadata, string devicePath, List> values, List timestamps) + private Tablet BuildSessionTablet(DeviceMetadata metadata, string devicePath, List columns, List> values, List 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 /// /// 已解析的设备数据元数据 /// 表名称 + /// 数据列集合 /// 数据集合 /// 时间戳集合 /// - private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List> values, List timestamps) + private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List columns, List> values, List 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 BuildQuerySQL(IoTDBQueryOptions options) where T : IoTEntity { var metadata = await GetMetadata(); - 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(); var sb = new StringBuilder(); - if (!_runtimeContext.UseTableSessionPool) + if (!UseTableSessionPool) { sb.Append("DELETE "); } @@ -471,16 +534,16 @@ namespace JiShe.CollectBus.IoTDB.Provider /// /// 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} 属于异常情况") }; } - + /// /// 获取查询条件的总数量 /// @@ -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(); var metadata = await GetMetadata(); - var properties = typeof(T).GetProperties(); + var accessor = SourceEntityAccessorFactory.GetAccessor(); + var memberCache = BuildMemberCache(accessor); - var columns = new List() { "Timestamps" }; - var dataTypes = new List() { 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 /// /// 获取设备元数据的列 /// - /// + /// /// - private List CollectColumnMetadata(Type type) + private List CollectColumnMetadata(ISourceEntityAccessor accessor) { var columns = new List(); + 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(); + var tagAttr = attributes.OfType().FirstOrDefault(); + var attrColumn = attributes.OfType().FirstOrDefault(); + var fieldColumn = attributes.OfType().FirstOrDefault(); + var singleMeasuringAttr = attributes.OfType().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() is not null ? new ColumnInfo( - name: prop.Name, - category: ColumnCategory.TAG, - dataType: GetDataTypeFromTypeName(typeName), - false - ) : prop.GetCustomAttribute() is not null ? new ColumnInfo( - prop.Name, - ColumnCategory.ATTRIBUTE, - GetDataTypeFromTypeName(typeName), - false - ) : prop.GetCustomAttribute() is not null ? new ColumnInfo( - prop.Name, - ColumnCategory.FIELD, - GetDataTypeFromTypeName(typeName), - false) - : null; - - //最先检查是不是单侧点模式 - SingleMeasuringAttribute singleMeasuringAttribute = prop.GetCustomAttribute(); - - if (singleMeasuringAttribute != null && column == null) + // 单测模式处理 + if (singleMeasuringAttr != null && column == null) { - //warning: 单侧点模式注意事项 - //Entity实体 字段类型是 Tuple,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 /// 待解析的类 /// 已处理好的数据列 /// - private DeviceMetadata BuildDeviceMetadata(List columns) where T : IoTEntity + private DeviceMetadata BuildDeviceMetadata(List columns, ISourceEntityAccessor 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(); - - 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; } + /// + /// 验证单测点名称格式 + /// + 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}' 不能全为数字"); + } + } + + /// + /// 取值的处理器 + /// + /// + /// + private Func 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 + }; + } + + /// + /// 设置值的处理 + /// + /// + /// + private Func SetterConverter(string columnName) => + columnName.ToLower().EndsWith("time") + ? value => value != null ? TimestampHelper.ConvertToDateTime(Convert.ToInt64(value), TimestampUnit.Nanoseconds) : null + : value => value; + /// /// 处理不同列类型的逻辑 /// @@ -704,6 +852,11 @@ namespace JiShe.CollectBus.IoTDB.Provider /// public string Name { get; } + /// + /// 声明的类型的名称 + /// + public string DeclaredTypeName { get; } + /// /// 是否是单测点 /// @@ -719,12 +872,13 @@ namespace JiShe.CollectBus.IoTDB.Provider /// 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) }; + + /// + /// 缓存实体属性信息 + /// + /// + /// + /// + private Dictionary BuildMemberCache(ISourceEntityAccessor accessor) + { + var cache = new Dictionary(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); } } diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs b/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs index ee71cf1..26ea4c7 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs @@ -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; diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs b/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs index dc4f0ee..8edb112 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs @@ -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(); diff --git a/modules/JiShe.CollectBus.Kafka.Test/JiShe.CollectBus.Kafka.Test.csproj b/modules/JiShe.CollectBus.Kafka.Test/JiShe.CollectBus.Kafka.Test.csproj index db97b00..c312740 100644 --- a/modules/JiShe.CollectBus.Kafka.Test/JiShe.CollectBus.Kafka.Test.csproj +++ b/modules/JiShe.CollectBus.Kafka.Test/JiShe.CollectBus.Kafka.Test.csproj @@ -31,10 +31,14 @@ - + + diff --git a/modules/JiShe.CollectBus.Kafka.Test/KafkaProduceBenchmark.cs b/modules/JiShe.CollectBus.Kafka.Test/KafkaProduceBenchmark.cs index a8b8d93..4152a33 100644 --- a/modules/JiShe.CollectBus.Kafka.Test/KafkaProduceBenchmark.cs +++ b/modules/JiShe.CollectBus.Kafka.Test/KafkaProduceBenchmark.cs @@ -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(config); + services.Configure(options => + { + config.GetSection("Kafka").Bind(options); + }); + services.Configure(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(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddTransient(); // 构建ServiceProvider _serviceProvider = services.BuildServiceProvider(); @@ -72,10 +85,10 @@ namespace JiShe.CollectBus.Kafka.Test var adminClientService = _serviceProvider.GetRequiredService(); - + //await adminClientService.DeleteTopicAsync(topic); // 创建 topic - adminClientService.CreateTopicAsync(topic, 3, 3).ConfigureAwait(false).GetAwaiter(); + //adminClientService.CreateTopicAsync(topic, 3, 3).ConfigureAwait(false).GetAwaiter(); _consumerService = _serviceProvider.GetRequiredService(); @@ -100,9 +113,9 @@ namespace JiShe.CollectBus.Kafka.Test List tasks = new(); for (int i = 0; i < N; ++i) { - var task = _producerService.ProduceAsync(topic, i.ToString(),null); + var task = _producerService.ProduceAsync(topic, i.ToString(), null); } await Task.WhenAll(tasks); } - } + } } diff --git a/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Common.dll b/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Common.dll new file mode 100644 index 0000000..5d9bd8d Binary files /dev/null and b/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Common.dll differ diff --git a/modules/JiShe.CollectBus.Kafka.Test/Program.cs b/modules/JiShe.CollectBus.Kafka.Test/Program.cs index 3c99810..d932806 100644 --- a/modules/JiShe.CollectBus.Kafka.Test/Program.cs +++ b/modules/JiShe.CollectBus.Kafka.Test/Program.cs @@ -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(); @@ -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(config.GetSection("Kafka")); + //services.Configure(config.GetSection("Kafka")); + //services.Configure(config.GetSection("ServerApplicationOptions")); + var dss = config.GetSection("Kafka"); + + services.Configure(options => + { + config.GetSection("Kafka").Bind(options); + }); + services.Configure(options => + { + config.GetSection(nameof(ServerApplicationOptions)).Bind(options); + }); services.AddSingleton(); services.AddSingleton(); @@ -86,8 +90,20 @@ var host = Host.CreateDefaultBuilder(args) var loggerFactory = host.Services.GetRequiredService(); var logger = loggerFactory.CreateLogger(); logger.LogInformation("程序启动"); + + +var _kafkaPollyPipeline = host.Services.GetRequiredService(); +if (_kafkaPollyPipeline == null) +{ + logger.LogInformation("KafkaPollyPipeline未注册!"); +} + + var adminClientService = host.Services.GetRequiredService(); var configuration = host.Services.GetRequiredService(); + +var kafkaOptionConfig=host.Services.GetRequiredService>(); + string topic = ProtocolConst.TESTTOPIC; //await adminClientService.DeleteTopicAsync(topic); // 创建 topic diff --git a/modules/JiShe.CollectBus.Kafka.Test/Properties/launchSettings.json b/modules/JiShe.CollectBus.Kafka.Test/Properties/launchSettings.json new file mode 100644 index 0000000..33504c9 --- /dev/null +++ b/modules/JiShe.CollectBus.Kafka.Test/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "WSL": { + "commandName": "WSL2", + "distributionName": "" + } + } +} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka.Test/appsettings.json b/modules/JiShe.CollectBus.Kafka.Test/appsettings.json index 9767dee..0734e89 100644 --- a/modules/JiShe.CollectBus.Kafka.Test/appsettings.json +++ b/modules/JiShe.CollectBus.Kafka.Test/appsettings.json @@ -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", //策略为NetworkTopologyStrategy时才会有多个数据中心,SimpleStrategy用在只有一个数据中心的情况下 @@ -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": "" } \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/AdminClient/AdminClientService.cs b/modules/JiShe.CollectBus.Kafka/AdminClient/AdminClientService.cs index 66643a5..ac793b2 100644 --- a/modules/JiShe.CollectBus.Kafka/AdminClient/AdminClientService.cs +++ b/modules/JiShe.CollectBus.Kafka/AdminClient/AdminClientService.cs @@ -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 _logger; - + private readonly KafkaOptionConfig _kafkaOptionConfig; /// /// Initializes a new instance of the class. /// /// /// - public AdminClientService(IConfiguration configuration, ILogger logger) + public AdminClientService(IConfiguration configuration, ILogger logger, IOptions kafkaOptionConfig) { _logger = logger; - Instance = GetInstance(configuration); + _kafkaOptionConfig = kafkaOptionConfig.Value; + Instance = GetInstance(); } /// @@ -142,22 +145,19 @@ public class AdminClientService : IAdminClientService, IDisposable, ISingletonDe /// /// Gets the instance. /// - /// The configuration. /// - 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(); } diff --git a/modules/JiShe.CollectBus.Kafka/Consumer/ConsumerService.cs b/modules/JiShe.CollectBus.Kafka/Consumer/ConsumerService.cs index fc853e9..043af46 100644 --- a/modules/JiShe.CollectBus.Kafka/Consumer/ConsumerService.cs +++ b/modules/JiShe.CollectBus.Kafka/Consumer/ConsumerService.cs @@ -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 /// /// 消费完或者无数据时的延迟时间 /// - 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 /// public async Task SubscribeAsync(string[] topics, Func> 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(groupId), - cts - )).Consumer as IConsumer; - - 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(groupId), + cts + )).Consumer as IConsumer; + + 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 /// public async Task SubscribeAsync(string[] topics, Func> 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(groupId), - cts - )).Consumer as IConsumer; - - 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(groupId), + cts + )).Consumer as IConsumer; - 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 /// 批次超时时间 public async Task SubscribeBatchAsync(string topic, Func, Task> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null) where TKey : notnull where TValue : class { - await SubscribeBatchAsync(new[] { topic }, messageBatchHandler, groupId, batchSize, batchTimeout); + try + { + await SubscribeBatchAsync(new[] { topic }, messageBatchHandler, groupId, batchSize, batchTimeout); + } + catch (Exception ex) + { + + throw; + } } /// @@ -310,112 +340,125 @@ namespace JiShe.CollectBus.Kafka.Consumer /// 批次超时时间 public async Task SubscribeBatchAsync(string[] topics, Func, Task> 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(groupId), - cts - )).Consumer as IConsumer; - 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(groupId), + cts + )).Consumer as IConsumer; + 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(); + 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(); - 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 /// 消费等待时间 public async Task SubscribeBatchAsync(string topic, Func, Task> 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 /// 消费等待时间 public async Task SubscribeBatchAsync(string[] topics, Func, Task> 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(groupId), - cts - )).Consumer as IConsumer; - - 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(groupId), + cts + )).Consumer as IConsumer; + + 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(); + 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(); - 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 /// public void Unsubscribe(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; } } diff --git a/modules/JiShe.CollectBus.Kafka/Internal/KafkaPollyPipeline.cs b/modules/JiShe.CollectBus.Kafka/Internal/KafkaPollyPipeline.cs index c467921..fd4bb1b 100644 --- a/modules/JiShe.CollectBus.Kafka/Internal/KafkaPollyPipeline.cs +++ b/modules/JiShe.CollectBus.Kafka/Internal/KafkaPollyPipeline.cs @@ -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 { diff --git a/modules/JiShe.CollectBus.Kafka/KafkaSubscribeExtensions.cs b/modules/JiShe.CollectBus.Kafka/KafkaSubscribeExtensions.cs index 3c50aae..ccbe540 100644 --- a/modules/JiShe.CollectBus.Kafka/KafkaSubscribeExtensions.cs +++ b/modules/JiShe.CollectBus.Kafka/KafkaSubscribeExtensions.cs @@ -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>(); - 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 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 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(); 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(); + 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(); + + // 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(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(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 /// private static async Task ProcessMessageAsync(List 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 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 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 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 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; } } diff --git a/modules/JiShe.CollectBus.Kafka/Producer/ProducerService.cs b/modules/JiShe.CollectBus.Kafka/Producer/ProducerService.cs index 50df423..72e9096 100644 --- a/modules/JiShe.CollectBus.Kafka/Producer/ProducerService.cs +++ b/modules/JiShe.CollectBus.Kafka/Producer/ProducerService.cs @@ -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 /// public async Task ProduceAsync(string topic, TKey key, TValue value)where TKey : notnull where TValue : class { - var typeKey = typeof(KafkaProducer); - var producer = GetProducer(typeKey); - var message = new Message + try { - Key = key, - Value = value, - Headers = new Headers{ + var typeKey = typeof(KafkaProducer); + var producer = GetProducer(typeKey); + var message = new Message + { + 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; + } } /// @@ -136,17 +147,24 @@ namespace JiShe.CollectBus.Kafka.Producer /// public async Task ProduceAsync(string topic, TValue value) where TValue : class { - var typeKey = typeof(KafkaProducer); - var producer = GetProducer(typeKey); - var message = new Message + try { - //Key= _kafkaOptionConfig.ServerTagName, - Value = value, - Headers = new Headers{ + var typeKey = typeof(KafkaProducer); + var producer = GetProducer(typeKey); + var message = new Message + { + 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; + } } /// @@ -162,26 +180,34 @@ namespace JiShe.CollectBus.Kafka.Producer /// public async Task ProduceAsync(string topic,TKey key,TValue value,int? partition=null, Action>? deliveryHandler = null)where TKey : notnull where TValue : class { - var message = new Message + try { - Key = key, - Value = value, - Headers = new Headers{ + var message = new Message + { + Key = key, + Value = value, + Headers = new Headers{ { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } } - }; - var typeKey = typeof(KafkaProducer); - var producer = GetProducer(typeKey); - if (partition.HasValue) - { - var topicPartition = new TopicPartition(topic, partition.Value); - producer.Produce(topicPartition, message, deliveryHandler); + }; + var typeKey = typeof(KafkaProducer); + var producer = GetProducer(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 /// public async Task ProduceAsync(string topic, TValue value, int? partition=null, Action>? deliveryHandler = null) where TValue : class { - var message = new Message + try { - //Key = _kafkaOptionConfig.ServerTagName, - Value = value, - Headers = new Headers{ + var message = new Message + { + Value = value, + Headers = new Headers{ { "route-key", Encoding.UTF8.GetBytes(_applicationOptions.ServerTagName) } } - }; - var typeKey = typeof(KafkaProducer); - var producer = GetProducer(typeKey); - if (partition.HasValue) - { - var topicPartition = new TopicPartition(topic, partition.Value); - producer.Produce(topicPartition, message, deliveryHandler); + }; + var typeKey = typeof(KafkaProducer); + var producer = GetProducer(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() diff --git a/modules/JiShe.CollectBus.Kafka/Serialization/JsonSerializer.cs b/modules/JiShe.CollectBus.Kafka/Serialization/JsonSerializer.cs index 8034954..98fda49 100644 --- a/modules/JiShe.CollectBus.Kafka/Serialization/JsonSerializer.cs +++ b/modules/JiShe.CollectBus.Kafka/Serialization/JsonSerializer.cs @@ -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(data, _options)!; + return JsonSerializer.Deserialize(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; + } } } } diff --git a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContext.cs b/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContext.cs index ebc5ad1..c0ddd77 100644 --- a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContext.cs +++ b/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContext.cs @@ -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 MessageIssueds => Collection(); - protected override void CreateModel(IMongoModelBuilder modelBuilder) { diff --git a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbModule.cs b/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbModule.cs index f427d19..89fd079 100644 --- a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbModule.cs +++ b/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbModule.cs @@ -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(); - }); + options.AddRepository(); + }); context.Services.AddAlwaysDisableUnitOfWorkTransaction(); Configure(options => { diff --git a/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/ILogRecordRepository.cs b/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/ILogRecordRepository.cs new file mode 100644 index 0000000..8d1c203 --- /dev/null +++ b/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/ILogRecordRepository.cs @@ -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 + { + /// + /// 批量插入 + /// + /// + /// + /// + Task InsertManyAsync(List entities, + DateTime? dateTime); + + /// + /// 单个插入 + /// + /// + /// + /// + Task InsertAsync(LogRecords entity, DateTime? dateTime); + + /// + /// 单条更新 + /// + /// 过滤条件,示例:Builders.Filter.Eq(x => x.Id, filter.Id) + /// 包含待更新的内容,示例:Builders.Update.Set(x => x.SendHexMessage, SendHexMessage).Set(x => x.MessageId, MessageId) + /// 数据实体,用于获取对应的分片库 + /// + Task UpdateOneAsync(FilterDefinition filter, UpdateDefinition update, LogRecords entity); + + /// + /// 单个获取 + /// + /// + /// + /// + Task FirOrDefaultAsync(LogRecords entity, DateTime dateTime); + + /// + /// 多集合数据查询 + /// + /// + /// + /// + Task> ParallelQueryAsync(DateTime startTime, DateTime endTime); + } +} diff --git a/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/LogRecordRepository.cs b/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/LogRecordRepository.cs new file mode 100644 index 0000000..415ad06 --- /dev/null +++ b/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/LogRecordRepository.cs @@ -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, ILogRecordRepository + { + + private readonly HourShardingStrategy _hourShardingStrategy; + private readonly IMongoDbContextProvider _dbContextProvider; + + public LogRecordRepository( + IMongoDbContextProvider dbContextProvider, + HourShardingStrategy hourShardingStrategy + ) + : base(dbContextProvider) + { + _dbContextProvider = dbContextProvider; + _hourShardingStrategy = hourShardingStrategy; + } + + /// + /// 批量插入 + /// + /// + /// + /// + public override async Task> InsertManyAsync(IEnumerable entities, bool autoSave = false, CancellationToken cancellationToken = default(CancellationToken)) + { + var collection = await GetShardedCollection(DateTime.Now); + await collection.InsertManyAsync(entities); + + return entities; + } + + /// + /// 批量插入 + /// + /// + /// + /// + public async Task InsertManyAsync(List entities, DateTime? dateTime) + { + var collection = await GetShardedCollection(dateTime); + await collection.InsertManyAsync(entities); + } + + + /// + /// 单条插入 + /// + /// + /// + /// + public override async Task InsertAsync(LogRecords entity, bool autoSave = false, CancellationToken cancellationToken = default(CancellationToken)) + { + var collection = await GetShardedCollection(DateTime.Now); + await collection.InsertOneAsync(entity); + return entity; + } + + + /// + /// 单条插入 + /// + /// + /// + /// + public async Task InsertAsync(LogRecords entity, DateTime? dateTime) + { + var collection = await GetShardedCollection(dateTime); + await collection.InsertOneAsync(entity); + return entity; + } + + /// + /// 单条更新 + /// + /// 过滤条件,示例:Builders.Filter.Eq(x => x.Id, filter.Id) + /// 包含待更新的内容,示例:Builders.Update.Set(x => x.SendHexMessage, SendHexMessage).Set(x => x.MessageId, MessageId) + /// 数据实体,用于获取对应的分片库 + /// + public async Task UpdateOneAsync(FilterDefinition filter, UpdateDefinition update, LogRecords entity) + { + var collection = await GetShardedCollection(entity.CreationTime); + + await collection.UpdateOneAsync(filter, update); + return entity; + } + + + /// + /// 单个获取 + /// + /// + /// + /// + /// + public async Task 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(); + } + + /// + /// 多集合数据查询 + /// + /// + /// + /// + public async Task> 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(name); + var filter = Builders.Filter.And( + Builders.Filter.Gte(x => x.CreationTime, startTime), + Builders.Filter.Lte(x => x.CreationTime, endTime) + ); + return await collection.Find(filter).ToListAsync(); + }); + + var results = await Task.WhenAll(tasks); + return results.SelectMany(r => r).ToList(); + } + + /// + /// 获得分片集合 + /// + /// + private async Task> 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(collectionName); + } + } +} diff --git a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/DayShardingStrategy.cs b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/DayShardingStrategy.cs index f26136d..0c721a5 100644 --- a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/DayShardingStrategy.cs +++ b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/DayShardingStrategy.cs @@ -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)}"; } /// @@ -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)}"; } /// @@ -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); } diff --git a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/HourShardingStrategy.cs b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/HourShardingStrategy.cs new file mode 100644 index 0000000..20f65de --- /dev/null +++ b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/HourShardingStrategy.cs @@ -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 +{ + /// + /// 按小时分表 + /// + /// + public class HourShardingStrategy + { + /// + /// 获取指定时间对应的集合名 + /// + /// + /// + public string GetCollectionName(DateTime dateTime) + { + var baseName = typeof(TEntity).Name; + return $"{baseName}_{dateTime.GetDataTableShardingStrategy(TableTimeStrategyEnum.HourShardingStrategy)}"; + } + + /// + /// 获取当前时间对应的集合名 + /// + /// + public string GetCurrentCollectionName() + { + var baseName = typeof(TEntity).Name; + return $"{baseName}_{DateTime.Now.GetDataTableShardingStrategy(TableTimeStrategyEnum.HourShardingStrategy)}"; + } + + /// + /// 用于查询时确定目标集合 + /// + /// + /// + /// + public IEnumerable GetQueryCollectionNames(DateTime? startTime, DateTime? endTime) + { + var list = new List(); + 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(); + } + } +} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F188_AnalysisDto.cs b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IHourShardingStrategy.cs similarity index 51% rename from services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F188_AnalysisDto.cs rename to modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IHourShardingStrategy.cs index 1afb8ff..ad0654c 100644 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F188_AnalysisDto.cs +++ b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IHourShardingStrategy.cs @@ -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 + public interface IHourShardingStrategy : IShardingStrategy { } } diff --git a/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketBuilder.cs b/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketBuilder.cs index e5511f2..7dc8e43 100644 --- a/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketBuilder.cs +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketBuilder.cs @@ -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() { "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() { "A0", "17", "00", d_data }; var dataList = Build188SendData.Build188SendCommand(request.MeterAddress, c_data, dataUnit); diff --git a/protocols/JiShe.CollectBus.Protocol.T1882018/T1882018ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T1882018/T1882018ProtocolPlugin.cs index 5aa1b1f..5b3044a 100644 --- a/protocols/JiShe.CollectBus.Protocol.T1882018/T1882018ProtocolPlugin.cs +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/T1882018ProtocolPlugin.cs @@ -91,8 +91,10 @@ namespace JiShe.CollectBus.Protocol.T1882018 List dataUnit = new List(); //数据转发场景 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; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F1_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F1_Analysis.cs index 63ab925..6fd96e1 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F1_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F1_Analysis.cs @@ -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 /// /// 5.1.3.1 F1:全部确认:对收到报文中的全部数据单元标识进行确认 /// - public class AFN0_F1_Analysis: IAnalysisStrategy> + public class AFN0_F1_Analysis: IAnalysisStrategy { private readonly ILogger _logger; + private readonly DataStorage _dataStorage; - public AFN0_F1_Analysis(ILogger logger) + public AFN0_F1_Analysis(ILogger logger, DataStorage dataStorage) { _logger = logger; + _dataStorage= dataStorage; } - public Task> ExecuteAsync(TB3761 tB3761) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { - ArgumentNullException.ThrowIfNull(nameof(tB3761)); - UnitDataAnalysis dto = new UnitDataAnalysis + ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); + var data = new AnalysisBaseDto() { - 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> dto = new UnitDataAnalysis> + { + 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(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); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs index 5ae0b45..2e465b8 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs @@ -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 /// /// 5.1.3.2 F2:全部否认 /// - public class AFN0_F2_Analysis : IAnalysisStrategy> + public class AFN0_F2_Analysis : IAnalysisStrategy { private readonly ILogger _logger; - - public AFN0_F2_Analysis(ILogger logger) + private readonly DataStorage _dataStorage; + public AFN0_F2_Analysis(ILogger logger, DataStorage dataStorage) { _logger = logger; + _dataStorage = dataStorage; } - public Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); - UnitDataAnalysis dto = new UnitDataAnalysis + ArgumentNullException.ThrowIfNull(input.A.Code); + var data = new AnalysisBaseDto() + { + 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> dto = new UnitDataAnalysis> { 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(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); } + + } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F1_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F1_Analysis.cs new file mode 100644 index 0000000..686d027 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F1_Analysis.cs @@ -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 +{ + /// + /// 5.3.3.1 F1:登录 + /// + public class AFN2_F1_Analysis : IAnalysisStrategy + { + private readonly ILogger _logger; + private readonly DataStorage _dataStorage; + public AFN2_F1_Analysis(ILogger logger, DataStorage dataStorage) + { + _logger = logger; + _dataStorage= dataStorage; + } + + public async Task ExecuteAsync(TB3761 input, Action? result = null) + { + try + { + ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); + var data = new AnalysisBaseDto() + { + 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> dto = new UnitDataAnalysis> + { + 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(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); + } + + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F2_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F2_Analysis.cs new file mode 100644 index 0000000..6428063 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F2_Analysis.cs @@ -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 +{ + /// + /// 5.3.3.2 F2:退出登录 + /// + public class AFN2_F2_Analysis : IAnalysisStrategy + { + private readonly ILogger _logger; + private readonly DataStorage _dataStorage; + public AFN2_F2_Analysis(ILogger logger, DataStorage dataStorage) + { + _logger = logger; + _dataStorage = dataStorage; + } + + public async Task ExecuteAsync(TB3761 input, Action? result = null) + { + try + { + ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); + var data = new AnalysisBaseDto() + { + 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> dto = new UnitDataAnalysis> + { + 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(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); + } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F3_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F3_Analysis.cs new file mode 100644 index 0000000..1c3027b --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_02H/AFN2_F3_Analysis.cs @@ -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 +{ + /// + /// 5.3.3.3 F3:心跳 + /// + public class AFN2_F3_Analysis : IAnalysisStrategy + { + private readonly ILogger _logger; + private readonly DataStorage _dataStorage; + public AFN2_F3_Analysis(ILogger logger, DataStorage dataStorage) + { + _logger = logger; + _dataStorage = dataStorage; + } + + public async Task ExecuteAsync(TB3761 input, Action? result = null) + { + try + { + ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); + var data = new AnalysisBaseDto() + { + 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> dto = new UnitDataAnalysis> + { + 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(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); + } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_09H/AFN9_F1_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_09H/AFN9_F1_Analysis.cs index fd93dab..5011b4e 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_09H/AFN9_F1_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_09H/AFN9_F1_Analysis.cs @@ -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 /// /// 5.9.1.2 F1:终端版本信息 /// - public class AFN9_F1_Analysis : IAnalysisStrategy> + public class AFN9_F1_Analysis : IAnalysisStrategy { private readonly ILogger _logger; - public AFN9_F1_Analysis(ILogger logger) + private readonly DataStorage _dataStorage; + + public AFN9_F1_Analysis(ILogger logger, DataStorage dataStorage) { _logger = logger; + _dataStorage = dataStorage; } - public Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? 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 dto = new UnitDataAnalysis + 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() { - 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> dto = new UnitDataAnalysis> + { + 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 hexMessageList) diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_09H/AFN9_F9_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_09H/AFN9_F9_Analysis.cs index 5d7f9f7..7547662 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_09H/AFN9_F9_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_09H/AFN9_F9_Analysis.cs @@ -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 /// /// 5.9.2.4.9 F9:远程通信模块版本信息(只读解析SIM卡号) /// - public class AFN9_F9_Analysis : IAnalysisStrategy> + public class AFN9_F9_Analysis : IAnalysisStrategy { private readonly ILogger _logger; - - public AFN9_F9_Analysis(ILogger logger) + private readonly DataStorage _dataStorage; + public AFN9_F9_Analysis(ILogger logger, DataStorage dataStorage) { _logger = logger; + _dataStorage = dataStorage; } - public Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList); - UnitDataAnalysis dto = new UnitDataAnalysis + var data = new AnalysisBaseDto() { - 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> dto = new UnitDataAnalysis> + { + 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); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F10_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F10_Analysis.cs index b6d190f..7e36e11 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F10_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F10_Analysis.cs @@ -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 /// /// 5.10.1.3.1 F10:终端电能表/交流采样装置配置参数 /// - internal class AFN10_F10_Analysis : IAnalysisStrategy> + internal class AFN10_F10_Analysis : IAnalysisStrategy { private readonly ILogger _logger; - public AFN10_F10_Analysis(ILogger logger) + private readonly DataStorage _dataStorage; + public AFN10_F10_Analysis(ILogger logger, DataStorage dataStorage) { _logger = logger; + _dataStorage = dataStorage; } - - public Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList); Tuple> tuple = AFN10F10EntityAnalysis(input.UnitData.HexMessageList); - UnitDataAnalysis dto = new UnitDataAnalysis + + var data = new AnalysisBaseDto() { - 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> dto = new UnitDataAnalysis> + { + 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(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> AFN10F10EntityAnalysis(List hexMessageList) { List> meterList = new List>(); @@ -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 "其他协议"; } + + } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F66_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F66_Analysis.cs index c197509..5305476 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F66_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F66_Analysis.cs @@ -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 { /// /// 5.5.1.3.53 F66:定时上报 2 类数据任务设置 /// - public class AFN10_F66_Analysis : IAnalysisStrategy> + public class AFN10_F66_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN10_F66_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN10_F66_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; - _analysisStrategyContext= analysisStrategyContext; + _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public async Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? 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 dto = new UnitDataAnalysis + + var data = new AnalysisBaseDto() { - 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> dto = new UnitDataAnalysis> + { + 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(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 GenerateFinalResult(List 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, 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>(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); diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F68_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F68_Analysis.cs index f9358e2..48aa519 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F68_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0AH/AFN10_F68_Analysis.cs @@ -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 /// /// 5.5.1.3.55 F68:定时上报 2 类数据任务启动/停止设置 /// - public class AFN10_F68_Analysis : IAnalysisStrategy> + public class AFN10_F68_Analysis : IAnalysisStrategy { private readonly ILogger _logger; - - public AFN10_F68_Analysis(ILogger logger) + private readonly DataStorage _dataStorage; + public AFN10_F68_Analysis(ILogger logger, DataStorage dataStorage) { _logger = logger; + _dataStorage = dataStorage; } - public Task> ExecuteAsync(TB3761 input) + + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList); - UnitDataAnalysis dto = new UnitDataAnalysis + var data = new AnalysisBaseDto() { - 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> dto = new UnitDataAnalysis> + { + 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(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); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs index 248317d..35c258f 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs @@ -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 { /// /// 5.12.2.4.85 F129:当前正向有功电能示值(总、费率1~M) /// - public class AFN12_F129_Analysis : IAnalysisStrategy>> + public class AFN12_F129_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - private readonly IIoTDbProvider _dbProvider; - - public AFN12_F129_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, IIoTDbProvider dbProvider) + private readonly DataStorage _dataStorage; + public AFN12_F129_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; - _dbProvider= dbProvider; + _dataStorage = dataStorage; } - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); ArgumentNullException.ThrowIfNull(input.A.A3?.D1_D7); - UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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 datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); - List list = GenerateFinalResult(2, datas, "正向有功电能示值", input.AFN_FC.AFN, input.DT.Fn); + List> 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, decimal>(nameof(Appendix_A14), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A14), arr, (value) => + { + values.Add(value.ToString()); + }); //从第10个开始,每加5个字节为下一个值的开始 } } return values; } #endregion - public List GenerateFinalResult(int index, List data, string remark = "", int afn = 0, int fn = 0) + public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0) { - List list = new List(); + List> list = new List>(); for (int i = index; i < data.Count; i++) { - AFN12_F129_AnalysisDto meter = new AFN12_F129_AnalysisDto(); - - decimal value = 0; + AnalysisBaseDto meter = new AnalysisBaseDto + { + 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; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs index 009e9d2..3f28d97 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs @@ -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 { /// /// 5.12.2.4.86 F130:当前正向无功(组合无功 1)电能示值(总、费率 1~M) /// - public class AFN12_F130_Analysis : IAnalysisStrategy>> + public class AFN12_F130_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F130_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F130_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); - List list = GenerateFinalResult(2, datas, "正向无功电能示值", input.AFN_FC.AFN, input.DT.Fn); - UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + { + 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> AnalysisDataUnitAsync(List hexMessageList) @@ -62,27 +94,40 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); //从第10个开始,每加5个字节为下一个值的开始 } } return values; } - public List GenerateFinalResult(int index, List data, string remark = "", int afn = 0, int fn = 0) + public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0) { - List list = new List(); + List> list = new List>(); for (int i = index; i < data.Count; i++) { - AFN12_F130_AnalysisDto meter = new AFN12_F130_AnalysisDto(); - decimal value = 0; + AnalysisBaseDto meter = new AnalysisBaseDto + { + 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; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs index 36492fb..887e982 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs @@ -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 { /// /// 5.12.2.4.87 F131:当前反向有功电能示值(总、费率 1~M) /// - public class AFN12_F131_Analysis : IAnalysisStrategy>> + public class AFN12_F131_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F131_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F131_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); - List list = GenerateFinalResult(2, datas, "反向有功总电能示值", input.AFN_FC.AFN, input.DT.Fn); - UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + { + 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, decimal>(nameof(Appendix_A14), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A14), arr, (value) => + { + values.Add(value.ToString()); + }); //从第10个开始,每加5个字节为下一个值的开始 } } return values; } - public List GenerateFinalResult(int index, List data, string remark = "", int afn = 0, int fn = 0) + public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0) { - List list = new List(); + List> list = new List>(); for (int i = index; i < data.Count; i++) { - AFN12_F131_AnalysisDto meter = new AFN12_F131_AnalysisDto(); - decimal value = 0; + AnalysisBaseDto meter = new AnalysisBaseDto + { + 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; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs index 59a41fb..55ab674 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs @@ -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 { /// /// 5.12.2.4.88 F132:当前反向无功(组合无功 2)电能示值(总、费率 1~M) /// - public class AFN12_F132_Analysis : IAnalysisStrategy>> + public class AFN12_F132_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F132_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F132_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); - List list = GenerateFinalResult(2, datas, "反向无功电能示值", (int)input.AFN_FC.AFN!, (int)input.DT.Fn!); - UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> + string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + { + 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> AnalysisDataUnitAsync(List hexMessageList) @@ -63,27 +97,43 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加4个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); //从第10个开始,每加5个字节为下一个值的开始 } } return values; } - public List GenerateFinalResult(int index, List data, string remark = "",int afn=0,int fn=0) + public List> GenerateFinalResult(int index, List data, string itemType, string filedDesc = "") { - List list = new List(); + List> list = new List>(); for (int i = index; i < data.Count; i++) { - AFN12_F132_AnalysisDto meter = new AFN12_F132_AnalysisDto(); - decimal value = 0; + AnalysisBaseDto meter = new AnalysisBaseDto + { + 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; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs index ec72e1a..13541e3 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs @@ -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 { /// /// 5.12.2.4.101 F145:当月正向有功最大需量及发生时间(总、费率 1~M) /// - public class AFN12_F145_Analysis : IAnalysisStrategy> + public class AFN12_F145_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F145_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F145_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public async Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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 unitDataAnalysis = new UnitDataAnalysis + string itemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; + + AnalysisBaseDto 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> unitDataAnalysis = new UnitDataAnalysis> + { + 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, decimal>(nameof(Appendix_A23), arr); - values.Add(value.ToString());//正向有功总最大需量 + await _analysisStrategyContext.ExecuteAsync>(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, string>(nameof(Appendix_A17), arr); - values.Add(value.ToString());//正向有功总最大需量发生时间 + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A17), arr, (value) => + { + values.Add(value.ToString()); + });//正向有功总最大需量发生时间 } } return values; } - public AFN12_F145_AnalysisDto GenerateFinalResult(int index, List data, string remark = "") + public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc,string itemType) { - AFN12_F145_AnalysisDto dto = new AFN12_F145_AnalysisDto(); - - decimal value = 0; + AnalysisBaseDto dto = new AnalysisBaseDto + { + 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; } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs index 07480f0..1a32132 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs @@ -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 { /// /// 5.12.2.4.105 F149:上月(上一结算日)正向有功最大需量及发生时间(总、费率 1~M) /// - public class AFN12_F149_Analysis : IAnalysisStrategy>> + public class AFN12_F149_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -29,26 +32,29 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH } - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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 data = GenerateFinalResult(datas, dataType,"上月(上一结算日)正向有功最大需量及发生时间"); - // 查询电表信息 - AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data.MeterType.ToString(), "15"); - if (ammeterInfo != null) + AnalysisBaseDto 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> unitDataAnalysis = new UnitDataAnalysis> + + UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveDataToIotDbAsync(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> AnalysisDataUnit(List hexMessageList) @@ -86,8 +96,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(nameof(Appendix_A23), arr); - values.Add(value.ToString());//正向有功总最大需量 + await _analysisStrategyContext.ExecuteAsync>(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, string>(nameof(Appendix_A17), arr);//正向有功总最大需量发生时间 - values.Add(value);//正向有功总最大需量 + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A17), arr, (value) => + { + values.Add(value.ToString()); + });//正向有功总最大需量 } } return values; } - public AnalysisBaseDto GenerateFinalResult(List data,string dataType, string filedDesc = "") + public AnalysisBaseDto GenerateFinalResult(List data,string itemType, string filedDesc = "") { - AnalysisBaseDto dto = new AnalysisBaseDto(); - + AnalysisBaseDto dto = new AnalysisBaseDto + { + 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; } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs index e3eaee7..a95bd09 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs @@ -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 { /// /// 水表抄读取 /// - public class AFN12_F188_Analysis : IAnalysisStrategy> + public class AFN12_F188_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F188_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F188_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public async Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? 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 dto = new UnitDataAnalysis + string itemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; + AnalysisBaseDto 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> dto = new UnitDataAnalysis> + { + 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 hexMessageList) + public AnalysisBaseDto GenerateFinalResult(List hexMessageList,string itemType) { - AFN12_F149_AnalysisDto dto = new AFN12_F149_AnalysisDto(); - decimal value = 0; + AnalysisBaseDto dto = new AnalysisBaseDto + { + 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; } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs index 5b3cb9e..e6e6096 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs @@ -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 { /// /// 5.12.2.4.22 F25:当前三相及总有/无功功率、功率因数,三相电压、电流、零序电流、视在功率 /// - public class AFN12_F25_Analysis : IAnalysisStrategy>> + public class AFN12_F25_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F25_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F25_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public List DataType { get; set; } = new List() { "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 ItemType { get; set; } = new List() { "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>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List remarks = new List() { "当前总有功功率", "当前A相有功功率", "当前B相有功功率", "当前C相有功功率", "当前总无功功率", "当前A相无功功率", "当前B相无功功率", "当前C相无功功率", "当前总功率因数", "当前A相功率因数", "当前B相功率因数", "当前C相功率因数", "当前A相电压", "当前B相电压", "当前C相电压", "当前A相电流", "当前C相电流", "当前 C相电流", "当前零序电流", "当前总视在功率", "当前A相视在功率", "当前B相视在功率", "当前C相视在功率" }; - List list = new List(); + List> list = new List>(); List 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 dto = new AnalysisBaseDto + { + 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> unitDataAnalysis = new UnitDataAnalysis> + 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>> unitDataAnalysis = new UnitDataAnalysis>> + { + 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> AnalysisDataUnitAsync(List hexMessageList) @@ -102,8 +142,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(appendixName, arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs index 44c94a7..a54db8c 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs @@ -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 { /// /// 5.12.2.4.1 F2:终端日历时钟 /// - public class AFN12_F2_Analysis : IAnalysisStrategy> + public class AFN12_F2_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F2_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F2_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public async Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? 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 dto = new UnitDataAnalysis + 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> dto = new UnitDataAnalysis> + { + 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 GenerateFinalResultAsync(List hexMessageList) + public async Task> GenerateFinalResultAsync(List hexMessageList,string itemType) { - AFN12_F2_AnalysisDto dto = new AFN12_F2_AnalysisDto(); + AnalysisBaseDto dto = new AnalysisBaseDto(); 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, string>(nameof(Appendix_A1), arr); - + { + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A1), arr, (value) => + { + var data = (Tuple)value; + dto.DataValue = $"{data.Item1} {data.Item2}"; + }); + } + dto.ItemType = itemType; dto.FiledName = "TerminalTime"; dto.FiledDesc = "召读终端时间"; return await Task.FromResult(dto); diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F33_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F33_Analysis.cs index 50bcfd8..fd7dd30 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F33_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F33_Analysis.cs @@ -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 { /// /// 5.12.2.4.30 F33:当前正向有/无功电能示值、一/四象限无功电能示值(总、费率 1~M,1≤M≤12) /// - public class AFN12_F33_Analysis : IAnalysisStrategy> + public class AFN12_F33_Analysis : IAnalysisStrategy { private List DataUnitHexList { get; set; }=new List(); private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F33_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F33_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - - public async Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? 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 unitDataAnalysis = new UnitDataAnalysis + var data = new AnalysisBaseDto() { - 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> unitDataAnalysis = new UnitDataAnalysis> + { + 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 GetDataAsync(int ratingCount, int startIndex, int len, string appendxName) { ParentNodes parent = new ParentNodes(); - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(appendxName, DataUnitHexList.GetRange(startIndex, len)); - parent.Total_Value = value; + var arr = DataUnitHexList.GetRange(startIndex, len); + await _analysisStrategyContext.ExecuteAsync>(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 children = new List(); for (int i = 0; i < RatingCount; i++) { - ChildNodes model = new ChildNodes() + var arr = DataUnitHexList.GetRange((i * len) + (startIndex + len), len); + await _analysisStrategyContext.ExecuteAsync>(appendxName, arr, (value) => { - Value = await _analysisStrategyContext.ExecuteAsync, 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; } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs index 3e6f45a..257a666 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs @@ -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 { /// /// 5.12.2.4.46 F49:当前电压、电流相位角 /// - public class AFN12_F49_Analysis : IAnalysisStrategy>> + public class AFN12_F49_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; - - public AFN12_F49_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext) + private readonly DataStorage _dataStorage; + public AFN12_F49_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public List DataType { get; set; } = new List() { "Uab_Ua", "Ub", "Ucb_Uc", "Ia", "Ib", "Ic" }; + public List ItemType { get; set; } = new List() { "Uab_Ua", "Ub", "Ucb_Uc", "Ia", "Ib", "Ic" }; - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); - + ArgumentNullException.ThrowIfNull(input.A.Code); List data = await AnalysisDataUnitAsync(input.UnitData?.HexMessageList!); List remarks = new List() { "Uab/Ua 相位角", "Ub 相位角", "Ucb/Uc 相位角", "Ia 相位角", "Ib 相位角", "Ic 相位角" }; - List list = new List(); + List> list = new List>(); for (int i = 0; i < data.Count; i++) { - AFN12_F49_AnalysisDto dto = new AFN12_F49_AnalysisDto(); - decimal value = 0; + AnalysisBaseDto dto = new AnalysisBaseDto + { + 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> unitDataAnalysis = new UnitDataAnalysis> + 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>> unitDataAnalysis = new UnitDataAnalysis>> + { + 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> AnalysisDataUnitAsync(List hexMessageList) { @@ -80,8 +115,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH values.Add(errorCode.Item1); else { - var value= await _analysisStrategyContext.ExecuteAsync,decimal>(nameof(Appendix_A5), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A5), arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F100_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F100_Analysis.cs index 80af3c8..8fbad80 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F100_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F100_Analysis.cs @@ -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 { /// /// 5.13.2.4.78 F100:测量点反向无功总电能量曲线 /// - public class AFN13_F100_Analysis : IAnalysisStrategy>>> + public class AFN13_F100_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -26,36 +30,38 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向无功总电能量"); + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A13), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A13), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F101_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F101_Analysis.cs index 4a81d20..10f52b2 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F101_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F101_Analysis.cs @@ -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 { /// /// 5.13.2.4.79 F101:测量点正向有功总电能示值曲线 /// - public class AFN13_F101_Analysis : IAnalysisStrategy>>> + public class AFN13_F101_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _analysisStrategyContext = analysisStrategyContext; _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向有功总电能示值"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F102_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F102_Analysis.cs index 7f9d101..e40c2e8 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F102_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F102_Analysis.cs @@ -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 { /// /// 5.13.2.4.80 F102:测量点正向无功总电能示值曲线 /// - public class AFN13_F102_Analysis : IAnalysisStrategy>>> + public class AFN13_F102_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +28,38 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向无功总电能示值"); + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F103_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F103_Analysis.cs index 0882271..ed7d4c1 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F103_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F103_Analysis.cs @@ -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 { /// /// 5.13.2.4.81 F103:测量点反向有功总电能示值曲线 /// - public class AFN13_F103_Analysis : IAnalysisStrategy>>> + public class AFN13_F103_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +29,38 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> 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> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F104_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F104_Analysis.cs index 408a5af..6b0585e 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F104_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F104_Analysis.cs @@ -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 { /// /// 5.13.2.4.82 F104:测量点反向无功总电能示值曲线 /// - public class AFN13_F104_Analysis : IAnalysisStrategy>>> + public class AFN13_F104_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向无功总电能示值"); + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F105_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F105_Analysis.cs index 1d1fd4c..78eadd8 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F105_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F105_Analysis.cs @@ -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 { /// /// 5.13.2.4.83 F105:测量点功率因数曲线 /// - public class AFN13_F105_Analysis : IAnalysisStrategy>>> + public class AFN13_F105_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "功率因数"); + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A5), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A5), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F106_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F106_Analysis.cs index 5dbd7a3..ff5e8e6 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F106_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F106_Analysis.cs @@ -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 { /// /// 5.13.2.4.84 F106:测量点 A相功率因数曲线 /// - public class AFN13_F106_Analysis : IAnalysisStrategy>>> + public class AFN13_F106_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "A相功率因数"); + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A5), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A5), arr, (value) => + { + values.Add(value.ToString()); + }); + } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F107_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F107_Analysis.cs index d5b1584..6f26aa9 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F107_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F107_Analysis.cs @@ -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 { /// /// 5.13.2.4.84 F107:测量点 B相功率因数曲线 /// - public class AFN13_F107_Analysis : IAnalysisStrategy>>> + public class AFN13_F107_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "B相功率因数"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A5), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A5), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F108_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F108_Analysis.cs index 3a54a06..ced6c30 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F108_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F108_Analysis.cs @@ -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 { /// /// 5.13.2.4.84 F108:测量点 C相功率因数曲线 /// - public class AFN13_F108_Analysis : IAnalysisStrategy>>> + public class AFN13_F108_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "C相功率因数"); + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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> AnalysisDataUnitAsync(List hexMessageList) @@ -89,8 +98,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(nameof(Appendix_A5), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A5), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F11_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F11_Analysis.cs index 495f0dc..becaf19 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F11_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F11_Analysis.cs @@ -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 { /// /// 5.13.2.4.11 F11:抄表日冻结电能表正向有/无功最大需量及发生时间(总、费率 1~M,1≤M≤12) /// - public class AFN13_F11_Analysis : IAnalysisStrategy>>> + public class AFN13_F11_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -26,33 +30,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; - List> data = GenerateFinalResult(datas,3, dataType, "抄表日冻结电能表正向有功最大需量及发生时间"); + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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);//费率数 M(1≤M≤12) values.Add(ratingCount.ToString()); int handlerNum = 13; - values.AddRange(await GetDataAsync(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(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(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(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> GetDataAsync(List data, int ratingCount, int len, string appendixName) + private async Task> GetDataAsync(List data, int ratingCount, int len, string appendixName) { List values = new List(); 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, T>(nameof(Appendix_A5), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; } - public List> GenerateFinalResult(List data, int index, string dataType, string filedDesc = "") + public List> GenerateFinalResult(List data, int index, string dataType, string filedDesc = "") { - List> list = new List>(); + List> list = new List>(); int fCount = Convert.ToInt32(data[2]) + 1; for (int i = 1; i <= 2; i++) { - AnalysisBaseDto meter = new AnalysisBaseDto + AnalysisBaseDto meter = new AnalysisBaseDto { - 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); } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F145_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F145_Analysis.cs index 125ef90..7ffa444 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F145_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F145_Analysis.cs @@ -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 { /// /// 5.13.2.4.104 F145:测量点一象限无功总电能示值曲线 /// - public class AFN13_F145_Analysis : IAnalysisStrategy>>> + public class AFN13_F145_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "一象限无功电能示值"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F146_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F146_Analysis.cs index 3113c9b..e5d011f 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F146_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F146_Analysis.cs @@ -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 { /// /// 5.13.2.4.105 F146:测量点四象限无功总电能示值曲线 /// - public class AFN13_F146_Analysis : IAnalysisStrategy>>> + public class AFN13_F146_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); - + List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "四象限无功电能示值"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F147_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F147_Analysis.cs index cdc58cc..4ec9e9f 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F147_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F147_Analysis.cs @@ -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 { /// /// 5.13.2.4.106 F147:测量点二象限无功总电能示值曲线 /// - public class AFN13_F147_Analysis : IAnalysisStrategy>>> + public class AFN13_F147_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "二象限无功电能示值"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F148_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F148_Analysis.cs index dc978e3..d10dcce 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F148_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F148_Analysis.cs @@ -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 { /// /// 5.13.2.4.107 F148:测量点三象限无功总电能示值曲线 /// - public class AFN13_F148_Analysis : IAnalysisStrategy>>> + public class AFN13_F148_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +29,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "三象限无功电能示值"); + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F161_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F161_Analysis.cs index a5c7c04..382134e 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F161_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F161_Analysis.cs @@ -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 { /// /// 5.13.2.4.116 F161:日冻结正向有功电能示值(总、费率 1~M) /// - public class AFN13_F161_Analysis : IAnalysisStrategy>>> + public class AFN13_F161_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +28,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType,timeSpan, "正向有功总电能示值").IsValidData(new List() { "0D_161", "0D_161_1", "0D_161_2", "0D_161_3", "0D_161_4" }); + List> list = datas.GenerateFinalResultTd_d(3, dataType,timeSpan, "正向有功总电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A14), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A14), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F162_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F162_Analysis.cs index 3a3853d..90991c9 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F162_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F162_Analysis.cs @@ -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 { /// /// 5.13.2.4.117 F162:日冻结正向无功(组合无功 1)电能示值(总、费率 1~M) /// - public class AFN13_F162_Analysis : IAnalysisStrategy>>> + public class AFN13_F162_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "正向无功(组合无功 1)电能示值").IsValidData(new List() { "0D_162", "0D_162_1", "0D_162_2", "0D_162_3", "0D_162_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "正向无功(组合无功 1)电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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> AnalysisDataUnitAsync(List hexMessageList) @@ -92,8 +100,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F163_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F163_Analysis.cs index 7748948..e2bb0b0 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F163_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F163_Analysis.cs @@ -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 { /// /// 5.13.2.4.118 F163:日冻结反向有功电能示值(总、费率 1~M) /// - public class AFN13_F163_Analysis : IAnalysisStrategy>>> + public class AFN13_F163_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,35 +28,37 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "反向有功总电能示值").IsValidData(new List() { "0D_163", "0D_163_1", "0D_163_2", "0D_163_3", "0D_163_4" }); + List> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "反向有功总电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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> AnalysisDataUnitAsync(List hexMessageList) @@ -93,8 +101,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(nameof(Appendix_A14), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A14), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F164_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F164_Analysis.cs index 81cd07f..c636e4c 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F164_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F164_Analysis.cs @@ -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 { /// /// 5.13.2.4.119 F164:日冻结反向无功(组合无功 1)电能示值(总、费率 1~M) /// - public class AFN13_F164_Analysis : IAnalysisStrategy>>> + public class AFN13_F164_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结反向无功(组合无功 1)电能示值").IsValidData(new List() { "0D_164", "0D_164_1", "0D_164_2", "0D_164_3", "0D_164_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结反向无功(组合无功 1)电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F165_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F165_Analysis.cs index d7a821c..d69b3a1 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F165_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F165_Analysis.cs @@ -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 { /// /// 5.13.2.4.120 F165:日冻结一象限无功电能示值(总、费率 1~M) /// - public class AFN13_F165_Analysis : IAnalysisStrategy>>> + public class AFN13_F165_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结一象限无功电能示值").IsValidData(new List() { "0D_165", "0D_165_1", "0D_165_2", "0D_165_3", "0D_165_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结一象限无功电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F166_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F166_Analysis.cs index cce8772..b02c99b 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F166_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F166_Analysis.cs @@ -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 { /// /// 5.13.2.4.121 F166:日冻结二象限无功电能示值(总、费率 1~M) /// - public class AFN13_F166_Analysis : IAnalysisStrategy>>> + public class AFN13_F166_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结二象限无功电能示值").IsValidData(new List() { "0D_166", "0D_166_1", "0D_166_2", "0D_166_3", "0D_166_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结二象限无功电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F167_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F167_Analysis.cs index 2f1fc28..fb99e97 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F167_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F167_Analysis.cs @@ -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 { /// /// 5.13.2.4.122 F167:日冻结三象限无功电能示值(总、费率 1~M) /// - public class AFN13_F167_Analysis : IAnalysisStrategy>>> + public class AFN13_F167_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结三象限无功电能示值").IsValidData(new List() { "0D_167", "0D_167_1", "0D_167_2", "0D_167_3", "0D_167_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结三象限无功电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F168_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F168_Analysis.cs index 2553c0b..4b7d39a 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F168_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F168_Analysis.cs @@ -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 { /// /// 5.13.2.4.123 F168:日冻结四象限无功电能示值(总、费率 1~M) /// - public class AFN13_F168_Analysis : IAnalysisStrategy>>> + public class AFN13_F168_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,34 +28,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结四象限无功电能示值").IsValidData(new List() { "0D_168", "0D_168_1", "0D_168_2", "0D_168_3", "0D_168_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "日冻结四象限无功电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F177_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F177_Analysis.cs index 624f2c6..e147c17 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F177_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F177_Analysis.cs @@ -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 { /// /// 5.13.2.4.132 F177:月冻结正向有功电能示值(总、费率 1~M) /// - public class AFN13_F177_Analysis : IAnalysisStrategy>>> + public class AFN13_F177_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,33 +28,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结正向有功电能示值").IsValidData(new List() { "0D_177", "0D_177_1", "0D_177_2", "0D_177_3", "0D_177_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结正向有功电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A14), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A14), arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F178_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F178_Analysis.cs index dc882c4..d60bd89 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F178_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F178_Analysis.cs @@ -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 { /// /// F178:月冻结正向无功(组合无功 1)电能示值(总、费率 1~M) /// - public class AFN13_F178_Analysis : IAnalysisStrategy>>> + public class AFN13_F178_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结正向无功(组合无功 1)电能示值").IsValidData(new List() { "0D_178", "0D_178_1", "0D_178_2", "0D_178_3", "0D_178_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结正向无功(组合无功 1)电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F179_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F179_Analysis.cs index 07ff2b2..b685ec3 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F179_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F179_Analysis.cs @@ -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 { /// /// 5.13.2.4.134 F179:月冻结反向有功电能示值(总、费率 1~M) /// - public class AFN13_F179_Analysis : IAnalysisStrategy>>> + public class AFN13_F179_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "反向有功总电能示值").IsValidData(new List() { "0D_179", "0D_179_1", "0D_179_2", "0D_179_3", "0D_179_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "反向有功总电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A14), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A14), arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F180_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F180_Analysis.cs index 0fed8cb..9c42518 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F180_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F180_Analysis.cs @@ -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 { /// /// 5.13.2.4.135 F180:月冻结反向无功(组合无功 1)电能示值(总、费率 1~M) /// - public class AFN13_F180_Analysis : IAnalysisStrategy>>> + public class AFN13_F180_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,33 +28,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结反向无功(组合无功 1)电能示值").IsValidData(new List() { "0D_180", "0D_180_1", "0D_180_2", "0D_180_3", "0D_180_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结反向无功(组合无功 1)电能示值").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F181_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F181_Analysis.cs index 466da30..24c4195 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F181_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F181_Analysis.cs @@ -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 { /// /// 5.13.2.4.136 F181:月冻结一象限无功电能示值(总、费率 1~M) /// - public class AFN13_F181_Analysis : IAnalysisStrategy>>> + public class AFN13_F181_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结一象限无功电能示值(总、费率 1~M)").IsValidData(new List() { "0D_181", "0D_181_1", "0D_181_2", "0D_181_3", "0D_181_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结一象限无功电能示值(总、费率 1~M)").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F182_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F182_Analysis.cs index 0833b9f..820dfc1 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F182_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F182_Analysis.cs @@ -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 { /// /// 5.13.2.4.137 F182:月冻结二象限无功电能示值(总、费率 1~M) /// - public class AFN13_F182_Analysis : IAnalysisStrategy>>> + public class AFN13_F182_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结二象限无功电能示值(总、费率 1~M)").IsValidData(new List() { "0D_182", "0D_182_1", "0D_182_2", "0D_182_3", "0D_182_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结二象限无功电能示值(总、费率 1~M)").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F183_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F183_Analysis.cs index fc73291..45307ce 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F183_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F183_Analysis.cs @@ -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 { /// /// 5.13.2.4.138 F183:月冻结三象限无功电能示值(总、费率 1~M) /// - public class AFN13_F183_Analysis : IAnalysisStrategy>>> + public class AFN13_F183_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -25,33 +28,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结三象限无功电能示值(总、费率 1~M)").IsValidData(new List() { "0D_183", "0D_183_1", "0D_183_2", "0D_183_3", "0D_183_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结三象限无功电能示值(总、费率 1~M)").IsValidData(new List() { "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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F184_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F184_Analysis.cs index 103d49c..7714ed2 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F184_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F184_Analysis.cs @@ -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 { /// /// 5.13.2.4.139 F184:月冻结四象限无功电能示值(总、费率 1~M) /// - public class AFN13_F184_Analysis : IAnalysisStrategy>>> + public class AFN13_F184_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -26,33 +29,35 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结四象限无功电能示值(总、费率 1~M)").IsValidData(new List() { "0D_184", "0D_184_1", "0D_184_2", "0D_184_3", "0D_184_4" }); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_m(3, dataType, timeSpan, "月冻结四象限无功电能示值(总、费率 1~M)").IsValidData(new List() { "0D_184", "0D_184_1", "0D_184_2", "0D_184_3", "0D_184_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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_184解析失败:{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, decimal>(nameof(Appendix_A11), arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A11), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F189_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F189_Analysis.cs index 1fba574..c826ffb 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F189_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F189_Analysis.cs @@ -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 { /// /// 5.13.2.4.144 F189:抄表日冻结正向有功最大需量及发生时间(总、费率 1~M) /// - public class AFN13_F189_Analysis : IAnalysisStrategy>>> + public class AFN13_F189_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -26,34 +29,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "抄表日冻结正向有功最大需量及发生时间"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_d(3, dataType, timeSpan, "抄表日冻结正向有功最大需量及发生时间"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_189解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } @@ -85,13 +93,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH int ratingCount = hexMessageList.GetRatingCount(12, 1); values.Add(ratingCount.ToString()); int handlerNum = 13; - values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 3), ratingCount, 3, nameof(Appendix_A23)));//正向有功总最大需量 + values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 3), ratingCount, 3, nameof(Appendix_A23)));//正向有功总最大需量 handlerNum += 3; - values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 4), ratingCount, 4, nameof(Appendix_A17)));//正向有功总最大需量发生时间 + values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 4), ratingCount, 4, nameof(Appendix_A17)));//正向有功总最大需量发生时间 return values; } - private async Task> GetDataAsync(List data, int ratingCount, int len, string appendixName) + private async Task> GetDataAsync(List data, int ratingCount, int len, string appendixName) { List values = new List(); for (int i = 0; i < ratingCount + 1; i++) @@ -102,8 +110,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, T>(appendixName, arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, arr, (value) => + { + values.Add(value.ToString()); + }); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F190_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F190_Analysis.cs index 956eb11..d6bf837 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F190_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F190_Analysis.cs @@ -1,20 +1,23 @@ 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 static FreeSql.Internal.GlobalFilter; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.145 F190:抄表日冻结正向无功最大需量及发生时间(总、费率 1~M) /// - public class AFN13_F190_Analysis : IAnalysisStrategy>> + public class AFN13_F190_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -26,28 +29,29 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); - - AnalysisBaseDto data = GenerateFinalResult(datas, "抄表日冻结正向无功最大需量及发生时间"); - data.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; + string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; + AnalysisBaseDto data = GenerateFinalResult(datas, "抄表日冻结正向无功最大需量及发生时间", dataType); - // 查询电表信息 - AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data.MeterType.ToString(), "15"); - if (ammeterInfo != null) + // 查询设备信息 + 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> unitDataAnalysis = new UnitDataAnalysis> + UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -56,18 +60,21 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH 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.Day + DensityUnit = DensityUnit.Day, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_190解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } @@ -79,18 +86,18 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH int ratingCount = hexMessageList.GetRatingCount(12, 1); values.Add(ratingCount.ToString()); int handlerNum = 13; - values.AddRange(await GetDataAsync(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(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(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(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> GetDataAsync(List data, int ratingCount, int len, string appendixName) + private async Task> GetDataAsync(List data, int ratingCount, int len, string appendixName) { List values = new List(); for (int i = 0; i < ratingCount + 1; i++) @@ -101,22 +108,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, T>(appendixName, arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; } - public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc = "") + public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc,string dataType) { - List> list = new List>(); - AnalysisBaseDto meter = new AnalysisBaseDto + List> list = new List>(); + AnalysisBaseDto meter = new AnalysisBaseDto { - MeterType = MeterTypeEnum.Ammeter + DeviceType = MeterTypeEnum.Ammeter }; - - decimal value = 0; var errorCode = data[3].CheckErrorCode(); if (errorCode != null) { @@ -124,17 +131,20 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH meter.ErrorCodeMsg = errorCode.Item2; } else - decimal.TryParse(data[3], out value); - meter.DataValue = value; - - string timeSpan = $"{DateTime.Now.Year}-{data[4].Substring(0, 2)}-{data[4].Substring(2, 2)} {data[4].Substring(4, 2)}:{data[4].Substring(6, 2)}:00";//$"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)}"; - DateTime readingDate = DateTime.Now; - if (DateTime.TryParse(timeSpan, out readingDate)) + { + if(decimal.TryParse(data[3], out decimal value)) + { + meter.DataValue = value; + } + } + string timeSpan = $"{DateTime.Now.Year}-{data[4].Substring(0, 2)}-{data[4].Substring(2, 2)} {data[4].Substring(4, 2)}:{data[4].Substring(6, 2)}:00"; + if (DateTime.TryParse(timeSpan, out DateTime readingDate)) { meter.TimeSpan = readingDate; } + meter.ItemType = dataType; meter.FiledDesc = filedDesc; - meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty; + meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty; return meter; } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F193_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F193_Analysis.cs index 2e0c48d..f6d698e 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F193_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F193_Analysis.cs @@ -8,14 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.Common.Consts; +using static FreeSql.Internal.GlobalFilter; +using JiShe.CollectBus.IotSystems.Devices; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.148 F193:月冻结正向有功最大需量及发生时间(总、费率 1~M) /// - public class AFN13_F193_Analysis : IAnalysisStrategy>> + public class AFN13_F193_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -27,27 +30,29 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); - - AnalysisBaseDto data = GenerateFinalResult(datas, "月冻结正向有功最大需量及发生时间"); - data.DataType= $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; - // 查询电表信息 - AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data.MeterType.ToString(), "15"); - if (ammeterInfo != null) + string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; + + AnalysisBaseDto data = GenerateFinalResult(datas, "月冻结正向有功最大需量及发生时间", dataType); + // 查询设备信息 + 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> unitDataAnalysis = new UnitDataAnalysis> + UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -56,18 +61,21 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH 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 + DensityUnit = DensityUnit.Month, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_193解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } @@ -81,13 +89,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH int ratingCount = hexMessageList.GetRatingCount(11, 1); values.Add(ratingCount.ToString()); int handlerNum = 12; - values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 3), 3, nameof(Appendix_A23)));//正向有功总最大需量 + values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 3), 3, nameof(Appendix_A23)));//正向有功总最大需量 handlerNum += 3; - values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 4), 4, nameof(Appendix_A17)));//正向有功总最大需量发生时间 + values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 4), 4, nameof(Appendix_A17)));//正向有功总最大需量发生时间 return values; } - private async Task> GetDataAsync(List data, int len, string appendixName) + private async Task> GetDataAsync(List data, int len, string appendixName) { List values = new List(); var errorCode = data.CheckErrorCode(); @@ -95,19 +103,19 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, T>(appendixName, data); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, data, (value) => + { + values.Add(value.ToString()); + }); } return values; } - public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc = "") + public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc, string dataType) { - AnalysisBaseDto meter = new AnalysisBaseDto + AnalysisBaseDto meter = new AnalysisBaseDto { - MeterType = MeterTypeEnum.Ammeter, + DeviceType = MeterTypeEnum.Ammeter, }; - - decimal value = 0; var errorCode = data[3].CheckErrorCode(); if (errorCode != null) { @@ -115,17 +123,20 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH meter.ErrorCodeMsg = errorCode.Item2; } else - decimal.TryParse(data[3], out value); - meter.DataValue = value; - - string timeSpan = $"{data[0].Substring(0, 4)}-{data[4].Substring(0, 2)}-{data[4].Substring(2, 2)} {data[4].Substring(4, 2)}:{data[4].Substring(6, 2)}:00";//$"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)}"; - DateTime readingDate = DateTime.Now; - if (DateTime.TryParse(timeSpan, out readingDate)) + { + if(decimal.TryParse(data[3], out decimal value)) + { + meter.DataValue = value; + } + } + string timeSpan = $"{data[0].Substring(0, 4)}-{data[4].Substring(0, 2)}-{data[4].Substring(2, 2)} {data[4].Substring(4, 2)}:{data[4].Substring(6, 2)}:00"; + if (DateTime.TryParse(timeSpan, out DateTime readingDate)) { meter.TimeSpan = readingDate; } + meter.ItemType = dataType; meter.FiledDesc = filedDesc; - meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty; + meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty; return meter; } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F195_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F195_Analysis.cs index c7ffe04..ceda00c 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F195_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F195_Analysis.cs @@ -7,15 +7,18 @@ using JiShe.CollectBus.Protocol3761; using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using static FreeSql.Internal.GlobalFilter; +using JiShe.CollectBus.IotSystems.Devices; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.150 F195:月冻结反向有功最大需量及发生时间(总、费率 1~M) /// - public class AFN13_F195_Analysis : IAnalysisStrategy>> + public class AFN13_F195_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -27,27 +30,29 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); + string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; - AnalysisBaseDto data = GenerateFinalResult(datas, "月冻结反向有功最大需量及发生时间"); - data.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; - // 查询电表信息 - AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data.MeterType.ToString(), "15"); - if (ammeterInfo != null) + AnalysisBaseDto data = GenerateFinalResult(datas, "月冻结反向有功最大需量及发生时间", dataType); + // 查询设备信息 + 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> unitDataAnalysis = new UnitDataAnalysis> + UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -56,18 +61,21 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH 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 + DensityUnit = DensityUnit.Month, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_195解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } @@ -81,13 +89,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH int ratingCount = hexMessageList.GetRatingCount(11, 1); values.Add(ratingCount.ToString()); int handlerNum = 12; - values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 3), 3,nameof(Appendix_A23)));//正向有功总最大需量 + values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 3), 3,nameof(Appendix_A23)));//正向有功总最大需量 handlerNum += 3; - values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 4), 4, nameof(Appendix_A17)));//正向有功总最大需量发生时间 + values.AddRange(await GetDataAsync(hexMessageList.GetRange(handlerNum, 4), 4, nameof(Appendix_A17)));//正向有功总最大需量发生时间 return values; } - private async Task> GetDataAsync(List data, int len, string appendixName) + private async Task> GetDataAsync(List data, int len, string appendixName) { List values = new List(); var errorCode = data.CheckErrorCode(); @@ -95,19 +103,19 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, T>(appendixName, data); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, data, (value) => + { + values.Add(value.ToString()); + }); } return values; } - public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc = "") + public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc,string dataType) { - AnalysisBaseDto meter = new AnalysisBaseDto + AnalysisBaseDto meter = new AnalysisBaseDto { - MeterType = MeterTypeEnum.Ammeter + DeviceType = MeterTypeEnum.Ammeter }; - - decimal value = 0; var errorCode = data[3].CheckErrorCode(); if (errorCode != null) { @@ -115,17 +123,20 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH meter.ErrorCodeMsg = errorCode.Item2; } else - decimal.TryParse(data[3], out value); - meter.DataValue = value; - - string timeSpan = $"{data[0].Substring(0, 4)}-{data[4].Substring(0, 2)}-{data[4].Substring(2, 2)} {data[4].Substring(4, 2)}:{data[4].Substring(6, 2)}:00";//$"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)}"; - DateTime readingDate = DateTime.Now; - if (DateTime.TryParse(timeSpan, out readingDate)) + { + if(decimal.TryParse(data[3], out decimal value)) + { + meter.DataValue = value; + } + } + string timeSpan = $"{data[0].Substring(0, 4)}-{data[4].Substring(0, 2)}-{data[4].Substring(2, 2)} {data[4].Substring(4, 2)}:{data[4].Substring(6, 2)}:00"; + if (DateTime.TryParse(timeSpan, out DateTime readingDate)) { meter.TimeSpan = readingDate; } + meter.ItemType = dataType; meter.FiledDesc = filedDesc; - meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty; + meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty; return meter; } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F19_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F19_Analysis.cs index 5cda5b3..531b234 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F19_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F19_Analysis.cs @@ -8,15 +8,19 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using System.Data; using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using YamlDotNet.Core.Tokens; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.15 F19:月冻结电能表正向有/无功最大需量及发生时间(总、费率 1~M,1≤M≤12) /// - public class AFN13_F19_Analysis : IAnalysisStrategy>>> + public class AFN13_F19_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -28,32 +32,34 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}"; - List> data = GenerateFinalResult(datas, dataType, "月冻结电能表正向有功最大需量及发生时间"); - if (data.Count > 0) + List> list = GenerateFinalResult(datas, 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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 = 1,//密度-间隔, - DensityUnit = DensityUnit.Day + DensityUnit = DensityUnit.Day, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_19解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } @@ -85,18 +94,18 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH int ratingCount = hexMessageList.GetRatingCount(11, 1); values.Add(ratingCount.ToString()); int handlerNum = 12; - values.AddRange(await GetDataAsync(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); - values.AddRange(await GetDataAsync(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); - values.AddRange(await GetDataAsync(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); - values.AddRange(await GetDataAsync(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> GetDataAsync(List data, int ratingCount, int len, string appendixName) + private async Task> GetDataAsync(List data, int ratingCount, int len, string appendixName) { List values = new List(); for (int i = 0; i < ratingCount + 1; i++) @@ -107,23 +116,24 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, T>(appendixName, arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; } - public List> GenerateFinalResult(List data, string dataType,string filedDesc = "") + public List> GenerateFinalResult(List data, string dataType,string filedDesc = "") { - List> list = new List>(); + List> list = new List>(); int fCount = Convert.ToInt32(data[2]) + 1; for (int i = 1; i <= 2; i++) { - AnalysisBaseDto meter = new AnalysisBaseDto(); - meter.MeterType= MeterTypeEnum.Ammeter; + AnalysisBaseDto meter = new AnalysisBaseDto(); + meter.DeviceType= MeterTypeEnum.Ammeter; int startIndex = i == 1 ? 3 : (3 + i * fCount); - decimal value = 0; var errorCode = data[startIndex].CheckErrorCode(); if (errorCode != null) { @@ -131,20 +141,21 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH meter.ErrorCodeMsg = errorCode.Item2; } else - decimal.TryParse(data[startIndex], out value); - meter.DataValue = value; - //2021 01 15 + { + 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); } return list; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F3_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F3_Analysis.cs index f53b936..7ed137e 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F3_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F3_Analysis.cs @@ -10,14 +10,17 @@ using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using Volo.Abp.Domain.Entities; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.3 F3:日冻结正向有/无功最大需量及发生时间(总、费率 1~M,1≤M≤12) /// - public class AFN13_F3_Analysis : IAnalysisStrategy>>> + public class AFN13_F3_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -29,11 +32,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); @@ -41,23 +45,24 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH //冻结数据时标 var time = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00"; - List> data = GenerateFinalResult(datas,dataType, "日冻结正向有/无功最大需量及发生时间"); - if (data.Count > 0) + List> list = GenerateFinalResult(datas,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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -65,19 +70,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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_3解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } private async Task> AnalysisDataUnitAsync(List hexMessageList) @@ -90,18 +98,18 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH int ratingCount = hexMessageList.GetRatingCount(12, 1);//费率数 M(1≤M≤12) values.Add(ratingCount.ToString()); int handlerNum = 13; - values.AddRange(await GetDataAsync(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(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(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(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> GetDataAsync(List data, int ratingCount, int len, string appendixName) + private async Task> GetDataAsync(List data, int ratingCount, int len, string appendixName) { List values = new List(); for (int i = 0; i < ratingCount + 1; i++) @@ -112,68 +120,61 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, T>(appendixName, arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; } - public List> GenerateFinalResult(List data,string dataType, string filedDesc = "") + public List> GenerateFinalResult(List data,string dataType, string filedDesc = "") { - List> list = new List>(); + List> list = new List>(); int fCount = Convert.ToInt32(data[2]) + 1; for (int i = 1; i <= 2; i++) { - try + AnalysisBaseDto meter = new AnalysisBaseDto { - AnalysisBaseDto meter = new AnalysisBaseDto - { - MeterType = MeterTypeEnum.Ammeter - }; - int startIndex = i == 1 ? 3 : (3 + i * fCount); + DeviceType = MeterTypeEnum.Ammeter + }; + int startIndex = i == 1 ? 3 : (3 + i * fCount); - var errorCode = data[startIndex].CheckErrorCode(); - if (errorCode != null) - meter.ValidData = false; - decimal.TryParse(data[startIndex], out decimal value);//decimal.TryParse(data[startIndex], out value); + var errorCode = data[startIndex].CheckErrorCode(); + if (errorCode != null) + meter.ValidData = false; + if(decimal.TryParse(data[startIndex], out decimal value)) meter.DataValue = value; - //TODO:日冻结类数据时标Td 20210824 - var dataTime = string.Empty; - errorCode = data[0].CheckErrorCode(); - if (data[0].Length == 8 && errorCode is null) - dataTime = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} 00:00:00"; - if (!DateTime.TryParse(dataTime, out DateTime readingDate)) - meter.ValidData = false; - meter.TimeSpan = readingDate;// - + //TODO:日冻结类数据时标Td + var dataTime = string.Empty; + errorCode = data[0].CheckErrorCode(); + if (data[0].Length == 8 && errorCode is null) + dataTime = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} 00:00:00"; + if (DateTime.TryParse(dataTime, out DateTime readingDate)) + meter.TimeSpan = readingDate; + else + meter.ValidData = false; //TODO:最大需量发生时间 - errorCode = data[startIndex + fCount].CheckErrorCode(); - if (errorCode != null && data[startIndex + fCount].Length != 8) + errorCode = data[startIndex + fCount].CheckErrorCode(); + if (errorCode != null && data[startIndex + fCount].Length != 8) + meter.ValidData = false; + else + { + string timeSpan = $"{data[0].Substring(0, 4)}-{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"; + if (!DateTime.TryParse(timeSpan, out DateTime tsField)) meter.ValidData = false; else - { - string timeSpan = $"{data[0].Substring(0, 4)}-{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"; - if (!DateTime.TryParse(timeSpan, out DateTime tsField)) - meter.ValidData = false; - else - meter.TimeSpan=tsField; - } - - meter.DataType = i == 1 ? dataType : $"{dataType}_{ i - 1}"; - filedDesc = i == 1 ? filedDesc : filedDesc.Replace("有功", "无功"); - meter.FiledDesc = filedDesc; - meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty; - list.Add(meter); - } - catch - { + meter.TimeSpan=tsField; } + meter.ItemType = i == 1 ? dataType : $"{dataType}_{ i - 1}"; + filedDesc = i == 1 ? filedDesc : filedDesc.Replace("有功", "无功"); + meter.FiledDesc = filedDesc; + meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty; + list.Add(meter); + } - if (list.Count == 0) - throw new Exception("错误数据"); - return list; } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F4_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F4_Analysis.cs index 7af6f21..c99a894 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F4_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F4_Analysis.cs @@ -9,14 +9,17 @@ using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using AutoMapper.Internal.Mappers; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.4 F4:日冻结反向有/无功最大需量及发生时间(总、费率 1~M,1≤M≤12) /// - public class AFN13_F4_Analysis : IAnalysisStrategy>>> + public class AFN13_F4_Analysis : IAnalysisStrategy { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -28,11 +31,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); @@ -40,23 +44,24 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH //冻结数据时标 var time = $"{datas[0].Substring(0, 4)}-{datas[0].Substring(4, 2)}-{datas[0].Substring(6, 2)} 00:00:00"; - List> data = GenerateFinalResult(datas, dataType, "日冻结反向有/无功最大需量及发生时间"); - if (data.Count > 0) + List> list = GenerateFinalResult(datas, 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -64,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 = 1,//密度-间隔, - DensityUnit = DensityUnit.Day + DensityUnit = DensityUnit.Day, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_4解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } private async Task> AnalysisDataUnitAsync(List hexMessageList) @@ -89,18 +97,18 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH int ratingCount = hexMessageList.GetRatingCount(12, 1);//费率数 M(1≤M≤12) values.Add(ratingCount.ToString()); int handlerNum = 13; - values.AddRange(await GetDataAsync(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(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(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(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> GetDataAsync(List data, int ratingCount, int len, string appendixName) + private async Task> GetDataAsync(List data, int ratingCount, int len, string appendixName) { List values = new List(); for (int i = 0; i < ratingCount + 1; i++) @@ -111,22 +119,24 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, T>(appendixName, arr); //从第10个开始,每加5个字节为下一个值的开始 - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(appendixName, arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; } - public List> GenerateFinalResult(List data,string dataType, string filedDesc = "") + public List> GenerateFinalResult(List data,string dataType, string filedDesc = "") { - List> list = new List>(); + List> list = new List>(); int fCount = Convert.ToInt32(data[2]) + 1; for (int i = 1; i <= 2; i++) { - AnalysisBaseDto meter = new AnalysisBaseDto + AnalysisBaseDto meter = new AnalysisBaseDto { - MeterType = MeterTypeEnum.Ammeter + DeviceType = MeterTypeEnum.Ammeter }; int startIndex = i == 1 ? 3 : (3 + i * fCount); @@ -136,17 +146,17 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH meter.ValidData = false; meter.ErrorCodeMsg = errorCode.Item2; } - decimal.TryParse(data[startIndex], out decimal value);//decimal.TryParse(data[startIndex], out value); - meter.DataValue = value; - - //TODO:日冻结类数据时标Td 20210824 + if(decimal.TryParse(data[startIndex], out decimal value)) + meter.DataValue = value; + //TODO:日冻结类数据时标Td var dataTime = string.Empty; errorCode = data[0].CheckErrorCode(); if (data[0].Length == 8 && errorCode is null) dataTime = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} 00:00:00"; if (!DateTime.TryParse(dataTime, out DateTime readingDate)) meter.ValidData = false; - meter.TimeSpan = readingDate; + else + meter.TimeSpan = readingDate; //TODO:最大需量发生时间 errorCode = data[startIndex + fCount].CheckErrorCode(); @@ -160,12 +170,11 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH else meter.TimeSpan = tsField; } - 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); - } return list; } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F81_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F81_Analysis.cs index fd9eaf5..4bf1e2e 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F81_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F81_Analysis.cs @@ -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 { /// /// 5.13.2.4.60 F81:测量点有功功率曲线 /// - public class AFN13_F81_Analysis : IAnalysisStrategy>>> + public class AFN13_F81_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -26,34 +30,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "有功功率曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_81解析失败:{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, decimal>(nameof(Appendix_A9), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A9), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F82_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F82_Analysis.cs index 724cad2..0c4aa75 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F82_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F82_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.61 F82:测量点 A相有功功率曲线 /// - public class AFN13_F82_Analysis : IAnalysisStrategy>>> + public class AFN13_F82_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "A相有功功率曲线"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_c(3, density, dataType, "A相有功功率曲线"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_82解析失败:{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, decimal>(nameof(Appendix_A9), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A9), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F83_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F83_Analysis.cs index 2ffbd12..ef77a80 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F83_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F83_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.61 F83:测量点 B相有功功率曲线 /// - public class AFN13_F83_Analysis : IAnalysisStrategy>>> + public class AFN13_F83_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "B相有功功率曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_83解析失败:{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, decimal>(nameof(Appendix_A9), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A9), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F84_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F84_Analysis.cs index 36bc660..66216bc 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F84_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F84_Analysis.cs @@ -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 { /// /// 5.13.2.4.61 F84:测量点 C相有功功率曲线 /// - public class AFN13_F84_Analysis : IAnalysisStrategy>>> + public class AFN13_F84_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -26,34 +30,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "C相有功功率曲线"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_c(3, density, dataType, "C相有功功率曲线"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_84解析失败:{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, decimal>(nameof(Appendix_A9), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A9), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F85_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F85_Analysis.cs index 1437d2f..b9103b8 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F85_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F85_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.64 F85:测量点无功功率曲线 /// - public class AFN13_F85_Analysis : IAnalysisStrategy>>> + public class AFN13_F85_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "无功功率曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_85解析失败:{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, decimal>(nameof(Appendix_A9), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A9), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F86_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F86_Analysis.cs index 09c5a4a..1748a3d 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F86_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F86_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.65 F86:测量点 A相无功功率曲线 /// - public class AFN13_F86_Analysis : IAnalysisStrategy>>> + public class AFN13_F86_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "A相无功功率曲线"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_c(3, density, dataType, "A相无功功率曲线"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_86解析失败:{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, decimal>(nameof(Appendix_A9), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A9), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F87_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F87_Analysis.cs index d2b8dc1..26dfcd1 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F87_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F87_Analysis.cs @@ -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 { /// /// 5.13.2.4.66 F87:测量点 B相无功功率曲线 /// - public class AFN13_F87_Analysis : IAnalysisStrategy>>> + public class AFN13_F87_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -26,34 +30,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "B相无功功率曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_87解析失败:{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, decimal>(nameof(Appendix_A9), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A9), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F88_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F88_Analysis.cs index 3eb020c..29fb978 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F88_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F88_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.67 F88:测量点 C相无功功率曲线 /// - public class AFN13_F88_Analysis : IAnalysisStrategy>>> + public class AFN13_F88_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "C相无功功率曲线"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_c(3, density, dataType, "C相无功功率曲线"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_88解析失败:{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, decimal>(nameof(Appendix_A9), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A9), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F89_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F89_Analysis.cs index d9863e4..330cf0a 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F89_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F89_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.68 F89:测量点 A相电压曲线 /// - public class AFN13_F89_Analysis : IAnalysisStrategy>>> + public class AFN13_F89_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "A相电压曲线"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_c(3, density, dataType, "A相电压曲线"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_89解析失败:{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, decimal>(nameof(Appendix_A7), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A7), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F90_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F90_Analysis.cs index a11a586..3033c76 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F90_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F90_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.68 F89:测量点 B相电压曲线 /// - public class AFN13_F90_Analysis : IAnalysisStrategy>>> + public class AFN13_F90_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "B相电压曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_90解析失败:{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, decimal>(nameof(Appendix_A7), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A7), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F91_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F91_Analysis.cs index 740aa7f..b18d244 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F91_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F91_Analysis.cs @@ -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 { /// /// 5.13.2.4.68 F89:测量点 C相电压曲线 /// - public class AFN13_F91_Analysis : IAnalysisStrategy>>> + public class AFN13_F91_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -26,34 +30,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "C相电压曲线"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_c(3, density, dataType, "C相电压曲线"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { 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(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_91解析失败:{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, decimal>(nameof(Appendix_A7), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A7), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F92_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F92_Analysis.cs index 83a1aca..1d1bff5 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F92_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F92_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.71 F92:测量点 A相电流曲线 /// - public class AFN13_F92_Analysis : IAnalysisStrategy>>> + public class AFN13_F92_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "A相电流曲线"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_c(3, density, dataType, "A相电流曲线"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_92解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } private async Task> AnalysisDataUnitAsync(List hexMessageList) @@ -91,8 +100,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(nameof(Appendix_A25), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A25), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F93_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F93_Analysis.cs index 085c209..bbd8f0d 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F93_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F93_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.72 F93:测量点 B相电流曲线 /// - public class AFN13_F93_Analysis : IAnalysisStrategy>>> + public class AFN13_F93_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "B相电流曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_93解析失败:{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, decimal>(nameof(Appendix_A25), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A25), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F94_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F94_Analysis.cs index b701b5c..19e6d2f 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F94_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F94_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.73 F94:测量点 C相电流曲线 /// - public class AFN13_F94_Analysis : IAnalysisStrategy>>> + public class AFN13_F94_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "C相电流曲线"); - if (data.Count > 0) + List> list = datas.GenerateFinalResultTd_c(3, density, dataType, "C相电流曲线"); + 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_94解析失败:{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, decimal>(nameof(Appendix_A25), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A25), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F95_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F95_Analysis.cs index 1021cf9..842496f 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F95_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F95_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.74 F95:测量点零序电流曲线 /// - public class AFN13_F95_Analysis : IAnalysisStrategy>>> + public class AFN13_F95_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "测量点零序电流曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_95解析失败:{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, decimal>(nameof(Appendix_A25), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A25), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F97_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F97_Analysis.cs index 44a27e6..8ce25e1 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F97_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F97_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.75 F97:测量点正向有功总电能量曲线 /// - public class AFN13_F97_Analysis : IAnalysisStrategy>>> + public class AFN13_F97_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向有功总电能量曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_97解析失败:{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, decimal>(nameof(Appendix_A13), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A13), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F98_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F98_Analysis.cs index 5fad048..6da01d5 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F98_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F98_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.76 F98:测量点正向无功总电能量曲线 /// - public class AFN13_F98_Analysis : IAnalysisStrategy>>> + public class AFN13_F98_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向无功总电能量曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_98解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + return await Task.FromResult(false); } } private async Task> AnalysisDataUnitAsync(List hexMessageList) @@ -91,8 +100,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH values.Add(errorCode.Item1); else { - var value = await _analysisStrategyContext.ExecuteAsync, decimal>(nameof(Appendix_A13), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A13), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F99_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F99_Analysis.cs index 974740b..33b8560 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F99_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F99_Analysis.cs @@ -8,13 +8,17 @@ using Microsoft.Extensions.Logging; using JiShe.CollectBus.Protocol.T37612012.Appendix; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.Devices; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH { /// /// 5.13.2.4.77 F99:测量点反向有功总电能量曲线 /// - public class AFN13_F99_Analysis : IAnalysisStrategy>>> + public class AFN13_F99_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -27,34 +31,36 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH _dataStorage = dataStorage; } - public async Task>>> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List 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> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向有功总电能量曲线"); - if (data.Count > 0) + List> 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>> unitDataAnalysis = new UnitDataAnalysis>> + UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -62,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 + DensityUnit = DensityUnit.Minute, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data, }; - await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"0D_99解析失败:{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, decimal>(nameof(Appendix_A13), arr); - values.Add(value.ToString()); + await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A13), arr, (value) => + { + values.Add(value.ToString()); + }); } } return values; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0EH/AFN14_F1_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0EH/AFN14_F1_Analysis.cs index 7ca9c21..7dc7275 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0EH/AFN14_F1_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0EH/AFN14_F1_Analysis.cs @@ -1,8 +1,16 @@ -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.Protocol3761; using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0EH { @@ -11,68 +19,115 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0EH /// Item1=停电事件 /// Item2=上电事件 /// - public class AFN14_F1_Analysis : IAnalysisStrategy>> + public class AFN14_F1_Analysis : IAnalysisStrategy { private readonly ILogger _logger; - - public AFN14_F1_Analysis(ILogger logger) + private readonly DataStorage _dataStorage; + public AFN14_F1_Analysis(ILogger logger, DataStorage dataStorage) { _logger = logger; + _dataStorage= dataStorage; } - public Task>> ExecuteAsync(TB3761 tB3761) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { - ArgumentNullException.ThrowIfNull(nameof(tB3761)); - ArgumentNullException.ThrowIfNull(nameof(tB3761.UnitData.HexMessageList)); - int erc = tB3761.UnitData.HexMessageList![8].HexToDec(); + ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); + ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList); + int erc = input.UnitData.HexMessageList![8].HexToDec(); bool isOnOffPower = erc.Equals(14) ? true : false; if (!isOnOffPower) { - throw new Exception($"ERC{erc}非上掉电事件"); + // TODO:非终端停/上电事件直接确认 + _logger.LogWarning($"0E_1解析ERC{erc}非终端停/上电事件:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString}"); + return await Task.FromResult(true); } - UnitDataAnalysis> dto = new UnitDataAnalysis> + + List> list = AnalysisDataUnit(input.UnitData.HexMessageList); + if (list.Count > 0) { - Code = tB3761.A.Code!, - AFN = tB3761.AFN_FC.AFN, - Fn = tB3761.DT.Fn, - Pn = tB3761.DA.Pn, - Data = AnalysisDataUnit(tB3761.UnitData.HexMessageList) + // 查询设备信息 + DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + if (deviceInfo != null) + { + list.ForEach(item => + { + item.ProjectId = deviceInfo.ProjectID; + item.DeviceId = deviceInfo.MeterId; + item.DatabaseBusiID = deviceInfo.DatabaseBusiID; + item.DeviceAddress = deviceInfo.MeterAddress; + item.DeviceType = MeterTypeEnum.Focus; + item.FocusId = deviceInfo.FocusId; + }); + } + } + UnitDataAnalysis>> dto = new UnitDataAnalysis>> + { + Code = input.A.Code!, + AFN = input.AFN_FC.AFN, + Fn = input.DT.Fn, + Pn = input.DA.Pn, + Data = list, + ReceivedHexMessage = input.BaseHexMessage.HexMessageString, + MessageId = input.MessageId, + ReceivedTime = input.ReceivedTime, + DensityUnit = DensityUnit.None, + TimeDensity = -1, + DataType = IOTDBDataTypeConst.Event, }; // meterData.DataType = "0E_1"; - return Task.FromResult(dto); + result?.Invoke(dto); + await _dataStorage.SaveMultipleStatusToIotDbAsync(dto); + return await Task.FromResult(true); } catch (Exception ex) { - _logger.LogError(ex, $"0E_1解析失败:{tB3761.A.Code}-{tB3761.DT.Fn}-{tB3761.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + _logger.LogError(ex, $"0E_1解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); } + return await Task.FromResult(false); } - private Tuple AnalysisDataUnit(List hexMessageList) + private List> AnalysisDataUnit(List hexMessageList) { /// Item1=停电事件 /// Item2=上电事件 - return Tuple.Create(HandlerTime(hexMessageList.GetRange(10, 5)), HandlerTime(hexMessageList.GetRange(15, 5))); + List > values = new List> + { + new AnalysisBaseDto + { + FiledDesc = "停电事件", + FiledName = "Type", + DataValue = "PowerDownEvent", + TimeSpan=HandlerTime(hexMessageList.GetRange(10, 5)) + }, + new AnalysisBaseDto + { + FiledDesc = "上电事件", + FiledName = "Type", + DataValue = "PowerOnEvent", + TimeSpan=HandlerTime(hexMessageList.GetRange(15, 5)) + } + }; + return values; } /// /// /解析时间 /// /// - /// 时间验证失败是否默认为当前时间 /// - private string HandlerTime(List times) + private DateTime? HandlerTime(List times) { - var time = string.Empty; try { times.Reverse(); - time = $"{DateTime.Now.ToString("yyyy").Substring(0, 2)}{times[0]}-{times[1]}-{times[2]} {times[3]}:{times[4]}:00"; - + string time = $"{DateTime.Now.ToString("yyyy").Substring(0, 2)}{times[0]}-{times[1]}-{times[2]} {times[3]}:{times[4]}:00"; + DateTime.TryParse(time, out DateTime dateTime); + return dateTime; } catch { } - return time; + return null; } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F101_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F101_Analysis.cs index ce5a7a3..284aaab 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F101_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F101_Analysis.cs @@ -1,44 +1,78 @@ -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.AnalysisData; using JiShe.CollectBus.Protocol3761; using Microsoft.Extensions.Logging; +using System.Text; namespace GatherService.WattMeter.AnalysisData.AFN_10H { /// /// 5.16.1.2.1 F1:透明转发 读取SIM卡信息 /// - public class AFN16_F101_Analysis : IAnalysisStrategy> + public class AFN16_F101_Analysis : IAnalysisStrategy { private readonly ILogger _logger; - - public AFN16_F101_Analysis(ILogger logger) + private readonly DataStorage _dataStorage; + public AFN16_F101_Analysis(ILogger logger, DataStorage dataStorage) { _logger = logger; + _dataStorage = dataStorage; } - public Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList); - UnitDataAnalysis dto = new UnitDataAnalysis + var data = new AnalysisBaseDto() { - Code = input.A.Code, + FiledDesc = "透读取SIM卡信息", + DataValue = AnalysisDataUnit(input.UnitData.HexMessageList), + 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> dto = new UnitDataAnalysis> + { + Code = input.A.Code!, AFN = input.AFN_FC.AFN, Fn = input.DT.Fn, Pn = input.DA.Pn, - Data = AnalysisDataUnit(input.UnitData.HexMessageList) //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, $"10_101解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}"); - return null; + } + return await Task.FromResult(false); } private string AnalysisDataUnit(List hexMessageList) { diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F1_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F1_Analysis.cs index 9f9b120..d760e94 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F1_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F1_Analysis.cs @@ -1,5 +1,8 @@ using GatherService.WattMeter.AnalysisData.AFN_10H; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; +using JiShe.CollectBus.IotSystems.Devices; using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto; using JiShe.CollectBus.Protocol.Dto; using JiShe.CollectBus.Protocol.Interfaces; @@ -17,52 +20,86 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_10H /// /// 5.16 数据转发(AFN=10H) /// - public class AFN16_F1_Analysis : IAnalysisStrategy> + public class AFN16_F1_Analysis : IAnalysisStrategy { private readonly ILogger _logger; - - public AFN16_F1_Analysis(ILogger logger) + private readonly AnalysisStrategyContext _analysisStrategyContext; + private readonly DataStorage _dataStorage; + public AFN16_F1_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) { _logger = logger; + _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; } - public Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); - ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageList); - UnitDataAnalysis dto = new UnitDataAnalysis + ArgumentNullException.ThrowIfNull(input.A.Code); + ArgumentNullException.ThrowIfNull(input.BaseHexMessage.HexMessageList); + ArgumentNullException.ThrowIfNull(input.UnitData.HexMessageString); + // TODO: 待定,等确认如何匹配规则 + string value = input.UnitData.HexMessageString; + if (value.Contains(F10TranspondMatch.ReadNormal)) { - Code = input.A.Code!, - AFN = input.AFN_FC.AFN, - Fn = input.DT.Fn, - Pn = input.DA.Pn, - Data = AnalysisDataUnit(input.UnitData.HexMessageList) - }; - return Task.FromResult(dto); + if (value.Contains(F10TranspondMatch.PowerHz))//电网频率 + await _analysisStrategyContext.ExecuteAsync(nameof(AFN16_F97_Analysis), input, dto => + { + result?.Invoke(dto); + }); + else if (value.Contains(F10TranspondMatch.JumpClosingNormal) || value.Contains(F10TranspondMatch.JumpClosingError))//跳合闸 + await _analysisStrategyContext.ExecuteAsync(nameof(AFN16_F98_Analysis), input, dto => + { + result?.Invoke(dto); + }); + else + { + //TODO: 写入1条日志 + var data = new AnalysisBaseDto() + { + FiledDesc = "透明转发", + 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> dto = new UnitDataAnalysis> + { + 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 + }; + await _dataStorage.SaveDataToIotDbAsync(dto); + _logger.LogWarning($"未能找到透明传发解析方式:{input.BaseHexMessage.HexMessageString}"); + } + } + + return await Task.FromResult(true); } catch (Exception ex) { - _logger.LogError(ex, $"10_101解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}"); - return null; + _logger.LogError(ex, $"10_1解析失败:{input.A?.Code}-{input.DT?.Fn ?? 0}-{input?.BaseHexMessage?.HexMessageString},{ex.Message}"); + } + return await Task.FromResult(false); } - - - private string AnalysisDataUnit(List hexMessageList) - { - // TODO: 待定,等确认如何匹配规则 - string value = string.Join(" ", hexMessageList); - if (value.Contains(F10TranspondMatch.ReadNormal)) - { - if (value.Contains(F10TranspondMatch.PowerHz))//电网频率 - return "AFN16_F97_Analysis"; - //else if (value.Contains(F10TranspondMatch.ReadData))//读取电表地址 - // result = "AFN16_F105_Analysis"; - } - return ""; - } - } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F97_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F97_Analysis.cs new file mode 100644 index 0000000..0863213 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F97_Analysis.cs @@ -0,0 +1,145 @@ +using DeviceDetectorNET.Parser.Device; +using GatherService.WattMeter.AnalysisData.AFN_10H; +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; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static FreeSql.Internal.GlobalFilter; + +namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_10H +{ + /// + /// 透抄 电网频率 + /// + public class AFN16_F97_Analysis : IAnalysisStrategy + { + private readonly ILogger _logger; + private readonly AnalysisStrategyContext _analysisStrategyContext; + private readonly DataStorage _dataStorage; + public AFN16_F97_Analysis(ILogger logger, AnalysisStrategyContext analysisStrategyContext, DataStorage dataStorage) + { + _logger = logger; + _analysisStrategyContext = analysisStrategyContext; + _dataStorage = dataStorage; + } + public async Task ExecuteAsync(TB3761 input, Action? result = null) + { + try + { + ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); + ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); + + List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList); + AnalysisBaseDto data = GenerateFinalResult(datas); + + // 查询设备信息 + DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn, datas[1]); + if (deviceInfo != null) + { + data.ProjectId = deviceInfo.ProjectID; + data.DeviceId = deviceInfo.MeterId; + data.DatabaseBusiID = deviceInfo.DatabaseBusiID; + data.DeviceAddress = deviceInfo.MeterAddress; + data.FocusId = deviceInfo.FocusId; + } + UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis> + { + 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, + Data = data, + ReceivedHexMessage = input.BaseHexMessage.HexMessageString, + MessageId = input.MessageId, + TimeDensity = 1,//密度-间隔, + DensityUnit = DensityUnit.Hour, + ReceivedTime = input.ReceivedTime, + DataType = IOTDBDataTypeConst.Data + + }; + result?.Invoke(unitDataAnalysis); + await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); + + return await Task.FromResult(true); + } + catch (Exception ex) + { + _logger.LogError(ex, $"10_97解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); + return await Task.FromResult(false); + } + } + + private AnalysisBaseDto GenerateFinalResult(List data) + { + AnalysisBaseDto meter = new AnalysisBaseDto(); + meter.DeviceType = MeterTypeEnum.Ammeter; + var errorCode = data[4].CheckErrorCode(); + if (errorCode != null) + { + meter.ValidData = false; + meter.ErrorCodeMsg = errorCode.Item2; + } + else + { + if(decimal.TryParse(data[4], out decimal value)) + meter.DataValue = value; + } + + meter.ItemType = "10_97"; + meter.ValidData = data[2].Equals("91") || data[2].Equals("B1"); + meter.FiledDesc = "电网频率";//"电网频率"; + meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty; + return meter; + } + private async Task> AnalysisDataUnitAsync(List hexMessageList) + { + List values = new List(); + values.Add(hexMessageList.GetRange(4, 1)[0].HexToDec().ToString());//端口号 + var contentLengthArr = hexMessageList.GetRange(5, 2); + contentLengthArr.Reverse(); + int contentLength = string.Join("", contentLengthArr).HexToDec(); + //TODO:转发内容 + List contentArr = hexMessageList.GetRange(7, contentLength); + //TODO:表地址 + var addressList = contentArr.GetRange(1, 6); + addressList.Reverse(); + var address = string.Join("", addressList); + values.Add(address); + //TODO:控制码 + var controlCode = contentArr.GetRange(8, 1)[0]; + values.Add(controlCode); + //TODO:长度 + var len = contentArr.GetRange(9, 1)[0].HexToDec(); + //values.Add(len.ToString()); + //TODO:数据域 + var dataField = contentArr.GetRange(10, len); + if (dataField.Count > 0) + { + string dataMark = string.Join("",dataField.GetRange(0, 4).ReduceHex33(true)); + values.Add(dataMark);//数据标识 + var readValue = dataField.GetRange(4, len - 4).ReduceHex33(true);//值 + await _analysisStrategyContext.ExecuteAsync>($"Appendix_{dataMark}", readValue, (value) => + { + values.Add(value.ToString()); + }); + } + return values; + } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F98_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F98_Analysis.cs index a0e719d..bb504e9 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F98_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/AFN16_F98_Analysis.cs @@ -1,6 +1,10 @@ -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; +using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto; using JiShe.CollectBus.Protocol.Dto; using JiShe.CollectBus.Protocol.Interfaces; using JiShe.CollectBus.Protocol.T37612012.AnalysisData; @@ -12,7 +16,7 @@ namespace GatherService.WattMeter.AnalysisData.AFN_10H /// /// 透明转发---跳合闸 /// - public class AFN16_F98_Analysis : IAnalysisStrategy> + public class AFN16_F98_Analysis : IAnalysisStrategy { private readonly ILogger _logger; @@ -25,25 +29,34 @@ namespace GatherService.WattMeter.AnalysisData.AFN_10H _dataStorage = dataStorage; } - public async Task> ExecuteAsync(TB3761 input) + public async Task ExecuteAsync(TB3761 input, Action? result = null) { try { ArgumentNullException.ThrowIfNull(input); + ArgumentNullException.ThrowIfNull(input.A.Code); ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList); List datas = AnalysisDataUnit(input.UnitData.HexMessageList); - - // 查询电表信息 - //AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data.MeterType.ToString(), "15"); - //if (ammeterInfo != null) - //{ - // data.ProjectId = ammeterInfo.ProjectID; - // data.MeterId = ammeterInfo.MeterId; - // data.DatabaseBusiID = ammeterInfo.DatabaseBusiID; - // data.MeterAddress = ammeterInfo.AmmerterAddress; - //} - UnitDataAnalysis unitDataAnalysis = new UnitDataAnalysis + + var data = new AnalysisBaseDto() + { + FiledDesc = "跳合闸", + DataValue = (datas[2].Equals("9C") || datas[2].Equals("94")) ? true : false, + ItemType= "10_98", + }; + + // 查询设备信息 + 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> unitDataAnalysis = new UnitDataAnalysis> { Code = input.A.Code!, AFN = input.AFN_FC.AFN, @@ -51,20 +64,24 @@ namespace GatherService.WattMeter.AnalysisData.AFN_10H Pn = input.DA.Pn, MSA = input.A.A3!.D1_D7!, PSEQ = input.SEQ.PSEQ, - Data = (datas[2].Equals("9C") || datas[2].Equals("94")) ? true : false, - HexMessage = input.BaseHexMessage.HexMessageString, + Data = data, + ReceivedHexMessage = input.BaseHexMessage.HexMessageString, MessageId = input.MessageId, - TimeDensity = 1,//密度-间隔分钟数, - DensityUnit = DensityUnit.Second + ReceivedTime = input.ReceivedTime, + DensityUnit = DensityUnit.None, + TimeDensity = -1, + DataType = IOTDBDataTypeConst.Data }; - //await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); - return await Task.FromResult(unitDataAnalysis); + result?.Invoke(unitDataAnalysis); + await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis); + return await Task.FromResult(true); } catch (Exception ex) { _logger.LogError(ex, $"10_98跳合闸解析失败:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString},{ex.Message}"); - return null; + } + return await Task.FromResult(false); } private List AnalysisDataUnit(List hexMessageList) diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs index 6914c3c..ff9a29e 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs @@ -1,21 +1,35 @@ -using JiShe.CollectBus.Common; +using FreeRedis; +using JiShe.CollectBus.Common; using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.Common.Encrypt; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.FreeRedis; using JiShe.CollectBus.IoTDB.Context; using JiShe.CollectBus.IoTDB.Interface; using JiShe.CollectBus.IoTDB.Model; using JiShe.CollectBus.IoTDB.Options; using JiShe.CollectBus.IoTDB.Provider; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.IotSystems.Devices; +using JiShe.CollectBus.IotSystems.LogRecord; using JiShe.CollectBus.IotSystems.MeterReadingRecords; using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto; using JiShe.CollectBus.Protocol.Dto; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using System.Diagnostics; +using System.Diagnostics.Metrics; +using System.Threading.Channels; +using TouchSocket.Core; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using YamlDotNet.Core.Tokens; +using static FreeSql.Internal.GlobalFilter; +using static JiShe.CollectBus.Common.Consts.T37612012PacketItemCodeConst; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { @@ -23,26 +37,78 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { private readonly IGuidGenerator _guidGenerator; private readonly IIoTDbProvider _dbProvider; - private readonly ServerApplicationOptions _applicationOptions; - private readonly IoTDBRuntimeContext _runtimeContext; - public DataStorage(IIoTDbProvider dbProvider, IOptions applicationOptions, IGuidGenerator guidGenerator, IoTDBRuntimeContext runtimeContext) + private readonly ServerApplicationOptions _applicationOptions; + private readonly ILogger _logger; + private readonly IMemoryCache _imemoryCache; + private readonly IFreeRedisProvider _freeRedisProvider; + private RedisClient Instance { get; set; } + public DataStorage(IIoTDbProvider dbProvider, IOptions applicationOptions, + IGuidGenerator guidGenerator, ILogger logger, IMemoryCache memoryCache, IFreeRedisProvider freeRedisProvider) { _dbProvider= dbProvider; _applicationOptions = applicationOptions.Value; - _guidGenerator= guidGenerator; - _runtimeContext= runtimeContext; + _guidGenerator= guidGenerator; + _logger= logger; + _imemoryCache = memoryCache; + _freeRedisProvider = freeRedisProvider; + Instance = _freeRedisProvider.Instance; } /// - /// 获取缓存电表信息 + /// 日志保存通道写入 + /// + /// + public async Task LogSaveWriterAsync(ChannelWriter channelWriter, dynamic dataItems) + { + await channelWriter.WriteAsync(dataItems); + } + + /// + /// 日志刷新通道写入 + /// + /// + public async Task LogRefreshSaveWriterAsync(ChannelWriter channelWriter, dynamic dataItems) + { + await channelWriter.WriteAsync(dataItems); + } + + + /// + /// 获取缓存设备信息 /// /// /// /// - public async Task GetMeterInfoAsync(string meterType,string timeDensity="15") + public async Task GetDeviceInfoAsync(string code,int pn=1,string meterAddress=null) { - var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, _applicationOptions.SystemType, _applicationOptions.ServerTagName, meterType, timeDensity)}"; - return await Task.FromResult(new AmmeterInfo()); + string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, _applicationOptions.SystemType, _applicationOptions.ServerTagName)}"; + string deviceKey= $"{code}:{pn}"; + var deviceInfo= await _imemoryCache.GetOrCreateAsync(deviceKey, async entry => + { + List devices= await Instance.HGetAsync>(redisCacheDeviceInfoHashKey, code) ?? new List(); + var data = devices.Where(s => s.MeteringCode == pn).FirstOrDefault(); + if (data != null) + entry.SetSlidingExpiration(TimeSpan.FromMinutes(5)); + else + entry.SetSlidingExpiration(TimeSpan.FromSeconds(5)); + return data ?? default; + }); + if (deviceInfo == null && !string.IsNullOrWhiteSpace(meterAddress)) + { + // TODO:透明转发回来的pn为0情况 + string deviceAddressKey = $"{code}:{meterAddress}"; + deviceInfo = await _imemoryCache.GetOrCreateAsync(deviceAddressKey, async entry => + { + List devices = await Instance.HGetAsync>(redisCacheDeviceInfoHashKey, code) ?? new List(); + var data = devices.Where(s => s.MeterAddress == meterAddress).FirstOrDefault(); + if (data != null) + entry.SetSlidingExpiration(TimeSpan.FromMinutes(5)); + else + entry.SetSlidingExpiration(TimeSpan.FromSeconds(5)); + return data ?? default; + }); + } + return deviceInfo; } /// @@ -54,7 +120,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData public async Task SaveDataToIotDbAsync(UnitDataAnalysis> analysisBaseDto) { var data = analysisBaseDto.Data!; - + if(!data.TimeSpan.HasValue) + data.TimeSpan= analysisBaseDto.ReceivedTime; string taskMark = CommonHelper.GetTaskMark(analysisBaseDto.AFN, analysisBaseDto.Fn, analysisBaseDto.Pn, analysisBaseDto.MSA, analysisBaseDto.PSEQ); string scoreValue = $"{analysisBaseDto.Code}.{taskMark}".Md5Fun(); @@ -83,21 +150,22 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData var meter = new TreeModelSingleMeasuringEntity() { SystemName = _applicationOptions.SystemType, - DeviceId = $"{data.MeterId}", - DeviceType = $"{data.MeterType}", + DeviceId = $"{data.DeviceId}", + DeviceType = $"{data.DeviceType.ToString()}", ProjectId = $"{data.ProjectId}", - Timestamps = data.TimeSpan.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleMeasuring = new Tuple(data.FiledName ?? string.Empty, data.DataValue ?? default) + DataType = analysisBaseDto.DataType, + Timestamps = data.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity).GetDateTimeOffset().ToUnixTimeNanoseconds(), + SingleMeasuring = (data.FiledName ?? string.Empty, data.DataValue ?? default) }; - _runtimeContext.UseTableSessionPool = true; // 使用表模型池 - var taskSendInfo = await _dbProvider.QueryAsync(new IoTDBQueryOptions() { TableNameOrTreePath = DevicePathBuilder.GetTableName(), Conditions = conditions, PageIndex = 0, PageSize = 1 }); + + var taskSendInfo = await _dbProvider.GetSessionPool(true).QueryAsync(new IoTDBQueryOptions() { TableNameOrTreePath = DevicePathBuilder.GetTableName(), Conditions = conditions, PageIndex = 0, PageSize = 1 }); var taskData = taskSendInfo?.Items.FirstOrDefault(); if (taskData != null) { // 更新 - meter.Timestamps = taskData.Timestamps; + meter.Timestamps = taskData.PendingCopyReadTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); taskData.IsReceived=true; - taskData.ReceivedMessageHexString= analysisBaseDto.HexMessage; + taskData.ReceivedMessageHexString= analysisBaseDto.ReceivedHexMessage; taskData.ReceivedMessageId= analysisBaseDto.MessageId ?? string.Empty; } else @@ -108,36 +176,38 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { SystemName = _applicationOptions.SystemType, ProjectId = $"{data.ProjectId}", - DeviceType = $"{data.MeterType}", - DeviceId = $"{data.MeterId}", - Timestamps = DateTime.Now.CheckTimePoint().GetDateTimeOffset().ToUnixTimeNanoseconds(), + DeviceType = $"{data.DeviceType}", + DeviceId = $"{data.DeviceId}", + DataType = analysisBaseDto.DataType, + FocusId = data.FocusId, + FocusAddress = analysisBaseDto.Code, + Timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(), DatabaseBusiID = data.DatabaseBusiID, - PendingCopyReadTime = data.DataTime.CheckTimePoint(), + PendingCopyReadTime = data.TimeSpan.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity), CreationTime = currentTime, - MeterAddress = data.MeterAddress, + MeterAddress = analysisBaseDto.Code == data.DeviceAddress ? "" : data.DeviceAddress, // 判断是否能取到表地址 AFN = analysisBaseDto.AFN, Fn = analysisBaseDto.Fn, Seq = analysisBaseDto.PSEQ, MSA = analysisBaseDto.MSA, - ItemCode = data.DataType, + ItemCode = data.ItemType, TaskMark = taskMark, IsSend = false, ManualOrNot = false, Pn = analysisBaseDto.Pn, - ReceivedMessageId = analysisBaseDto.MessageId?? string.Empty, - ReceivedMessageHexString = analysisBaseDto.HexMessage, + ReceivedMessageId = analysisBaseDto.MessageId ?? string.Empty, + ReceivedMessageHexString = analysisBaseDto.ReceivedHexMessage, IsReceived = true, ReceivedRemark = data.ErrorCodeMsg ?? string.Empty, ScoreValue = $"{analysisBaseDto.Code}.{taskMark}".Md5Fun(), + ReceivedTime = analysisBaseDto.ReceivedTime, }; - } - - await _dbProvider.InsertAsync(taskData); + } + await _dbProvider.GetSessionPool(true).InsertAsync(taskData); //如果无字段名,则不保存数据 - if (string.IsNullOrWhiteSpace(data.FiledName)) - { - _runtimeContext.UseTableSessionPool = false; // 使树模型池 - await _dbProvider.InsertAsync(meter); + if (!string.IsNullOrWhiteSpace(data.FiledName)) + { + await _dbProvider.GetSessionPool(false).InsertAsync(meter); } return await Task.FromResult(true); } @@ -148,12 +218,17 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData /// /// /// + /// /// public async Task SaveMultipleDataToIotDbAsync(UnitDataAnalysis>> analysisBaseDto) { var data = analysisBaseDto.Data!; + List meterReadingTelemetryPacketInfos = new List(); + List> treeModelSingleMeasuringEntities = new List>(); foreach (var item in data) { + if(!item.TimeSpan.HasValue) + item.TimeSpan = analysisBaseDto.ReceivedTime; string taskMark = CommonHelper.GetTaskMark(analysisBaseDto.AFN, analysisBaseDto.Fn, analysisBaseDto.Pn, analysisBaseDto.MSA, analysisBaseDto.PSEQ); string scoreValue = $"{analysisBaseDto.Code}.{taskMark}".Md5Fun(); @@ -182,21 +257,21 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData var meter = new TreeModelSingleMeasuringEntity() { SystemName = _applicationOptions.SystemType, - DeviceId = $"{item.MeterId}", - DeviceType = $"{item.MeterType}", + DeviceId = $"{item.DeviceId}", + DeviceType = $"{item.DeviceType}", ProjectId = $"{item.ProjectId}", - Timestamps = item.TimeSpan.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleMeasuring = new Tuple(item.FiledName ?? string.Empty, item.DataValue ?? default) - }; - _runtimeContext.UseTableSessionPool = true; // 使用表模型池 - var taskSendInfo = await _dbProvider.QueryAsync(new IoTDBQueryOptions() { TableNameOrTreePath = DevicePathBuilder.GetTableName(), Conditions = conditions, PageIndex = 0, PageSize = 1 }); + DataType = analysisBaseDto.DataType, + Timestamps = item.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity).GetDateTimeOffset().ToUnixTimeNanoseconds(), // TODO:这里暂时格式化15分钟数据,需要进行调整 + SingleMeasuring =(item.FiledName ?? string.Empty, item.DataValue ?? default) + }; + var taskSendInfo = await _dbProvider.GetSessionPool(true).QueryAsync(new IoTDBQueryOptions() { TableNameOrTreePath = DevicePathBuilder.GetTableName(), Conditions = conditions, PageIndex = 0, PageSize = 1 }); var taskData = taskSendInfo?.Items.FirstOrDefault(); if (taskData != null) { // 更新 - meter.Timestamps = taskData.Timestamps; + meter.Timestamps = taskData.PendingCopyReadTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); taskData.IsReceived = true; - taskData.ReceivedMessageHexString = analysisBaseDto.HexMessage; + taskData.ReceivedMessageHexString = analysisBaseDto.ReceivedHexMessage; taskData.ReceivedMessageId = analysisBaseDto.MessageId ?? string.Empty; } else @@ -207,38 +282,246 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { SystemName = _applicationOptions.SystemType, ProjectId = $"{item.ProjectId}", - DeviceType = $"{item.MeterType}", - DeviceId = $"{item.MeterId}", + DeviceType = $"{item.DeviceType}", + DeviceId = $"{item.DeviceId}", + DataType = IOTDBDataTypeConst.Log, // 匹配不到下发记录标记为LOG Timestamps = DateTime.Now.CheckTimePoint().GetDateTimeOffset().ToUnixTimeNanoseconds(), DatabaseBusiID = item.DatabaseBusiID, - PendingCopyReadTime = item.DataTime.CheckTimePoint(), + PendingCopyReadTime = item.TimeSpan.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity), CreationTime = currentTime, - MeterAddress = item.MeterAddress, + FocusId = item.FocusId, + FocusAddress = analysisBaseDto.Code, + MeterAddress = analysisBaseDto.Code == item.DeviceAddress ? "" : item.DeviceAddress, // 判断是否能取到表地址 AFN = analysisBaseDto.AFN, Fn = analysisBaseDto.Fn, Seq = analysisBaseDto.PSEQ, MSA = analysisBaseDto.MSA, - ItemCode = item.DataType, + ItemCode = item.ItemType, TaskMark = taskMark, IsSend = false, ManualOrNot = false, Pn = analysisBaseDto.Pn, ReceivedMessageId = analysisBaseDto.MessageId ?? string.Empty, - ReceivedMessageHexString = analysisBaseDto.HexMessage, + ReceivedMessageHexString = analysisBaseDto.ReceivedHexMessage, IsReceived = true, ReceivedRemark = item.ErrorCodeMsg ?? string.Empty, ScoreValue = $"{analysisBaseDto.Code}.{taskMark}".Md5Fun(), + ReceivedTime = analysisBaseDto.ReceivedTime, }; } - - await _dbProvider.InsertAsync(taskData); - //如果无字段名,则不保存数据 - if (string.IsNullOrWhiteSpace(item.FiledName)) + meterReadingTelemetryPacketInfos.Add(taskData); + //如果无字段名,则不保存数据,如saveData=false 也不保存数据 + if (!string.IsNullOrWhiteSpace(item.FiledName) && item.ProjectId>0) { - _runtimeContext.UseTableSessionPool = false; // 使树模型池 - await _dbProvider.InsertAsync(meter); + treeModelSingleMeasuringEntities.Add(meter); } } + // 批量保存数据 + await _dbProvider.GetSessionPool(true).BatchInsertAsync(meterReadingTelemetryPacketInfos); + if (treeModelSingleMeasuringEntities.Count > 0) + { + await _dbProvider.GetSessionPool(false).BatchInsertAsync(treeModelSingleMeasuringEntities); + } + return await Task.FromResult(true); + } + + /// + /// 保存状态到IotDb + /// + /// + /// + /// + public async Task SaveStatusToIotDbAsync(UnitDataAnalysis> analysisBaseDto) + { + ArgumentNullException.ThrowIfNull(nameof(analysisBaseDto.Data)); + ArgumentException.ThrowIfNullOrWhiteSpace(nameof(analysisBaseDto.Data.FiledName)); + ArgumentException.ThrowIfNullOrWhiteSpace(nameof(analysisBaseDto.Data.DataValue)); + List> treeModelSingleMeasuringEntities = new List>(); + + var data = analysisBaseDto.Data!; + if (!data.TimeSpan.HasValue) + data.TimeSpan = analysisBaseDto.ReceivedTime; + // 类型(心跳,登录,上电,掉电) + if (data.ProjectId > 0) + { + long timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(); + var treeData = new TreeModelSingleMeasuringEntity() + { + SystemName = _applicationOptions.SystemType, + DeviceId = $"{data.DeviceId}", + DeviceType = $"{data.DeviceType}", + ProjectId = $"{data.ProjectId}", + DataType = IOTDBDataTypeConst.Status, + Timestamps = timestamps, + SingleMeasuring = (data.FiledName!, data.DataValue!) + }; + await _dbProvider.GetSessionPool(false).InsertAsync(treeData); + // 数据帧 + var treeFrameData = new TreeModelSingleMeasuringEntity() + { + SystemName = _applicationOptions.SystemType, + DeviceId = $"{data.DeviceId}", + DeviceType = $"{data.DeviceType}", + ProjectId = $"{data.ProjectId}", + DataType = IOTDBDataTypeConst.Status, + Timestamps = timestamps, + SingleMeasuring = (ConcentratorStatusFieldConst.FrameData, analysisBaseDto.ReceivedHexMessage ?? string.Empty) + }; + await _dbProvider.GetSessionPool(false).InsertAsync(treeFrameData); + + // 时间 + var treeRecordingTimeData = new TreeModelSingleMeasuringEntity() + { + SystemName = _applicationOptions.SystemType, + DeviceId = $"{data.DeviceId}", + DeviceType = $"{data.DeviceType}", + ProjectId = $"{data.ProjectId}", + Timestamps = timestamps, + DataType = IOTDBDataTypeConst.Status, + SingleMeasuring = (ConcentratorStatusFieldConst.RecordingTime, data.TimeSpan.HasValue ? data.TimeSpan.Value : DateTime.Now) + }; + await _dbProvider.GetSessionPool(false).InsertAsync(treeRecordingTimeData); + } + + // 新建 + string taskMark = CommonHelper.GetTaskMark(analysisBaseDto.AFN, analysisBaseDto.Fn, analysisBaseDto.Pn, analysisBaseDto.MSA, analysisBaseDto.PSEQ); + var currentTime = DateTime.Now; + var taskData = new MeterReadingTelemetryPacketInfo() + { + SystemName = _applicationOptions.SystemType, + ProjectId = $"{data.ProjectId}", + DeviceType = $"{data.DeviceType}", + DeviceId = $"{data.DeviceId}", + DataType = analysisBaseDto.DataType, + FocusId = data.FocusId, + FocusAddress = analysisBaseDto.Code, + Timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(), + DatabaseBusiID = data.DatabaseBusiID, + PendingCopyReadTime = data.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity), + CreationTime = currentTime, + MeterAddress = analysisBaseDto.Code == data.DeviceAddress ? "" : data.DeviceAddress,// 判断是否能取到表地址 + AFN = analysisBaseDto.AFN, + Fn = analysisBaseDto.Fn, + Seq = analysisBaseDto.PSEQ, + MSA = analysisBaseDto.MSA, + ItemCode = data.ItemType, + TaskMark = taskMark, + IsSend = false, + ManualOrNot = false, + Pn = analysisBaseDto.Pn, + ReceivedMessageId = analysisBaseDto.MessageId ?? string.Empty, + ReceivedMessageHexString = analysisBaseDto.ReceivedHexMessage, + IsReceived = true, + ReceivedRemark = data.ErrorCodeMsg ?? string.Empty, + ScoreValue = $"{analysisBaseDto.Code}.{taskMark}".Md5Fun(), + ReceivedTime=analysisBaseDto.ReceivedTime, + }; + await _dbProvider.GetSessionPool(true).InsertAsync(taskData); + + return await Task.FromResult(true); + } + + /// + /// 保存状态到IotDb + /// + /// + /// + /// + public async Task SaveMultipleStatusToIotDbAsync(UnitDataAnalysis>> analysisBaseDto) + { + ArgumentNullException.ThrowIfNull(nameof(analysisBaseDto.Data)); + List meterReadingTelemetryPacketInfos = new List(); + + var data = analysisBaseDto.Data!; + foreach (var item in data) + { + ArgumentException.ThrowIfNullOrWhiteSpace(nameof(item.FiledName)); + ArgumentException.ThrowIfNullOrWhiteSpace(nameof(item.DataValue)); + + if (!item.TimeSpan.HasValue) + item.TimeSpan = analysisBaseDto.ReceivedTime; + // 类型(心跳,登录,上电,掉电) + if (item.ProjectId > 0) + { + long timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(); + var treeData = new TreeModelSingleMeasuringEntity() + { + SystemName = _applicationOptions.SystemType, + DeviceId = $"{item.DeviceId}", + DeviceType = $"{item.DeviceType}", + ProjectId = $"{item.ProjectId}", + DataType = IOTDBDataTypeConst.Status, + Timestamps = timestamps, + SingleMeasuring = (item.FiledName!, item.DataValue!) + }; + await _dbProvider.GetSessionPool(false).InsertAsync(treeData); + // 数据帧 + var treeFrameData = new TreeModelSingleMeasuringEntity() + { + SystemName = _applicationOptions.SystemType, + DeviceType = $"{item.DeviceType}", + ProjectId = $"{item.ProjectId}", + DataType = IOTDBDataTypeConst.Status, + Timestamps = timestamps, + SingleMeasuring = (ConcentratorStatusFieldConst.FrameData, analysisBaseDto.ReceivedHexMessage ?? string.Empty) + }; + + await _dbProvider.GetSessionPool(false).InsertAsync(treeFrameData); + + // 时间 + var treeRecordingTimeData = new TreeModelSingleMeasuringEntity() + { + SystemName = _applicationOptions.SystemType, + DeviceType = $"{item.DeviceType}", + ProjectId = $"{item.ProjectId}", + DataType = IOTDBDataTypeConst.Status, + Timestamps = timestamps, + SingleMeasuring = (ConcentratorStatusFieldConst.RecordingTime, item.TimeSpan.HasValue ? item.TimeSpan.Value : DateTime.Now) + }; + await _dbProvider.GetSessionPool(false).InsertAsync(treeRecordingTimeData); + + } + + // 新建 + string taskMark = CommonHelper.GetTaskMark(analysisBaseDto.AFN, analysisBaseDto.Fn, analysisBaseDto.Pn, analysisBaseDto.MSA, analysisBaseDto.PSEQ); + var currentTime = DateTime.Now; + var taskData = new MeterReadingTelemetryPacketInfo() + { + SystemName = _applicationOptions.SystemType, + ProjectId = $"{item.ProjectId}", + DeviceType = $"{item.DeviceType}", + DeviceId = $"{item.DeviceId}", + DataType = analysisBaseDto.DataType, + Timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(), + DatabaseBusiID = item.DatabaseBusiID, + PendingCopyReadTime = item.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity), + CreationTime = currentTime, + FocusId = item.FocusId, + FocusAddress = analysisBaseDto.Code, + MeterAddress= analysisBaseDto.Code== item.DeviceAddress?"": item.DeviceAddress,// 判断是否能取到表地址 + AFN = analysisBaseDto.AFN, + Fn = analysisBaseDto.Fn, + Seq = analysisBaseDto.PSEQ, + MSA = analysisBaseDto.MSA, + ItemCode = item.ItemType, + TaskMark = taskMark, + IsSend = false, + ManualOrNot = false, + Pn = analysisBaseDto.Pn, + ReceivedMessageId = analysisBaseDto.MessageId ?? string.Empty, + ReceivedMessageHexString = analysisBaseDto.ReceivedHexMessage, + IsReceived = true, + ReceivedRemark = item.ErrorCodeMsg ?? string.Empty, + ScoreValue = $"{analysisBaseDto.Code}.{taskMark}".Md5Fun(), + ReceivedTime = analysisBaseDto.ReceivedTime, + }; + + meterReadingTelemetryPacketInfos.Add(taskData); + } + if (meterReadingTelemetryPacketInfos.Count > 0) + { + await _dbProvider.GetSessionPool(true).BatchInsertAsync(meterReadingTelemetryPacketInfos); + } return await Task.FromResult(true); } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_02800002.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_02800002.cs index 7245d70..da699e2 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_02800002.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_02800002.cs @@ -4,9 +4,9 @@ using Microsoft.Extensions.Logging; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { /// - /// 第一套第 2 日时段表数据 + /// Appendix_02800002 /// - public class Appendix_02800002 : IAnalysisStrategy, List> + public class Appendix_02800002 : IAnalysisStrategy> { private readonly ILogger _logger; @@ -15,21 +15,23 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; } - public Task> ExecuteAsync(List data) + public Task ExecuteAsync(List data, Action? result = null) { try { - if (data.Count != 2) - return null; - var value = string.Join(".", data); - var values= new List() { "电网频率", "10_97", "1", value }; - return Task.FromResult(values); + if (data.Count == 2) + { + var value = string.Join(".", data); + //电网频率 + result?.Invoke(value); + return Task.FromResult(true); + } } catch (Exception ex) { _logger.LogError(ex, $"Appendix_02800002解析失败:{ex.Message}"); - return null; } + return Task.FromResult(false); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000201.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000201.cs index 7c2db74..6345f90 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000201.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000201.cs @@ -7,7 +7,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 年时区数 p≤14 /// - public class Appendix_04000201 : IAnalysisStrategy, List> + public class Appendix_04000201 : IAnalysisStrategy> { private int valueByteCount = 1; private readonly ILogger _logger; @@ -17,7 +17,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { List values = new List(); values.Insert(0, "10_94"); @@ -27,7 +27,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix { values.Add(item.HexToDec().ToString()); } - return await Task.FromResult(values); + result?.Invoke(values); + return await Task.FromResult(true); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000202.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000202.cs index 20870cd..9ebafff 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000202.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000202.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 日时段表数 q≤8 /// - public class Appendix_04000202 : IAnalysisStrategy, List> + public class Appendix_04000202 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +17,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04000201", data); - values[0] = "日时段表数"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04000201), data, (values) => + { + values[0] = "日时段表数"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000203.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000203.cs index cf0c882..1a69d1c 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000203.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000203.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 日时段数(每日切换数) m≤14 /// - public class Appendix_04000203 : IAnalysisStrategy, List> + public class Appendix_04000203 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +17,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04000201", data); - values[0] = "日时段数(每日切换数)"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04000201), data, (values) => + { + values[0] = "日时段数(每日切换数)"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000204.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000204.cs index 56ab772..bed7fc0 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000204.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04000204.cs @@ -1,12 +1,13 @@ using JiShe.CollectBus.Protocol.Interfaces; using Microsoft.Extensions.Logging; +using TouchSocket.Core; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { /// /// 费率数 k≤63 /// - public class Appendix_04000204 : IAnalysisStrategy, List> + public class Appendix_04000204 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +18,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04000201", data); - values[0] = "费率数"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04000201), data, (values) => + { + values[0] = "费率数"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010000.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010000.cs index 4ce52fc..e77156e 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010000.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010000.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套时区表数据 /// - public class Appendix_04010000 : IAnalysisStrategy, List> + public class Appendix_04010000 : IAnalysisStrategy> { /// /// 每个值字节数 @@ -19,7 +19,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { List values = new List(); int valueCount = data.Count / valueByteCount; @@ -32,7 +32,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix values.Add($"{value[0]}:{value[1]}");//MM:DD 或hhmm values.Add(value[2]);//NN 费率号 } - return await Task.FromResult(values); + result?.Invoke(values); + return await Task.FromResult(true); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010001.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010001.cs index deb25fe..346a3be 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010001.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010001.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套第 1 日时段表数据: /// - public class Appendix_04010001 : IAnalysisStrategy, List> + public class Appendix_04010001 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +17,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04010000", data); - values[0] = "第一套第1日第{0}时段起始时间及费率号"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04010000), data, (values) => + { + values[0] = "第一套第1日第{0}时段起始时间及费率号"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010002.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010002.cs index 3dee4da..0d27da0 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010002.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010002.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套第 2 日时段表数据 /// - public class Appendix_04010002 : IAnalysisStrategy, List> + public class Appendix_04010002 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +17,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04010000", data); - values[0] = "第一套第2日第{0}时段起始时间及费率号"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04010000), data, (values) => + { + values[0] = "第一套第2日第{0}时段起始时间及费率号"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010003.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010003.cs index d3693c2..0a1a926 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010003.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010003.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套第 3 日时段表数据 /// - public class Appendix_04010003 : IAnalysisStrategy, List> + public class Appendix_04010003 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +17,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04010000", data); - values[0] = "第一套第3日第{0}时段起始时间及费率号"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04010000), data, (values) => + { + values[0] = "第一套第3日第{0}时段起始时间及费率号"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010004.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010004.cs index 68faa82..baee7f0 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010004.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010004.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套第 4 日时段表数据 /// - public class Appendix_04010004 : IAnalysisStrategy, List> + public class Appendix_04010004 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -16,11 +16,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List> ("Appendix_04010000", data); - values[0] = "第一套第4日第{0}时段起始时间及费率号"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04010000), data, (values) => + { + values[0] = "第一套第4日第{0}时段起始时间及费率号"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010005.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010005.cs index 9ef615f..605bae3 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010005.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010005.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套第 5 日时段表数据 /// - public class Appendix_04010005 : IAnalysisStrategy, List> + public class Appendix_04010005 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +17,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04010000", data); - values[0] = "第一套第5日第{0}时段起始时间及费率号"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04010000), data, (values) => + { + values[0] = "第一套第5日第{0}时段起始时间及费率号"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010006.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010006.cs index a31ae33..d7dc837 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010006.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010006.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套第 6 日时段表数据 /// - public class Appendix_04010006 : IAnalysisStrategy, List> + public class Appendix_04010006 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +17,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04010000", data); - values[0] = "第一套第6日第{0}时段起始时间及费率号"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04010000), data, (values) => + { + values[0] = "第一套第6日第{0}时段起始时间及费率号"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010007.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010007.cs index 5142cf7..273d040 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010007.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010007.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套第 7 日时段表数据 /// - public class Appendix_04010007 : IAnalysisStrategy, List> + public class Appendix_04010007 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -16,11 +16,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04010000", data); - values[0] = "第一套第7日第{0}时段起始时间及费率号"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04010000), data, (values) => + { + values[0] = "第一套第7日第{0}时段起始时间及费率号"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010008.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010008.cs index 0074290..70322b9 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010008.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_04010008.cs @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 第一套第 8 日时段表数据 /// - public class Appendix_04010008 : IAnalysisStrategy, List> + public class Appendix_04010008 : IAnalysisStrategy> { private readonly ILogger _logger; private readonly AnalysisStrategyContext _analysisStrategyContext; @@ -17,11 +17,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _analysisStrategyContext = analysisStrategyContext; } - public async Task> ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { - var values = await _analysisStrategyContext.ExecuteAsync, List>("Appendix_04010000", data); - values[0] = "第一套第8日第{0}时段起始时间及费率号"; - return await Task.FromResult(values); + return await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_04010000), data, (values) => + { + values[0] = "第一套第8日第{0}时段起始时间及费率号"; + result?.Invoke(values); + }); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A1.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A1.cs index 86d2149..eadc9a3 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A1.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A1.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.Logging; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { - public class Appendix_A1 : IAnalysisStrategy, string> + public class Appendix_A1 : IAnalysisStrategy> { private readonly ILogger _logger; @@ -13,7 +13,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; } - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { var seconds = data[0]; var minutes = data[1]; @@ -21,10 +21,14 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix var day = data[3]; string binString = data[4].HexTo4BinZero(); var months = (binString.Substring(3, 1).BinToDec() * 10) + Convert.ToInt32(binString.Substring(4, 4).BinToHex()); - var week = binString.Substring(0, 3).HexTo4BinZero(); + var week = binString.Substring(0, 3).BinToHex(); var year = $"{DateTime.Now.ToString("yyyy").Substring(0, 2)}{data[5]}"; - string date= $"{year}-{months.ToString().PadLeft(2, '0')}-{day} {hours}:{minutes}:{seconds}_{week}"; - return await Task.FromResult(date); + string date= $"{year}-{months.ToString().PadLeft(2, '0')}-{day} {hours}:{minutes}:{seconds}"; + string[] weekdays = {"", "星期一", "星期二", "星期三","星期四", "星期五", "星期六", "星期日"}; + int.TryParse(week, out int weekday); + // Item1=日期,Item2=星期几 + result?.Invoke(Tuple.Create(date, weekdays[weekday])); + return await Task.FromResult(true); } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A11.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A11.cs index 2713adb..4f6f6d9 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A11.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A11.cs @@ -7,7 +7,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 附录A.11数据格式 /// - class Appendix_A11 : IAnalysisStrategy, decimal> + class Appendix_A11 : IAnalysisStrategy> { private readonly ILogger _logger; @@ -16,7 +16,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; } - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { decimal value = 0.00M; List decimalDCBList = new List(); @@ -29,7 +29,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix int CalcType = i > 0 ? 2 : 1; value += GetByteDCD(data[i].HexTo4BinZero(), CalcType, decimalDCBList[i]); } - return await Task.FromResult(value); + result?.Invoke(value); + return await Task.FromResult(true); } /// diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A13.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A13.cs index 51d73ab..a0c8cb6 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A13.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A13.cs @@ -7,7 +7,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 附录A.13数据格式 /// - class Appendix_A13 : IAnalysisStrategy, decimal> + class Appendix_A13 : IAnalysisStrategy> { private readonly ILogger _logger; @@ -16,7 +16,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; } - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { decimal value = 0.00M; List decimalDCBList = new List(); @@ -29,7 +29,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix int CalcType = i > 1 ? 2 : 1; value += GetByteDCD(data[i].HexTo4BinZero(), CalcType, decimalDCBList[i]); } - return await Task.FromResult(value); + result?.Invoke(value); + return await Task.FromResult(true); } /// /// 附录A.13数据格式计算规则方法 diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A14.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A14.cs index 5d21ee8..66e7b97 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A14.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A14.cs @@ -7,7 +7,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix /// /// 附录A.14数据格式 /// - class Appendix_A14 : IAnalysisStrategy, decimal> + class Appendix_A14 : IAnalysisStrategy> { private readonly ILogger _logger; @@ -15,7 +15,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix { _logger = logger; } - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { decimal value = 0.0000M; List decimalDCBList = new List(); @@ -29,7 +29,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix int CalcType = i > 1 ? 2 : 1; value += GetByteDCD(data[i].HexTo4BinZero(), CalcType, decimalDCBList[i]); } - return await Task.FromResult(value); + result?.Invoke(value); + return await Task.FromResult(true); } /// diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A15.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A15.cs index 284c3f6..527bdf6 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A15.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A15.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Logging; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { - public class Appendix_A15 : IAnalysisStrategy, string> + public class Appendix_A15 : IAnalysisStrategy> { private readonly ILogger _logger; @@ -12,12 +12,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix _logger = logger; } - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { data.Reverse(); data.Insert(0, DateTime.Now.ToString("yyyy").Substring(0, 2)); string date= string.Join("", data); - return await Task.FromResult(date); + result?.Invoke(date); + return await Task.FromResult(true); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A17.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A17.cs index 942fc95..a7e65c5 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A17.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A17.cs @@ -2,13 +2,14 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix { - public class Appendix_A17 : IAnalysisStrategy, string> + public class Appendix_A17 : IAnalysisStrategy> { - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { data.Reverse(); string datasStr= string.Join("", data); - return await Task.FromResult(datasStr); + result?.Invoke(datasStr); + return await Task.FromResult(true); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A23.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A23.cs index 1a6efb5..ac58633 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A23.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A23.cs @@ -3,10 +3,10 @@ using JiShe.CollectBus.Protocol.Interfaces; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { - public class Appendix_A23 : IAnalysisStrategy, decimal> + public class Appendix_A23 : IAnalysisStrategy> { - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { decimal value = 0.000M; if (data[0].Check3761Byte()) @@ -15,7 +15,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix value += GetValue(0, 4, 10M, 4, 4, 100M, data[1], 1); if (data[2].Check3761Byte()) value += GetValue(0, 4, 10M, 4, 4, 1M, data[2], 0); - return await Task.FromResult(value); + result?.Invoke(value); + return await Task.FromResult(true); } /// /// 解析值 diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A25.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A25.cs index 3cda672..9cbeb28 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A25.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A25.cs @@ -3,9 +3,9 @@ using JiShe.CollectBus.Protocol.Interfaces; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { - public class Appendix_A25 : IAnalysisStrategy, decimal> + public class Appendix_A25 : IAnalysisStrategy> { - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { decimal value = 0.000M; string binString = string.Empty; @@ -26,7 +26,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix int sign = Convert.ToInt32(binString.Substring(0, 1));//正负值标记 value = sign == 0 ? value * 1 : value * -1; } - return await Task.FromResult(value); + result?.Invoke(value); + return await Task.FromResult(true); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A5.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A5.cs index 3815e85..8dec6b4 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A5.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A5.cs @@ -3,9 +3,9 @@ using JiShe.CollectBus.Protocol.Interfaces; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { - public class Appendix_A5 : IAnalysisStrategy, decimal> + public class Appendix_A5 : IAnalysisStrategy> { - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { decimal value = 0.0M; string binString = string.Empty; @@ -21,7 +21,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix int sign = Convert.ToInt32(binString.Substring(0, 1));//正负值标记 value = sign == 0 ? value * 1 : value * -1; } - return await Task.FromResult(value); + result?.Invoke(value); + return await Task.FromResult(true); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A7.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A7.cs index b75d733..86704b4 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A7.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A7.cs @@ -3,10 +3,10 @@ using JiShe.CollectBus.Protocol.Interfaces; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { - public class Appendix_A7 : IAnalysisStrategy, decimal> + public class Appendix_A7 : IAnalysisStrategy> { - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { decimal value = 0.0M; string binString = string.Empty; @@ -21,7 +21,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix if (binString.Check3761Byte()) value += (binString.Substring(0, 4).BinToDec() * 100M) + (binString.Substring(4, 4).BinToDec() * 10M); } - return await Task.FromResult(value); + result?.Invoke(value); + return await Task.FromResult(true); } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A9.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A9.cs index a3a0b38..28082c9 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A9.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Appendix/Appendix_A9.cs @@ -3,10 +3,10 @@ using JiShe.CollectBus.Protocol.Interfaces; namespace JiShe.CollectBus.Protocol.T37612012.Appendix { - public class Appendix_A9 : IAnalysisStrategy, decimal> + public class Appendix_A9 : IAnalysisStrategy> { - public async Task ExecuteAsync(List data) + public async Task ExecuteAsync(List data, Action? result = null) { decimal value = 0.0000M; string binString = string.Empty; @@ -29,7 +29,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.Appendix int sign = Convert.ToInt32(binString.Substring(0, 1));//正负值标记 value = sign == 0 ? value * 1 : value * -1; } - return await Task.FromResult(value); + result?.Invoke(value); + return await Task.FromResult(true); } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/CollectBusProtocolT37612012Module.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/CollectBusProtocolT37612012Module.cs index 53ec062..8a3466f 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/CollectBusProtocolT37612012Module.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/CollectBusProtocolT37612012Module.cs @@ -1,5 +1,7 @@ using System.Reflection; +using System.Threading.Channels; using JiShe.CollectBus.Protocol.Interfaces; +using JiShe.CollectBus.Protocol.T37612012.AnalysisData; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Volo.Abp; @@ -12,8 +14,10 @@ namespace JiShe.CollectBus.Protocol.T37612012 public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddKeyedSingleton(nameof(T37612012ProtocolPlugin)); - //RegisterProtocolAnalysis(context.Services); - LoadAnalysisStrategy(context.Services); + context.Services.AddMemoryCache(); + // TODO:先用之前的策略注册方式,后续验证后采用LoadAnalysisStrategy + RegisterProtocolAnalysis(context.Services); + //LoadAnalysisStrategy(context.Services); } public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context) @@ -31,8 +35,9 @@ namespace JiShe.CollectBus.Protocol.T37612012 public void LoadAnalysisStrategy(IServiceCollection services) { + services.AddTransient(); var assembly = Assembly.GetExecutingAssembly(); - var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<,>))); + var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<>))); foreach (var analysisStrategyType in analysisStrategyTypes) { var service = analysisStrategyType.GetInterfaces().First(); @@ -43,7 +48,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 public void RegisterProtocolAnalysis(IServiceCollection services) { // 扫描并注册所有策略 - var strategyMetadata = new Dictionary<(string, Type, Type), Type>(); + var strategyMetadata = new Dictionary<(string, Type), Type>(); services.AddTransient(); // 批量注册 @@ -61,19 +66,19 @@ namespace JiShe.CollectBus.Protocol.T37612012 .FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName); var assembly = existingAssembly ?? Assembly.LoadFrom(file); // 实现IAnalysisStrategy接口 - var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<,>))); + var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<>))); if (!analysisStrategyTypes.Any()) continue; foreach (var analysisStrategyType in analysisStrategyTypes) { // 通过反射获取静态元数据 var strategyType = analysisStrategyType.Name; - var genericArgs = analysisStrategyType.GetInterface($"IAnalysisStrategy`2")!.GetGenericArguments(); + var genericArgs = analysisStrategyType.GetInterface($"IAnalysisStrategy`1")!.GetGenericArguments(); var inputType = genericArgs[0]; - var resultType = genericArgs[1]; // 注册策略实现 services.AddTransient(analysisStrategyType); - strategyMetadata[(strategyType, inputType, resultType)] = analysisStrategyType; + strategyMetadata[(strategyType, inputType)] = analysisStrategyType; + } } @@ -81,22 +86,20 @@ namespace JiShe.CollectBus.Protocol.T37612012 services.AddSingleton(strategyMetadata); // 注册策略解析工厂 - services.AddTransient>(provider => (name, inputType, resultType) => + services.AddTransient>(provider => (name, inputType) => { - var metadata = provider.GetRequiredService>(); - if (metadata.TryGetValue((name, inputType, resultType), out var strategyType)) + var metadata = provider.GetRequiredService>(); + if (metadata.TryGetValue((name, inputType), out var strategyType)) { return provider.GetRequiredService(strategyType); } else { var logger = provider.GetRequiredService>(); - logger.LogWarning($"未能找到解析策略:{name}-{inputType}-{resultType}"); + logger.LogWarning($"未能找到解析策略:{name}-{inputType}"); return null; } }); - - } } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol3761Extensions.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol3761Extensions.cs index 2045a06..7ac67a2 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol3761Extensions.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol3761Extensions.cs @@ -1,9 +1,10 @@ -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.Enums; +using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; +using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto; using NUglify.JavaScript.Syntax; using System.Text.RegularExpressions; +using YamlDotNet.Core.Tokens; namespace JiShe.CollectBus.Protocol.T37612012 { @@ -144,6 +145,11 @@ namespace JiShe.CollectBus.Protocol.T37612012 return DateTime.Parse(dataTime); } + /// + /// 判断当前时间所在时标(5分钟) + /// + /// + /// public static DateTime CheckTimeFivePoint(this DateTime curTime) { string dataTime; @@ -175,8 +181,38 @@ namespace JiShe.CollectBus.Protocol.T37612012 return DateTime.Parse(dataTime); } + /// - /// 数据时标 + /// 格式化时间 + /// + /// + /// + /// + /// + public static DateTime GetFormatTime(this DateTime dateTime, DensityUnit densityUnit, int timeDensity) + { + switch (densityUnit) + { + case DensityUnit.Minute: + if (timeDensity == 1 || timeDensity == 30) + return DateTime.Parse(dateTime.ToString("yyyy-MM-dd HH:mm:00")); + if (timeDensity == 5) + return dateTime.CheckTimeFivePoint(); + if (timeDensity == 15) + return dateTime.CheckTimePoint(); + if (timeDensity == 60) + return DateTime.Parse(dateTime.ToString("yyyy-MM-dd HH:00:00")); + break; + case DensityUnit.Day: + return DateTime.Parse(dateTime.ToString("yyyy-MM-dd 00:00:00")); + case DensityUnit.Month: + return DateTime.Parse(dateTime.ToString("yyyy-MM-01 00:00:00")); + } + return dateTime; + } + + /// + /// 数据时标(曲线类型) /// /// /// @@ -204,15 +240,15 @@ namespace JiShe.CollectBus.Protocol.T37612012 /// /// /// - public static List> GenerateFinalResultTd_c(this List data, int index,int density,string dataType, string filedDesc = "") + public static List> GenerateFinalResultTd_c(this List data, int index,int density,string dataType, string filedDesc = "") { - List> list = new List>(); + List> list = new List>(); for (int i = index; i < data.Count; i++) { - AnalysisBaseDto meter = new AnalysisBaseDto(); - meter.MeterType= MeterTypeEnum.Ammeter; - - decimal value = 0; + AnalysisBaseDto meter = new AnalysisBaseDto + { + DeviceType = MeterTypeEnum.Ammeter + }; var errorCode = data[i].CheckErrorCode(); if (errorCode != null) { @@ -220,11 +256,15 @@ namespace JiShe.CollectBus.Protocol.T37612012 meter.ErrorCodeMsg = errorCode.Item2; } else - decimal.TryParse(data[i], out value); - meter.DataValue = value; - meter.DataType = dataType; + { + if(decimal.TryParse(data[i], out decimal value)) + { + meter.DataValue = value; + } + } + meter.ItemType = dataType; meter.FiledDesc = filedDesc; - meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty; + meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty; if (DateTime.TryParse(CalculateTimeSpan(i - 3, data[0], density), out DateTime readingDate)) meter.TimeSpan = readingDate; list.Add(meter); @@ -233,22 +273,21 @@ namespace JiShe.CollectBus.Protocol.T37612012 } /// - /// 月冻结 + /// 月冻结(曲线类型) /// /// /// /// /// - /// + /// /// - public static List> GenerateFinalResultTd_m(this List data, int index,string dataType,string timeSpan, string filedDesc = "") + public static List> GenerateFinalResultTd_m(this List data, int index,string dataType,string timeSpan, string filedDesc = "") { - List> list = new List>(); + List> list = new List>(); for (int i = index; i < data.Count; i++) { - AnalysisBaseDto meter = new AnalysisBaseDto(); - meter.MeterType = MeterTypeEnum.Ammeter; - decimal value = 0; + AnalysisBaseDto meter = new AnalysisBaseDto(); + meter.DeviceType = MeterTypeEnum.Ammeter; var errorCode = data[i].CheckErrorCode(); if (errorCode != null) { @@ -256,36 +295,40 @@ namespace JiShe.CollectBus.Protocol.T37612012 meter.ErrorCodeMsg = errorCode.Item2; } else - decimal.TryParse(data[i], out value); - meter.DataValue = value; + { + if(decimal.TryParse(data[i], out decimal value)) + { + meter.DataValue = value; + } + } if (DateTime.TryParse(timeSpan, out DateTime readingDate)) { meter.TimeSpan = readingDate; } - meter.DataType = i - index == 0 ? dataType : $"{dataType}_{i - index}"; + meter.ItemType = i - index == 0 ? dataType : $"{dataType}_{i - index}"; meter.FiledDesc = filedDesc; - meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty; + meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty; list.Add(meter); } return list; } /// - /// 日冻结 + /// 日冻结(曲线类型) /// /// /// /// /// - public static List> GenerateFinalResultTd_d(this List data, int index,string dataType, string timeSpan, string filedDesc = "") + public static List> GenerateFinalResultTd_d(this List data, int index,string dataType, string timeSpan, string filedDesc = "") { - List> list = new List>(); + List> list = new List>(); int typeIndex = 0; for (int i = index; i < data.Count; i++) { - AnalysisBaseDto meter = new AnalysisBaseDto + AnalysisBaseDto meter = new AnalysisBaseDto { - MeterType = MeterTypeEnum.Ammeter + DeviceType = MeterTypeEnum.Ammeter }; decimal value = 0; var errorCode = data[i].CheckErrorCode(); @@ -295,15 +338,19 @@ namespace JiShe.CollectBus.Protocol.T37612012 meter.ErrorCodeMsg = errorCode.Item2; } else - decimal.TryParse(data[i], out value); - meter.DataValue = value; + { + if(decimal.TryParse(data[i], out value)) + { + meter.DataValue = value; + } + } if (DateTime.TryParse(timeSpan, out DateTime readingDate)) { meter.TimeSpan = readingDate; } - meter.DataType = i - index == 0 ? dataType : $"{dataType}_{i - index}"; + meter.ItemType = i - index == 0 ? dataType : $"{dataType}_{i - index}"; meter.FiledDesc = filedDesc; - meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty; + meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty; list.Add(meter); typeIndex++; } @@ -329,29 +376,33 @@ namespace JiShe.CollectBus.Protocol.T37612012 /// /// /// - public static List> IsValidData(this List> meterDatas, List mark) + public static List> IsValidData(this List> meterDatas, List mark) { bool isUpload = false; var jfpgSum = 0M; - var totalItem = meterDatas.Find(f => f.DataType.Equals(mark[0]));//meterDatas.Find(f => f.DataType.Equals(mark[0])); - for (int i = 1; i <= meterDatas.Count - 1; i++) + foreach (var item in meterDatas) { - var value = meterDatas[i];//meterDatas.Find(f => f.DataType.Equals(mark[i])); - if (value.ValidData) - jfpgSum += value.DataValue; + if (item.ValidData && item.DataValue.HasValue) + jfpgSum += item.DataValue.Value; + } + var totalItem = meterDatas.FirstOrDefault(f => f.ItemType.Equals(mark[0]));//meterDatas.Find(f => f.DataType.Equals(mark[0])); + if (totalItem != null) + { + var floatingNum = (jfpgSum * 5 / 100);//上下浮动数据 + var minjfpgSum = jfpgSum - floatingNum;//100-(100*5/100); + var maxjfpgSum = jfpgSum + floatingNum; + if ((totalItem.DataValue <= maxjfpgSum || totalItem.DataValue >= minjfpgSum))//总值,在JFPG之和的浮动范围内 + isUpload = true; + else + isUpload = false; } - var floatingNum = (jfpgSum * 5 / 100);//上下浮动数据 - var minjfpgSum = jfpgSum - floatingNum;//100-(100*5/100); - var maxjfpgSum = jfpgSum + floatingNum; - if (totalItem.DataValue <= maxjfpgSum || totalItem.DataValue >= minjfpgSum)//总值,在JFPG之和的浮动范围内 - isUpload = true; - else - isUpload = false; if (!isUpload) + { meterDatas.ForEach(f => { f.ValidData = false; }); + } return meterDatas; } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketBuilder.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketBuilder.cs index ab43cc8..5540281 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketBuilder.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketBuilder.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using System.Data; +using System.Reflection; using JiShe.CollectBus.Common.BuildSendDatas; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Models; @@ -55,7 +56,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Fn = request.Fn }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion @@ -80,7 +81,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Fn = request.Fn }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion @@ -105,7 +106,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Fn = request.Fn }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion @@ -129,7 +130,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Fn = request.Fn }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion @@ -154,7 +155,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Fn = request.Fn }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion @@ -178,7 +179,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Fn = request.Fn }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion @@ -203,7 +204,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Fn = request.Fn }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion @@ -227,7 +228,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Fn = request.Fn }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion @@ -250,14 +251,21 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Pn = request.Pn, Fn = request.Fn }; - var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + + var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter,request.DataUnit); + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #endregion #region AFN10H 数据转发 public static Telemetry3761PacketResponse AFN10_Fn_Send(Telemetry3761PacketRequest request) { + + var baudRateValue = Build3761SendData.GetBaudreate($"{request.SubRequest.Baudrate}"); + + var dataUnit = Build3761SendData.BuildTransparentForwardingSendDataUnit(request.SubRequest.MeteringPort, baudRateValue, request.DataUnit); + dataUnit.AddRange(Build3761SendData.GetPW()); + var reqParameter = new ReqParameter2() { AFN = AFN.数据转发, @@ -274,8 +282,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData Pn = request.Pn, Fn = request.Fn }; - var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter, request.DataUnit); - return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; + var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter, dataUnit); + return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA,Pn = reqParameter.Pn,AFn = (int)reqParameter.AFN,Fn = reqParameter.Fn }; } #region SpecialAmmeter 特殊电表转发 diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketRequest.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketRequest.cs index f02efc9..a5d8593 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketRequest.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketRequest.cs @@ -1,4 +1,6 @@ -namespace JiShe.CollectBus.Protocol.T37612012.SendData +using JiShe.CollectBus.Protocol.Models; + +namespace JiShe.CollectBus.Protocol.T37612012.SendData { /// /// 构建3761报文参数 @@ -20,8 +22,13 @@ /// public int Pn { get; set; } + /// + /// 子协议请求 + /// + public SubProtocolBuildRequest SubRequest { get; set; } + /// - /// 透明转发单元 + /// 透明转发数据单元 /// public List DataUnit { get; set; } } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketResponse.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketResponse.cs index cd4ed6e..64c84b7 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketResponse.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketResponse.cs @@ -15,6 +15,22 @@ /// public int MSA { get; set; } + + /// + /// 帧功能域AFN + /// + public int AFn { get; set; } + + /// + /// 帧功能域FN + /// + public int Fn { get; set; } + + /// + /// 抄读计量点,也就是终端电表对应端口 + /// + public int Pn { get; set; } + /// /// 报文体 /// diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs index 1fc8d2a..ed82fa0 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs @@ -31,7 +31,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 private readonly ITcpService _tcpService; public readonly Dictionary T3761AFNHandlers; - + /// /// Initializes a new instance of the class. /// @@ -46,7 +46,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 T3761AFNHandlers = Telemetry3761PacketBuilder.T3761AFNHandlers; } - public override ProtocolInfo Info => new(nameof(T37612012ProtocolPlugin), "376.1", "TCP", "376.1协议", "DTS1980"); + public override ProtocolInfo Info => new(nameof(T37612012ProtocolPlugin), "376.1", "TCP", "376.1协议", "DTS1980"); public override async Task AnalyzeAsync(ITcpSessionClient client, string messageReceived, Action? sendAction = null) { @@ -64,11 +64,13 @@ namespace JiShe.CollectBus.Protocol.T37612012 if (tB3761.DT?.Fn == (int)FN.登录) { // 登录回复 + //todo 更新Redis数据缓存 if (tB3761.SEQ.CON == (int)CON.需要对该帧进行确认) await LoginAsync(client, messageReceived, tB3761.A.Code, tB3761.A.A3?.D1_D7, tB3761.SEQ?.PSEQ); } else if (tB3761.DT?.Fn == (int)FN.心跳) { + //todo 更新Redis数据缓存,主要是TCP连接,当前服务器连接配置数量满了以后,如何解决监控策略,通知新采购服务器 // 心跳回复 //心跳帧有两种情况: //1. 集中器先有登录帧,再有心跳帧 @@ -104,17 +106,15 @@ namespace JiShe.CollectBus.Protocol.T37612012 // MessageId = NewId.NextGuid().ToString() //}); - if (tB3761.AFN_FC.BaseHexMessage == null || tB3761.DT.BaseHexMessage == null || tB3761.BaseHexMessage.HexMessageString==null) + if (tB3761.AFN_FC.BaseHexMessage == null || tB3761.DT.BaseHexMessage == null || tB3761.BaseHexMessage.HexMessageString == null) { _logger.LogError("376.1协议解析AFN失败"); return; } - // 登录心跳已做了处理,故需要忽略登录和心跳帧 - if (tB3761.DT.Fn == (int)FN.登录 || tB3761.DT.Fn == (int)FN.心跳) - return; //TODO:根据AFN进行分流推送到kafka string topicName = string.Format(ProtocolConst.AFNTopicNameFormat, tB3761.AFN_FC.AFN.ToString().PadLeft(2, '0')); tB3761.MessageId = Guid.NewGuid().ToString(); + tB3761.ReceivedTime = DateTime.Now; MessageProtocolAnalysis messageReceivedAnalysis = new MessageProtocolAnalysis() { ClientId = tcpSessionClient.Id, @@ -123,7 +123,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 MessageHexString = tB3761.BaseHexMessage.HexMessageString!, DeviceNo = tB3761.A.Code!, MessageId = tB3761.MessageId, - ReceivedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), + ReceivedTime = tB3761.ReceivedTime.ToString("yyyy-MM-dd HH:mm:ss"), Data = tB3761 }; @@ -151,24 +151,25 @@ namespace JiShe.CollectBus.Protocol.T37612012 { string oldClientId = $"{client.Id}"; await client.ResetIdAsync(code); - var deviceInfoList = await _deviceRepository.GetListAsync(a => a.Number == code); - if (deviceInfoList != null && deviceInfoList.Count > 1) - { - //todo 推送集中器编号重复预警 - _logger.LogError($"集中器编号:{code},存在多个集中器,请检查集中器编号是否重复"); - return; - } + //var deviceInfoList = await _deviceRepository.GetListAsync(a => a.Number == code); + //if (deviceInfoList != null && deviceInfoList.Count > 1) + //{ + // //todo 推送集中器编号重复预警 + // _logger.LogError($"集中器编号:{code},存在多个集中器,请检查集中器编号是否重复"); + // return; + //} + + //var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code); + //if (entity == null) + //{ + // await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online)); + //} + //else + //{ + // entity.UpdateByLoginAndHeartbeat(oldClientId); + // await _deviceRepository.UpdateAsync(entity); + //} - var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code); - if (entity == null) - { - await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online)); - } - else - { - entity.UpdateByLoginAndHeartbeat(oldClientId); - await _deviceRepository.UpdateAsync(entity); - } var messageReceivedLoginEvent = new MessageReceivedLogin { @@ -178,9 +179,10 @@ namespace JiShe.CollectBus.Protocol.T37612012 MessageHexString = messageReceived, DeviceNo = code, MessageId = Guid.NewGuid().ToString(), - ReceivedTime=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ReceivedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; - await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginReceivedEventName, messageReceivedLoginEvent); + //await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginReceivedEventName, messageReceivedLoginEvent); + var reqParam = new ReqParameter2 { AFN = AFN.确认或否认, @@ -210,8 +212,8 @@ namespace JiShe.CollectBus.Protocol.T37612012 if (_tcpService.ClientExists(issuedEventMessage.ClientId)) { await _tcpService.SendAsync(issuedEventMessage.ClientId, issuedEventMessage.Message); - _logger.LogInformation($"集中器地址{issuedEventMessage.ClientId} 登录回复下发内容:{Convert.ToHexString(bytes)}"); - await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginIssuedEventName, issuedEventMessage); + _logger.LogWarning($"集中器地址{issuedEventMessage.ClientId} 登录回复下发内容:{Convert.ToHexString(bytes)}"); + // await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginIssuedEventName, issuedEventMessage); } } @@ -227,34 +229,34 @@ namespace JiShe.CollectBus.Protocol.T37612012 { string clientId = code; - string oldClientId = $"{client.Id}"; - var deviceInfoList = await _deviceRepository.GetListAsync(a => a.Number == code); - if (deviceInfoList != null && deviceInfoList.Count > 1) - { - //todo 推送集中器编号重复预警 - _logger.LogError($"集中器编号:{code},存在多个集中器,请检查集中器编号是否重复"); - return; - } + //string oldClientId = $"{client.Id}"; + //var deviceInfoList = await _deviceRepository.GetListAsync(a => a.Number == code); + //if (deviceInfoList != null && deviceInfoList.Count > 1) + //{ + // //todo 推送集中器编号重复预警 + // _logger.LogError($"集中器编号:{code},存在多个集中器,请检查集中器编号是否重复"); + // return; + //} - var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code); - if (entity == null) //没有登录帧的设备,只有心跳帧 - { + //var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code); + //if (entity == null) //没有登录帧的设备,只有心跳帧 + //{ await client.ResetIdAsync(clientId); - await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online)); - } - else - { - if (clientId != oldClientId) - { - entity.UpdateByLoginAndHeartbeat(oldClientId); - } - else - { - entity.UpdateByLoginAndHeartbeat(); - } + //await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online)); + //} + //else + //{ + // if (clientId != oldClientId) + // { + // entity.UpdateByLoginAndHeartbeat(oldClientId); + // } + // else + // { + // entity.UpdateByLoginAndHeartbeat(); + // } - await _deviceRepository.UpdateAsync(entity); - } + // await _deviceRepository.UpdateAsync(entity); + //} var messageReceivedHeartbeatEvent = new MessageReceivedHeartbeat { @@ -266,8 +268,8 @@ namespace JiShe.CollectBus.Protocol.T37612012 MessageId = Guid.NewGuid().ToString(), ReceivedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; - await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatReceivedEventName, messageReceivedHeartbeatEvent); - + // await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatReceivedEventName, messageReceivedHeartbeatEvent); + var reqParam = new ReqParameter2() { AFN = AFN.确认或否认, @@ -286,7 +288,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 Fn = 1 }; var bytes = Build3761SendData.BuildSendCommandBytes(reqParam); - + IssuedEventMessage issuedEventMessage = new IssuedEventMessage { ClientId = messageReceivedHeartbeatEvent.ClientId, @@ -299,12 +301,12 @@ namespace JiShe.CollectBus.Protocol.T37612012 { await _tcpService.SendAsync(issuedEventMessage.ClientId, bytes); _logger.LogWarning($"集中器地址{issuedEventMessage.ClientId} 心跳回复下发内容:{Convert.ToHexString(bytes)}"); - await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatIssuedEventName, issuedEventMessage); + // await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatIssuedEventName, issuedEventMessage); } - + } - + /// /// 组装报文 /// @@ -390,13 +392,14 @@ namespace JiShe.CollectBus.Protocol.T37612012 } else { + BaseHexMessage baseHexMessage = new BaseHexMessage + { + HexMessageList = hexStringList + }; + baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); TB3761 tB3761 = new TB3761 { - BaseHexMessage = new BaseHexMessage - { - HexMessageString = messageReceived, - HexMessageList = hexStringList - }, + BaseHexMessage=baseHexMessage, C = Analysis_C(hexStringList), A = Analysis_A(hexStringList), AFN_FC = Analysis_AFN_FC(hexStringList), @@ -430,9 +433,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 { HexMessageList = hexStringList.GetRange(6, 1) // 控制域 1字节 }; - baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); - if (baseHexMessage.HexMessageList.Count == 0) - return null; + baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList); string binStr = baseHexMessage.HexMessageString.HexTo4BinZero(); c = new C { @@ -470,7 +471,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 { HexMessageList = hexStringList.GetRange(7, 5) // 地址域 5个字节 }; - baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList); a = new A { BaseHexMessage = baseHexMessage, @@ -507,7 +508,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 { HexMessageList = hexAList.GetRange(4, 1) // 站地址和组地址标志A3 1个字节 }; - baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList); var binStr = baseHexMessage.HexMessageString.HexTo4BinZero(); a3 = new A3 { @@ -534,14 +535,14 @@ namespace JiShe.CollectBus.Protocol.T37612012 AFN_FC aFN_FC = new AFN_FC(); try { - if (hexStringList.Count == 0) + if (hexStringList.Count > 12) { BaseHexMessage baseHexMessage = new BaseHexMessage { HexMessageList = hexStringList.GetRange(12, 1) //AFN功能码 1个字节 }; - baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList); aFN_FC = new AFN_FC { @@ -568,16 +569,17 @@ namespace JiShe.CollectBus.Protocol.T37612012 SEQ seq = new SEQ(); try { - if (hexStringList.Count != 0) + if (hexStringList.Count>13) { BaseHexMessage baseHexMessage = new BaseHexMessage { HexMessageList = hexStringList.GetRange(13, 1) //帧序列域 SEQ 1个字节 }; - baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList); var binStr = baseHexMessage.HexMessageString.HexTo4BinZero(); seq = new SEQ { + BaseHexMessage= baseHexMessage, PSEQ = binStr.Substring(binStr.Length - 4, 4).BinToDec(), CON = binStr.Substring(3, 1).BinToDec(), FIN = binStr.Substring(2, 1).BinToDec(), @@ -603,13 +605,13 @@ namespace JiShe.CollectBus.Protocol.T37612012 UnitData unitData = new UnitData(); try { - if (hexStringList.Count != 0) + if (hexStringList.Count>14) { unitData = new UnitData { HexMessageList = hexStringList.GetRange(14, hexStringList.Count - 14 - 2) //总数字节数-固定长度报文头-控制域C-地址域A-校验和CS-结束字符(16H) }; - unitData.HexMessageString = string.Join("", unitData.HexMessageList); + unitData.HexMessageString = string.Join(" ", unitData.HexMessageList); } } catch (Exception ex) @@ -628,13 +630,13 @@ namespace JiShe.CollectBus.Protocol.T37612012 DA da = new DA(); try { - if (hexStringList.Count != 0) + if (hexStringList.Count > 14) { BaseHexMessage baseHexMessage = new BaseHexMessage { HexMessageList = hexStringList.GetRange(14, 2) //信息点DA Pn 2个字节 }; - baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList); var da1 = baseHexMessage.HexMessageList[0]; var da2 = baseHexMessage.HexMessageList[1]; da = new DA() @@ -660,13 +662,13 @@ namespace JiShe.CollectBus.Protocol.T37612012 DT dt = new DT(); try { - if (hexStringList.Count != 0) + if (hexStringList.Count > 16) { BaseHexMessage baseHexMessage = new BaseHexMessage { HexMessageList = hexStringList.GetRange(16, 2) //信息类DT Fn 2个字节 }; - baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList); var dt1 = baseHexMessage.HexMessageList[0]; var dt2 = baseHexMessage.HexMessageList[1]; dt = new DT() @@ -703,6 +705,33 @@ namespace JiShe.CollectBus.Protocol.T37612012 /// public static int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1")); + #region 下行 + /// + /// 生成二类项采集项时间数据单元 + /// + /// + /// + /// + public virtual List Generate_DataUnit(DataTimeMark timeMark) + { + List values = new List(); + values.AddRange(SplitDataTime(timeMark.DataTime));//数据时间 + if (timeMark.Density > 0) + values.Add(timeMark.Density.HexToDecStr().PadLeft(2, '0'));//密度 + if (timeMark.Point > 0) + values.Add(timeMark.Point.HexToDecStr().PadLeft(2, '0'));//数据点数 + return values; + } + + + private List SplitDataTime(DateTime dataTime) + { + //2101060815 + List values = new List() { $"{dataTime:yy}", $"{dataTime:MM}", $"{dataTime:dd}", $"{dataTime:HH}", $"{dataTime:mm}", }; + values.Reverse(); + return values; + } + #endregion #region 上行命令 @@ -831,7 +860,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 var a = $"{a1}{a2Dec.ToString().PadLeft(5, '0')}"; return a; } - + #endregion } } diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketBuilder.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketBuilder.cs index 2d20272..61dfbaa 100644 --- a/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketBuilder.cs +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketBuilder.cs @@ -47,7 +47,7 @@ namespace JiShe.CollectBus.Protocol.T6452007.SendData { var itemCodeArr = request.ItemCode.Split('_'); var c_data = itemCodeArr[0]; - var n_data = itemCodeArr[1]; + var n_data = itemCodeArr[2]; string password = request.Password; string pwdLevel = "02"; @@ -78,7 +78,7 @@ namespace JiShe.CollectBus.Protocol.T6452007.SendData { var itemCodeArr = request.ItemCode.Split('_'); var c_data = itemCodeArr[0]; - var n_data = itemCodeArr[1]; + var n_data = itemCodeArr[2]; string password = request.Password; if (!string.IsNullOrWhiteSpace(password) && password.Contains("|")) @@ -98,6 +98,29 @@ namespace JiShe.CollectBus.Protocol.T6452007.SendData var dataList = Build645SendData.Build645SendCommand(request.MeterAddress, c_data, dataUnit); return new Telemetry6452007PacketResponse() { Data = dataList }; } - #endregion + #endregion + + #region 读数据 + + /// + /// 变量数据标识编码处理 + /// + /// + /// + public static Telemetry6452007PacketResponse C11_02_Send(Telemetry6452007PacketRequest request) + { + var itemCodeArr = request.ItemCode.Split('_');//11_02_80_00_02 + var c_data = itemCodeArr[0]; + var DI3 = itemCodeArr[1]; + var DI2 = itemCodeArr[2]; + var DI1 = itemCodeArr[3]; + var DI0 = itemCodeArr[4]; + + var dataUnit = new List() { DI3, DI2, DI1, DI0 }; + + var dataList = Build645SendData.Build645SendCommand(request.MeterAddress, c_data, dataUnit); + return new Telemetry6452007PacketResponse() { Data = dataList }; + } + #endregion } } diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketRequest.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketRequest.cs index c367206..b819b91 100644 --- a/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketRequest.cs +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketRequest.cs @@ -1,23 +1,12 @@ -namespace JiShe.CollectBus.Protocol.T6452007.SendData +using JiShe.CollectBus.Protocol.Models; + +namespace JiShe.CollectBus.Protocol.T6452007.SendData { /// /// 构建645报文参数 /// - public class Telemetry6452007PacketRequest + public class Telemetry6452007PacketRequest: SubProtocolBuildRequest { - /// - /// 表地址 - /// - public required string MeterAddress { get; set; } - - /// - /// 密码 - /// - public required string Password { get; set; } - - /// - /// 操作码 - /// - public required string ItemCode { get; set; } + } } diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/T6452007ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/T6452007ProtocolPlugin.cs index 7e3b620..98b1e7f 100644 --- a/protocols/JiShe.CollectBus.Protocol.T6452007/T6452007ProtocolPlugin.cs +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/T6452007ProtocolPlugin.cs @@ -93,7 +93,9 @@ namespace JiShe.CollectBus.Protocol.T6452007 //数据转发场景 10H_F1 if (request.ItemCode == T37612012PacketItemCodeConst.AFN10HFN01H && request.SubProtocolRequest != null && string.IsNullOrWhiteSpace(request.SubProtocolRequest.ItemCode) == false) { - var t645PacketHandlerName = $"C{request.SubProtocolRequest.ItemCode}_Send"; + var subItemCodeArr = request.SubProtocolRequest.ItemCode.Split("_"); + var t645PacketHandlerName = $"C{subItemCodeArr[0]}_{subItemCodeArr[1]}_Send";//C1C_01_Send + Telemetry6452007PacketResponse t645PacketResponse = null; if (T645ControlHandlers != null && T645ControlHandlers.TryGetValue(t645PacketHandlerName @@ -113,6 +115,11 @@ namespace JiShe.CollectBus.Protocol.T6452007 } } + if (aFNStr == "0D")//二类数据 + { + dataUnit = Generate_DataUnit(request.DataTimeMark); + } + string afnMethonCode = $"AFN{aFNStr}_Fn_Send"; if (base.T3761AFNHandlers != null && base.T3761AFNHandlers.TryGetValue(afnMethonCode , out var handler)) @@ -122,6 +129,7 @@ namespace JiShe.CollectBus.Protocol.T6452007 FocusAddress = request.FocusAddress, Fn = fn, Pn = request.Pn, + SubRequest = request.SubProtocolRequest, DataUnit = dataUnit, }); } @@ -131,139 +139,10 @@ namespace JiShe.CollectBus.Protocol.T6452007 return new ProtocolBuildResponse(); } - var result = builderResponse.Adapt(); + var result = builderResponse.Adapt(); result.IsSuccess = true; return await Task.FromResult(result); - } - - - #region 上行命令 - - //68 - //32 00 - //32 00 - //68 - //C9 1100'1001. 控制域C。 - // D7=1, (终端发送)上行方向。 - // D6=1, 此帧来自启动站。 - // D5=0, (上行方向)要求访问位。表示终端无事件数据等待访问。 - // D4=0, 保留 - // D3~D0=9, 功能码。链路测试 - - //20 32 行政区划码 - //90 26 终端地址 - //00 主站地址和组地址标志。终端为单地址。 //3220 09 87 2 - // 终端启动的发送帧的 MSA 应为 0, 其主站响应帧的 MSA 也应为 0. - //02 应用层功能码。AFN=2, 链路接口检测 - //70 0111'0000. 帧序列域。无时间标签、单帧、需要确认。 - //00 00 信息点。DA1和DA2全为“0”时,表示终端信息点。 - //01 00 信息类。F1, 登录。 - //44 帧尾,包含用户区数据校验和 - //16 帧结束标志 - - /// - /// 解析上行命令 - /// - /// - /// - public CommandReulst? AnalysisCmd(string cmd) - { - CommandReulst? commandReulst = null; - var hexStringList = cmd.StringToPairs(); - - if (hexStringList.Count < hearderLen) - { - return commandReulst; - } - //验证起始字符 - if (!hexStringList[0].IsStartStr() || !hexStringList[5].IsStartStr()) - { - return commandReulst; - } - - var lenHexStr = $"{hexStringList[2]}{hexStringList[1]}"; - var lenBin = lenHexStr.HexToBin(); - var len = lenBin.Remove(lenBin.Length - 2).BinToDec(); - //验证长度 - if (hexStringList.Count - 2 != hearderLen + len) - return commandReulst; - - var userDataIndex = hearderLen; - var c = hexStringList[userDataIndex];//控制域 1字节 - userDataIndex += 1; - - var aHexList = hexStringList.Skip(userDataIndex).Take(5).ToList();//地址域 5字节 - var a = AnalysisA(aHexList); - var a3Bin = aHexList[4].HexToBin().PadLeft(8, '0'); - var mSA = a3Bin.Substring(0, 7).BinToDec(); - userDataIndex += 5; - - var aFN = (AFN)hexStringList[userDataIndex].HexToDec();//1字节 - userDataIndex += 1; - - var seq = hexStringList[userDataIndex].HexToBin().PadLeft(8, '0'); - var tpV = (TpV)Convert.ToInt32(seq.Substring(0, 1)); - var fIRFIN = (FIRFIN)Convert.ToInt32(seq.Substring(1, 2)); - var cON = (CON)Convert.ToInt32(seq.Substring(3, 1)); - var prseqBin = seq.Substring(4, 4); - userDataIndex += 1; - - // (DA2 - 1) * 8 + DA1 = pn - var da1Bin = hexStringList[userDataIndex].HexToBin(); - var da1 = da1Bin == "0" ? 0 : da1Bin.Length; - userDataIndex += 1; - var da2 = hexStringList[userDataIndex].HexToDec(); - var pn = da2 == 0 ? 0 : (da2 - 1) * 8 + da1; - userDataIndex += 1; - //(DT2*8)+DT1=fn - var dt1Bin = hexStringList[userDataIndex].HexToBin(); - var dt1 = dt1Bin != "0" ? dt1Bin.Length : 0; - userDataIndex += 1; - var dt2 = hexStringList[userDataIndex].HexToDec(); - var fn = dt2 * 8 + dt1; - userDataIndex += 1; - - //数据单元 - var datas = hexStringList.Skip(userDataIndex).Take(len + hearderLen - userDataIndex).ToList(); - - //EC - //Tp - commandReulst = new CommandReulst() - { - A = a, - MSA = mSA, - AFN = aFN, - Seq = new Seq() - { - TpV = tpV, - FIRFIN = fIRFIN, - CON = cON, - PRSEQ = prseqBin.BinToDec(), - }, - CmdLength = len, - Pn = pn, - Fn = fn, - HexDatas = datas - }; - - return commandReulst; - } - - /// - /// 解析地址 - /// - /// - /// - private string AnalysisA(List aHexList) - { - var a1 = aHexList[1] + aHexList[0]; - var a2 = aHexList[3] + aHexList[2]; - var a2Dec = a2.HexToDec(); - var a3 = aHexList[4]; - var a = $"{a1}{a2Dec.ToString().PadLeft(5, '0')}"; - return a; - } - #endregion + } } } diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisStrategyContext.cs b/protocols/JiShe.CollectBus.Protocol/AnalysisStrategyContext.cs index cb66bcf..2485f2b 100644 --- a/protocols/JiShe.CollectBus.Protocol/AnalysisStrategyContext.cs +++ b/protocols/JiShe.CollectBus.Protocol/AnalysisStrategyContext.cs @@ -12,17 +12,16 @@ namespace JiShe.CollectBus.Protocol /// 执行策略 /// /// - /// /// /// + /// /// - public Task ExecuteAsync(string type, TInput input) + public async Task ExecuteAsync(string type, TInput input,Action? result=null) { - var factory = _provider.GetRequiredService>(); - var strategy = (IAnalysisStrategy)factory(type, typeof(TInput), typeof(TResult)); - return strategy.ExecuteAsync(input); + var factory = _provider.GetRequiredService>(); + var strategy = (IAnalysisStrategy)factory(type, typeof(TInput)); + return await strategy.ExecuteAsync(input, result); } + } - - } diff --git a/protocols/JiShe.CollectBus.Protocol/Interfaces/IAnalysisStrategy.cs b/protocols/JiShe.CollectBus.Protocol/Interfaces/IAnalysisStrategy.cs index 0066c19..7be9cbc 100644 --- a/protocols/JiShe.CollectBus.Protocol/Interfaces/IAnalysisStrategy.cs +++ b/protocols/JiShe.CollectBus.Protocol/Interfaces/IAnalysisStrategy.cs @@ -1,7 +1,9 @@ -namespace JiShe.CollectBus.Protocol.Interfaces +using JiShe.CollectBus.Protocol.Dto; + +namespace JiShe.CollectBus.Protocol.Interfaces { - public interface IAnalysisStrategy + public interface IAnalysisStrategy { - Task ExecuteAsync(TInput input); + Task ExecuteAsync(TInput input, Action? result = null); } } diff --git a/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj b/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj index f75b5dd..7fead27 100644 --- a/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj +++ b/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj @@ -19,8 +19,7 @@ - - + diff --git a/protocols/JiShe.CollectBus.Protocol/Models/DataTimeMark.cs b/protocols/JiShe.CollectBus.Protocol/Models/DataTimeMark.cs new file mode 100644 index 0000000..2efbaad --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Models/DataTimeMark.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol +{ + /// + /// 数据时间标记 + /// + public class DataTimeMark + { + /// + /// 数据时间 + /// + public DateTime DataTime { get; set;} + + /// + /// 数据点数 + /// + public int Point { get; set; } + + /// + /// 冻结密度(-1、采集项本身无密度位,0、无,1、15分钟,2、30分钟,3、60分钟,245、5分钟,255、1分钟) + /// + public int Density { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildRequest.cs b/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildRequest.cs index 9936dc6..e287547 100644 --- a/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildRequest.cs +++ b/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildRequest.cs @@ -1,4 +1,6 @@ -namespace JiShe.CollectBus.Protocol.Models +using JiShe.CollectBus.Common.BuildSendDatas; + +namespace JiShe.CollectBus.Protocol.Models { /// /// 报文构建参数 @@ -20,6 +22,11 @@ /// public required string ItemCode { get; set; } + /// + /// 任务时间 + /// + public DataTimeMark DataTimeMark { get; set; } + /// /// 集中器转发协议构建构建参数 /// diff --git a/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildResponse.cs b/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildResponse.cs index b371460..16243a8 100644 --- a/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildResponse.cs +++ b/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildResponse.cs @@ -19,7 +19,12 @@ /// 帧功能域FN /// public int Fn { get; set; } - + + /// + /// 抄读计量点,也就是终端电表对应端口 + /// + public int Pn { get; set; } + /// /// 帧序列域SEQ /// @@ -30,6 +35,11 @@ /// public int MSA { get; set; } + /// + /// 任务时间戳 + /// + public long TimeStamp { get; set; } + /// /// 报文体 /// diff --git a/protocols/JiShe.CollectBus.Protocol/Models/SubProtocolBuildRequest.cs b/protocols/JiShe.CollectBus.Protocol/Models/SubProtocolBuildRequest.cs index 09a5c55..15526e2 100644 --- a/protocols/JiShe.CollectBus.Protocol/Models/SubProtocolBuildRequest.cs +++ b/protocols/JiShe.CollectBus.Protocol/Models/SubProtocolBuildRequest.cs @@ -10,6 +10,16 @@ /// public required string MeterAddress { get; set; } + /// + /// 波特率 default(2400) + /// + public int Baudrate { get; set; } + + /// + /// 计量端口 + /// + public int MeteringPort { get; set; } + /// /// 密码 /// diff --git a/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs b/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs index 0368151..d51b7be 100644 --- a/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs +++ b/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs @@ -1,10 +1,12 @@ using System.Text.RegularExpressions; +using JiShe.CollectBus.Common; using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.FreeRedis; using JiShe.CollectBus.IotSystems.Protocols; using JiShe.CollectBus.Protocol.Interfaces; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Volo.Abp; using Volo.Abp.DependencyInjection; @@ -15,12 +17,14 @@ namespace JiShe.CollectBus.Protocol.Services private readonly IFreeRedisProvider _freeRedisProvider; private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; + private readonly ServerApplicationOptions _serverApplicationOptions; - public ProtocolService(IFreeRedisProvider freeRedisProvider, IServiceProvider serviceProvider, ILogger logger) + public ProtocolService(IFreeRedisProvider freeRedisProvider, IServiceProvider serviceProvider, ILogger logger,IOptions serverApplicationOptions) { _freeRedisProvider = freeRedisProvider; _serviceProvider = serviceProvider; _logger= logger; + _serverApplicationOptions = serverApplicationOptions.Value; } /// @@ -36,7 +40,7 @@ namespace JiShe.CollectBus.Protocol.Services var keyValuePair = protocols.FirstOrDefault(a => ContainsExactPartRegex(deviceCode, a.Value.RegularExpression)); if (!keyValuePair.Key.IsNullOrWhiteSpace() || keyValuePair.Value != null) return keyValuePair.Value; if (isSpecial) throw new UserFriendlyException("The device protocol plugin does not exist!", ExceptionCode.NotFound); - var hasStandardProtocolPlugin = protocols.TryGetValue("StandardProtocolPlugin", out var protocolInfo); + var hasStandardProtocolPlugin = protocols.TryGetValue(_serverApplicationOptions.DefaultProtocolPlugin, out var protocolInfo); if (!hasStandardProtocolPlugin) throw new UserFriendlyException("Standard protocol plugin does not exist!", ExceptionCode.NotFound); return protocolInfo; } @@ -51,6 +55,7 @@ namespace JiShe.CollectBus.Protocol.Services { try { + //todo 必须添加本地内存缓存,然后是否需走个redis订阅???? ProtocolInfo protocolInfo= await FirstOrDefaultByDeviceAsync(deviceCode, isSpecial); if(protocolInfo==null) return null; diff --git a/services/JiShe.CollectBus.Application.Contracts/DataChannels/IDataChannelManageService.cs b/services/JiShe.CollectBus.Application.Contracts/DataChannels/IDataChannelManageService.cs new file mode 100644 index 0000000..a126910 --- /dev/null +++ b/services/JiShe.CollectBus.Application.Contracts/DataChannels/IDataChannelManageService.cs @@ -0,0 +1,33 @@ +using JiShe.CollectBus.IotSystems.MeterReadingRecords; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Channels; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.DataChannels +{ + /// + /// 数据通道管理服务 + /// + public interface IDataChannelManageService + { + #region 下发任务通道 + + /// + /// 定时任务数据通道写入 + /// + /// + Task ScheduledMeterTaskWriterAsync(ChannelWriter>> _telemetryPacketInfoWriter, ValueTuple> dataItems); + + /// + /// 定时任务数据入库和Kafka推送通道 + /// + /// + Task ScheduledMeterTaskReadingAsync(ChannelReader>> _telemetryPacketInfoReader ); + #endregion + } +} diff --git a/services/JiShe.CollectBus.Application.Contracts/RedisDataCache/IRedisDataCacheService.cs b/services/JiShe.CollectBus.Application.Contracts/RedisDataCache/IRedisDataCacheService.cs index eb400c7..5ed2924 100644 --- a/services/JiShe.CollectBus.Application.Contracts/RedisDataCache/IRedisDataCacheService.cs +++ b/services/JiShe.CollectBus.Application.Contracts/RedisDataCache/IRedisDataCacheService.cs @@ -1,4 +1,5 @@ using JiShe.CollectBus.Common.Models; +using JiShe.CollectBus.IotSystems.Ammeters; using System; using System.Collections.Generic; using System.Linq; @@ -27,20 +28,20 @@ namespace JiShe.CollectBus.Application.Contracts string redisZSetScoresIndexCacheKey, T data) where T : DeviceCacheBasicModel; + /// /// 批量添加数据 /// /// - /// 主数据存储Hash缓存Key /// Set索引缓存Key - /// ZSET索引缓存Key + /// hash缓存Key /// 待缓存数据集合 /// Task BatchInsertDataAsync( - string redisHashCacheKey, string redisSetIndexCacheKey, - string redisZSetScoresIndexCacheKey, - IEnumerable items) where T : DeviceCacheBasicModel; + string redisDeviceInfoHashCacheKey, + Dictionary> items) where T : DeviceCacheBasicModel; + /// /// 删除缓存信息 @@ -90,26 +91,48 @@ namespace JiShe.CollectBus.Application.Contracts string redisZSetScoresIndexCacheKey, T newData) where T : DeviceCacheBasicModel; - ///// - ///// 通过集中器与表计信息排序索引获取数据 - ///// - ///// - ///// 主数据存储Hash缓存Key - ///// ZSET索引缓存Key - ///// 分页尺寸 - ///// 最后一个索引 - ///// 最后一个唯一标识 - ///// 排序方式 - ///// - //Task> GetPagedData( - //string redisHashCacheKey, - //string redisZSetScoresIndexCacheKey, - //IEnumerable focusIds, - //int pageSize = 10, - //decimal? lastScore = null, - //string lastMember = null, - //bool descending = true) - //where T : DeviceCacheBasicModel; + /// + /// 通过集中器与表计信息排序索引获取数据 + /// + /// + /// 主数据存储Hash缓存Key + /// ZSET索引缓存Key + /// 分页尺寸 + /// 最后一个索引 + /// 最后一个唯一标识 + /// 排序方式 + /// + Task> GetPagedData( + string redisHashCacheKey, + string redisZSetScoresIndexCacheKey, + IEnumerable focusIds, + int pageSize = 10, + decimal? lastScore = null, + string lastMember = null, + bool descending = true) + where T : DeviceCacheBasicModel; + + /// + /// 通过集中器与表计信息排序索引获取数据 + /// + /// + /// 主数据存储Hash缓存Key + /// ZSET索引缓存Key + /// ZSET索引的原始数据,例如集中地址和点位的组合 + /// 分页尺寸 + /// 最后一个索引 + /// 最后一个唯一标识 + /// 排序方式 + /// + Task> GetSingleData( + string redisHashCacheKey, + string redisZSetScoresIndexCacheKey, + string scoreValueRawData, + int pageSize = 10, + decimal? lastScore = null, + string lastMember = null, + bool descending = true) + where T : DeviceCacheBasicModel; /// @@ -132,45 +155,24 @@ namespace JiShe.CollectBus.Application.Contracts bool descending = true) where T : DeviceCacheBasicModel; - - ///// - ///// 游标分页查询 - ///// - ///// 排序索引ZSET缓存Key - ///// 分页数量 - ///// 开始索引 - ///// 开始唯一标识 - ///// 排序方式 - ///// - //Task<(List Members, bool HasNext)> GetPagedMembers( - // string redisZSetScoresIndexCacheKey, - // int pageSize, - // decimal? startScore, - // string excludeMember, - // bool descending); - - ///// - ///// 批量获取指定分页的数据 - ///// - ///// - ///// Hash表缓存key - ///// Hash表字段集合 - ///// - //Task> BatchGetData( - // string redisHashCacheKey, - // IEnumerable members) - // where T : DeviceCacheBasicModel; - - ///// - ///// 获取下一页游标 - ///// - ///// 排序索引ZSET缓存Key - ///// 最后一个唯一标识 - ///// 排序方式 - ///// - //Task GetNextScore( - // string redisZSetScoresIndexCacheKey, - // string lastMember, - // bool descending); + /// + /// 通过ZSET索引获取数据,支持10万级别数据处理,控制在13秒以内。 + /// + /// + /// ZSET索引缓存Key + /// 主数据存储Hash缓存Key + /// 分页尺寸 + /// 最后一个索引 + /// 最后一个唯一标识 + /// 排序方式 + /// + Task> GetAllPagedData2( + string redisCacheDeviceGroupSetIndexKey, + string redisCacheDeviceInfoHashKey, + int pageSize = 1000, + decimal? lastScore = null, + string lastMember = null, + bool descending = true) + where T : DeviceCacheBasicModel; } } diff --git a/services/JiShe.CollectBus.Application.Contracts/Samples/SampleDto.cs b/services/JiShe.CollectBus.Application.Contracts/Samples/SampleDto.cs index 12f46d1..c32d892 100644 --- a/services/JiShe.CollectBus.Application.Contracts/Samples/SampleDto.cs +++ b/services/JiShe.CollectBus.Application.Contracts/Samples/SampleDto.cs @@ -14,3 +14,12 @@ public class SampleDto2 { public int Value { get; set; } } + + +public class KafkaSendDto +{ + public string Address { get; set; } + + public string Frame { get; set; } + +} diff --git a/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs index 5650a57..b82feab 100644 --- a/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs @@ -4,6 +4,8 @@ using System.Threading.Tasks; using JiShe.CollectBus.Ammeters; using JiShe.CollectBus.GatherItem; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.IotSystems.Devices; +using JiShe.CollectBus.IotSystems.MeterReadingRecords; using JiShe.CollectBus.IotSystems.Watermeter; using Volo.Abp.Application.Services; @@ -33,7 +35,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// /// 采集端Code /// - Task> GetAmmeterInfoList(string gatherCode = ""); + Task> GetAmmeterInfoList(string gatherCode = ""); /// /// 初始化电表缓存数据 @@ -71,14 +73,37 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 电表自动阀控 /// /// - Task AmmeterScheduledAutoValveControl(); + Task> AmmeterScheduledAutoValveControl(); /// /// 电表自动校时 /// /// 采集频率 + /// 电表信息 + /// 集中器所在分组 + /// 采集频率对应的时间戳 /// - Task AmmeterScheduledAutomaticVerificationTime(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps); + Task> AmmeterScheduledAutomaticVerificationTime(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); + + /// + /// 日冻结抄读 + /// + /// 采集频率 + /// 电表信息 + /// 集中器所在分组 + /// 采集频率对应的时间戳 + /// + Task> AmmeterScheduledGetAutomaticDayFreezeData(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); + + /// + /// 月冻结数据抄读 + /// + /// 采集频率 + /// 电表信息 + /// 集中器所在分组 + /// 采集频率对应的时间戳 + /// + Task> AmmeterScheduledGetAutomaticMonthFreezeData(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); #endregion @@ -88,7 +113,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// /// 采集端Code /// - Task> GetWatermeterInfoList(string gatherCode = ""); + Task> GetWatermeterInfoList(string gatherCode = ""); /// /// 初始化水表缓存数据,只获取任务数据下发,不构建任务 @@ -101,7 +126,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 水表数据采集 /// /// - Task WatermeterScheduledMeterAutoReading(); + Task WatermeterScheduledMeterAutoReadding(); #endregion @@ -115,7 +140,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - Task ConcentratorScheduledAutomaticGetTerminalVersion(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps); + Task> ConcentratorScheduledAutomaticGetTerminalVersion(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); /// /// 自动获取远程通信模块(SIM)版本信息 @@ -125,7 +150,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - Task ConcentratorScheduledAutomaticGetTelematicsModule(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps); + Task> ConcentratorScheduledAutomaticGetTelematicsModule(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); #endregion diff --git a/services/JiShe.CollectBus.Application.Contracts/Subscribers/IWorkerSubscriberAppService.cs b/services/JiShe.CollectBus.Application.Contracts/Subscribers/IWorkerSubscriberAppService.cs index 950f4d9..e899ce4 100644 --- a/services/JiShe.CollectBus.Application.Contracts/Subscribers/IWorkerSubscriberAppService.cs +++ b/services/JiShe.CollectBus.Application.Contracts/Subscribers/IWorkerSubscriberAppService.cs @@ -1,6 +1,8 @@ -using JiShe.CollectBus.IotSystems.MessageIssueds; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.IotSystems.MessageIssueds; using JiShe.CollectBus.IotSystems.MessageReceiveds; using JiShe.CollectBus.IotSystems.MeterReadingRecords; +using JiShe.CollectBus.Kafka.Attributes; using JiShe.CollectBus.Kafka.Internal; using System.Collections.Generic; using System.Threading.Tasks; @@ -17,37 +19,83 @@ namespace JiShe.CollectBus.Subscribers #region 电表消息采集 /// - /// 1分钟采集电表数据下行消息消费订阅 + /// 一分钟定时抄读任务消息消费订阅 /// + /// /// - Task AmmeterScheduledMeterOneMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo issuedEventMessage); + Task AmmeterScheduledMeterOneMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo receivedMessage); /// /// 5分钟采集电表数据下行消息消费订阅 /// + /// /// - Task AmmeterScheduledMeterFiveMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo issuedEventMessage); + Task AmmeterScheduledMeterFiveMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo receivedMessage); /// /// 15分钟采集电表数据下行消息消费订阅 /// + /// /// - Task AmmeterScheduledMeterFifteenMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo issuedEventMessage); + Task AmmeterScheduledMeterFifteenMinuteReadingIssuedEvent(List receivedMessage); /// /// 电表自动阀控下行消息消费订阅 /// + /// /// - Task AmmeterScheduledAutoValveControl(MeterReadingTelemetryPacketInfo issuedEventMessage); + Task AmmeterScheduledAutoValveControl(List receivedMessage); + + /// + /// 其他采集数据下行消息主题,日冻结,月冻结、集中器版本号、SIM卡号、定时校时等下行消息消费订阅 + /// + /// + /// + Task AmmeterScheduledOther(List receivedMessage); + + /// + /// 电表手动阀控下行消息消费订阅 + /// + /// + /// + Task AmmeterScheduledManualValveControl(MeterReadingTelemetryPacketInfo receivedMessage); + + /// + /// 电表手动抄读下行消息消费订阅 + /// + /// + /// + Task AmmeterScheduledManualValveReading(MeterReadingTelemetryPacketInfo receivedMessage); #endregion #region 水表消息采集 /// - /// 1分钟采集水表数据下行消息消费订阅 + /// 水表数据下行消息消费订阅 /// + /// /// - Task WatermeterSubscriberWorkerAutoReadingIssuedEvent(MeterReadingTelemetryPacketInfo issuedEventMessage); - + Task WatermeterScheduledAutoReading(MeterReadingTelemetryPacketInfo receivedMessage); + + /// + /// 水表自动阀控下行消息消费订阅 + /// + /// + /// + Task WatermeterScheduleAutoValveControl(MeterReadingTelemetryPacketInfo receivedMessage); + + /// + /// 水表手动阀控下行消息消费订阅 + /// + /// + /// + Task WatermeterScheduleManualValveControl(MeterReadingTelemetryPacketInfo receivedMessage); + /// + /// 水表手动抄读下行消息消费订阅 + /// + /// + /// + Task WatermeterScheduleManualValveReading(MeterReadingTelemetryPacketInfo receivedMessage); + #endregion } } diff --git a/services/JiShe.CollectBus.Application/CollectBusAppService.cs b/services/JiShe.CollectBus.Application/CollectBusAppService.cs index 7c66b95..bd4a232 100644 --- a/services/JiShe.CollectBus.Application/CollectBusAppService.cs +++ b/services/JiShe.CollectBus.Application/CollectBusAppService.cs @@ -25,200 +25,5 @@ public abstract class CollectBusAppService : ApplicationService { LocalizationResource = typeof(CollectBusResource); ObjectMapperContext = typeof(CollectBusApplicationModule); - } - - /// - /// Lua脚本批量获取缓存的表计信息 - /// - /// 表信息数据对象 - /// 采集频率对应的缓存Key集合 - /// 系统类型 - /// 服务器标识 - /// 采集频率,1分钟、5分钟、15分钟 - /// 表计类型 - /// - protected async Task>> GetMeterRedisCacheDictionaryData(string[] redisKeys, string systemType, string serverTagName, string timeDensity, MeterTypeEnum meterType) where T : class - { - if (redisKeys == null || redisKeys.Length <= 0 || string.IsNullOrWhiteSpace(systemType) || string.IsNullOrWhiteSpace(serverTagName) || string.IsNullOrWhiteSpace(timeDensity)) - { - throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 获取缓存的表计信息失败,参数异常,-101"); - } - - var meterInfos = new Dictionary>(); - var luaScript = @" - local results = {} - for i, key in ipairs(KEYS) do - local data = redis.call('HGETALL', key) - results[i] = {key, data} - end - return results"; - - // 分页参数:每页处理10000个键 - int pageSize = 10000; - int totalPages = (int)Math.Ceiling(redisKeys.Length / (double)pageSize); - - for (int page = 0; page < totalPages; page++) - { - // 分页获取当前批次的键 - var batchKeys = redisKeys - .Skip(page * pageSize) - .Take(pageSize) - .ToArray(); - - // 执行Lua脚本获取当前批次数据 - var merterResult = await FreeRedisProvider.Instance.EvalAsync(luaScript, batchKeys); - if (merterResult == null) - { - throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 获取缓存的表计信息失败,第 {page + 1} 页数据未返回,-102"); - } - - // 解析当前批次的结果 - if (merterResult is object[] arr) - { - foreach (object[] item in arr) - { - string key = (string)item[0]; - object[] fieldsAndValues = (object[])item[1]; - var redisCacheKey = $"{string.Format(RedisConst.CacheMeterInfoHashKey, systemType, serverTagName, meterType, timeDensity)}"; - string focusAddress = key.Replace(redisCacheKey, ""); - - var meterHashs = new Dictionary(); - for (int i = 0; i < fieldsAndValues.Length; i += 2) - { - string meterId = (string)fieldsAndValues[i]; - string meterStr = (string)fieldsAndValues[i + 1]; - - T meterInfo = default!; - if (!string.IsNullOrWhiteSpace(meterStr)) - { - meterInfo = meterStr.Deserialize()!; - } - if (meterInfo != null) - { - meterHashs[meterId] = meterInfo; - } - else - { - throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 缓存表计数据异常,集中器 {key} 的表计 {meterId} 解析失败,-103"); - } - } - - // 合并到总结果,若存在重复key则覆盖 - if (meterInfos.ContainsKey(focusAddress)) - { - foreach (var kvp in meterHashs) - { - meterInfos[focusAddress][kvp.Key] = kvp.Value; - } - } - else - { - meterInfos[focusAddress] = meterHashs; - } - } - } - else - { - throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 第 {page + 1} 页数据解析失败,返回类型不符,-104"); - } - } - - return meterInfos; - } - - /// - /// Lua脚本批量获取缓存的表计信息 - /// - /// 表信息数据对象 - /// 采集频率对应的缓存Key集合 - /// 系统类型 - /// 服务器标识 - /// 采集频率,1分钟、5分钟、15分钟 - /// 表计类型 - /// - protected async Task> GetMeterRedisCacheListData(string[] redisKeys, string systemType, string serverTagName, string timeDensity, MeterTypeEnum meterType) where T : class - { - if (redisKeys == null || redisKeys.Length <= 0 || - string.IsNullOrWhiteSpace(systemType) || - string.IsNullOrWhiteSpace(serverTagName) || - string.IsNullOrWhiteSpace(timeDensity)) - { - throw new Exception($"{nameof(GetMeterRedisCacheListData)} 参数异常,-101"); - } - - var meterInfos = new List(); - var luaScript = @" - local results = {} - for i, key in ipairs(KEYS) do - local data = redis.call('HGETALL', key) - results[i] = {key, data} - end - return results"; - - // 分页参数:每页10000个键 - int pageSize = 10000; - int totalPages = (int)Math.Ceiling(redisKeys.Length / (double)pageSize); - - for (int page = 0; page < totalPages; page++) - { - // 分页获取当前批次键 - var batchKeys = redisKeys - .Skip(page * pageSize) - .Take(pageSize) - .ToArray(); - - // 执行Lua脚本获取当前页数据 - var merterResult = await FreeRedisProvider.Instance.EvalAsync(luaScript, batchKeys); - if (merterResult == null) - { - throw new Exception($"{nameof(GetMeterRedisCacheListData)} 第 {page + 1} 页数据未返回,-102"); - } - - // 解析当前页结果 - if (merterResult is object[] arr) - { - foreach (object[] item in arr) - { - string key = (string)item[0]; - object[] fieldsAndValues = (object[])item[1]; - var redisCacheKey = string.Format( - RedisConst.CacheMeterInfoHashKey, - systemType, - serverTagName, - meterType, - timeDensity - ); - string focusAddress = key.Replace(redisCacheKey, ""); - - for (int i = 0; i < fieldsAndValues.Length; i += 2) - { - string meterId = (string)fieldsAndValues[i]; - string meterStr = (string)fieldsAndValues[i + 1]; - - T meterInfo = default!; - if (!string.IsNullOrWhiteSpace(meterStr)) - { - meterInfo = meterStr.Deserialize()!; - } - if (meterInfo != null) - { - meterInfos.Add(meterInfo); - } - else - { - throw new Exception( - $"{nameof(GetMeterRedisCacheListData)} 表计 {meterId} 解析失败(页 {page + 1}),-103" - ); - } - } - } - } - else - { - throw new Exception($"{nameof(GetMeterRedisCacheListData)} 第 {page + 1} 页数据格式错误,-104"); - } - } - - return meterInfos; } } diff --git a/services/JiShe.CollectBus.Application/CollectBusApplicationModule.cs b/services/JiShe.CollectBus.Application/CollectBusApplicationModule.cs index ce2e5aa..69c986a 100644 --- a/services/JiShe.CollectBus.Application/CollectBusApplicationModule.cs +++ b/services/JiShe.CollectBus.Application/CollectBusApplicationModule.cs @@ -1,18 +1,22 @@ -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using Cassandra.Mapping; +using Cassandra.Mapping; using JiShe.CollectBus.Cassandra; +using JiShe.CollectBus.DataChannels; using JiShe.CollectBus.FreeRedis; using JiShe.CollectBus.FreeSql; using JiShe.CollectBus.Interceptors; using JiShe.CollectBus.IoTDB; +using JiShe.CollectBus.IotSystems.MeterReadingRecords; using JiShe.CollectBus.Kafka; using JiShe.CollectBus.Mappers; using JiShe.CollectBus.Protocol; -using JiShe.CollectBus.Protocol.Contracts; using JiShe.CollectBus.ScheduledMeterReading; using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Channels; +using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Application; using Volo.Abp.Autofac; @@ -66,12 +70,30 @@ public class CollectBusApplicationModule : AbpModule .ToList(); foreach (var type in types) await context.AddBackgroundWorkerAsync(type); - Task.Run(() => - { - //默认初始化表计信息 - var dbContext = context.ServiceProvider.GetRequiredService(); - dbContext.InitAmmeterCacheData(); - //await dbContext.InitWatermeterCacheData(); - }).ConfigureAwait(false); + //Task.Run(() => + //{ + // //默认初始化表计信息 + // var dbContext = context.ServiceProvider.GetRequiredService(); + // dbContext.InitAmmeterCacheData(); + // //await dbContext.InitWatermeterCacheData(); + //}).ConfigureAwait(false); + + //下发任务通道构建 + DataChannelManage.TaskDataChannel = Channel.CreateUnbounded>>(); + + + // 日志存储通道构建 + DataChannelManage.LogSaveChannel = Channel.CreateUnbounded(); + + // 日志刷新通道构建 + DataChannelManage.LogRefreshChannel = Channel.CreateUnbounded(); + + // 启动通道任务 + var _dataChannelManage = context.ServiceProvider.GetRequiredService(); + _ = _dataChannelManage.LogSaveAsync(DataChannelManage.LogSaveChannel.Reader); + + //默认初始化表计信息 + var dbContext = context.ServiceProvider.GetRequiredService(); + await dbContext.InitAmmeterCacheData(); } } \ No newline at end of file diff --git a/services/JiShe.CollectBus.Application/DataChannels/DataChannelManage.cs b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManage.cs new file mode 100644 index 0000000..6130a25 --- /dev/null +++ b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManage.cs @@ -0,0 +1,30 @@ +using JiShe.CollectBus.IotSystems.MeterReadingRecords; +using JiShe.CollectBus.Protocol.Dto; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Channels; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.DataChannels +{ + public static class DataChannelManage + { + /// + /// 下发任务通道 + /// + public static Channel>> TaskDataChannel; + + /// + /// 日志保存管道 + /// + public static Channel LogSaveChannel; + + /// + /// 日志刷新管道 + /// + public static Channel LogRefreshChannel; + + } +} diff --git a/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs new file mode 100644 index 0000000..58b5718 --- /dev/null +++ b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs @@ -0,0 +1,332 @@ +using Amazon.Runtime.Internal.Transform; +using DnsClient.Protocol; +using JiShe.CollectBus.Common; +using JiShe.CollectBus.Common.DeviceBalanceControl; +using JiShe.CollectBus.IoTDB.Context; +using JiShe.CollectBus.IoTDB.Interface; +using JiShe.CollectBus.IotSystems.LogRecord; +using JiShe.CollectBus.IotSystems.MeterReadingRecords; +using JiShe.CollectBus.Kafka.Internal; +using JiShe.CollectBus.Kafka.Producer; +using JiShe.CollectBus.Protocol.Dto; +using JiShe.CollectBus.Protocol.Models; +using JiShe.CollectBus.Repository.LogRecord; +using Mapster; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Channels; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace JiShe.CollectBus.DataChannels +{ + /// + /// 数据通道管理服务 + /// + public class DataChannelManageService : IDataChannelManageService, ITransientDependency + { + private readonly ILogger _logger; + private readonly IIoTDbProvider _dbProvider; + private readonly IProducerService _producerService; + private readonly KafkaOptionConfig _kafkaOptions; + private readonly ServerApplicationOptions _applicationOptions; + private readonly ILogRecordRepository _logRecordRepository; + + public DataChannelManageService( + ILogger logger, + IIoTDbProvider dbProvider, + IProducerService producerService, + IOptions kafkaOptions, + IOptions applicationOptions, + ILogRecordRepository logRecordRepository) + { + _logger = logger; + _dbProvider = dbProvider; + _producerService = producerService; + _kafkaOptions = kafkaOptions.Value; + _applicationOptions = applicationOptions.Value; + _logRecordRepository= logRecordRepository; + } + + /// + /// 定时任务数据通道写入 + /// + /// + public async Task ScheduledMeterTaskWriterAsync(ChannelWriter>> _telemetryPacketInfoWriter, ValueTuple> dataItems) + { + await _telemetryPacketInfoWriter.WriteAsync(dataItems); + } + /// + /// 定时任务数据入库和Kafka推送通道 + /// + public async Task ScheduledMeterTaskReadingAsync( + ChannelReader>> telemetryPacketInfoReader) + { + const int BatchSize = 50000; + const int EmptyWaitMilliseconds = 50; + var timeout = TimeSpan.FromMilliseconds(50); + var timer = Stopwatch.StartNew(); + long timeoutMilliseconds = 0; + var metadata = await _dbProvider.GetMetadata(); + var timeoutStopwatch = Stopwatch.StartNew(); + + try + { + while (true) + { + var batch = new List>>(); + var canRead = telemetryPacketInfoReader.Count; + if (canRead <= 0) + { + if (timeoutMilliseconds > 0) + { + _logger.LogError($"{nameof(ScheduledMeterTaskReadingAsync)} 任务数据通道处理数据耗时{timeoutMilliseconds}毫秒"); + } + timeoutMilliseconds = 0; + //无消息时短等待50毫秒 + await Task.Delay(EmptyWaitMilliseconds); + continue; + } + + timer.Restart(); + timeoutStopwatch.Restart(); + + try + { + // 异步批量读取数据 + while (batch != null && batch.Count < BatchSize && timeoutStopwatch.Elapsed <= timeout) + { + try + { + if (telemetryPacketInfoReader.TryRead(out var dataItem)) + { + batch.Add(dataItem); + } + } + catch (Exception) + { + throw; + } + } + } + catch (Exception) + { + throw; + } + + + if (batch.Count == 0) + { + await Task.Delay(EmptyWaitMilliseconds); + continue; + } + + // 按TopicName分组处理 + var topicGroups = new Dictionary>(); + foreach (var (topicName, records) in batch) + { + if (!topicGroups.TryGetValue(topicName, out var list)) + { + list = new List(); + topicGroups[topicName] = list; + } + list.AddRange(records); + } + + // 处理每个分组 + foreach (var (topicName, records) in topicGroups) + { + try + { + // 批量写入数据库 + await _dbProvider.GetSessionPool(true).BatchInsertAsync(metadata, records); + + // 限流推送Kafka + await DeviceGroupBalanceControl.ProcessWithThrottleAsync( + items: records, + deviceIdSelector: data => data.DeviceId, + processor: async (data, groupIndex) => + await KafkaProducerIssuedMessageAction(topicName, data, groupIndex) + ); + } + catch (Exception ex) + { + _logger.LogError(ex, "数据通道处理主题 {TopicName} 数据时发生异常", topicName); + } + } + + batch.Clear(); + timer.Stop(); + + timeoutStopwatch.Stop(); + timeoutMilliseconds = timeoutMilliseconds + timer.ElapsedMilliseconds; + } + } + catch (Exception ex) + { + _logger.LogCritical(ex, "定时任务处理发生致命错误"); + throw; + } + } + + /// + /// Kafka推送消息(增加重试机制和参数校验) + /// + protected async Task KafkaProducerIssuedMessageAction( + string topicName, + T taskRecord, + int partition) where T : class + { + if (string.IsNullOrWhiteSpace(topicName) || taskRecord == null) + { + throw new Exception($"{nameof(KafkaProducerIssuedMessageAction)} 推送消息失败,参数异常,-101"); + } + + const int maxRetries = 3;//重试次数 + for (int retry = 0; retry < maxRetries; retry++) + { + try + { + await _producerService.ProduceAsync(topicName, taskRecord, partition); + return; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Kafka推送{topicName}主题分区{partition}重试中({Retry}/{MaxRetries})", topicName, partition, retry + 1, maxRetries); + if (retry == maxRetries - 1) throw; + await Task.Delay(1000 * (retry + 1)); + } + } + } + + + + /// + /// 日志保存 + /// + /// + /// + public async Task LogSaveAsync(ChannelReader channelReader) + { + const int BatchSize = 1000; + const int EmptyWaitMilliseconds = 1000; + var timeout = TimeSpan.FromSeconds(2); + var timer = Stopwatch.StartNew(); + long timeoutMilliseconds = 0; + try + { + while (true) + { + var batch = new List(); + var canRead = channelReader.Count; + if (canRead <= 0) + { + if (timeoutMilliseconds > 0) + { + _logger.LogError($"{nameof(LogSaveAsync)} 通道处理数据耗时{timeoutMilliseconds}毫秒"); + } + timeoutMilliseconds = 0; + //无消息时短等待1秒 + await Task.Delay(EmptyWaitMilliseconds); + continue; + } + + timer.Restart(); + var startTime = DateTime.Now; + + try + { + // 异步批量读取数据 + while (batch != null && batch.Count < BatchSize && (DateTime.Now - startTime) < timeout) + { + try + { + if (channelReader.TryRead(out var dataItem)) + { + batch.Add(dataItem); + } + } + catch (Exception) + { + throw; + } + } + } + catch (Exception) + { + throw; + } + + if (batch == null || batch.Count == 0) + { + await Task.Delay(EmptyWaitMilliseconds); + continue; + } + try + { + + // 按小时分组 + var hourGroups = new Dictionary>(); + DateTime? dateTime = null; + List batchList = new List(); + int index = 1; + foreach (var item in batch) + { + var records = item.Adapt(); + + if (!records.ReceivedTime.HasValue) + records.ReceivedTime = DateTime.Now; + var curDateTime = new DateTime(records.ReceivedTime.Value.Year, records.ReceivedTime.Value.Month, records.ReceivedTime.Value.Hour, records.ReceivedTime.Value.Day, records.ReceivedTime.Value.Hour, 0, 0); + if (!dateTime.HasValue || curDateTime != dateTime) + { + dateTime = curDateTime; + if (batchList.Count > 0) + { + var immutableList = ImmutableList.CreateRange(batchList); + hourGroups.Add(dateTime.Value, immutableList.ToList()); + batchList.Clear(); + } + } + batchList.Add(records); + // 最后一批 + if(index== batch.Count) + { + var immutableList = ImmutableList.CreateRange(batchList); + hourGroups.Add(dateTime.Value, immutableList.ToList()); + batchList.Clear(); + } + index++; + } + foreach (var (time, records) in hourGroups) + { + // 批量写入数据库 + await _logRecordRepository.InsertManyAsync(records, time); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "数据通道处理日志数据时发生异常"); + } + batch.Clear(); + timer.Stop(); + + timeoutMilliseconds = timeoutMilliseconds + timer.ElapsedMilliseconds; + + startTime = DateTime.Now; + } + } + catch (Exception ex) + { + _logger.LogCritical(ex, "日志处理发生致命错误"); + throw; + } + } + + } +} diff --git a/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj b/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj index 3ab9831..01878c2 100644 --- a/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj +++ b/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj @@ -19,17 +19,18 @@ - - + + - + + diff --git a/services/JiShe.CollectBus.Application/Plugins/ServerMonitor.cs b/services/JiShe.CollectBus.Application/Plugins/ServerMonitor.cs index 2b3c15a..b90b372 100644 --- a/services/JiShe.CollectBus.Application/Plugins/ServerMonitor.cs +++ b/services/JiShe.CollectBus.Application/Plugins/ServerMonitor.cs @@ -5,7 +5,7 @@ using TouchSocket.Sockets; namespace JiShe.CollectBus.Plugins { - public partial class ServerMonitor(ILogger logger) : PluginBase, IServerStartedPlugin, IServerStopedPlugin + public partial class ServerMonitor(ILogger logger) : PluginBase, IServerStartedPlugin, IServerStoppedPlugin { public Task OnServerStarted(IServiceBase sender, ServiceStateEventArgs e) { @@ -31,7 +31,7 @@ namespace JiShe.CollectBus.Plugins return e.InvokeNext(); } - public Task OnServerStoped(IServiceBase sender,ServiceStateEventArgs e) + public Task OnServerStopped(IServiceBase sender,ServiceStateEventArgs e) { logger.LogInformation("服务已停止"); return e.InvokeNext(); diff --git a/services/JiShe.CollectBus.Application/Plugins/TcpMonitor.cs b/services/JiShe.CollectBus.Application/Plugins/TcpMonitor.cs index 6eadb0a..0e92ff6 100644 --- a/services/JiShe.CollectBus.Application/Plugins/TcpMonitor.cs +++ b/services/JiShe.CollectBus.Application/Plugins/TcpMonitor.cs @@ -1,9 +1,11 @@ -using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.Common; +using JiShe.CollectBus.IotSystems.Ammeters; using JiShe.CollectBus.IotSystems.Devices; using JiShe.CollectBus.Kafka.Producer; using JiShe.CollectBus.Protocol.Interfaces; using JiShe.CollectBus.Protocol3761; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using System; using System.Threading.Tasks; using TouchSocket.Core; @@ -14,7 +16,7 @@ using Volo.Abp.Domain.Repositories; namespace JiShe.CollectBus.Plugins { - public partial class TcpMonitor : PluginBase, ITransientDependency, ITcpReceivedPlugin, ITcpConnectingPlugin, ITcpConnectedPlugin, ITcpClosedPlugin + public partial class TcpMonitor : PluginBase, ITransientDependency, ITcpReceivedPlugin, ITcpConnectingPlugin, ITcpConnectedPlugin, ITcpClosedPlugin, ITcpClosingPlugin { private readonly IProducerService _producerService; private readonly ILogger _logger; @@ -22,6 +24,7 @@ namespace JiShe.CollectBus.Plugins private readonly IDistributedCache _ammeterInfoCache; private readonly IServiceProvider _serviceProvider; private readonly IProtocolService _protocolService; + private readonly ServerApplicationOptions _serverApplicationOptions; /// /// @@ -31,10 +34,15 @@ namespace JiShe.CollectBus.Plugins /// /// /// + /// + /// public TcpMonitor(IProducerService producerService, ILogger logger, IRepository deviceRepository, - IDistributedCache ammeterInfoCache, IServiceProvider serviceProvider, IProtocolService protocolService) + IDistributedCache ammeterInfoCache, + IServiceProvider serviceProvider, + IOptions serverApplicationOptions, + IProtocolService protocolService) { _producerService = producerService; _logger = logger; @@ -42,38 +50,43 @@ namespace JiShe.CollectBus.Plugins _ammeterInfoCache = ammeterInfoCache; _serviceProvider= serviceProvider; _protocolService = protocolService; - - + _serverApplicationOptions = serverApplicationOptions.Value; } public async Task OnTcpReceived(ITcpSession client, ReceivedDataEventArgs e) { + if (string.IsNullOrWhiteSpace(_serverApplicationOptions.DefaultProtocolPlugin)) + { + _logger.LogError($"请配置默认的端到云协议插件!"); + } var messageHexString = Convert.ToHexString(e.ByteBlock.Span); - var protocolPlugin = await _protocolService.GetProtocolServiceAsync("376.1"); + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(_serverApplicationOptions.DefaultProtocolPlugin); if (protocolPlugin == null) { - _logger.LogError("协议不存在!"); + _logger.LogError($"默认的端到云协议插件{_serverApplicationOptions.DefaultProtocolPlugin}不存在!"); } var tcpSessionClient = (ITcpSessionClient)client; + TB3761? tB3761 = await protocolPlugin!.AnalyzeAsync(tcpSessionClient, messageHexString); if (tB3761 == null) { // TODO: 暂时不处理,后续再处理 _logger.LogError($"指令初步解析失败,指令内容:{messageHexString}"); } + + // TODO:要注意保存树模型的时时标字段,如果没有时标,则取接受时间做兼容 await e.InvokeNext(); } - //[GeneratorPlugin(typeof(ITcpConnectingPlugin))] + public async Task OnTcpConnecting(ITcpSession client, ConnectingEventArgs e) { var tcpSessionClient = (ITcpSessionClient)client; - + _logger.LogInformation($"[TCP] ID:{tcpSessionClient.Id} IP:{client.GetIPPort()}正在连接中..."); await e.InvokeNext(); } - //[GeneratorPlugin(typeof(ITcpConnectedPlugin))] public async Task OnTcpConnected(ITcpSession client, ConnectedEventArgs e) { var tcpSessionClient = (ITcpSessionClient)client; @@ -83,24 +96,30 @@ namespace JiShe.CollectBus.Plugins await e.InvokeNext(); } - //[GeneratorPlugin(typeof(ITcpClosedPlugin))]//ITcpSessionClient public async Task OnTcpClosed(ITcpSession client, ClosedEventArgs e) { - + //todo: 删除Redis缓存 var tcpSessionClient = (ITcpSessionClient)client; - var entity = await _deviceRepository.FindAsync(a => a.ClientId == tcpSessionClient.Id); - if (entity != null) - { - entity.UpdateByOnClosed(); - await _deviceRepository.UpdateAsync(entity); - } - else - { - _logger.LogWarning($"[TCP] ID:{tcpSessionClient.Id} IP:{client.GetIPPort()}已关闭连接,但采集程序检索失败"); - } + //var entity = await _deviceRepository.FindAsync(a => a.ClientId == tcpSessionClient.Id); + //if (entity != null) + //{ + // entity.UpdateByOnClosed(); + // await _deviceRepository.UpdateAsync(entity); + //} + //else + //{ + //_logger.LogWarning($"[TCP] ID:{tcpSessionClient.Id} IP:{client.GetIPPort()}已关闭连接,但采集程序检索失败"); + //} + _logger.LogWarning($"[TCP] ID:{tcpSessionClient.Id} IP:{client.GetIPPort()}已关闭连接"); await e.InvokeNext(); } + public Task OnTcpClosing(ITcpSession client, ClosingEventArgs e) + { + var tcpSessionClient = (ITcpSessionClient)client; + _logger.LogWarning($"[TCP] ID:{tcpSessionClient.Id} IP:{client.GetIPPort()}终端主动关闭"); + return Task.CompletedTask; + } } } diff --git a/services/JiShe.CollectBus.Application/RedisDataCache/RedisDataCacheService.cs b/services/JiShe.CollectBus.Application/RedisDataCache/RedisDataCacheService.cs index 625c1e6..cc64378 100644 --- a/services/JiShe.CollectBus.Application/RedisDataCache/RedisDataCacheService.cs +++ b/services/JiShe.CollectBus.Application/RedisDataCache/RedisDataCacheService.cs @@ -16,6 +16,7 @@ using Volo.Abp.DependencyInjection; using static FreeSql.Internal.GlobalFilter; using static System.Runtime.InteropServices.JavaScript.JSType; using static Volo.Abp.UI.Navigation.DefaultMenuNames.Application; +using JiShe.CollectBus.IotSystems.Ammeters; namespace JiShe.CollectBus.RedisDataCache { @@ -42,8 +43,6 @@ namespace JiShe.CollectBus.RedisDataCache Instance = _freeRedisProvider.Instance; } - //todo 单个数据查询 - /// /// 单个添加数据 /// @@ -95,22 +94,20 @@ namespace JiShe.CollectBus.RedisDataCache /// 批量添加数据 /// /// - /// 主数据存储Hash缓存Key /// Set索引缓存Key - /// ZSET索引缓存Key + /// hash缓存Key /// 待缓存数据集合 /// public async Task BatchInsertDataAsync( - string redisHashCacheKey, string redisSetIndexCacheKey, - string redisZSetScoresIndexCacheKey, - IEnumerable items) where T : DeviceCacheBasicModel + string redisDeviceInfoHashCacheKey, + Dictionary> items) where T : DeviceCacheBasicModel { if (items == null || items.Count() <= 0 - || string.IsNullOrWhiteSpace(redisHashCacheKey) || string.IsNullOrWhiteSpace(redisSetIndexCacheKey) - || string.IsNullOrWhiteSpace(redisZSetScoresIndexCacheKey)) + || string.IsNullOrWhiteSpace(redisDeviceInfoHashCacheKey) + ) { _logger.LogError($"{nameof(BatchInsertDataAsync)} 参数异常,-101"); return; @@ -128,15 +125,13 @@ namespace JiShe.CollectBus.RedisDataCache using (var pipe = Instance.StartPipe()) { foreach (var item in batch) - { - // 主数据存储Hash - pipe.HSet(redisHashCacheKey, item.MemberId, item.Serialize()); - + { // Set索引缓存 - pipe.SAdd(redisSetIndexCacheKey, item.MemberId); + pipe.SAdd(redisSetIndexCacheKey, $"{item.Value.First().TimeDensity.ToString().PadLeft(2, '0')}:{item.Value.First().FocusAddress}"); + + //设备信息缓存 + pipe.HSet(redisDeviceInfoHashCacheKey, item.Key, item.Value.Serialize()); - // ZSET索引缓存Key - pipe.ZAdd(redisZSetScoresIndexCacheKey, item.ScoreValue, item.MemberId); } pipe.EndPipe(); } @@ -367,7 +362,121 @@ namespace JiShe.CollectBus.RedisDataCache { throw new Exception(); } - + + + /// + /// 通过集中器与表计信息排序索引获取单个数据 + /// + /// + /// 主数据存储Hash缓存Key + /// ZSET索引缓存Key + /// ZSET索引的原始数据,例如集中地址和点位的组合 + /// 分页尺寸 + /// 最后一个索引 + /// 最后一个唯一标识 + /// 排序方式 + /// + public async Task> GetSingleData( + string redisHashCacheKey, + string redisZSetScoresIndexCacheKey, + string scoreValueRawData, + int pageSize = 10, + decimal? lastScore = null, + string lastMember = null, + bool descending = true) + where T : DeviceCacheBasicModel + { + // 参数校验 + if (string.IsNullOrWhiteSpace(redisHashCacheKey) || + string.IsNullOrWhiteSpace(redisZSetScoresIndexCacheKey) || + string.IsNullOrWhiteSpace(scoreValueRawData)) + { + _logger.LogError($"{nameof(GetSingleData)} 参数异常,-101"); + return new BusCacheGlobalPagedResult { Items = new List() }; + } + + // 解析原始数据 + var rawDataArray = scoreValueRawData.Split(':'); + if (rawDataArray.Length != 2) + { + _logger.LogError($"{nameof(GetSingleData)} scoreValueRawData格式错误,应为[focusAddress:point]"); + return new BusCacheGlobalPagedResult { Items = new List() }; + } + + // 计算Score值 + long scoreValue; + try + { + var focusAddress = rawDataArray[0]; + var point = Convert.ToInt32(rawDataArray[1]); + scoreValue = CommonHelper.GetFocusScores(focusAddress, point); + } + catch (Exception ex) + { + _logger.LogError(ex, $"{nameof(GetSingleData)} 计算Score值失败"); + return new BusCacheGlobalPagedResult { Items = new List() }; + } + + // Lua脚本:原子化查询操作 + const string luaScript = @" + local zsetKey = KEYS[1] + local hashKey = KEYS[2] + local targetScore = ARGV[1] + + -- 精确匹配Score并获取第一个成员 + local members = redis.call('ZRANGEBYSCORE', zsetKey, targetScore, targetScore, 'LIMIT', 0, 1) + if #members == 0 then + return nil + end + + -- 获取哈希表数据 + local member = members[1] + local data = redis.call('HGET', hashKey, member) + return {member, data}"; + + try + { + // 执行脚本 + var result = await Instance.EvalAsync( + luaScript, + new[] { redisZSetScoresIndexCacheKey, redisHashCacheKey }, + new object[] { scoreValue }); + + // 处理空结果 + if (result == null) + return new BusCacheGlobalPagedResult { Items = new List() }; + + // 解析Redis返回数据 + var resultArray = (object[])result; + var memberId = (string)resultArray[0]; + var dataStr = (string)resultArray[1]; + + // 反序列化数据 + var data = BusJsonSerializer.Deserialize(dataStr); + if (data == null) + { + _logger.LogError($"{nameof(GetSingleData)} 反序列化失败,MemberId: {memberId}"); + return new BusCacheGlobalPagedResult { Items = new List() }; + } + + // 构造返回结果 + return new BusCacheGlobalPagedResult + { + Items = new List { data }, + TotalCount = 1, + PageSize = 1, + HasNext = false, + NextScore = null, + NextMember = null + }; + } + catch (Exception ex) + { + _logger.LogError(ex, $"{nameof(GetSingleData)} Redis操作异常"); + return new BusCacheGlobalPagedResult { Items = new List() }; + } + } + /// /// 通过ZSET索引获取数据,支持10万级别数据处理,控制在13秒以内。 /// @@ -527,66 +636,166 @@ namespace JiShe.CollectBus.RedisDataCache }; } - ///// - ///// 通过集中器与表计信息排序索引获取数据 - ///// - ///// - ///// 主数据存储Hash缓存Key - ///// ZSET索引缓存Key - ///// 分页尺寸 - ///// 最后一个索引 - ///// 最后一个唯一标识 - ///// 排序方式 - ///// - //public async Task> GetAllPagedData( - //string redisHashCacheKey, - //string redisZSetScoresIndexCacheKey, - //int pageSize = 1000, - //decimal? lastScore = null, - //string lastMember = null, - //bool descending = true) - //where T : DeviceCacheBasicModel - //{ - // // 参数校验增强 - // if (string.IsNullOrWhiteSpace(redisHashCacheKey) || string.IsNullOrWhiteSpace(redisZSetScoresIndexCacheKey)) - // { - // _logger.LogError($"{nameof(GetAllPagedData)} 参数异常,-101"); - // return null; - // } - // if (pageSize < 1 || pageSize > 10000) - // { - // _logger.LogError($"{nameof(GetAllPagedData)} 分页大小应在1-10000之间,-102"); - // return null; - // } + /// + /// 通过ZSET索引获取数据,支持10万级别数据处理,控制在13秒以内。 + /// + /// + /// ZSET索引缓存Key + /// 主数据存储Hash缓存Key + /// 分页尺寸 + /// 最后一个索引 + /// 最后一个唯一标识 + /// 排序方式 + /// + public async Task> GetAllPagedData2( + string redisCacheDeviceGroupSetIndexKey, + string redisCacheDeviceInfoHashKey, + int pageSize = 1000, + decimal? lastScore = null, + string lastMember = null, + bool descending = true) + where T : DeviceCacheBasicModel + { + // 参数校验增强 + if (string.IsNullOrWhiteSpace(redisCacheDeviceInfoHashKey) || + string.IsNullOrWhiteSpace(redisCacheDeviceGroupSetIndexKey)) + { + _logger.LogError($"{nameof(GetAllPagedData)} 参数异常,-101"); + return new BusCacheGlobalPagedResult { Items = new List() }; + } - // //// 分页参数解析 - // //var (startScore, excludeMember) = descending - // // ? (lastScore ?? decimal.MaxValue, lastMember) - // // : (lastScore ?? 0, lastMember); + pageSize = Math.Clamp(pageSize, 1, 10000); - // //执行分页查询(整合游标处理) - // var pageResult = await GetPagedMembers( - // redisZSetScoresIndexCacheKey, - // pageSize, - // lastScore, - // lastMember, - // descending); + var luaScript = @" + local command = ARGV[1] + local range_start = ARGV[2] + local range_end = ARGV[3] + local limit = tonumber(ARGV[4]) + local last_score = ARGV[5] + local last_member = ARGV[6] - // // 批量获取数据(优化内存分配) - // var dataDict = await BatchGetData(redisHashCacheKey, pageResult.Members); + -- 获取原始数据 + local members + if command == 'ZRANGEBYSCORE' then + members = redis.call(command, KEYS[1], range_start, range_end, 'WITHSCORES', 'LIMIT', 0, limit * 2) + else + members = redis.call('ZREVRANGEBYSCORE', KEYS[1], range_start, range_end, 'WITHSCORES', 'LIMIT', 0, limit * 2) + end + + -- 过滤数据 + local filtered_members = {} + local count = 0 + for i = 1, #members, 2 do + local member = members[i] + local score = members[i+1] + local include = true + if last_score ~= '' and last_member ~= '' then + if command == 'ZRANGEBYSCORE' then + -- 升序:score > last_score 或 (score == last_score 且 member > last_member) + if score == last_score then + include = member > last_member + else + include = tonumber(score) > tonumber(last_score) + end + else + -- 降序:score < last_score 或 (score == last_score 且 member < last_member) + if score == last_score then + include = member < last_member + else + include = tonumber(score) < tonumber(last_score) + end + end + end + if include then + table.insert(filtered_members, member) + table.insert(filtered_members, score) + count = count + 1 + if count >= limit then + break + end + end + end + + -- 提取有效数据 + local result_members, result_scores = {}, {} + for i=1,#filtered_members,2 do + table.insert(result_members, filtered_members[i]) + table.insert(result_scores, filtered_members[i+1]) + end + + if #result_members == 0 then return {0,{},{},{}} end + + -- 获取Hash数据 + local hash_data = redis.call('HMGET', KEYS[2], unpack(result_members)) + return {#result_members, result_members, result_scores, hash_data}"; + + // 调整范围构造逻辑(移除排他符号) + string rangeStart, rangeEnd; + if (descending) + { + rangeStart = lastScore.HasValue ? lastScore.Value.ToString() : "+inf"; + rangeEnd = "-inf"; + } + else + { + rangeStart = lastScore.HasValue ? lastScore.Value.ToString() : "-inf"; + rangeEnd = "+inf"; + } + + var scriptResult = (object[])await Instance.EvalAsync(luaScript, + new[] { redisCacheDeviceGroupSetIndexKey, redisCacheDeviceInfoHashKey }, + new object[] + { + descending ? "ZREVRANGEBYSCORE" : "ZRANGEBYSCORE", + rangeStart, + rangeEnd, + (pageSize + 1).ToString(), // 获取pageSize+1条以判断是否有下一页 + lastScore?.ToString() ?? "", + lastMember ?? "" + }); + + if ((long)scriptResult[0] == 0) + return new BusCacheGlobalPagedResult { Items = new List() }; + + // 处理结果集 + var members = ((object[])scriptResult[1]).Cast().ToList(); + var scores = ((object[])scriptResult[2]).Cast().Select(decimal.Parse).ToList(); + var hashData = ((object[])scriptResult[3]).Cast().ToList(); + + var validItems = members.AsParallel() + .Select((m, i) => + { + try { return BusJsonSerializer.Deserialize(hashData[i]); } + catch { return null; } + }) + .Where(x => x != null) + .ToList(); + + var hasNext = validItems.Count > pageSize; + var actualItems = hasNext ? validItems.Take(pageSize) : validItems; + + //分页锚点索引 + decimal? nextScore = null; + string nextMember = null; + if (hasNext && actualItems.Any()) + { + var lastIndex = actualItems.Count() - 1; // 使用actualItems的最后一个索引 + nextScore = scores[lastIndex]; + nextMember = members[lastIndex]; + } + + return new BusCacheGlobalPagedResult + { + Items = actualItems.ToList(), + HasNext = hasNext, + NextScore = nextScore, + NextMember = nextMember, + TotalCount = await GetTotalCount(redisCacheDeviceGroupSetIndexKey), + PageSize = pageSize, + }; + } - // return new BusCacheGlobalPagedResult - // { - // Items = pageResult.Members.Select(m => dataDict.TryGetValue(m, out var v) ? v : default) - // .Where(x => x != null).ToList(), - // HasNext = pageResult.HasNext, - // NextScore = pageResult.NextScore, - // NextMember = pageResult.NextMember, - // TotalCount = await GetTotalCount(redisZSetScoresIndexCacheKey), - // PageSize = pageSize, - // }; - //} /// /// 游标分页查询 diff --git a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs index 31a3494..40c2db2 100644 --- a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs +++ b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs @@ -1,4 +1,7 @@ -using JiShe.CollectBus.Ammeters; +using Confluent.Kafka; +using DeviceDetectorNET.Parser.Device; +using FreeSql.Internal.CommonProvider; +using JiShe.CollectBus.Ammeters; using JiShe.CollectBus.Application.Contracts; using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.Common.DeviceBalanceControl; @@ -10,10 +13,14 @@ using JiShe.CollectBus.IoTDB.Context; using JiShe.CollectBus.IoTDB.Interface; using JiShe.CollectBus.IoTDB.Model; using JiShe.CollectBus.IoTDB.Options; +using JiShe.CollectBus.IoTDB.Provider; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.IotSystems.Devices; +using JiShe.CollectBus.IotSystems.MeterReadingRecords; using JiShe.CollectBus.IotSystems.PrepayModel; using JiShe.CollectBus.Kafka.Attributes; using JiShe.CollectBus.Kafka.Internal; +using JiShe.CollectBus.Kafka.Producer; using JiShe.CollectBus.Protocol.Interfaces; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -24,6 +31,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; +using TouchSocket.Core; +using TouchSocket.Sockets; +using static IdentityModel.ClaimComparer; namespace JiShe.CollectBus.Samples; @@ -35,14 +45,18 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS private readonly IoTDbOptions _options; private readonly IRedisDataCacheService _redisDataCacheService; + private readonly IProducerService _producerService; + private readonly ITcpService _tcpService; public SampleAppService(IIoTDbProvider iotDBProvider, IOptions options, - IoTDBRuntimeContext dbContext, ILogger logger, IRedisDataCacheService redisDataCacheService) + IoTDBRuntimeContext dbContext, ILogger logger, IRedisDataCacheService redisDataCacheService, IProducerService producerService, ITcpService tcpService) { _iotDBProvider = iotDBProvider; _options = options.Value; _dbContext = dbContext; _logger = logger; _redisDataCacheService = redisDataCacheService; + _producerService = producerService; + _tcpService = tcpService; } /// @@ -53,6 +67,10 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task UseSessionPool(long testTime) { + var dataTime = DateTime.Now; + + List values = new List() { $"{dataTime:yy}", $"{dataTime:MM}", $"{dataTime:dd}", $"{dataTime:HH}", $"{dataTime:mm}", }; + ElectricityMeterTreeModel meter = new ElectricityMeterTreeModel() { @@ -66,6 +84,13 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS IssuedMessageHexString = "messageHexString", Timestamps = testTime// DateTimeOffset.UtcNow.ToUnixTimeNanoseconds()//testTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), }; + //ElectricityMeterTreeModelExtension.GetCurrent() + //SourceEntityAccessorFactory.SetCurrent(meter); + + //ElectricityMeterTreeModelAccessor. + //TableModelSingleMeasuringEntityExtension + //TableModelSingleMeasuringEntityAccessor.GetSystemName(meter); + //ElectricityMeterAccessor await _iotDBProvider.InsertAsync(meter); } @@ -76,7 +101,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task UseTableSessionPool(DateTime time) { - var testTime = time; + var testTime = time; ElectricityMeterTreeModel meter2 = new ElectricityMeterTreeModel() { SystemName = "energy", @@ -89,9 +114,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS Timestamps = DateTimeOffset.Now.ToUnixTimeNanoseconds(), }; - await _iotDBProvider.InsertAsync(meter2); - - _dbContext.UseTableSessionPool = true; + await _iotDBProvider.GetSessionPool(false).InsertAsync(meter2); ElectricityMeter meter = new ElectricityMeter() { @@ -102,9 +125,28 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS MeterModel = "DDZY-1980", ProjectId = "10059", Voltage = 10, + CurrentdDateTime = DateTime.Now, Timestamps = DateTimeOffset.Now.ToUnixTimeNanoseconds(), }; - await _iotDBProvider.InsertAsync(meter); + await _iotDBProvider.GetSessionPool(true).InsertAsync(meter); + + QueryCondition conditions = new QueryCondition() + { + Field = "DeviceId", + Operator = "=", + Value = meter.DeviceId + }; + + + var query = new IoTDBQueryOptions() + { + TableNameOrTreePath = nameof(ElectricityMeter), + PageIndex = 1, + PageSize = 1, + Conditions = new List() { conditions }, + }; + + var pageResult = await _iotDBProvider.GetSessionPool(true).QueryAsync(query); } @@ -131,9 +173,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS }; await _iotDBProvider.InsertAsync(meter2); - - _dbContext.UseTableSessionPool = true; - + ElectricityMeter meter3 = new ElectricityMeter() { @@ -164,14 +204,18 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTreeModelSingleMeasuringEntity(string measuring, string value, DateTime time) { - var meter = new TreeModelSingleMeasuringEntity() + time = DateTime.Now; + //System.Reflection.PropertyInfo; + //System.Reflection.FieldInfo + //TreeModelSingleMeasuringEntityAccessor + var meter = new TreeModelSingleMeasuringEntity() { SystemName = "energy", DeviceId = "402440506", DeviceType = "1", ProjectId = "10059", Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleMeasuring = new Tuple(measuring, value) + SingleMeasuring = (measuring, 34.534m) }; await _iotDBProvider.InsertAsync(meter); } @@ -184,18 +228,61 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTreeModelSingleMeasuringEntity2(string measuring, int value, DateTime time) { - var meter = new TreeModelSingleMeasuringEntity() + time = DateTime.Now; + var meter = new TreeModelSingleMeasuringEntity() { SystemName = "energy", DeviceId = "402440506", DeviceType = "Ammeter", ProjectId = "10059", Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleMeasuring = new Tuple(measuring, value) + SingleMeasuring = (measuring, true) }; await _iotDBProvider.InsertAsync(meter); } + /// + /// 测试树模型单个测点数据项查询 + /// + /// + /// + [HttpGet] + public async Task TestTreeModelSingleMeasuringEntityQuery() + { + + var time = DateTime.Now; + + var meter = new TreeModelSingleMeasuringEntity() + { + SystemName = "energy", + DeviceId = "402440506", + DeviceType = "Ammeter", + ProjectId = "10059", + Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), + SingleMeasuring = ("measuring", true) + }; + + QueryCondition conditions = new QueryCondition() + { + Field = "DeviceId", + Operator = "=", + Value = meter.DeviceId + }; + + + var query = new IoTDBQueryOptions() + { + TableNameOrTreePath = meter.DevicePath, + PageIndex = 1, + PageSize = 1, + Conditions = new List() { conditions }, + }; + + var pageResult = await _iotDBProvider.QueryAsync(query); + + await _iotDBProvider.InsertAsync(meter); + } + /// /// 测试表模型单个测点数据项 /// @@ -204,6 +291,8 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTableModelSingleMeasuringEntity(string measuring, string value, DateTime time) { + time = DateTime.Now; + var meter = new TableModelSingleMeasuringEntity() { SystemName = "energy", @@ -211,7 +300,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS DeviceType = "Ammeter", ProjectId = "10059", Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleColumn = new Tuple(measuring, value) + SingleColumn = (measuring, value) }; _dbContext.UseTableSessionPool = true; await _iotDBProvider.InsertAsync(meter); @@ -225,6 +314,8 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTableModelSingleMeasuringEntity2(string measuring, int value, DateTime time) { + time = DateTime.Now; + var meter = new TableModelSingleMeasuringEntity() { SystemName = "energy", @@ -232,10 +323,39 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS DeviceType = "Ammeter", ProjectId = "10059", Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleColumn = new Tuple(measuring, value) + SingleColumn = (measuring, value) }; _dbContext.UseTableSessionPool = true; await _iotDBProvider.InsertAsync(meter); + + var meter3 = new TableModelSingleMeasuringEntity() + { + SystemName = "energy", + DeviceId = "402440506", + DeviceType = "Ammeter", + ProjectId = "10059", + Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), + SingleColumn = ("DeviceResult", true) + }; + _dbContext.UseTableSessionPool = true; + + QueryCondition conditions = new QueryCondition() + { + Field = "DeviceId", + Operator = "=", + Value = meter.DeviceId + }; + + + var query = new IoTDBQueryOptions() + { + TableNameOrTreePath = meter.DevicePath, + PageIndex = 1, + PageSize = 1, + Conditions = new List() { conditions }, + }; + + var pageResult = await _iotDBProvider.QueryAsync(query); } /// @@ -255,22 +375,22 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS //// 初始化缓存 //DeviceGroupBalanceControl.InitializeCache(deviceList); - var timeDensity = "15"; - //获取缓存中的电表信息 - var redisKeyList = $"{string.Format(RedisConst.CacheMeterInfoHashKey, "Energy", "JiSheCollectBus", MeterTypeEnum.Ammeter.ToString(), timeDensity)}*"; + //var timeDensity = "15"; + ////获取缓存中的电表信息 + //var redisKeyList = $"{string.Format(RedisConst.CacheMeterInfoHashKey, "Energy", "JiSheCollectBus", MeterTypeEnum.Ammeter.ToString(), timeDensity)}*"; - var oneMinutekeyList = await FreeRedisProvider.Instance.KeysAsync(redisKeyList); - var meterInfos = await GetMeterRedisCacheListData(oneMinutekeyList, "Energy", "JiSheCollectBus", timeDensity, MeterTypeEnum.Ammeter); - List focusAddressDataLista = new List(); - foreach (var item in meterInfos) - { - focusAddressDataLista.Add(item.FocusAddress); - } + //var oneMinutekeyList = await FreeRedisProvider.Instance.KeysAsync(redisKeyList); + //var meterInfos = await GetMeterRedisCacheListData(oneMinutekeyList, "Energy", "JiSheCollectBus", timeDensity, MeterTypeEnum.Ammeter); + //List focusAddressDataLista = new List(); + //foreach (var item in meterInfos) + //{ + // focusAddressDataLista.Add(item.FocusAddress); + //} - DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista); - - // 打印分布统计 - DeviceGroupBalanceControl.PrintDistributionStats(); + //DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista); + + //// 打印分布统计 + //DeviceGroupBalanceControl.PrintDistributionStats(); await Task.CompletedTask; } @@ -282,13 +402,13 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS /// [HttpGet] public async Task TestGetDeviceGroupBalanceControl(string deviceAddress) - { + { var groupId = DeviceGroupBalanceControl.GetDeviceGroupId(deviceAddress); Console.WriteLine(groupId); await Task.CompletedTask; } - + /// /// 测试Redis批量读取10万条数据性能 @@ -297,46 +417,46 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestRedisCacheGetAllPagedData() { - var timeDensity = "15"; - string SystemType = "Energy"; - string ServerTagName = "JiSheCollectBus2"; - var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; - var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; - var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + //var timeDensity = "15"; + //string SystemType = "Energy"; + //string ServerTagName = "JiSheCollectBus2"; + //var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + //var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + //var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; - var timer1 = Stopwatch.StartNew(); - decimal? cursor = null; - string member = null; - bool hasNext; - List meterInfos = new List(); - do - { - var page = await _redisDataCacheService.GetAllPagedData( - redisCacheMeterInfoHashKeyTemp, - redisCacheMeterInfoZSetScoresIndexKeyTemp, - pageSize: 1000, - lastScore: cursor, - lastMember: member); + //var timer1 = Stopwatch.StartNew(); + //decimal? cursor = null; + //string member = null; + //bool hasNext; + //List meterInfos = new List(); + //do + //{ + // var page = await _redisDataCacheService.GetAllPagedData( + // redisCacheMeterInfoHashKeyTemp, + // redisCacheMeterInfoZSetScoresIndexKeyTemp, + // pageSize: 1000, + // lastScore: cursor, + // lastMember: member); - meterInfos.AddRange(page.Items); - cursor = page.HasNext ? page.NextScore : null; - member = page.HasNext ? page.NextMember : null; - hasNext = page.HasNext; - } while (hasNext); + // meterInfos.AddRange(page.Items); + // cursor = page.HasNext ? page.NextScore : null; + // member = page.HasNext ? page.NextMember : null; + // hasNext = page.HasNext; + //} while (hasNext); - timer1.Stop(); - _logger.LogError($"读取数据更花费时间{timer1.ElapsedMilliseconds}毫秒"); + //timer1.Stop(); + //_logger.LogError($"读取数据更花费时间{timer1.ElapsedMilliseconds}毫秒"); - List focusAddressDataLista = new List(); - foreach (var item in meterInfos) - { - focusAddressDataLista.Add(item.FocusAddress); - } + //List focusAddressDataLista = new List(); + //foreach (var item in meterInfos) + //{ + // focusAddressDataLista.Add(item.FocusAddress); + //} - DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista); + //DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista); - // 打印分布统计 - DeviceGroupBalanceControl.PrintDistributionStats(); + //// 打印分布统计 + //DeviceGroupBalanceControl.PrintDistributionStats(); await Task.CompletedTask; } @@ -351,7 +471,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS { DateTime nextTaskTime = Convert.ToDateTime(time); - return await Task.FromResult(nextTaskTime.CalculateNextCollectionTime(timeDensity)); + return await Task.FromResult(nextTaskTime.CalculateNextCollectionTime(timeDensity)); } @@ -387,7 +507,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [AllowAnonymous] public bool GetTestProtocol() { - var aa = LazyServiceProvider.GetKeyedService("TestProtocolPlugin"); + var aa = LazyServiceProvider.GetKeyedService("TestProtocolPlugin"); return aa == null; } @@ -396,7 +516,74 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS public async Task KafkaSubscribeAsync(object obj) { _logger.LogWarning($"收到订阅消息: {obj}"); - return SubscribeAck.Success(); + return SubscribeAck.Success(); + } + + /// + /// 测试Kafka下发报文 + /// + /// + /// + [AllowAnonymous] + public async Task KafkaSendAsync(KafkaSendDto input) + { + ArgumentException.ThrowIfNullOrWhiteSpace(input.Address); + ArgumentException.ThrowIfNullOrWhiteSpace(input.Frame); + input.Frame = input.Frame.Replace(" ", ""); + await _producerService.ProduceAsync(ProtocolConst.TESTSENDTOPIC, input); + return await Task.FromResult(true); + } + + + /// + /// 订阅下发的数据 + /// + /// + /// + [KafkaSubscribe(ProtocolConst.TESTSENDTOPIC), ApiExplorerSettings(IgnoreApi = true)] + + public async Task KafkaSubscribeTestSendAsync(KafkaSendDto dto) + { + if (_tcpService.ClientExists(dto.Address)) + { + // 发送给设备 + await _tcpService.SendAsync(dto.Address, Convert.FromHexString(dto.Frame)); + _logger.LogWarning($"{dto.Address}下发消息报文:{dto.Frame}"); + } + else + { + _logger.LogWarning($"{dto.Address}集中器未上线: {dto.Serialize()}"); + } + // 测试不管是否上线都ACK + return SubscribeAck.Success(); + } + + + /// + /// 测试Redis批量读取10万条数据性能 + /// + /// + [HttpGet] + public async Task TestRedisCacheGetData(string scores) + { + //var timeDensity = "15"; + //string SystemType = "Energy"; + //string ServerTagName = "JiSheCollectBus5"; + //var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + //var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + //var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + + //var page = await _redisDataCacheService.GetSingleData( + // redisCacheMeterInfoHashKeyTemp, + // redisCacheMeterInfoZSetScoresIndexKeyTemp, + // "973219481:17", + // pageSize: 1000, + // lastScore: 100, + // lastMember: "memberId", + // descending: true + // ); + + await Task.CompletedTask; } } diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs index a159326..a1424f9 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs @@ -7,18 +7,19 @@ using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.Common.Models; +using JiShe.CollectBus.DataChannels; using JiShe.CollectBus.GatherItem; -using JiShe.CollectBus.IoTDB.Context; using JiShe.CollectBus.IoTDB.Interface; using JiShe.CollectBus.IoTDB.Model; using JiShe.CollectBus.IoTDB.Options; using JiShe.CollectBus.IoTDB.Provider; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.IotSystems.Devices; using JiShe.CollectBus.IotSystems.MeterReadingRecords; -using JiShe.CollectBus.IotSystems.Watermeter; using JiShe.CollectBus.Kafka.Internal; -using JiShe.CollectBus.Kafka.Producer; using JiShe.CollectBus.Protocol.Interfaces; +using JiShe.CollectBus.Protocol.Models; +using Mapster; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; @@ -26,7 +27,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using JiShe.CollectBus.Protocol.Models; +using Volo.Abp.Guids; namespace JiShe.CollectBus.ScheduledMeterReading { @@ -37,35 +38,36 @@ namespace JiShe.CollectBus.ScheduledMeterReading { private readonly ILogger _logger; private readonly IIoTDbProvider _dbProvider; - private readonly IProducerService _producerService; + private readonly IDataChannelManageService _dataChannelManage; private readonly IRedisDataCacheService _redisDataCacheService; + private readonly IProtocolService _protocolService; private readonly KafkaOptionConfig _kafkaOptions; private readonly ServerApplicationOptions _applicationOptions; - private readonly IoTDBRuntimeContext _runtimeContext; - private readonly IProtocolService _protocolService; + private readonly IGuidGenerator _guidGenerator; - int pageSize = 3000; + int pageSize = 10000; public BasicScheduledMeterReadingService( ILogger logger, - IProducerService producerService, + IDataChannelManageService dataChannelManage, IRedisDataCacheService redisDataCacheService, IIoTDbProvider dbProvider, - IoTDBRuntimeContext runtimeContext, IProtocolService protocolService, + IGuidGenerator guidGenerator, IOptions kafkaOptions, IOptions applicationOptions) { _logger = logger; _dbProvider = dbProvider; - _runtimeContext = runtimeContext; - _producerService = producerService; + _dataChannelManage = dataChannelManage; _redisDataCacheService = redisDataCacheService; - _kafkaOptions = kafkaOptions.Value; - _applicationOptions = applicationOptions.Value; _protocolService = protocolService; - _runtimeContext.UseTableSessionPool = true; + _kafkaOptions = kafkaOptions.Value; + _applicationOptions = applicationOptions.Value; + + _guidGenerator = guidGenerator; + } /// @@ -110,9 +112,9 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"{nameof(CreateToBeIssueTasks)} 构建待处理的下发指令任务处理时没有缓存数据,-101"); return; } - var currentTime = DateTime.Now; + //定时抄读 foreach (var item in taskInfos) { @@ -135,49 +137,182 @@ namespace JiShe.CollectBus.ScheduledMeterReading //电表定时广播校时,一天一次。 string currentTimeStr = $"{currentTime:HH:mm:00}"; - if (string.Equals(currentTimeStr, _applicationOptions.AutomaticVerificationTime, StringComparison.CurrentCultureIgnoreCase))//自动校时 - { - //_logger.LogInformation($"{nameof(AmmeterScheduledAutomaticVerificationTime)} 电表自动校时,非自动校时时间"); - //return; + //if (string.Equals(currentTimeStr, _applicationOptions.AutomaticVerificationTime, StringComparison.CurrentCultureIgnoreCase))//自动校时 + //{ + // //_logger.LogInformation($"{nameof(AmmeterScheduledAutomaticVerificationTime)} 电表自动校时,非自动校时时间"); + // //return; - _ = CreateMeterPublishTask( - timeDensity: timeDensity, - nextTaskTime: currentTime, - meterType: MeterTypeEnum.Ammeter, - taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => - { - await AmmeterScheduledAutomaticVerificationTime(timeDensity, data, groupIndex, timestamps); - }); - } - else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticGetTerminalVersionTime, StringComparison.CurrentCultureIgnoreCase))//集中器版本号读取 - { - _ = CreateMeterPublishTask( - timeDensity: timeDensity, - nextTaskTime: currentTime, - meterType: MeterTypeEnum.Ammeter, - taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => - { - await ConcentratorScheduledAutomaticGetTerminalVersion(timeDensity, data, groupIndex, timestamps); - }); - } - else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticGetTelematicsModuleTime, StringComparison.CurrentCultureIgnoreCase))//SIM卡读取 - { - _ = CreateMeterPublishTask( - timeDensity: timeDensity, - nextTaskTime: currentTime, - meterType: MeterTypeEnum.Ammeter, - taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => - { - await ConcentratorScheduledAutomaticGetTelematicsModule(timeDensity, data, groupIndex, timestamps); - }); - } - else - { - _logger.LogInformation($"{nameof(CreateToBeIssueTasks)} 不是自动校时、采集终端信息等时间,继续处理其他"); - } + // _ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await AmmeterScheduledAutomaticVerificationTime(timeDensity, data, groupIndex, timestamps); + + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"电表自动校时 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); + //} + //else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticTerminalVersionTime, StringComparison.CurrentCultureIgnoreCase))//集中器版本号读取 + //{ + // _ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await ConcentratorScheduledAutomaticGetTerminalVersion(timeDensity, data, groupIndex, timestamps); + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"集中器 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); + //} + //else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticTelematicsModuleTime, StringComparison.CurrentCultureIgnoreCase))//SIM卡读取 + //{ + // _ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await ConcentratorScheduledAutomaticGetTelematicsModule(timeDensity, data, groupIndex, timestamps); + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"集中器 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); + //} + //else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticTelematicsModuleTime, StringComparison.CurrentCultureIgnoreCase))//月冻结 + //{ + // _ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await AmmeterScheduledGetAutomaticDayFreezeData(timeDensity, data, groupIndex, timestamps); + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); + //} + //else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticDayFreezeTime, StringComparison.CurrentCultureIgnoreCase))//日冻结 + //{ + // _ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await AmmeterScheduledGetAutomaticMonthFreezeData(timeDensity, data, groupIndex, timestamps); + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); + //} + //else + //{ + // _logger.LogInformation($"{nameof(CreateToBeIssueTasks)} 不是自动校时、采集终端信息等时间,继续处理其他"); + //} + + + //_ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await AmmeterScheduledAutomaticVerificationTime(timeDensity, data, groupIndex, timestamps); + + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"电表自动校时 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); + + _ = CreateMeterPublishTask( + timeDensity: timeDensity, + nextTaskTime: currentTime, + meterType: MeterTypeEnum.Ammeter, + taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + { + var tempTask = await ConcentratorScheduledAutomaticGetTerminalVersion(timeDensity, data, groupIndex, timestamps); + if (tempTask == null || tempTask.Count <= 0) + { + _logger.LogWarning($"集中器 {data.Name} 任务数据构建失败:{data.Serialize()}"); + return; + } + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + }); + + //_ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await ConcentratorScheduledAutomaticGetTelematicsModule(timeDensity, data, groupIndex, timestamps); + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"集中器 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); + + //_ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await AmmeterScheduledGetAutomaticDayFreezeData(timeDensity, data, groupIndex, timestamps); + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); + + + + //_ = CreateMeterPublishTask( + // timeDensity: timeDensity, + // nextTaskTime: currentTime, + // meterType: MeterTypeEnum.Ammeter, + // taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + // { + // var tempTask = await AmmeterScheduledGetAutomaticMonthFreezeData(timeDensity, data, groupIndex, timestamps); + // if (tempTask == null || tempTask.Count <= 0) + // { + // _logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); + // return; + // } + // _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + // }); //检查任务时间节点,由于定时任务10秒钟运行一次,需要判定当前时间是否在任务时间节点内,不在则跳过 - if (!IsTaskTime(tasksToBeIssueModel.NextTaskTime, timeDensity)) + var currentTaskTime = tasksToBeIssueModel.LastTaskTime.CalculateNextCollectionTime(timeDensity);//程序启动缓存电表的时候,NextTaskTime需要格式化到下一个采集点时间。 + if (!IsTaskTime(currentTaskTime, timeDensity))//todo 如果时间超过两个采集频率周期,就一直处理,直到追加到下一个采集频率周期。 { _logger.LogInformation($"{nameof(CreateToBeIssueTasks)} 构建待处理的下发指令任务处理时Key=>{item}时间节点不在当前时间范围内,103"); continue; @@ -185,12 +320,11 @@ namespace JiShe.CollectBus.ScheduledMeterReading var meterTypes = EnumExtensions.ToEnumDictionary(); - var currentTaskTime = tasksToBeIssueModel.NextTaskTime;//程序启动缓存电表的时候,NextTaskTime已经格式化到下一个采集点时间。 + //tasksToBeIssueModel.NextTaskTime; - var metadata = await _dbProvider.GetMetadata(); if (meteryType == MeterTypeEnum.Ammeter.ToString()) { - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTaskTime, meterType: MeterTypeEnum.Ammeter, @@ -199,16 +333,16 @@ namespace JiShe.CollectBus.ScheduledMeterReading var tempTask = await AmmerterCreatePublishTaskAction(timeDensity, data, groupIndex, timestamps); if (tempTask == null || tempTask.Count <= 0) { - _logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); + //_logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dbProvider.BatchInsertAsync(metadata, tempTask); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, tempTask)); }); } else if (meteryType == MeterTypeEnum.WaterMeter.ToString()) { - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTaskTime, meterType: MeterTypeEnum.WaterMeter, @@ -221,7 +355,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"水表 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dbProvider.BatchInsertAsync(metadata, tempTask); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.WatermeterSubscriberWorkerAutoReadingIssuedEventName, tempTask)); }); } else @@ -236,12 +370,18 @@ namespace JiShe.CollectBus.ScheduledMeterReading //根据当前的采集频率和类型,重新更新下一个任务点,把任务的创建源固定在当前逻辑,避免任务处理的逻辑异常导致任务创建失败。 tasksToBeIssueModel.LastTaskTime = currentTaskTime; tasksToBeIssueModel.NextTaskTime = currentTaskTime.CalculateNextCollectionTime(timeDensity); - await FreeRedisProvider.Instance.SetAsync(item, tasksToBeIssueModel); + await FreeRedisProvider.Instance.SetAsync(item, tasksToBeIssueModel); } - //电表定时阀控任务处理。 - _= AmmeterScheduledAutoValveControl(); - + ////电表定时阀控任务处理。 + //var autoValveControlTask = await AmmeterScheduledAutoValveControl(); + + //if (autoValveControlTask == null || autoValveControlTask.Count <= 0) + //{ + // _logger.LogWarning($"{nameof(AmmeterScheduledAutoValveControl)}电表定时阀控没有可操作的任务"); + // return; + //} + //_ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, autoValveControlTask)); } #region 电表采集处理 @@ -251,7 +391,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// /// 采集端Code /// - public virtual Task> GetAmmeterInfoList(string gatherCode = "") + public virtual Task> GetAmmeterInfoList(string gatherCode = "") { throw new NotImplementedException($"{nameof(GetAmmeterInfoList)}请根据不同系统类型进行实现"); } @@ -263,177 +403,178 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// public virtual async Task InitAmmeterCacheData(string gatherCode = "") { - //此处代码不要删除 - //#if DEBUG - // var timeDensity = "15"; - // var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}"; - // var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}"; - // var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}"; + //return; - // List meterInfos = new List(); - // List focusAddressDataLista = new List(); - // var timer1 = Stopwatch.StartNew(); - - // var allIds = new HashSet(); - // decimal? score = null; - // string member = null; - - // while (true) - // { - // var page = await _redisDataCacheService.GetAllPagedData( - // redisCacheMeterInfoHashKeyTemp, - // redisCacheMeterInfoZSetScoresIndexKeyTemp, - // pageSize: 1000, - // lastScore: score, - // lastMember: member); - - // meterInfos.AddRange(page.Items); - // focusAddressDataLista.AddRange(page.Items.Select(d => d.FocusAddress)); - // foreach (var item in page.Items) - // { - // if (!allIds.Add(item.MemberId)) - // { - // _logger.LogError($"{item.MemberId}Duplicate data found!"); - // } - // } - // if (!page.HasNext) break; - // score = page.NextScore; - // member = page.NextMember; - // } - - - // timer1.Stop(); - // _logger.LogError($"读取数据总共花费时间{timer1.ElapsedMilliseconds}毫秒"); - // DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista, _kafkaOptions.NumPartitions); - // return; - //#else - // var meterInfos = await GetAmmeterInfoList(gatherCode); - //#endif - var meterInfos = await GetAmmeterInfoList(gatherCode); - if (meterInfos == null || meterInfos.Count <= 0) + try { - throw new NullReferenceException($"{nameof(InitAmmeterCacheData)} 初始化电表缓存数据时,电表数据为空"); - } + // 创建取消令牌源 + //var cts = new CancellationTokenSource(); - //获取采集项类型数据 - var gatherItemInfos = await GetGatherItemByDataTypes(); - if (gatherItemInfos == null || gatherItemInfos.Count <= 0) - { - throw new NullReferenceException($"{nameof(InitAmmeterCacheData)} 初始化电表缓存数据时,采集项类型数据为空"); - } - var timer = Stopwatch.StartNew(); + _ = _dataChannelManage.ScheduledMeterTaskReadingAsync(DataChannelManage.TaskDataChannel.Reader); - List deviceIds = new List();//用于处理Kafka主题分区数据的分发和处理。 + // //此处代码不要删除 + //#if DEBUG + // var redisCacheDeviceInfoHashKeyTemp = $"CollectBus:Energy:JiSheCollectBus2:DeviceInfo"; - //根据采集频率分组,获得采集频率分组 - var meterInfoGroupByTimeDensity = meterInfos.GroupBy(d => d.TimeDensity); + // var timer1 = Stopwatch.StartNew(); + // Dictionary> keyValuePairsTemps = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceInfoHashKeyTemp); + // List meterInfos = new List(); + // List focusAddressDataLista = new List(); + // foreach (var item in keyValuePairsTemps) + // { + // foreach (var subItem in item.Value) + // { + // if (subItem.MeterType == MeterTypeEnum.Ammeter && subItem.TimeDensity == 15) + // { + // meterInfos.Add(subItem); + // focusAddressDataLista.Add(subItem.MeterId.ToString()); + // } + // } + // } - if (_applicationOptions.FirstCollectionTime.HasValue == false) - { - _applicationOptions.FirstCollectionTime = DateTime.Now; - } - //先处理采集频率任务缓存 - foreach (var item in meterInfoGroupByTimeDensity) - { - TasksToBeIssueModel nextTask = new TasksToBeIssueModel() + + // timer1.Stop(); + // _logger.LogError($"电表初始化读取数据总共花费时间{timer1.ElapsedMilliseconds}毫秒"); + // DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista, _kafkaOptions.NumPartitions); + // return; + //#else + // var meterInfos = await GetAmmeterInfoList(gatherCode); + //#endif + var meterInfos = await GetAmmeterInfoList(gatherCode); + if (meterInfos == null || meterInfos.Count <= 0) { - LastTaskTime = null, - TimeDensity = item.Key, - NextTaskTime = _applicationOptions.FirstCollectionTime.Value.CalculateNextCollectionTime(item.Key),//使用首次采集时间作为下一次采集时间 - }; + _logger.LogError($"{nameof(InitAmmeterCacheData)} 初始化电表缓存数据时,电表数据为空"); + return; + } - //todo 首次采集时间节点到目前运行时间中漏采的时间点,可以考虑使用IoTDB的存储,利用时间序列处理。 + _logger.LogError($"{nameof(InitAmmeterCacheData)} 初始化电表缓存数据时,读取数据成功"); - var taskRedisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, item.Key); - await FreeRedisProvider.Instance.SetAsync(taskRedisCacheKey, nextTask); - } - foreach (var itemTimeDensity in meterInfoGroupByTimeDensity) - { - var redisCacheMeterInfoHashKey = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, itemTimeDensity.Key)}"; - var redisCacheMeterInfoSetIndexKey = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, itemTimeDensity.Key)}"; - var redisCacheMeterInfoZSetScoresIndexKey = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, itemTimeDensity.Key)}"; - - List ammeterInfos = new List(); - //将表计信息根据集中器分组,获得集中器号 - var meterInfoGroup = itemTimeDensity.GroupBy(x => x.FocusAddress).ToList(); - foreach (var item in meterInfoGroup) + //获取采集项类型数据 + var gatherItemInfos = await GetGatherItemByDataTypes(); + if (gatherItemInfos == null || gatherItemInfos.Count <= 0) { - if (string.IsNullOrWhiteSpace(item.Key))//集中器号为空,跳过 - { - continue; - } + _logger.LogError($"{nameof(InitAmmeterCacheData)} 初始化电表缓存数据时,采集项类型数据为空"); + return; + } + var timer = Stopwatch.StartNew(); - foreach (var ammeter in item) - { - deviceIds.Add(ammeter.MeterId.ToString()); + List deviceIds = new List();//用于处理Kafka主题分区数据的分发和处理。 - //处理ItemCode - if (string.IsNullOrWhiteSpace(ammeter.ItemCodes) && !string.IsNullOrWhiteSpace(ammeter.DataTypes)) + //根据采集频率分组,获得采集频率分组 + var meterInfoGroupByTimeDensity = meterInfos.Select(d => d.TimeDensity).GroupBy(d => d); + var currentTaskTime = DateTime.Now; + if (_applicationOptions.FirstCollectionTime.HasValue == false) + { + _applicationOptions.FirstCollectionTime = currentTaskTime; + } + //先处理采集频率任务缓存 + foreach (var item in meterInfoGroupByTimeDensity) + { + TasksToBeIssueModel nextTask = new TasksToBeIssueModel() + { + LastTaskTime = _applicationOptions.FirstCollectionTime.Value.CalculateNextCollectionTime(item.Key), + TimeDensity = item.Key, + }; + nextTask.NextTaskTime = nextTask.LastTaskTime.CalculateNextCollectionTime(item.Key); + //todo 首次采集时间节点到目前运行时间中漏采的时间点,可以考虑使用IoTDB的存储,利用时间序列处理。 + + var taskRedisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, item.Key); + await FreeRedisProvider.Instance.SetAsync(taskRedisCacheKey, nextTask); + } + + //设备hash缓存key + string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; + + //设备分组集合key + string redisCacheDeviceGroupSetIndexKey = $"{string.Format(RedisConst.CacheDeviceGroupSetIndexKey, SystemType, ServerTagName)}"; + + Dictionary> keyValuePairs = new Dictionary>(); + + //处理设备缓存信息 + foreach (var ammeter in meterInfos) + { + deviceIds.Add(ammeter.MeterId.ToString()); + + //处理ItemCode + if (string.IsNullOrWhiteSpace(ammeter.ItemCodes) && !string.IsNullOrWhiteSpace(ammeter.DataTypes)) + { + var itemArr = ammeter.DataTypes.Split(',').ToList(); + + #region 拼接采集项 + List itemCodeList = new List(); + foreach (var dataType in itemArr) { - var itemArr = ammeter.DataTypes.Split(',').ToList(); - - #region 拼接采集项 - List itemCodeList = new List(); - foreach (var dataType in itemArr) + var excludeItemCode = "10_98,10_94";//TODO 排除透明转发:尖峰平谷时段、跳合闸,特殊电表 + var gatherItem = gatherItemInfos.FirstOrDefault(f => f.DataType.Equals(dataType)); + if (gatherItem != null) { - var excludeItemCode = "10_98,10_94";//TODO 排除透明转发:尖峰平谷时段、跳合闸,特殊电表 - var gatherItem = gatherItemInfos.FirstOrDefault(f => f.DataType.Equals(dataType)); - if (gatherItem != null) + if (!excludeItemCode.Contains(gatherItem.ItemCode)) { - if (!excludeItemCode.Contains(gatherItem.ItemCode)) - { - itemCodeList.Add(gatherItem.ItemCode); - } + itemCodeList.Add(gatherItem.ItemCode); } + } - #region 特殊电表采集项编号处理 - if (itemArr.Exists(e => e.Equals("95"))) //德力西DTS - { - itemCodeList.Add("10_95"); - } - if (itemArr.Exists(e => e.Equals("109")))//WAVE_109 - { - itemCodeList.Add("10_109"); - } - #endregion + #region 特殊电表采集项编号处理 + if (itemArr.Exists(e => e.Equals("95"))) //德力西DTS + { + itemCodeList.Add("10_95"); + } + if (itemArr.Exists(e => e.Equals("109")))//WAVE_109 + { + itemCodeList.Add("10_109"); } #endregion - - - - ammeter.ItemCodes = itemCodeList.Serialize();//转换成JSON字符串 - - if (!string.IsNullOrWhiteSpace(ammeter.ItemCodes)) - { - ammeter.ItemCodes = ammeter.ItemCodes.Replace("WAVE_109", "10_109"); - } } + #endregion - ammeterInfos.Add(ammeter); + + + ammeter.ItemCodes = itemCodeList.Serialize();//转换成JSON字符串 + + if (!string.IsNullOrWhiteSpace(ammeter.ItemCodes)) + { + ammeter.ItemCodes = ammeter.ItemCodes.Replace("WAVE_109", "10_109"); + } + } + + ammeter.ItemCodes = "10_97"; + + if (!keyValuePairs.ContainsKey(ammeter.FocusAddress)) + { + keyValuePairs[ammeter.FocusAddress] = new List() { ammeter.Adapt() }; + } + else + { + keyValuePairs[ammeter.FocusAddress].Add(ammeter.Adapt()); } } - await _redisDataCacheService.BatchInsertDataAsync( - redisCacheMeterInfoHashKey, - redisCacheMeterInfoSetIndexKey, - redisCacheMeterInfoZSetScoresIndexKey, ammeterInfos); - } + await _redisDataCacheService.BatchInsertDataAsync( + redisCacheDeviceGroupSetIndexKey, + redisCacheDeviceInfoHashKey, + keyValuePairs); - //初始化设备组负载控制 - if (deviceIds == null || deviceIds.Count <= 0) + //初始化设备组负载控制 + if (deviceIds == null || deviceIds.Count <= 0) + { + _logger.LogError($"{nameof(InitAmmeterCacheData)} 初始化设备组负载控制失败,没有找到对应的设备信息"); + + } + else + { + DeviceGroupBalanceControl.InitializeCache(deviceIds, _kafkaOptions.NumPartitions); + } + + timer.Stop(); + + _logger.LogWarning($"{nameof(InitAmmeterCacheData)} 初始化电表缓存数据完成,耗时{timer.ElapsedMilliseconds}毫秒"); + } + catch (Exception ex) { - _logger.LogError($"{nameof(InitAmmeterCacheData)} 初始化设备组负载控制失败,没有找到对应的设备信息"); - + _logger.LogError(ex, $"{nameof(InitAmmeterCacheData)} 初始化电表缓存数据异常"); + throw ex; } - else - { - DeviceGroupBalanceControl.InitializeCache(deviceIds, _kafkaOptions.NumPartitions); - } - - timer.Stop(); - - _logger.LogInformation($"{nameof(InitAmmeterCacheData)} 初始化电表缓存数据完成,耗时{timer.ElapsedMilliseconds}毫秒"); } /// @@ -446,13 +587,13 @@ namespace JiShe.CollectBus.ScheduledMeterReading var redisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity); var taskInfo = await FreeRedisProvider.Instance.GetAsync(redisCacheKey); - if (taskInfo == null || taskInfo.LastTaskTime.HasValue == false) + if (taskInfo == null) { _logger.LogError($"{nameof(AmmeterScheduledMeterFifteenMinuteReading)} {timeDensity}分钟获取任务下发信息失败,请检查Redis中是否有对应的任务下发信息"); return; } - var pendingCopyReadTime = taskInfo.LastTaskTime.Value.GetDateTimeOffset().ToUnixTimeNanoseconds(); + var pendingCopyReadTime = taskInfo.LastTaskTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); var conditions = new List(); conditions.Add(new QueryCondition() @@ -483,13 +624,13 @@ namespace JiShe.CollectBus.ScheduledMeterReading var redisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity); var taskInfo = await FreeRedisProvider.Instance.GetAsync(redisCacheKey); - if (taskInfo == null || taskInfo.LastTaskTime.HasValue == false) + if (taskInfo == null) { _logger.LogError($"{nameof(AmmeterScheduledMeterFifteenMinuteReading)} {timeDensity}分钟获取任务下发信息失败,请检查Redis中是否有对应的任务下发信息"); return; } - var pendingCopyReadTime = taskInfo.LastTaskTime.Value.GetDateTimeOffset().ToUnixTimeNanoseconds(); + var pendingCopyReadTime = taskInfo.LastTaskTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); var conditions = new List(); conditions.Add(new QueryCondition() @@ -519,13 +660,13 @@ namespace JiShe.CollectBus.ScheduledMeterReading var redisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity); var taskInfo = await FreeRedisProvider.Instance.GetAsync(redisCacheKey); - if (taskInfo == null || taskInfo.LastTaskTime.HasValue == false) + if (taskInfo == null) { _logger.LogError($"{nameof(AmmeterScheduledMeterFifteenMinuteReading)} {timeDensity}分钟获取任务下发信息失败,请检查Redis中是否有对应的任务下发信息"); return; } - var pendingCopyReadTime = taskInfo.LastTaskTime.Value.GetDateTimeOffset().ToUnixTimeNanoseconds(); + var pendingCopyReadTime = taskInfo.LastTaskTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); var conditions = new List(); conditions.Add(new QueryCondition() @@ -553,7 +694,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - private async Task> AmmerterCreatePublishTaskAction(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps) + private async Task> AmmerterCreatePublishTaskAction(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; @@ -561,30 +702,26 @@ namespace JiShe.CollectBus.ScheduledMeterReading var protocolPlugin = await _protocolService.GetProtocolServiceAsync(ammeterInfo.BrandType); if (protocolPlugin == null) { - //_logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有找到对应的协议组件,-105"); - //return; + //_logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 创建电表待发送的任务数据{currentTime}没有找到对应的协议组件,-105"); + return null; } - - - //todo 检查需要待补抄的电表的时间点信息,保存到需要待补抄的缓存中。如果此线程异常,该如何补偿? - if (string.IsNullOrWhiteSpace(ammeterInfo.ItemCodes)) { - _logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 集中器{ammeterInfo.FocusAddress}的电表{ammeterInfo.Name}数据采集指令生成失败,采集项为空,-101"); + //_logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 集中器{ammeterInfo.FocusAddress}的电表{ammeterInfo.Name}数据采集指令生成失败,采集项为空,-101"); return null; } //载波的不处理 if (ammeterInfo.MeteringPort == (int)MeterLinkProtocolEnum.Carrierwave) { - _logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 集中器{ammeterInfo.FocusAddress}的电表{ammeterInfo.Name}数据采集指令生成失败,载波不处理,-102"); + //_logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 集中器{ammeterInfo.FocusAddress}的电表{ammeterInfo.Name}数据采集指令生成失败,载波不处理,-102"); return null; } if (ammeterInfo.State.Equals(2)) { - _logger.LogWarning($"{nameof(AmmerterCreatePublishTaskAction)} {ammeterInfo.Name} 集中器{ammeterInfo.FocusAddress}的电表{ammeterInfo.Name}状态为禁用,不处理"); + //_logger.LogWarning($"{nameof(AmmerterCreatePublishTaskAction)} {ammeterInfo.Name} 集中器{ammeterInfo.FocusAddress}的电表{ammeterInfo.Name}状态为禁用,不处理"); return null; } @@ -597,22 +734,22 @@ namespace JiShe.CollectBus.ScheduledMeterReading if (string.IsNullOrWhiteSpace(ammeterInfo.AreaCode)) { - _logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 表ID:{ammeterInfo.MeterId},集中器通信区号为空"); + //_logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 表ID:{ammeterInfo.MeterId},集中器通信区号为空"); return null; } if (string.IsNullOrWhiteSpace(ammeterInfo.Address)) { - _logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 表ID:{ammeterInfo.MeterId},集中器通信地址为空"); + //_logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 表ID:{ammeterInfo.MeterId},集中器通信地址为空"); return null; } if (Convert.ToInt32(ammeterInfo.Address) > 65535) { - _logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 表ID:{ammeterInfo.MeterId},集中器通信地址无效,确保大于65535"); + //_logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 表ID:{ammeterInfo.MeterId},集中器通信地址无效,确保大于65535"); return null; } if (ammeterInfo.MeteringCode <= 0 || ammeterInfo.MeteringCode > 33) { - _logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 表ID:{ammeterInfo.MeterId},非有效测量点号({ammeterInfo.MeteringCode})"); + //_logger.LogError($"{nameof(AmmerterCreatePublishTaskAction)} 表ID:{ammeterInfo.MeterId},非有效测量点号({ammeterInfo.MeteringCode})"); return null; } @@ -668,12 +805,28 @@ namespace JiShe.CollectBus.ScheduledMeterReading //var aFN = (AFN)aFNStr.HexToDec(); //var fn = int.Parse(itemCodeArr[1]); + var itemCodeInfo = T37612012PacketItemCodeConst.MappingItemCodeTo645SubCodeRelationship(tempItem); + //TODO:特殊表 ProtocolBuildResponse builderResponse = await protocolPlugin.BuildAsync(new ProtocolBuildRequest() { FocusAddress = ammeterInfo.FocusAddress, Pn = ammeterInfo.MeteringCode, - ItemCode = tempItem, + ItemCode = itemCodeInfo.Item1, + DataTimeMark = new Protocol.DataTimeMark() + { + Density = ammeterInfo.TimeDensity.GetFocusDensity(),//转换成协议的值 + Point = 1, + DataTime = timestamps, + }, + SubProtocolRequest = new SubProtocolBuildRequest() + { + MeterAddress = ammeterInfo.MeterAddress, + Password = ammeterInfo.Password, + MeteringPort = ammeterInfo.MeteringPort, + Baudrate = ammeterInfo.Baudrate, + ItemCode = itemCodeInfo.Item2, //10_97 => 11_02_80_00_02 + } }); if (builderResponse == null || builderResponse.Data.Length <= 0) { @@ -681,34 +834,16 @@ namespace JiShe.CollectBus.ScheduledMeterReading continue; } - - string taskMark = CommonHelper.GetTaskMark(builderResponse.AFn, builderResponse.Fn, ammeterInfo.MeteringCode, builderResponse.MSA, builderResponse.Seq); - var meterReadingRecords = new MeterReadingTelemetryPacketInfo() - { - SystemName = SystemType, - ProjectId = $"{ammeterInfo.ProjectID}", - DeviceType = $"{MeterTypeEnum.Ammeter}", - DeviceId = $"{ammeterInfo.MeterId}", - Timestamps = DateTimeOffset.Now.ToUnixTimeNanoseconds(), - DatabaseBusiID = ammeterInfo.DatabaseBusiID, - PendingCopyReadTime = timestamps, - CreationTime = currentTime, - MeterAddress = ammeterInfo.AmmerterAddress, - AFN = builderResponse.AFn, - Fn = builderResponse.Fn, - Seq = builderResponse.Seq, - MSA = builderResponse.MSA, - ItemCode = tempItem, - TaskMark = taskMark, - IsSend = false, - ManualOrNot = false, - Pn = ammeterInfo.MeteringCode, - IssuedMessageId = GuidGenerator.Create().ToString(), - IssuedMessageHexString = Convert.ToHexString(builderResponse.Data), - IsReceived = false, - ScoreValue = $"{ammeterInfo.FocusAddress}.{taskMark}".Md5Fun(), - }; - + var meterReadingRecords = CreateAmmeterPacketInfo( + ammeterInfo: ammeterInfo, + timestamps: DateTimeOffset.Now.ToUnixTimeNanoseconds(), + builderResponse: builderResponse, + itemCode: tempItem, + subItemCode: null, + pendingCopyReadTime: timestamps, + creationTime: currentTime, + packetType: (TelemetryPacketTypeEnum)timeDensity, + _guidGenerator); taskList.Add(meterReadingRecords); } @@ -729,7 +864,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 电表自动阀控 /// /// - public virtual Task AmmeterScheduledAutoValveControl() + public virtual Task> AmmeterScheduledAutoValveControl() { throw new NotImplementedException($"{nameof(AmmeterScheduledAutoValveControl)}请根据不同系统类型进行实现"); } @@ -742,7 +877,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - public virtual async Task AmmeterScheduledAutomaticVerificationTime(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps) + public virtual async Task> AmmeterScheduledAutomaticVerificationTime(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm:00}"; @@ -750,14 +885,13 @@ namespace JiShe.CollectBus.ScheduledMeterReading try { //判断是否是自动校时时间 - if (!string.Equals(currentTimeStr , _applicationOptions.AutomaticVerificationTime,StringComparison.CurrentCultureIgnoreCase)) + if (!string.Equals(currentTimeStr, _applicationOptions.AutomaticVerificationTime, StringComparison.CurrentCultureIgnoreCase)) { _logger.LogInformation($"{nameof(AmmeterScheduledAutomaticVerificationTime)} 电表自动校时,非自动校时时间"); - return; + return null; } - + List taskList = new List(); - var metadata = await _dbProvider.GetMetadata(); var itemCode = T37612012PacketItemCodeConst.AFN10HFN01H; var subItemCode = T6452007PacketItemCodeConst.C08; @@ -767,9 +901,9 @@ namespace JiShe.CollectBus.ScheduledMeterReading if (protocolPlugin == null) { _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有找到对应的协议组件,-105"); - return; + return null; } - + ProtocolBuildResponse builderResponse = await protocolPlugin.BuildAsync(new ProtocolBuildRequest() { FocusAddress = ammeterInfo.FocusAddress, @@ -777,59 +911,31 @@ namespace JiShe.CollectBus.ScheduledMeterReading ItemCode = itemCode, SubProtocolRequest = new SubProtocolBuildRequest() { - MeterAddress = ammeterInfo.AmmerterAddress, + MeterAddress = ammeterInfo.MeterAddress, Password = ammeterInfo.Password, ItemCode = subItemCode, } }); - string taskMark = CommonHelper.GetTaskMark(builderResponse.AFn, builderResponse.Fn, ammeterInfo.MeteringCode, builderResponse.MSA, builderResponse.Seq); - var meterReadingRecords = new MeterReadingTelemetryPacketInfo() - { - SystemName = SystemType, - ProjectId = $"{ammeterInfo.ProjectID}", - DeviceType = $"{MeterTypeEnum.Ammeter}", - DeviceId = $"{ammeterInfo.MeterId}", - Timestamps = currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), - DatabaseBusiID = ammeterInfo.DatabaseBusiID, - PendingCopyReadTime = currentTime, - CreationTime = currentTime, - MeterAddress = ammeterInfo.AmmerterAddress, - AFN = builderResponse.AFn, - Fn = builderResponse.Fn, - Seq = builderResponse.Seq, - MSA = builderResponse.MSA, - ItemCode = itemCode, - SubItemCode = subItemCode, - TaskMark = taskMark, - IsSend = false, - ManualOrNot = false, - Pn = ammeterInfo.MeteringCode, - IssuedMessageId = GuidGenerator.Create().ToString(), - IssuedMessageHexString = Convert.ToHexString(builderResponse.Data), - IsReceived = false, - ScoreValue = $"{ammeterInfo.FocusAddress}.{taskMark}".Md5Fun(), - }; + var meterReadingRecords = CreateAmmeterPacketInfo( + ammeterInfo: ammeterInfo, + timestamps: currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), + builderResponse: builderResponse, + itemCode: itemCode, + subItemCode: subItemCode, + pendingCopyReadTime: currentTime, + creationTime: currentTime, + packetType: TelemetryPacketTypeEnum.AmmeterAutomaticVerificationTime, + _guidGenerator); taskList.Add(meterReadingRecords); if (taskList == null || taskList.Count <= 0) { _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有自动阀控任务生成,-106"); - return; + return null; } - //任务记录入库 - await _dbProvider.BatchInsertAsync(metadata, taskList); - - //任务信息推送Kafka - _ = DeviceGroupBalanceControl.ProcessWithThrottleAsync( - items: taskList, - deviceIdSelector: data => data.DeviceId, - processor: (data, groupIndex) => - { - _ = KafkaProducerIssuedMessageAction(ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, data, groupIndex); - } - ); + return null; //todo 阀控记录入库,推送到新的服务 } @@ -839,7 +945,216 @@ namespace JiShe.CollectBus.ScheduledMeterReading throw; } } - + + /// + /// 日冻结抄读 + /// + /// 采集频率 + /// 电表信息 + /// 集中器所在分组 + /// 采集频率对应的时间戳 + /// + public virtual async Task> AmmeterScheduledGetAutomaticDayFreezeData(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) + { + var currentTime = DateTime.Now; + string currentTimeStr = $"{currentTime:HH:mm:00}"; + + try + { + //判断是否是自动校时时间 + if (!string.Equals(currentTimeStr, _applicationOptions.AutomaticVerificationTime, StringComparison.CurrentCultureIgnoreCase)) + { + _logger.LogInformation($"{nameof(AmmeterScheduledAutomaticVerificationTime)} 电表自动校时,非自动校时时间"); + return null; + } + + List taskList = new List(); + + //根据电表型号获取协议插件 + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(ammeterInfo.BrandType); + if (protocolPlugin == null) + { + _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有找到对应的协议组件,-105"); + return null; + } + + foreach (var item in DayFreezeCodes) + { + ProtocolBuildResponse builderResponse = await protocolPlugin.BuildAsync(new ProtocolBuildRequest() + { + FocusAddress = ammeterInfo.FocusAddress, + Pn = ammeterInfo.MeteringCode, + ItemCode = item + }); + + var meterReadingRecords = CreateAmmeterPacketInfo( + ammeterInfo: ammeterInfo, + timestamps: currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), + builderResponse: builderResponse, + itemCode: item, + subItemCode: null, + pendingCopyReadTime: currentTime, + creationTime: currentTime, + packetType: TelemetryPacketTypeEnum.AmmeterDayFreeze, + _guidGenerator); + taskList.Add(meterReadingRecords); + } + + + if (taskList == null || taskList.Count <= 0) + { + _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 日冻结抄读时间{currentTime}没有任务生成,-106"); + return null; + } + + return taskList; + + } + catch (Exception) + { + + throw; + } + } + + /// + /// 月冻结数据抄读 + /// + /// 采集频率 + /// 电表信息 + /// 集中器所在分组 + /// 采集频率对应的时间戳 + /// + public virtual async Task> AmmeterScheduledGetAutomaticMonthFreezeData(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) + { + var currentTime = DateTime.Now; + string currentTimeStr = $"{currentTime:HH:mm:00}"; + + try + { + //判断是否是自动校时时间 + if (!string.Equals(currentTimeStr, _applicationOptions.AutomaticVerificationTime, StringComparison.CurrentCultureIgnoreCase)) + { + _logger.LogInformation($"{nameof(AmmeterScheduledAutomaticVerificationTime)} 电表自动校时,非自动校时时间"); + return null; + } + + List taskList = new List(); + + //根据电表型号获取协议插件 + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(ammeterInfo.BrandType); + if (protocolPlugin == null) + { + _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有找到对应的协议组件,-105"); + return null; + } + + foreach (var item in DayFreezeCodes) + { + ProtocolBuildResponse builderResponse = await protocolPlugin.BuildAsync(new ProtocolBuildRequest() + { + FocusAddress = ammeterInfo.FocusAddress, + Pn = ammeterInfo.MeteringCode, + ItemCode = item + }); + + var meterReadingRecords = CreateAmmeterPacketInfo( + ammeterInfo: ammeterInfo, + timestamps: currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), + builderResponse: builderResponse, + itemCode: item, + subItemCode: null, + pendingCopyReadTime: currentTime, + creationTime: currentTime, + packetType: TelemetryPacketTypeEnum.AmmeterMonthFreeze, + _guidGenerator); + taskList.Add(meterReadingRecords); + } + + + if (taskList == null || taskList.Count <= 0) + { + _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 日冻结抄读时间{currentTime}没有任务生成,-106"); + return null; + } + + return taskList; + + } + catch (Exception) + { + + throw; + } + } + + /// + /// 电表监控重试抄读任务 + /// + /// + /// + public virtual async Task AmmeterScheduledRetryReading(RetryReadingEnum retryReadingEnum) + { + // 根据任务获取不同的锁 + var tryLock = FreeRedisProvider.Instance.Lock(retryReadingEnum.ToString(), 10); + try + { + if (tryLock != null) + { + // 轮询IotDB未成果下发电表数据 + var conditions = new List(); + // 下次发布时间小于等于当前时间 + conditions.Add(new QueryCondition() + { + Field = "NextSendTime", + Operator = "<", + IsNumber = false, + Value = DateTime.Now + }); + // 重试次数少于3次 + conditions.Add(new QueryCondition() + { + Field = "SendNum", + Operator = "<", + IsNumber = true, + Value = 3 + }); + //已发布的 + conditions.Add(new QueryCondition() + { + Field = "IsSend", + Operator = "=", + IsNumber = false, + Value = true + }); + // 未响应 + conditions.Add(new QueryCondition() + { + Field = "IsReceived", + Operator = "=", + IsNumber = false, + Value = false + }); + //await CreateMeterKafkaTaskMessage(ProtocolConst.AmmeterSubscriberWorkerRetryEventName, new IoTDBQueryOptions() + //{ + // TableNameOrTreePath = DevicePathBuilder.GetTableName(), + // PageIndex = 1, + // PageSize = pageSize, + // Conditions = conditions, + //}); + // 释放锁 + tryLock.Unlock(); + } + + } + catch (Exception) + { + // 释放锁 + tryLock.Unlock(); + throw; + } + } + #endregion @@ -850,7 +1165,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// /// 采集端Code /// - public virtual Task> GetWatermeterInfoList(string gatherCode = "") + public virtual Task> GetWatermeterInfoList(string gatherCode = "") { throw new NotImplementedException($"{nameof(GetWatermeterInfoList)}请根据不同系统类型进行实现"); } @@ -878,10 +1193,11 @@ namespace JiShe.CollectBus.ScheduledMeterReading List deviceIds = new List();//用于处理Kafka主题分区数据的分发和处理。 //根据采集频率分组,获得采集频率分组 - var meterInfoGroupByTimeDensity = meterInfos.GroupBy(d => d.TimeDensity); + var meterInfoGroupByTimeDensity = meterInfos.Select(d => d.TimeDensity).GroupBy(d => d); + var currentTime = DateTime.Now; if (_applicationOptions.FirstCollectionTime.HasValue == false) { - _applicationOptions.FirstCollectionTime = DateTime.Now; + _applicationOptions.FirstCollectionTime = currentTime; } //先处理采集频率任务缓存 @@ -889,49 +1205,46 @@ namespace JiShe.CollectBus.ScheduledMeterReading { TasksToBeIssueModel nextTask = new TasksToBeIssueModel() { - LastTaskTime = null, + LastTaskTime = _applicationOptions.FirstCollectionTime.Value.CalculateNextCollectionTime(item.Key), TimeDensity = item.Key, - NextTaskTime = _applicationOptions.FirstCollectionTime.Value.CalculateNextCollectionTime(item.Key),//使用首次采集时间作为下一次采集时间 }; + nextTask.NextTaskTime = nextTask.LastTaskTime.CalculateNextCollectionTime(item.Key);//使用首次采集时间作为下一次采集时间 + //todo 首次采集时间节点到目前运行时间中漏采的时间点,可以考虑使用IoTDB的存储,利用时间序列处理。 var taskRedisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.WaterMeter, item.Key); await FreeRedisProvider.Instance.SetAsync(taskRedisCacheKey, nextTask); } - foreach (var itemTimeDensity in meterInfoGroupByTimeDensity) + //设备hash缓存key + string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; + + //设备分组集合key + string redisCacheDeviceGroupSetIndexKey = $"{string.Format(RedisConst.CacheDeviceGroupSetIndexKey, SystemType, ServerTagName)}"; + + Dictionary> keyValuePairs = new Dictionary>(); + foreach (var subItem in meterInfos) { - List watermeterInfo = new List(); + deviceIds.Add(subItem.MeterId.ToString()); - //将表计信息根据集中器分组,获得集中器号 - var meterInfoGroup = itemTimeDensity.GroupBy(x => x.FocusAddress).ToList(); - foreach (var item in meterInfoGroup) + if (!keyValuePairs.ContainsKey(subItem.FocusAddress)) { - if (string.IsNullOrWhiteSpace(item.Key)) - { - continue; - } - - - var redisCacheMeterInfoHashKey = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, itemTimeDensity.Key)}"; - var redisCacheMeterInfoSetIndexKey = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, itemTimeDensity.Key)}"; - var redisCacheMeterInfoZSetScoresIndexKey = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, itemTimeDensity.Key)}"; - - foreach (var subItem in item) - { - deviceIds.Add(subItem.MeterId.ToString()); - - watermeterInfo.Add(subItem); - } - - await _redisDataCacheService.BatchInsertDataAsync( - redisCacheMeterInfoHashKey, - redisCacheMeterInfoSetIndexKey, - redisCacheMeterInfoZSetScoresIndexKey, watermeterInfo); + keyValuePairs[subItem.FocusAddress] = new List() { subItem }; + } + else + { + keyValuePairs[subItem.FocusAddress].Add(subItem); } } + + + await _redisDataCacheService.BatchInsertDataAsync( + redisCacheDeviceGroupSetIndexKey, + redisCacheDeviceInfoHashKey, + keyValuePairs); + //初始化设备组负载控制 if (deviceIds == null || deviceIds.Count <= 0) { @@ -951,20 +1264,20 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 水表数据采集 /// /// - public virtual async Task WatermeterScheduledMeterAutoReading() + public virtual async Task WatermeterScheduledMeterAutoReadding() { //获取缓存中的水表信息 int timeDensity = 60;//水表目前只有一个采集频率 60分钟 var redisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.WaterMeter, timeDensity); var taskInfo = await FreeRedisProvider.Instance.GetAsync(redisCacheKey); - if (taskInfo == null || taskInfo.LastTaskTime.HasValue == false) + if (taskInfo == null) { _logger.LogError($"{nameof(AmmeterScheduledMeterFifteenMinuteReading)} {timeDensity}分钟获取任务下发信息失败,请检查Redis中是否有对应的任务下发信息"); return; } - var pendingCopyReadTime = taskInfo.LastTaskTime.Value.GetDateTimeOffset().ToUnixTimeNanoseconds(); + var pendingCopyReadTime = taskInfo.LastTaskTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); var conditions = new List(); conditions.Add(new QueryCondition() @@ -975,15 +1288,15 @@ namespace JiShe.CollectBus.ScheduledMeterReading Value = pendingCopyReadTime }); - _ = CreateMeterKafkaTaskMessage(ProtocolConst.WatermeterSubscriberWorkerAutoReadingIssuedEventName, new IoTDBQueryOptions() - { - TableNameOrTreePath = DevicePathBuilder.GetTableName(), - PageIndex = 1, - PageSize = pageSize, - Conditions = conditions, - }); + //_ = CreateMeterKafkaTaskMessage(ProtocolConst.WatermeterSubscriberWorkerAutoReadingIssuedEventName, new IoTDBQueryOptions() + //{ + // TableNameOrTreePath = DevicePathBuilder.GetTableName(), + // PageIndex = 1, + // PageSize = pageSize, + // Conditions = conditions, + //}); - _logger.LogInformation($"{nameof(WatermeterScheduledMeterAutoReading)} {timeDensity}分钟采集水表数据处理完成"); + _logger.LogInformation($"{nameof(WatermeterScheduledMeterAutoReadding)} {timeDensity}分钟采集水表数据处理完成"); } /// @@ -995,7 +1308,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 时间格式的任务批次名称 /// private async Task> WatermeterCreatePublishTaskAction(int timeDensity - , WatermeterInfo watermeter, int groupIndex, DateTime timestamps) + , DeviceInfo watermeter, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; @@ -1022,9 +1335,9 @@ namespace JiShe.CollectBus.ScheduledMeterReading List taskList = new List(); - + //根据表型号获取协议插件 - var protocolPlugin = await _protocolService.GetProtocolServiceAsync(watermeter.Code); + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(watermeter.BrandType); if (protocolPlugin == null) { //_logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有找到对应的协议组件,-105"); @@ -1068,6 +1381,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading DeviceId = $"{watermeter.MeterId}", Timestamps = DateTimeOffset.Now.ToUnixTimeNanoseconds(), DatabaseBusiID = watermeter.DatabaseBusiID, + PacketType = (int)TelemetryPacketTypeEnum.WatermeterAutoReadding, PendingCopyReadTime = timestamps, CreationTime = currentTime, MeterAddress = watermeter.MeterAddress, @@ -1104,22 +1418,24 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - public virtual async Task ConcentratorScheduledAutomaticGetTerminalVersion(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps) + public virtual async Task> ConcentratorScheduledAutomaticGetTerminalVersion(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm:00}"; try { +#if DEBUG +#else //判断是否是自动获取版本号时间 - if (!string.Equals(currentTimeStr, _applicationOptions.AutomaticGetTerminalVersionTime, StringComparison.CurrentCultureIgnoreCase)) + if (!string.Equals(currentTimeStr, _applicationOptions.AutomaticTerminalVersionTime, StringComparison.CurrentCultureIgnoreCase)) { _logger.LogInformation($"{nameof(ConcentratorScheduledAutomaticGetTerminalVersion)} 集中器自动获取版本号,非自动处理时间"); - return; + return null; } +#endif List taskList = new List(); - var metadata = await _dbProvider.GetMetadata(); var itemCode = T37612012PacketItemCodeConst.AFN09HFN01H; //var subItemCode = T6452007PacketItemCodeConst.C08; @@ -1129,7 +1445,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading if (protocolPlugin == null) { _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 集中器自动获取版本号{currentTime}没有找到对应的协议组件,-105"); - return; + return null; } ProtocolBuildResponse builderResponse = await protocolPlugin.BuildAsync(new ProtocolBuildRequest() @@ -1145,53 +1461,26 @@ namespace JiShe.CollectBus.ScheduledMeterReading //} }); - string taskMark = CommonHelper.GetTaskMark(builderResponse.AFn, builderResponse.Fn, ammeterInfo.MeteringCode, builderResponse.MSA, builderResponse.Seq); - var meterReadingRecords = new MeterReadingTelemetryPacketInfo() - { - SystemName = SystemType, - ProjectId = $"{ammeterInfo.ProjectID}", - DeviceType = $"{MeterTypeEnum.Ammeter}", - DeviceId = $"{ammeterInfo.MeterId}", - Timestamps = currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), - DatabaseBusiID = ammeterInfo.DatabaseBusiID, - PendingCopyReadTime = currentTime, - CreationTime = currentTime, - MeterAddress = ammeterInfo.AmmerterAddress, - AFN = builderResponse.AFn, - Fn = builderResponse.Fn, - Seq = builderResponse.Seq, - MSA = builderResponse.MSA, - ItemCode = itemCode, - //SubItemCode = subItemCode, - TaskMark = taskMark, - IsSend = false, - ManualOrNot = false, - Pn = ammeterInfo.MeteringCode, - IssuedMessageId = GuidGenerator.Create().ToString(), - IssuedMessageHexString = Convert.ToHexString(builderResponse.Data), - IsReceived = false, - ScoreValue = $"{ammeterInfo.FocusAddress}.{taskMark}".Md5Fun(), - }; + var meterReadingRecords = CreateAmmeterPacketInfo( + ammeterInfo: ammeterInfo, + timestamps: currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), + builderResponse: builderResponse, + itemCode: itemCode, + subItemCode: null, + pendingCopyReadTime: currentTime, + creationTime: currentTime, + packetType: TelemetryPacketTypeEnum.TerminalVersion, + _guidGenerator); + taskList.Add(meterReadingRecords); if (taskList == null || taskList.Count <= 0) { _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有自动阀控任务生成,-106"); - return; + return null; } - //任务记录入库 - await _dbProvider.BatchInsertAsync(metadata, taskList); - - //任务信息推送Kafka - _ = DeviceGroupBalanceControl.ProcessWithThrottleAsync( - items: taskList, - deviceIdSelector: data => data.DeviceId, - processor: (data, groupIndex) => - { - _ = KafkaProducerIssuedMessageAction(ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, data, groupIndex); - } - ); + return taskList; } catch (Exception) { @@ -1208,7 +1497,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - public virtual async Task ConcentratorScheduledAutomaticGetTelematicsModule(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps) + public virtual async Task> ConcentratorScheduledAutomaticGetTelematicsModule(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm:00}"; @@ -1216,14 +1505,13 @@ namespace JiShe.CollectBus.ScheduledMeterReading try { //判断是否是自动获取版本号时间 - if (!string.Equals(currentTimeStr, _applicationOptions.AutomaticGetTerminalVersionTime, StringComparison.CurrentCultureIgnoreCase)) + if (!string.Equals(currentTimeStr, _applicationOptions.AutomaticTerminalVersionTime, StringComparison.CurrentCultureIgnoreCase)) { _logger.LogInformation($"{nameof(ConcentratorScheduledAutomaticGetTelematicsModule)} 自动获取远程通信模块(SIM)版本信息,非自动处理时间"); - return; + return null; } List taskList = new List(); - var metadata = await _dbProvider.GetMetadata(); var itemCode = T37612012PacketItemCodeConst.AFN09HFN09H; @@ -1232,7 +1520,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading if (protocolPlugin == null) { _logger.LogError($"{nameof(ConcentratorScheduledAutomaticGetTelematicsModule)} 自动获取远程通信模块(SIM)版本信息{currentTime}没有找到对应的协议组件,-105"); - return; + return null; } ProtocolBuildResponse builderResponse = await protocolPlugin.BuildAsync(new ProtocolBuildRequest() @@ -1242,53 +1530,26 @@ namespace JiShe.CollectBus.ScheduledMeterReading ItemCode = itemCode, }); - string taskMark = CommonHelper.GetTaskMark(builderResponse.AFn, builderResponse.Fn, ammeterInfo.MeteringCode, builderResponse.MSA, builderResponse.Seq); - var meterReadingRecords = new MeterReadingTelemetryPacketInfo() - { - SystemName = SystemType, - ProjectId = $"{ammeterInfo.ProjectID}", - DeviceType = $"{MeterTypeEnum.Ammeter}", - DeviceId = $"{ammeterInfo.MeterId}", - Timestamps = currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), - DatabaseBusiID = ammeterInfo.DatabaseBusiID, - PendingCopyReadTime = currentTime, - CreationTime = currentTime, - MeterAddress = ammeterInfo.AmmerterAddress, - AFN = builderResponse.AFn, - Fn = builderResponse.Fn, - Seq = builderResponse.Seq, - MSA = builderResponse.MSA, - ItemCode = itemCode, - //SubItemCode = subItemCode, - TaskMark = taskMark, - IsSend = false, - ManualOrNot = false, - Pn = ammeterInfo.MeteringCode, - IssuedMessageId = GuidGenerator.Create().ToString(), - IssuedMessageHexString = Convert.ToHexString(builderResponse.Data), - IsReceived = false, - ScoreValue = $"{ammeterInfo.FocusAddress}.{taskMark}".Md5Fun(), - }; + var meterReadingRecords = CreateAmmeterPacketInfo( + ammeterInfo: ammeterInfo, + timestamps: currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), + builderResponse: builderResponse, + itemCode: itemCode, + subItemCode: null, + pendingCopyReadTime: currentTime, + creationTime: currentTime, + packetType: TelemetryPacketTypeEnum.TelematicsModule, + _guidGenerator); + taskList.Add(meterReadingRecords); if (taskList == null || taskList.Count <= 0) { _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有自动阀控任务生成,-106"); - return; + return null; } - //任务记录入库 - await _dbProvider.BatchInsertAsync(metadata, taskList); - - //任务信息推送Kafka - _ = DeviceGroupBalanceControl.ProcessWithThrottleAsync( - items: taskList, - deviceIdSelector: data => data.DeviceId, - processor: (data, groupIndex) => - { - _ = KafkaProducerIssuedMessageAction(ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, data, groupIndex); - } - ); + return taskList; } catch (Exception) { @@ -1296,7 +1557,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading throw; } } - #endregion +#endregion #region 公共处理方法 @@ -1330,29 +1591,34 @@ namespace JiShe.CollectBus.ScheduledMeterReading var timer = Stopwatch.StartNew(); //获取对应频率中的所有电表信息 - var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, ServerTagName, meterType, timeDensity)}"; - var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, ServerTagName, meterType, timeDensity)}"; - var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, ServerTagName, meterType, timeDensity)}"; + //设备hash缓存key + string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; - List meterInfos = new List(); - decimal? cursor = null; - string member = null; - bool hasNext; - do - { - var page = await _redisDataCacheService.GetAllPagedData( - redisCacheMeterInfoHashKeyTemp, - redisCacheMeterInfoZSetScoresIndexKeyTemp, - pageSize: 1000, - lastScore: cursor, - lastMember: member); + //设备分组集合key + string redisCacheDeviceGroupSetIndexKey = $"{string.Format(RedisConst.CacheDeviceGroupSetIndexKey, SystemType, ServerTagName)}"; - meterInfos.AddRange(page.Items); - cursor = page.HasNext ? page.NextScore : null; - member = page.HasNext ? page.NextMember : null; - hasNext = page.HasNext; - } while (hasNext); + //List meterInfos = new List(); + //decimal? cursor = null; + //string member = null; + //while (true) + //{ + // var page = await _redisDataCacheService.GetAllPagedData2( + // redisCacheDeviceGroupSetIndexKey, + // redisCacheDeviceInfoHashKey, + // pageSize: 1000, + // lastScore: cursor, + // lastMember: member); + + // meterInfos.AddRange(page.Items); + // if (!page.HasNext) + // { + // break; + // } + + // cursor = page.NextScore; + // member = page.NextMember; + //} //var page = await _redisDataCacheService.GetAllPagedData( // redisCacheMeterInfoHashKeyTemp, @@ -1362,16 +1628,37 @@ namespace JiShe.CollectBus.ScheduledMeterReading // lastMember: member); //meterInfos.AddRange(page.Items); - if (meterInfos == null || meterInfos.Count <= 0) + //if (meterInfos == null || meterInfos.Count <= 0) + //{ + // timer.Stop(); + // _logger.LogError($"{nameof(CreateMeterPublishTask)} {meterType}的{timeDensity}分钟采集待下发任务创建失败,没有获取到缓存信息,-105"); + // return; + //} + + Dictionary> keyValuePairs = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceInfoHashKey); + + timer.Stop(); + + _logger.LogError($"{nameof(CreateMeterPublishTask)} 构建采集待下发任务,缓存获取信息共花费{timer.ElapsedMilliseconds}毫秒"); + + + List meterInfos = new List(); + foreach (var item in keyValuePairs) { - timer.Stop(); - _logger.LogError($"{nameof(CreateMeterPublishTask)} {meterType}的{timeDensity}分钟采集待下发任务创建失败,没有获取到缓存信息,-105"); - return; + foreach (var subItem in item.Value) + { + if (subItem.MeterType == meterType && subItem.TimeDensity == timeDensity) + { + meterInfos.Add(subItem); + } + } } + timer.Restart(); + await DeviceGroupBalanceControl.ProcessWithThrottleAsync( items: meterInfos, - deviceIdSelector: data => data.FocusAddress, + deviceIdSelector: data => data.MeterId.ToString(), processor: (data, groupIndex) => { taskCreateAction(timeDensity, data, groupIndex, nextTaskTime); @@ -1379,7 +1666,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading ); timer.Stop(); - _logger.LogInformation($"{nameof(CreateMeterPublishTask)} {meterType} {timeDensity}分钟采集待下发任务创建完成,耗时{timer.ElapsedMilliseconds}毫秒,总共{meterInfos.Count}表计信息"); + _logger.LogError($"{nameof(CreateMeterPublishTask)} {meterType} {timeDensity}分钟采集待下发任务创建完成,耗时{timer.ElapsedMilliseconds}毫秒,总共{meterInfos.Count}表计信息"); } @@ -1397,31 +1684,34 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogInformation($"{nameof(CreateMeterKafkaTaskMessage)} Kafka消息推送主题不能为空,-101"); return; } - int pageNumber = 0; + int pageNumber = 103; bool hasNext; var stopwatch = Stopwatch.StartNew(); do { + var stopwatch2 = Stopwatch.StartNew(); + options.PageIndex = pageNumber++; var pageResult = await _dbProvider.QueryAsync(options); hasNext = pageResult.HasNext; - await DeviceGroupBalanceControl.ProcessWithThrottleAsync( + _ = DeviceGroupBalanceControl.ProcessWithThrottleAsync( items: pageResult.Items.ToList(), deviceIdSelector: data => data.DeviceId, processor: (data, groupIndex) => { - _ = KafkaProducerIssuedMessageAction(ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, data, groupIndex); + _ = KafkaProducerIssuedMessageAction(kafkaTopicName, data, groupIndex); } ); - + stopwatch2.Stop(); + _logger.LogWarning($"{nameof(CreateMeterKafkaTaskMessage)} {kafkaTopicName}主题的任务 {options.TableNameOrTreePath} 路径批次{options.PageIndex}任务数据读取完成,共消耗{stopwatch2.ElapsedMilliseconds}毫秒。"); } while (hasNext); stopwatch.Stop(); - _logger.LogInformation($"{nameof(CreateMeterKafkaTaskMessage)} {kafkaTopicName}主题的任务 {options.TableNameOrTreePath} 路径任务推送完成,共消耗{stopwatch.ElapsedMilliseconds}毫秒。"); + _logger.LogWarning($"{nameof(CreateMeterKafkaTaskMessage)} {kafkaTopicName}主题的任务 {options.TableNameOrTreePath} 路径任务推送完成,共消耗{stopwatch.ElapsedMilliseconds}毫秒。"); } /// @@ -1439,9 +1729,62 @@ namespace JiShe.CollectBus.ScheduledMeterReading throw new Exception($"{nameof(KafkaProducerIssuedMessageAction)} 推送消息失败,参数异常,-101"); } - await _producerService.ProduceAsync(topicName, taskRecord, partition); + // await _dataChannelManage.ProduceAsync(topicName, taskRecord, partition); } + /// + /// 构建报文保存对象 + /// + /// 电表信息 + /// IoTDB存储时标 + /// 报文构建返回结果 + /// 端到云协议采集项编码 + /// 端到端采集项编码 + /// 待采集时间,定时采集频率才是特殊情况,其他默认当前时间戳 + /// 数据创建时间戳 + /// 数据包类型 + /// Guid生成器 + /// + protected MeterReadingTelemetryPacketInfo CreateAmmeterPacketInfo(DeviceInfo ammeterInfo, long timestamps, ProtocolBuildResponse builderResponse, string itemCode, string subItemCode, DateTime pendingCopyReadTime, DateTime creationTime, TelemetryPacketTypeEnum packetType, IGuidGenerator guidGenerator) + { + try + { + string taskMark = CommonHelper.GetTaskMark(builderResponse.AFn, builderResponse.Fn, ammeterInfo.MeteringCode, builderResponse.MSA, builderResponse.Seq); + return new MeterReadingTelemetryPacketInfo() + { + SystemName = SystemType, + ProjectId = $"{ammeterInfo.ProjectID}", + DeviceType = $"{MeterTypeEnum.Ammeter}", + DeviceId = $"{ammeterInfo.MeterId}", + Timestamps = timestamps, + DatabaseBusiID = ammeterInfo.DatabaseBusiID, + PendingCopyReadTime = pendingCopyReadTime, + CreationTime = creationTime, + MeterAddress = ammeterInfo.MeterAddress, + PacketType = (int)packetType, + AFN = builderResponse.AFn, + Fn = builderResponse.Fn, + Seq = builderResponse.Seq, + MSA = builderResponse.MSA, + FocusId = ammeterInfo.FocusId, + FocusAddress = ammeterInfo.FocusAddress, + ItemCode = itemCode, + SubItemCode = subItemCode, + TaskMark = taskMark, + IsSend = false, + ManualOrNot = false, + Pn = ammeterInfo.MeteringCode, + IssuedMessageId = guidGenerator.Create().ToString(), + IssuedMessageHexString = Convert.ToHexString(builderResponse.Data), + IsReceived = false, + ScoreValue = $"{ammeterInfo.FocusAddress}.{taskMark}".Md5Fun(), + }; + } + catch (Exception ex) + { + throw ex; + } + } #endregion } diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs index 9dc2fc3..c1fd4e4 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs @@ -1,21 +1,19 @@ using JiShe.CollectBus.Application.Contracts; using JiShe.CollectBus.Common; using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.DeviceBalanceControl; -using JiShe.CollectBus.Common.Encrypt; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.DataChannels; using JiShe.CollectBus.FreeSql; using JiShe.CollectBus.GatherItem; -using JiShe.CollectBus.IoTDB.Context; using JiShe.CollectBus.IoTDB.Interface; using JiShe.CollectBus.IotSystems.Ammeters; +using JiShe.CollectBus.IotSystems.Devices; using JiShe.CollectBus.IotSystems.MeterReadingRecords; -using JiShe.CollectBus.IotSystems.Watermeter; using JiShe.CollectBus.Kafka.Internal; -using JiShe.CollectBus.Kafka.Producer; using JiShe.CollectBus.Protocol.Interfaces; +using JiShe.CollectBus.Protocol.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -23,7 +21,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using JiShe.CollectBus.Protocol.Models; +using Volo.Abp.Guids; namespace JiShe.CollectBus.ScheduledMeterReading @@ -35,36 +33,38 @@ namespace JiShe.CollectBus.ScheduledMeterReading //[Route($"/energy/app/scheduled")] public class EnergySystemScheduledMeterReadingService : BasicScheduledMeterReadingService { + string systemType = string.Empty; string serverTagName = string.Empty; private readonly ILogger _logger; - private readonly IIoTDbProvider _dbProvider; private readonly IProtocolService _protocolService; + private readonly IGuidGenerator _guidGenerator; public EnergySystemScheduledMeterReadingService( ILogger logger, + IDataChannelManageService dataChannelManage, + IRedisDataCacheService redisDataCacheService, IIoTDbProvider dbProvider, - IOptions kafkaOptions, - IOptions applicationOptions, - IoTDBRuntimeContext runtimeContext, - IProducerService producerService, IProtocolService protocolService, - IRedisDataCacheService redisDataCacheService) + IGuidGenerator guidGenerator, + IOptions kafkaOptions, + IOptions applicationOptions) : base(logger, - producerService, + dataChannelManage, redisDataCacheService, dbProvider, - runtimeContext, protocolService, + guidGenerator, kafkaOptions, applicationOptions) { serverTagName = applicationOptions.Value.ServerTagName; - _dbProvider = dbProvider; + systemType = applicationOptions.Value.SystemType; _logger = logger; _protocolService = protocolService; + _guidGenerator = guidGenerator; } - public sealed override string SystemType => SystemTypeConst.Energy; + public sealed override string SystemType => systemType; public sealed override string ServerTagName => serverTagName; @@ -94,58 +94,185 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// //[HttpGet] //[Route($"ammeter/list")] - public override async Task> GetAmmeterInfoList(string gatherCode = "V4-Gather-8890") + public override async Task> GetAmmeterInfoList(string gatherCode = "V4-Gather-8890") { + //#if DEBUG + // var redisCacheDeviceInfoHashKeyTemp = $"CollectBus:Energy:JiSheCollectBus109:DeviceInfo"; - //List ammeterInfos = new List(); - //ammeterInfos.Add(new AmmeterInfo() - //{ - // Baudrate = 2400, - // FocusAddress = "402440506", - // Name = "张家祠工务(三相电表)", - // FocusId = 95780, - // DatabaseBusiID = 1, - // MeteringCode = 1, - // AmmerterAddress = "402410040506", - // MeterId = 127035, - // TypeName = 3, - // DataTypes = "449,503,581,582,583,584,585,586,587,588,589,590,591,592,593,594,597,598,599,600,601,602,603,604,605,606,607,608,661,663,677,679", - // TimeDensity = 15, - // BrandType = "", - //}); - //ammeterInfos.Add(new AmmeterInfo() - //{ - // Baudrate = 2400, - // FocusAddress = "542400504", - // Name = "五号配(长芦二所四排)(单相电表)", - // FocusId = 69280, - // DatabaseBusiID = 1, - // MeteringCode = 2, - // AmmerterAddress = "542410000504", - // MeterId = 95594, - // TypeName = 1, - // DataTypes = "581,589,592,597,601", - // TimeDensity = 15, - // BrandType = "", - //}); + // List ammeterInfos = FreeRedisProvider.Instance.Get>(redisCacheDeviceInfoHashKeyTemp);//542400504 - //return ammeterInfos; + // if (ammeterInfos == null || ammeterInfos.Count <= 0) + // { + // ammeterInfos = new List(); + // //ammeterInfos.Add(new DeviceInfo() + // //{ + // // Baudrate = 2400, + // // FocusAddress = "442400040", + // // Name = "保利单箱电表1", + // // FocusId = 95780, + // // DatabaseBusiID = 1, + // // MeteringCode = 0, + // // MeterAddress = "442405000040", + // // MeterId = 127035, + // // TypeName = 1, + // // DataTypes = "581,589,592,597,601", + // // TimeDensity = 15, + // // BrandType = "DTS1980", + // // MeterType = MeterTypeEnum.Ammeter, + // // ProjectID = 1, + // // MeteringPort = MeteringPortConst.MeteringPortTwo, + // // Password = "000000", + // //}); - string sql = $@"SELECT C.ID as MeterId,C.Name,C.FocusID as FocusId,C.SingleRate,C.MeteringCode,C.Code AS BrandType,C.Baudrate,C.Password,C.MeteringPort,C.[Address] AS AmmerterAddress,C.TypeName,C.Protocol,C.TripState,C.[State],B.[Address],B.AreaCode,B.AutomaticReport,D.DataTypes,B.TimeDensity,A.GatherCode,C.Special,C.[ProjectID],B.AbnormalState,B.LastTime,CONCAT(B.AreaCode, B.[Address]) AS FocusAddress,(select top 1 DatabaseBusiID from TB_Project where ID = B.ProjectID) AS DatabaseBusiID - FROM TB_GatherInfo(NOLOCK) AS A - INNER JOIN TB_FocusInfo(NOLOCK) AS B ON A.ID = B.GatherInfoID AND B.RemoveState >= 0 AND B.State>=0 - INNER JOIN TB_AmmeterInfo(NOLOCK) AS C ON B.ID = C.FocusID AND C.State>= 0 AND C.State<100 - INNER JOIN TB_AmmeterGatherItem(NOLOCK) AS D ON C.ID = D.AmmeterID AND D.State>=0 - WHERE 1=1 and C.Special = 0 "; - //TODO 记得移除特殊表过滤 + // //ammeterInfos.Add(new DeviceInfo() + // //{ + // // Baudrate = 2400, + // // FocusAddress = "442400039", + // // Name = "保利单箱电表2", + // // FocusId = 69280, + // // DatabaseBusiID = 1, + // // MeteringCode = 0, + // // MeterAddress = "442405000039", + // // MeterId = 95594, + // // TypeName = 1, + // // DataTypes = "581,589,592,597,601", + // // TimeDensity = 15, + // // BrandType = "DTS1980", + // // MeterType = MeterTypeEnum.Ammeter, + // // ProjectID = 1, + // // MeteringPort = MeteringPortConst.MeteringPortTwo, + // // Password = "000000", + // //}); - if (!string.IsNullOrWhiteSpace(gatherCode)) + // //ammeterInfos.Add(new DeviceInfo() + // //{ + // // Baudrate = 2400, + // // FocusAddress = "402440506", + // // Name = "中环半导体9#冷却泵-220KW(三相电表)", + // // FocusId = 106857, + // // DatabaseBusiID = 1, + // // MeteringCode = 0, + // // MeterAddress = "402410040506", + // // MeterId = 139059, + // // TypeName = 3, + // // DataTypes = "449,503,581,582,583,584,585,586,587,588,589,590,591,592,593,594,597,598,599,600,601,602,603,604,605,606,607,608,661,663,677,679", + // // TimeDensity = 15, + // // BrandType = "DTS1980", + // // Password = "000000", + // // ProjectID = 1, + // // MeterType = MeterTypeEnum.Ammeter, + // // MeteringPort = MeteringPortConst.MeteringPortTwo, + // //}); + + + // ammeterInfos.Add(new DeviceInfo() + // { + // Baudrate = 2400, + // FocusAddress = "942411321", + // Name = "DDS1980-T4(5-60) ML307A 长稳 942408011321", + // FocusId = 57682, + // DatabaseBusiID = 1, + // MeteringCode = 0, + // MeterAddress = "942408011321", + // MeterId = 78970, + // TypeName = 3, + // DataTypes = "449,503,581,582,583,584,585,586,587,588,589,590,591,592,593,594,597,598,599,600,601,602,603,604,605,606,607,608,661,663,677,679", + // TimeDensity = 15, + // BrandType = "DTS1980", + // Password = "000000", + // ProjectID = 1, + // MeterType = MeterTypeEnum.Ammeter, + // MeteringPort = MeteringPortConst.MeteringPortTwo, + // }); + + + // ammeterInfos.Add(new DeviceInfo() + // { + // Baudrate = 2400, + // FocusAddress = "942411319", + // Name = "DDS1980-T4(5-60) ML307A 长稳 942408011319", + // FocusId = 57685, + // DatabaseBusiID = 1, + // MeteringCode = 0, + // MeterAddress = "942408011319", + // MeterId = 78973, + // TypeName = 3, + // DataTypes = "449,503,581,582,583,584,585,586,587,588,589,590,591,592,593,594,597,598,599,600,601,602,603,604,605,606,607,608,661,663,677,679", + // TimeDensity = 15, + // BrandType = "DTS1980", + // Password = "000000", + // ProjectID = 1, + // MeterType = MeterTypeEnum.Ammeter, + // MeteringPort = MeteringPortConst.MeteringPortTwo, + // }); + + + // FreeRedisProvider.Instance.Set(redisCacheDeviceInfoHashKeyTemp, ammeterInfos); + // } + + // return ammeterInfos; + //#else + + + //#endif + + + try { - sql = $@"{sql} AND A.GatherCode = '{gatherCode}'"; + string sql = $@"SELECT + C.ID as MeterId, + C.Name, + C.FocusID as FocusId, + C.SingleRate, + C.MeteringCode, + C.Code AS BrandType, + C.Baudrate, + C.Password, + C.MeteringPort, + C.[Address] AS MeterAddress, + C.TypeName, + C.Protocol, + C.TripState, + C.[State], + B.[Address], + B.AreaCode, + B.AutomaticReport, + D.DataTypes, + B.TimeDensity, + A.GatherCode, + C.Special, + C.[ProjectID], + B.AbnormalState, + B.LastTime, + 1 as MeterType, + CONCAT(B.AreaCode, B.[Address]) AS FocusAddress, + (select top 1 DatabaseBusiID from TB_Project where ID = B.ProjectID) AS DatabaseBusiID + FROM TB_GatherInfo(NOLOCK) AS A + INNER JOIN TB_FocusInfo(NOLOCK) AS B ON A.ID = B.GatherInfoID AND B.RemoveState >= 0 AND B.State>=0 + INNER JOIN TB_AmmeterInfo(NOLOCK) AS C ON B.ID = C.FocusID AND C.State>= 0 AND C.State<100 + INNER JOIN TB_AmmeterGatherItem(NOLOCK) AS D ON C.ID = D.AmmeterID AND D.State>=0 + WHERE 1=1 and C.Special = 0 "; + //TODO 记得移除特殊表过滤 + + + #if DEBUG + //// sql = $@"{sql} and c.Address in('542410000504','442405000040','442405000039','402410040506')"; + sql = $@"{sql} and c.Address in('402410040506')"; +#endif + + if (!string.IsNullOrWhiteSpace(gatherCode)) + { + sql = $@"{sql} AND A.GatherCode = '{gatherCode}'"; + } + return await SqlProvider.Instance.Change(DbEnum.EnergyDB) + .Ado + .QueryAsync(sql); } - return await SqlProvider.Instance.Change(DbEnum.EnergyDB) - .Ado - .QueryAsync(sql); + catch (Exception ex) + { + throw ex; + } + } @@ -156,22 +283,30 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// public override async Task> GetAmmeterAutoValveControlSetting(string currentTime) { - string sql = $@"SELECT A.*,B.AmmeterID as MeterId,E.GatherCode,D.AreaCode,D.[Address],CONCAT(D.AreaCode, D.[Address]) AS FocusAddress,D.ID as FocusId + try + { + string sql = $@"SELECT A.*,B.AmmeterID as MeterId,E.GatherCode,D.AreaCode,D.[Address],CONCAT(D.AreaCode, D.[Address]) AS FocusAddress,D.ID as FocusId FROM TB_AutoTripTask(nolock) AS A INNER JOIN TB_AutoTripAmmeter(nolock) AS B ON A.ID=B.TripTaskID INNER JOIN TB_AmmeterInfo(nolock) AS C ON B.AmmeterID=C.ID INNER JOIN TB_FocusInfo(nolock) AS D ON D.ID=C.FocusID INNER JOIN TB_GatherInfo(NOLOCK) AS E ON E.ID=D.GatherInfoID - WHERE A.IsForbid=0 and A.State<>-1 and E.GatherCode LIKE '%V4%' and A.TripTime"; + WHERE A.IsForbid=0 and A.State<>-1 and E.GatherCode LIKE '%V4%' "; - if (!string.IsNullOrWhiteSpace(currentTime)) - { - sql = $@"{sql} AND A.TripTime = '{currentTime}'"; + if (!string.IsNullOrWhiteSpace(currentTime)) + { + sql = $@"{sql} AND A.TripTime = '{currentTime}'"; + } + + return await SqlProvider.Instance.Change(DbEnum.EnergyDB) + .Ado + .QueryAsync(sql); } + catch (Exception) + { - return await SqlProvider.Instance.Change(DbEnum.EnergyDB) - .Ado - .QueryAsync(sql); + throw; + } } @@ -179,26 +314,130 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 电表自动阀控 /// /// - public override async Task AmmeterScheduledAutoValveControl() + public override async Task> AmmeterScheduledAutoValveControl() { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm}"; try { +#if DEBUG + //电表自动阀控缓存 + string redisCacheDeviceSettingInfoHashKey = $"redisCacheDeviceSettingInfoHashKey_{SystemType}_{ServerTagName}"; + + var settingInfos = FreeRedisProvider.Instance.Get>(redisCacheDeviceSettingInfoHashKey); + if (settingInfos == null || settingInfos.Count <= 0) + { + settingInfos = new List(); + //settingInfos.Add(new AmmeterAutoValveControlSetting() + //{ + // MeterType = MeterTypeEnum.Ammeter, + // AmmerterAddress = "442405000040", + // FocusAddress = "442400040", + // FocusId = 57683, + // ProjectID = 1, + // TripType = "on", + // TripTime = $"{DateTime.Now:HH:mm}", + // MeterId = 78971, + // LoopType = "EachDay", + // EachDayWithout = "周六,周日", + // TimeDensity = 15, + //}); + //settingInfos.Add(new AmmeterAutoValveControlSetting() + //{ + // MeterType = MeterTypeEnum.Ammeter, + // AmmerterAddress = "442405000039", + // FocusAddress = "442400039", + // FocusId = 57684, + // ProjectID = 1, + // TripType = "on", + // TripTime = $"{DateTime.Now:HH:mm}", + // MeterId = 78972, + // LoopType = "EachDay", + // EachDayWithout = "周六,周日", + // TimeDensity = 15, + //}); + + //settingInfos.Add(new AmmeterAutoValveControlSetting() + //{ + // MeterType = MeterTypeEnum.Ammeter, + // AmmerterAddress = "542410000504", + // FocusAddress = "542400504", + // FocusId = 57686, + // ProjectID = 1, + // TripType = "on", + // TripTime = $"{DateTime.Now:HH:mm}", + // MeterId = 78974, + // LoopType = "EachDay", + // EachDayWithout = "周六,周日", + // TimeDensity = 15, + //}); + + //settingInfos.Add(new AmmeterAutoValveControlSetting() + //{ + // MeterType = MeterTypeEnum.Ammeter, + // AmmerterAddress = "402410040506", + // FocusAddress = "402440506", + // FocusId = 57685, + // ProjectID = 1, + // TripType = "on", + // TripTime = $"{DateTime.Now:HH:mm}", + // MeterId = 78973, + // LoopType = "EachDay", + // EachDayWithout = "周六,周日", + // TimeDensity = 15, + //}); + + settingInfos.Add(new AmmeterAutoValveControlSetting() + { + MeterType = MeterTypeEnum.Ammeter, + AmmerterAddress = "402410040506", + FocusAddress = "402440506", + FocusId = 57685, + ProjectID = 1, + TripType = "on", + TripTime = $"{DateTime.Now:HH:mm}", + MeterId = 78973, + LoopType = "EachDay", + EachDayWithout = "周六", + TimeDensity = 15, + }); + + FreeRedisProvider.Instance.Set(redisCacheDeviceSettingInfoHashKey, settingInfos); + } + + List meterInfos = await GetAmmeterInfoList(); +#else //获取电表阀控配置 var settingInfos = await GetAmmeterAutoValveControlSetting(currentTimeStr); - if (settingInfos == null || settingInfos.Count <= 0) { _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 电表自动阀控时,阀控数据为空, -101"); - return; + return null; } - //批量获取对应的缓存电表信息 - var ammeterInfos = new List(); + //设备hash缓存key + string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; + + Dictionary> keyValuePairsTemps = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceInfoHashKey); + List meterInfos = new List(); + List focusAddressDataLista = new List(); + foreach (var item in keyValuePairsTemps) + { + foreach (var subItem in item.Value) + { + if (subItem.MeterType == MeterTypeEnum.Ammeter && subItem.TimeDensity == 15) + { + meterInfos.Add(subItem); + focusAddressDataLista.Add(subItem.MeterId.ToString()); + } + } + } +#endif + + + List taskList = new List(); - var metadata = await _dbProvider.GetMetadata(); foreach (var settingInfo in settingInfos) { @@ -225,25 +464,31 @@ namespace JiShe.CollectBus.ScheduledMeterReading } //获取对应的缓存电表信息 - var ammeterInfo = ammeterInfos.First(); + var ammeterInfo = meterInfos.Where(d => d.MeterId == settingInfo.MeterId).FirstOrDefault(); + if (ammeterInfo == null) + { + _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 电表自动阀控时,未找到对应电表信息,电表Id={settingInfo.MeterId}, -102"); + continue; + } + bool tripStateResult = false; string itemCode = T37612012PacketItemCodeConst.AFN10HFN01H; string subItemCode = string.Empty; - if (settingInfo.TripType.Equals("on")) + if (settingInfo.TripType.Equals("on"))//当前电表断闸,需要合闸 { ammeterInfo.TripState = 0; tripStateResult = true; - subItemCode = T6452007PacketItemCodeConst.C1C01C; - if (ammeterInfo.TypeName != 1) + subItemCode = T6452007PacketItemCodeConst.C1C011C; + if (ammeterInfo.TypeName > 3) { - subItemCode = T6452007PacketItemCodeConst.C1C01B; + subItemCode = T6452007PacketItemCodeConst.C1C011B; } } - else if (settingInfo.TripType.Equals("off")) + else if (settingInfo.TripType.Equals("off"))//当前电表合闸,需要断闸 { ammeterInfo.TripState = 1; tripStateResult = false; - subItemCode = T6452007PacketItemCodeConst.C1C01A; + subItemCode = T6452007PacketItemCodeConst.C1C011A; } else { @@ -257,7 +502,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading if (protocolPlugin == null) { _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有找到对应的协议组件,-105"); - return; + return null; } ProtocolBuildResponse builderResponse = await protocolPlugin.BuildAsync(new ProtocolBuildRequest() @@ -267,60 +512,34 @@ namespace JiShe.CollectBus.ScheduledMeterReading ItemCode = itemCode, SubProtocolRequest = new SubProtocolBuildRequest() { - MeterAddress = ammeterInfo.AmmerterAddress, + MeterAddress = ammeterInfo.MeterAddress, Password = ammeterInfo.Password, ItemCode = subItemCode, + Baudrate = ammeterInfo.Baudrate, + MeteringPort = ammeterInfo.MeteringPort } }); - string taskMark = CommonHelper.GetTaskMark(builderResponse.AFn, builderResponse.Fn, ammeterInfo.MeteringCode, builderResponse.MSA, builderResponse.Seq); - var meterReadingRecords = new MeterReadingTelemetryPacketInfo() - { - SystemName = SystemType, - ProjectId = $"{ammeterInfo.ProjectID}", - DeviceType = $"{MeterTypeEnum.Ammeter}", - DeviceId = $"{ammeterInfo.MeterId}", - Timestamps = currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), - DatabaseBusiID = ammeterInfo.DatabaseBusiID, - PendingCopyReadTime = currentTime, - CreationTime = currentTime, - MeterAddress = ammeterInfo.AmmerterAddress, - AFN = builderResponse.AFn, - Fn = builderResponse.Fn, - Seq = builderResponse.Seq, - MSA = builderResponse.MSA, - ItemCode = itemCode, - SubItemCode = subItemCode, - TaskMark = taskMark, - IsSend = false, - ManualOrNot = false, - Pn = ammeterInfo.MeteringCode, - IssuedMessageId = GuidGenerator.Create().ToString(), - IssuedMessageHexString = Convert.ToHexString(builderResponse.Data), - IsReceived = false, - ScoreValue = $"{ammeterInfo.FocusAddress}.{taskMark}".Md5Fun(), - }; + + var meterReadingRecords = CreateAmmeterPacketInfo( + ammeterInfo: ammeterInfo, + timestamps: currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), + builderResponse: builderResponse, + itemCode: itemCode, + subItemCode: subItemCode, + pendingCopyReadTime: currentTime, + creationTime: currentTime, + packetType: TelemetryPacketTypeEnum.AmmeterAutoValveControl, + _guidGenerator); taskList.Add(meterReadingRecords); } if (taskList == null || taskList.Count <= 0) { _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有自动阀控任务生成,-106"); - return; + return null; } - //任务记录入库 - await _dbProvider.BatchInsertAsync(metadata, taskList); - - //任务信息推送Kafka - _ = DeviceGroupBalanceControl.ProcessWithThrottleAsync( - items: taskList, - deviceIdSelector: data => data.DeviceId, - processor: (data, groupIndex) => - { - _ = KafkaProducerIssuedMessageAction(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, data, groupIndex); - } - ); - + return taskList; //todo 阀控记录入库,推送到新的服务 } catch (Exception) @@ -337,9 +556,11 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// //[HttpGet] //[Route($"ammeter/list")] - public override async Task> GetWatermeterInfoList(string gatherCode = "V4-Gather-8890") + public override async Task> GetWatermeterInfoList(string gatherCode = "V4-Gather-8890") { - string sql = $@"SELECT + try + { + string sql = $@"SELECT A.ID as MeterId, A.Name, A.FocusID as FocusId, @@ -366,6 +587,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading A.[ProjectID], B.AbnormalState, B.LastTime, + 2 as MeterType, CONCAT(B.AreaCode, B.[Address]) AS FocusAddress, (select top 1 DatabaseBusiID from TB_Project where ID = b.ProjectID) AS DatabaseBusiID FROM [dbo].[TB_WatermeterInfo](NOLOCK) AS A @@ -373,13 +595,19 @@ namespace JiShe.CollectBus.ScheduledMeterReading INNER JOIN [dbo].[TB_GatherInfo](NOLOCK) AS C ON B.GatherInfoID=C.ID WHERE A.State>=0 AND A.State<100 "; - if (!string.IsNullOrWhiteSpace(gatherCode)) - { - sql = $@"{sql} AND C.GatherCode= '{gatherCode}'"; + if (!string.IsNullOrWhiteSpace(gatherCode)) + { + sql = $@"{sql} AND C.GatherCode= '{gatherCode}'"; + } + return await SqlProvider.Instance.Change(DbEnum.EnergyDB) + .Ado + .QueryAsync(sql); + } + catch (Exception) + { + + throw; } - return await SqlProvider.Instance.Change(DbEnum.EnergyDB) - .Ado - .QueryAsync(sql); } } } \ No newline at end of file diff --git a/services/JiShe.CollectBus.Application/Subscribers/SubscriberAnalysisAppService.cs b/services/JiShe.CollectBus.Application/Subscribers/SubscriberAnalysisAppService.cs index 3fd32fb..7b3517b 100644 --- a/services/JiShe.CollectBus.Application/Subscribers/SubscriberAnalysisAppService.cs +++ b/services/JiShe.CollectBus.Application/Subscribers/SubscriberAnalysisAppService.cs @@ -14,6 +14,8 @@ using System; using System.Threading.Tasks; using JiShe.CollectBus.Protocol; using TouchSocket.Sockets; +using JiShe.CollectBus.Protocol.Dto; +using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto; namespace JiShe.CollectBus.Subscribers { @@ -55,7 +57,7 @@ namespace JiShe.CollectBus.Subscribers } else { - if (receivedMessage.Data==null) + if (receivedMessage.Data == null) { Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); return SubscribeAck.Success(); @@ -70,11 +72,465 @@ namespace JiShe.CollectBus.Subscribers //var data = await analysisStrategy.ExecuteAsync>(tB3761); var executor = _serviceProvider.GetRequiredService(); - await executor.ExecuteAsync(serverName, receivedMessage.Data); + await executor.ExecuteAsync(serverName, receivedMessage.Data); } return SubscribeAck.Fail(); } + /// + /// 解析AFN01H + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN01HReceivedEventNameTemp)] + public async Task ReceivedAFN01Event(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + } + + return SubscribeAck.Fail(); + } + + + /// + /// 解析AFN02H + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN02HReceivedEventNameTemp)] + public async Task ReceivedAFN02Event(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data, (result) => + { + var ssss = (UnitDataAnalysis>)result; + _logger.LogInformation($"解析AFN02H数据:{ssss.Serialize()}"); + }); + return SubscribeAck.Success(); + } + return SubscribeAck.Fail(); + + } + + + /// + /// 解析AFN03H + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN03HReceivedEventNameTemp)] + public async Task ReceivedAFN03Event(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + + /// + /// 解析AFN04H + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN04HReceivedEventNameTemp)] + public async Task ReceivedAFN04Event(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + + /// + /// 解析AFN05H + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN05HReceivedEventNameTemp)] + public async Task ReceivedAFN05Event(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + + /// + /// 解析AFN09H + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN09HReceivedEventNameTemp)] + public async Task ReceivedAFN09Event(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + /// + /// 解析AFN0AH + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN0AHReceivedEventNameTemp)] + public async Task ReceivedAFN0AEvent(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + /// + /// 解析AFN0BH + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN0BHReceivedEventNameTemp)] + public async Task ReceivedAFN0BEvent(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + /// + /// 解析AFN0CH + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN0CHReceivedEventNameTemp)] + public async Task ReceivedAFN0CEvent(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + + /// + /// 解析AFN0DH + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN0DHReceivedEventNameTemp)] + public async Task ReceivedAFN0DEvent(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + + /// + /// 解析AFN0EH + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN0EHReceivedEventNameTemp)] + public async Task ReceivedAFN0EEvent(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } + + + /// + /// 解析AFN0HH + /// + /// + /// + [KafkaSubscribe(ProtocolConst.SubscriberAFN10HReceivedEventNameTemp)] + public async Task ReceivedAFN0HEvent(MessageProtocolAnalysis receivedMessage) + { + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); + if (protocolPlugin == null) + { + _logger.LogError("协议不存在!"); + } + else + { + if (receivedMessage.Data == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + if (receivedMessage.Data.DT == null || receivedMessage.Data.AFN_FC == null) + { + Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); + return SubscribeAck.Success(); + } + string serverName = $"AFN{receivedMessage.Data.AFN_FC.AFN}_F{receivedMessage.Data.DT.Fn}_Analysis"; + //var analysisStrategy = _serviceProvider.GetKeyedService($"AFN0_F1_Analysis"); + + //var data = await analysisStrategy.ExecuteAsync>(tB3761); + var executor = _serviceProvider.GetRequiredService(); + await executor.ExecuteAsync(serverName, receivedMessage.Data); + return SubscribeAck.Success(); + } + + return SubscribeAck.Fail(); + } } } diff --git a/services/JiShe.CollectBus.Application/Subscribers/SubscriberAppService.cs b/services/JiShe.CollectBus.Application/Subscribers/SubscriberAppService.cs index a082551..670fd7c 100644 --- a/services/JiShe.CollectBus.Application/Subscribers/SubscriberAppService.cs +++ b/services/JiShe.CollectBus.Application/Subscribers/SubscriberAppService.cs @@ -62,21 +62,19 @@ namespace JiShe.CollectBus.Subscribers [KafkaSubscribe(ProtocolConst.SubscriberLoginIssuedEventName, EnableBatch = true)] public async Task LoginIssuedEvent(List issuedEventMessages) { - bool isAck = false; + bool isAck = true; foreach (var issuedEventMessage in issuedEventMessages) { - var loginEntity = await _messageReceivedLoginEventRepository.FirstOrDefaultAsync(a => a.MessageId == issuedEventMessage.MessageId); - if (loginEntity == null) - { - isAck=false; - break; - } + //var loginEntity = await _messageReceivedLoginEventRepository.FirstOrDefaultAsync(a => a.MessageId == issuedEventMessage.MessageId); + //if (loginEntity == null) + //{ + // isAck=false; + // break; + //} - loginEntity.AckTime = Clock.Now; - loginEntity.IsAck = true; - await _messageReceivedLoginEventRepository.UpdateAsync(loginEntity); - isAck = true; - + //loginEntity.AckTime = Clock.Now; + //loginEntity.IsAck = true; + //await _messageReceivedLoginEventRepository.UpdateAsync(loginEntity); } // TODO:暂时ACK,等后续处理是否放到私信队列中 return isAck? SubscribeAck.Success(): SubscribeAck.Fail(); @@ -85,19 +83,19 @@ namespace JiShe.CollectBus.Subscribers [KafkaSubscribe(ProtocolConst.SubscriberHeartbeatIssuedEventName, EnableBatch = true)] public async Task HeartbeatIssuedEvent(List issuedEventMessages) { - bool isAck = false; - foreach (var issuedEventMessage in issuedEventMessages) - { - var heartbeatEntity = await _messageReceivedHeartbeatEventRepository.FirstOrDefaultAsync(a => a.MessageId == issuedEventMessage.MessageId); - if (heartbeatEntity == null) - { - isAck = false; - break; - } - heartbeatEntity.AckTime = Clock.Now; - heartbeatEntity.IsAck = true; - await _messageReceivedHeartbeatEventRepository.UpdateAsync(heartbeatEntity); - } + bool isAck = true; + //foreach (var issuedEventMessage in issuedEventMessages) + //{ + // var heartbeatEntity = await _messageReceivedHeartbeatEventRepository.FirstOrDefaultAsync(a => a.MessageId == issuedEventMessage.MessageId); + // if (heartbeatEntity == null) + // { + // isAck = false; + // break; + // } + // heartbeatEntity.AckTime = Clock.Now; + // heartbeatEntity.IsAck = true; + // await _messageReceivedHeartbeatEventRepository.UpdateAsync(heartbeatEntity); + // } // TODO:暂时ACK,等后续处理是否放到私信队列中 return isAck ? SubscribeAck.Success() : SubscribeAck.Fail(); } diff --git a/services/JiShe.CollectBus.Application/Subscribers/WorkerSubscriberAppService.cs b/services/JiShe.CollectBus.Application/Subscribers/WorkerSubscriberAppService.cs index e34c087..ee5f646 100644 --- a/services/JiShe.CollectBus.Application/Subscribers/WorkerSubscriberAppService.cs +++ b/services/JiShe.CollectBus.Application/Subscribers/WorkerSubscriberAppService.cs @@ -1,12 +1,15 @@ using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.IoTDB.Interface; using JiShe.CollectBus.IotSystems.MeterReadingRecords; using JiShe.CollectBus.Kafka.Attributes; using JiShe.CollectBus.Kafka.Internal; using Microsoft.Extensions.Logging; using System; +using System.Collections.Generic; using System.Threading.Tasks; using TouchSocket.Sockets; +using static FreeSql.Internal.GlobalFilter; namespace JiShe.CollectBus.Subscribers { @@ -45,7 +48,7 @@ namespace JiShe.CollectBus.Subscribers [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerOneMinuteIssuedEventName)] public async Task AmmeterScheduledMeterOneMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo receivedMessage) { - _logger.LogInformation("1分钟采集电表数据下行消息消费队列开始处理"); + _logger.LogError($"1分钟采集电表数据下行消息消费队列开始处理:{receivedMessage.Serialize()}"); return await SendMessagesAsync(receivedMessage); } @@ -55,10 +58,10 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerFiveMinuteIssuedEventName)] + [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerFiveMinuteIssuedEventName, EnableBatch = true, BatchSize = 500)] public async Task AmmeterScheduledMeterFiveMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo receivedMessage) { - _logger.LogInformation("5分钟采集电表数据下行消息消费队列开始处理"); + _logger.LogError($"5分钟采集电表数据下行消息消费队列开始处理:{receivedMessage.Serialize()}"); return await SendMessagesAsync(receivedMessage); } @@ -67,11 +70,16 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName)] - public async Task AmmeterScheduledMeterFifteenMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo receivedMessage) + [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, EnableBatch = true, TaskCount = 30, BatchSize = 500)] + public async Task AmmeterScheduledMeterFifteenMinuteReadingIssuedEvent(List receivedMessage) { - _logger.LogInformation("15分钟采集电表数据下行消息消费队列开始处理"); - return await SendMessagesAsync(receivedMessage); + + foreach (var item in receivedMessage) + { + _logger.LogError($"15分钟采集电表数据下行消息消费队列开始处理_ItemCode_{item.ItemCode}_{item.Serialize()}"); + await SendMessagesAsync(item); + } + return SubscribeAck.Success(); } /// @@ -79,13 +87,94 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName)] - public async Task AmmeterScheduledAutoValveControl(MeterReadingTelemetryPacketInfo receivedMessage) + [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, EnableBatch = true, BatchSize = 500)] + public async Task AmmeterScheduledAutoValveControl(List receivedMessage) { //todo 如果是时段自动阀控,需要检查当前的时间,如果时间在自动阀控时间段内,则发送自动阀控报文,否则不发送,尤其是消息队列阻塞或者延时过长的时候。以免造成生产事故。 - _logger.LogInformation("电表自动阀控下行消息消费队列开始处理"); - return await SendMessagesAsync(receivedMessage); + foreach (var item in receivedMessage) + { + _logger.LogError($"电表自动阀控下行消息消费队列开始处理:{item.Serialize()}"); + await SendMessagesAsync(item); + } + return SubscribeAck.Success(); } + + /// + /// 其他采集数据下行消息主题,日冻结,月冻结、集中器版本号、SIM卡号、定时校时等下行消息消费订阅 + /// + /// + /// + [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, EnableBatch = true, BatchSize = 500)] + public async Task AmmeterScheduledOther(List receivedMessage) + { + foreach (var item in receivedMessage) + { + _logger.LogError($"其他采集数据下行消息消费队列开始处理:{item.Serialize()}"); + await SendMessagesAsync(item); + } + return SubscribeAck.Success(); + } + + /// + /// 电表手动阀控下行消息消费订阅 + /// + /// + /// + [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerManualValveControlIssuedEventName)] + public async Task AmmeterScheduledManualValveControl(MeterReadingTelemetryPacketInfo receivedMessage) + { + _logger.LogError($"电表手动阀控下行消息消费队列开始处理:{receivedMessage.Serialize()}"); + + await SendMessagesAsync(receivedMessage); + return SubscribeAck.Success(); + } + + /// + /// 电表手动抄读下行消息消费订阅 + /// + /// + /// + [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName)] + public async Task AmmeterScheduledManualValveReading(MeterReadingTelemetryPacketInfo receivedMessage) + { + _logger.LogError($"电表手动抄读下行消息消费队列开始处理:{receivedMessage.Serialize()}"); + + await SendMessagesAsync(receivedMessage); + return SubscribeAck.Success(); + } + + /// + /// 重试电表下行消息消费队列 + /// + /// + /// + [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerRetryEventName)] + public async Task AmmeterScheduledMeterRetryReadingEvent(MeterReadingTelemetryPacketInfo receivedMessage) + { + _logger.LogInformation("重试电表数据下行消息消费队列开始处理"); + //return await SendMessagesAsync(receivedMessage); + try + { + var checkResult = _tcpService.ClientExists(receivedMessage.FocusAddress); + if (checkResult) + { + await _tcpService.SendAsync(receivedMessage.FocusAddress, Convert.FromHexString(receivedMessage.IssuedMessageHexString)); + receivedMessage.IsSend = true; + // 增加·发送次数和重试开始时间 + receivedMessage.SendNum += 1; + receivedMessage.NextSendTime = DateTime.Now.AddHours(1); + await _dbProvider.GetSessionPool(true).InsertAsync(receivedMessage); + // TODO: 第4次的时候会推送到地方预警处理 + } + // 由于有3次重试机会,故每次消息都会被确认 + return SubscribeAck.Success(); + } + catch (Exception) + { + throw; + } + } + #endregion #region 水表消息采集 @@ -96,9 +185,54 @@ namespace JiShe.CollectBus.Subscribers /// /// [KafkaSubscribe(ProtocolConst.WatermeterSubscriberWorkerAutoReadingIssuedEventName)] - public async Task WatermeterSubscriberWorkerAutoReadingIssuedEvent(MeterReadingTelemetryPacketInfo receivedMessage) + public async Task WatermeterScheduledAutoReading(MeterReadingTelemetryPacketInfo receivedMessage) { - return await SendMessagesAsync(receivedMessage); + _logger.LogError($"水表数据下行消息消费队列开始处理:{receivedMessage.Serialize()}"); + + await SendMessagesAsync(receivedMessage); + return SubscribeAck.Success(); + } + + /// + /// 水表自动阀控下行消息消费订阅 + /// + /// + /// + [KafkaSubscribe(ProtocolConst.WatermeterSubscriberWorkerAutoValveControlIssuedEventName)] + public async Task WatermeterScheduleAutoValveControl(MeterReadingTelemetryPacketInfo receivedMessage) + { + _logger.LogError($"水表自动阀控下行消息消费队列开始处理:{receivedMessage.Serialize()}"); + + await SendMessagesAsync(receivedMessage); + return SubscribeAck.Success(); + } + + /// + /// 水表手动阀控下行消息消费订阅 + /// + /// + /// + [KafkaSubscribe(ProtocolConst.WatermeterSubscriberWorkerManualValveControlIssuedEventName)] + public async Task WatermeterScheduleManualValveControl(MeterReadingTelemetryPacketInfo receivedMessage) + { + _logger.LogError($"水表手动阀控下行消息消费队列开始处理:{receivedMessage.Serialize()}"); + + await SendMessagesAsync(receivedMessage); + return SubscribeAck.Success(); + } + + /// + /// 水表手动抄读下行消息消费订阅 + /// + /// + /// + [KafkaSubscribe(ProtocolConst.WatermeterSubscriberWorkerManualValveReadingIssuedEventName)] + public async Task WatermeterScheduleManualValveReading(MeterReadingTelemetryPacketInfo receivedMessage) + { + _logger.LogError($"水表手动抄读下行消息消费队列开始处理:{receivedMessage.Serialize()}"); + + await SendMessagesAsync(receivedMessage); + return SubscribeAck.Success(); } #endregion @@ -117,7 +251,10 @@ namespace JiShe.CollectBus.Subscribers await _tcpService.SendAsync(receivedMessage.FocusAddress, Convert.FromHexString(receivedMessage.IssuedMessageHexString)); receivedMessage.IsSend = true; - await _dbProvider.InsertAsync(receivedMessage); + // 增加·发送次数和重试开始时间 + receivedMessage.SendNum += 1; + receivedMessage.NextSendTime = DateTime.Now.AddHours(1); + await _dbProvider.GetSessionPool(true).InsertAsync(receivedMessage); return SubscribeAck.Success(); } diff --git a/services/JiShe.CollectBus.Application/Workers/CreateToBeIssueTaskWorker.cs b/services/JiShe.CollectBus.Application/Workers/CreateToBeIssueTaskWorker.cs index 654abc4..d1de00a 100644 --- a/services/JiShe.CollectBus.Application/Workers/CreateToBeIssueTaskWorker.cs +++ b/services/JiShe.CollectBus.Application/Workers/CreateToBeIssueTaskWorker.cs @@ -1,43 +1,43 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Hangfire; -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.ScheduledMeterReading; -using Microsoft.Extensions.Logging; -using Volo.Abp.BackgroundWorkers.Hangfire; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Uow; +//using System; +//using System.Threading; +//using System.Threading.Tasks; +//using Hangfire; +//using JiShe.CollectBus.Common.Consts; +//using JiShe.CollectBus.ScheduledMeterReading; +//using Microsoft.Extensions.Logging; +//using Volo.Abp.BackgroundWorkers.Hangfire; +//using Volo.Abp.DependencyInjection; +//using Volo.Abp.Uow; -namespace JiShe.CollectBus.Workers -{ - /// - /// 构建待处理的下发指令任务处理 - /// - public class CreateToBeIssueTaskWorker : HangfireBackgroundWorkerBase, ITransientDependency, ICollectWorker - { - private readonly ILogger _logger; - private readonly IScheduledMeterReadingService _scheduledMeterReadingService; +//namespace JiShe.CollectBus.Workers +//{ +// /// +// /// 构建待处理的下发指令任务处理 +// /// +// public class CreateToBeIssueTaskWorker : HangfireBackgroundWorkerBase, ITransientDependency, ICollectWorker +// { +// private readonly ILogger _logger; +// private readonly IScheduledMeterReadingService _scheduledMeterReadingService; - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// 定时任务 - public CreateToBeIssueTaskWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) - { - _logger = logger; - RecurringJobId = nameof(CreateToBeIssueTaskWorker); - CronExpression = "0 0/1 * * * *"; - TimeZone = TimeZoneInfo.Local; - this._scheduledMeterReadingService = scheduledMeterReadingService; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The logger. +// /// 定时任务 +// public CreateToBeIssueTaskWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) +// { +// _logger = logger; +// RecurringJobId = nameof(CreateToBeIssueTaskWorker); +// CronExpression = "0 0/1 * * * *"; +// TimeZone = TimeZoneInfo.Local; +// this._scheduledMeterReadingService = scheduledMeterReadingService; +// } - public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) - { - _logger.LogError($"{DateTime.Now}"); - // await _scheduledMeterReadingService.CreateToBeIssueTasks(); - } - } -} +// public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// _logger.LogError($"{DateTime.Now}"); +// // await _scheduledMeterReadingService.CreateToBeIssueTasks(); +// } +// } +//} diff --git a/services/JiShe.CollectBus.Application/Workers/DataDetectionFifteenMinuteWorker.cs b/services/JiShe.CollectBus.Application/Workers/DataDetectionFifteenMinuteWorker.cs new file mode 100644 index 0000000..392c801 --- /dev/null +++ b/services/JiShe.CollectBus.Application/Workers/DataDetectionFifteenMinuteWorker.cs @@ -0,0 +1,39 @@ +//using JiShe.CollectBus.ScheduledMeterReading; +//using Microsoft.Extensions.Logging; +//using System; +//using System.Collections.Generic; +//using System.Linq; +//using System.Text; +//using System.Threading; +//using System.Threading.Tasks; +//using Volo.Abp.BackgroundWorkers.Hangfire; +//using Volo.Abp.DependencyInjection; + +//namespace JiShe.CollectBus.Workers +//{ +// /// +// /// 定时数据检测1小时一次 +// /// +// public class DataDetectionFifteenMinuteWorker : HangfireBackgroundWorkerBase, ITransientDependency, ICollectWorker +// { + +// private readonly ILogger _logger; +// private readonly IScheduledMeterReadingService _scheduledMeterReadingService; + +// public DataDetectionFifteenMinuteWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) +// { +// _logger = logger; +// RecurringJobId = nameof(CreateToBeIssueTaskWorker); +// CronExpression = "0 0 0/1 * * ?"; +// TimeZone = TimeZoneInfo.Local; +// this._scheduledMeterReadingService = scheduledMeterReadingService; +// } + + +// public override Task DoWorkAsync(CancellationToken cancellationToken = default) +// { +// //throw new NotImplementedException(); +// return Task.CompletedTask; +// } +// } +//} diff --git a/services/JiShe.CollectBus.Application/Workers/EpiCollectWorker.cs b/services/JiShe.CollectBus.Application/Workers/EpiCollectWorker.cs index 925692e..037e2e2 100644 --- a/services/JiShe.CollectBus.Application/Workers/EpiCollectWorker.cs +++ b/services/JiShe.CollectBus.Application/Workers/EpiCollectWorker.cs @@ -1,39 +1,39 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Hangfire; -using JiShe.CollectBus.Common.Attributes; -using Microsoft.Extensions.Logging; -using Volo.Abp.BackgroundWorkers.Hangfire; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Uow; +//using System; +//using System.Threading; +//using System.Threading.Tasks; +//using Hangfire; +//using JiShe.CollectBus.Common.Attributes; +//using Microsoft.Extensions.Logging; +//using Volo.Abp.BackgroundWorkers.Hangfire; +//using Volo.Abp.DependencyInjection; +//using Volo.Abp.Uow; -namespace JiShe.CollectBus.Workers -{ - public class EpiCollectWorker : HangfireBackgroundWorkerBase, ITransientDependency,ICollectWorker - { - private readonly ILogger _logger; +//namespace JiShe.CollectBus.Workers +//{ +// public class EpiCollectWorker : HangfireBackgroundWorkerBase, ITransientDependency,ICollectWorker +// { +// private readonly ILogger _logger; - /// - /// Initializes a new instance of the class. - /// - /// The logger. - public EpiCollectWorker(ILogger logger) - { - _logger = logger; - RecurringJobId = nameof(EpiCollectWorker); - CronExpression = Cron.Daily(); +// /// +// /// Initializes a new instance of the class. +// /// +// /// The logger. +// public EpiCollectWorker(ILogger logger) +// { +// _logger = logger; +// RecurringJobId = nameof(EpiCollectWorker); +// CronExpression = Cron.Daily(); - } +// } - public override Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) - { - using (var uow = LazyServiceProvider.LazyGetRequiredService().Begin()) - { - Logger.LogInformation("Executed MyLogWorker..!"); - return Task.CompletedTask; - } - } - } -} +// public override Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// using (var uow = LazyServiceProvider.LazyGetRequiredService().Begin()) +// { +// Logger.LogInformation("Executed MyLogWorker..!"); +// return Task.CompletedTask; +// } +// } +// } +//} diff --git a/services/JiShe.CollectBus.Application/Workers/SubscriberFifteenMinuteWorker.cs b/services/JiShe.CollectBus.Application/Workers/SubscriberFifteenMinuteWorker.cs index 005d46b..a7ca7c9 100644 --- a/services/JiShe.CollectBus.Application/Workers/SubscriberFifteenMinuteWorker.cs +++ b/services/JiShe.CollectBus.Application/Workers/SubscriberFifteenMinuteWorker.cs @@ -1,48 +1,48 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Hangfire; -using JiShe.CollectBus.ScheduledMeterReading; -using Microsoft.Extensions.Logging; -using Volo.Abp.BackgroundWorkers.Hangfire; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Uow; +//using System; +//using System.Threading; +//using System.Threading.Tasks; +//using Hangfire; +//using JiShe.CollectBus.ScheduledMeterReading; +//using Microsoft.Extensions.Logging; +//using Volo.Abp.BackgroundWorkers.Hangfire; +//using Volo.Abp.DependencyInjection; +//using Volo.Abp.Uow; -namespace JiShe.CollectBus.Workers -{ - /// - /// 15分钟采集数据 - /// - public class SubscriberFifteenMinuteWorker : HangfireBackgroundWorkerBase, ITransientDependency, ICollectWorker - { - private readonly ILogger _logger; - private readonly IScheduledMeterReadingService _scheduledMeterReadingService; +//namespace JiShe.CollectBus.Workers +//{ +// /// +// /// 15分钟采集数据 +// /// +// public class SubscriberFifteenMinuteWorker : HangfireBackgroundWorkerBase, ITransientDependency, ICollectWorker +// { +// private readonly ILogger _logger; +// private readonly IScheduledMeterReadingService _scheduledMeterReadingService; - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// 定时任务 - public SubscriberFifteenMinuteWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) - { - _logger = logger; - RecurringJobId = nameof(SubscriberFifteenMinuteWorker); - CronExpression = "0 0/15 * * * *"; - TimeZone = TimeZoneInfo.Local; - this._scheduledMeterReadingService = scheduledMeterReadingService; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The logger. +// /// 定时任务 +// public SubscriberFifteenMinuteWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) +// { +// _logger = logger; +// RecurringJobId = nameof(SubscriberFifteenMinuteWorker); +// CronExpression = "0 0/15 * * * *"; +// TimeZone = TimeZoneInfo.Local; +// this._scheduledMeterReadingService = scheduledMeterReadingService; +// } - public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) - { - //await _scheduledMeterReadingService.AmmeterScheduledMeterFifteenMinuteReading(); - //await _scheduledMeterReadingService.WatermeterScheduledMeterFifteenMinuteReading(); +// public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// //await _scheduledMeterReadingService.AmmeterScheduledMeterFifteenMinuteReading(); +// //await _scheduledMeterReadingService.WatermeterScheduledMeterFifteenMinuteReading(); - //using (var uow = LazyServiceProvider.LazyGetRequiredService().Begin()) - //{ - // Logger.LogInformation("Executed MyLogWorker..!"); - // return Task.CompletedTask; - //} - } - } -} +// //using (var uow = LazyServiceProvider.LazyGetRequiredService().Begin()) +// //{ +// // Logger.LogInformation("Executed MyLogWorker..!"); +// // return Task.CompletedTask; +// //} +// } +// } +//} diff --git a/services/JiShe.CollectBus.Application/Workers/SubscriberFiveMinuteWorker.cs b/services/JiShe.CollectBus.Application/Workers/SubscriberFiveMinuteWorker.cs index fbd3668..119421e 100644 --- a/services/JiShe.CollectBus.Application/Workers/SubscriberFiveMinuteWorker.cs +++ b/services/JiShe.CollectBus.Application/Workers/SubscriberFiveMinuteWorker.cs @@ -1,42 +1,42 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Hangfire; -using JiShe.CollectBus.ScheduledMeterReading; -using Microsoft.Extensions.Logging; -using Volo.Abp.BackgroundWorkers.Hangfire; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Uow; +//using System; +//using System.Threading; +//using System.Threading.Tasks; +//using Hangfire; +//using JiShe.CollectBus.ScheduledMeterReading; +//using Microsoft.Extensions.Logging; +//using Volo.Abp.BackgroundWorkers.Hangfire; +//using Volo.Abp.DependencyInjection; +//using Volo.Abp.Uow; -namespace JiShe.CollectBus.Workers -{ - /// - /// 5分钟采集数据 - /// - public class SubscriberFiveMinuteWorker : HangfireBackgroundWorkerBase, ITransientDependency,ICollectWorker - { - private readonly ILogger _logger; - private readonly IScheduledMeterReadingService _scheduledMeterReadingService; +//namespace JiShe.CollectBus.Workers +//{ +// /// +// /// 5分钟采集数据 +// /// +// public class SubscriberFiveMinuteWorker : HangfireBackgroundWorkerBase, ITransientDependency,ICollectWorker +// { +// private readonly ILogger _logger; +// private readonly IScheduledMeterReadingService _scheduledMeterReadingService; - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// 定时任务 - public SubscriberFiveMinuteWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) - { - _logger = logger; - RecurringJobId = nameof(SubscriberFiveMinuteWorker); - CronExpression = "0 0/5 * * * *"; - TimeZone = TimeZoneInfo.Local; - this._scheduledMeterReadingService = scheduledMeterReadingService; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The logger. +// /// 定时任务 +// public SubscriberFiveMinuteWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) +// { +// _logger = logger; +// RecurringJobId = nameof(SubscriberFiveMinuteWorker); +// CronExpression = "0 0/5 * * * *"; +// TimeZone = TimeZoneInfo.Local; +// this._scheduledMeterReadingService = scheduledMeterReadingService; +// } - public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) - { - //await _scheduledMeterReadingService.AmmeterScheduledMeterFiveMinuteReading(); - //await _scheduledMeterReadingService.WatermeterScheduledMeterFiveMinuteReading(); - } - } -} +// public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// //await _scheduledMeterReadingService.AmmeterScheduledMeterFiveMinuteReading(); +// //await _scheduledMeterReadingService.WatermeterScheduledMeterFiveMinuteReading(); +// } +// } +//} diff --git a/services/JiShe.CollectBus.Application/Workers/SubscriberOneMinuteWorker.cs b/services/JiShe.CollectBus.Application/Workers/SubscriberOneMinuteWorker.cs index e9e0240..419a681 100644 --- a/services/JiShe.CollectBus.Application/Workers/SubscriberOneMinuteWorker.cs +++ b/services/JiShe.CollectBus.Application/Workers/SubscriberOneMinuteWorker.cs @@ -1,44 +1,44 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Hangfire; -using JiShe.CollectBus.ScheduledMeterReading; -using Microsoft.Extensions.Logging; -using Volo.Abp.BackgroundWorkers.Hangfire; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Uow; +//using System; +//using System.Threading; +//using System.Threading.Tasks; +//using Hangfire; +//using JiShe.CollectBus.ScheduledMeterReading; +//using Microsoft.Extensions.Logging; +//using Volo.Abp.BackgroundWorkers.Hangfire; +//using Volo.Abp.DependencyInjection; +//using Volo.Abp.Uow; -namespace JiShe.CollectBus.Workers -{ - /// - /// 1分钟采集数据 - /// - public class SubscriberOneMinuteWorker : HangfireBackgroundWorkerBase, ITransientDependency,ICollectWorker - { - private readonly ILogger _logger; - private readonly IScheduledMeterReadingService _scheduledMeterReadingService; +//namespace JiShe.CollectBus.Workers +//{ +// /// +// /// 1分钟采集数据 +// /// +// public class SubscriberOneMinuteWorker : HangfireBackgroundWorkerBase, ITransientDependency,ICollectWorker +// { +// private readonly ILogger _logger; +// private readonly IScheduledMeterReadingService _scheduledMeterReadingService; - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// 定时任务 - public SubscriberOneMinuteWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) - { - _logger = logger; - RecurringJobId = nameof(SubscriberOneMinuteWorker); - CronExpression = "0 0/1 * * * *"; - TimeZone = TimeZoneInfo.Local; - this._scheduledMeterReadingService = scheduledMeterReadingService; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The logger. +// /// 定时任务 +// public SubscriberOneMinuteWorker(ILogger logger, IScheduledMeterReadingService scheduledMeterReadingService) +// { +// _logger = logger; +// RecurringJobId = nameof(SubscriberOneMinuteWorker); +// CronExpression = "0 0/1 * * * *"; +// TimeZone = TimeZoneInfo.Local; +// this._scheduledMeterReadingService = scheduledMeterReadingService; +// } - public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) - { - //await _scheduledMeterReadingService.AmmeterScheduledMeterOneMinuteReading(); +// public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// //await _scheduledMeterReadingService.AmmeterScheduledMeterOneMinuteReading(); - //await _scheduledMeterReadingService.WatermeterScheduledMeterOneMinuteReading(); +// //await _scheduledMeterReadingService.WatermeterScheduledMeterOneMinuteReading(); - } - } -} +// } +// } +//} diff --git a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs index ee132d3..796f328 100644 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs +++ b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs @@ -1,15 +1,11 @@ -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.Analyzers.Shared; +using JiShe.CollectBus.IoTDB.Attributes; using JiShe.CollectBus.IoTDB.Model; +using System; namespace JiShe.CollectBus.Ammeters { - [EntityType(EntityTypeEnum.TableModel)] + [SourceAnalyzers(EntityTypeEnum.TableModel)] public class ElectricityMeter : IoTEntity { [ATTRIBUTEColumn] @@ -34,9 +30,12 @@ namespace JiShe.CollectBus.Ammeters public double Current { get; set; } [FIELDColumn] - public double Power => Voltage * Current; + public double Power { get; set; } [FIELDColumn] public double? Currentd { get; set; } + + [FIELDColumn] + public DateTime? CurrentdDateTime { get; set; } } } diff --git a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs index 7fe7ebc..6eb5ef4 100644 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs +++ b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs @@ -1,10 +1,11 @@ -using JiShe.CollectBus.IoTDB.Attribute; -using JiShe.CollectBus.IoTDB.Enums; +using JiShe.CollectBus.Analyzers.Shared; +using JiShe.CollectBus.IoTDB.Attributes; using JiShe.CollectBus.IoTDB.Model; +using System; namespace JiShe.CollectBus.Ammeters { - [EntityType(EntityTypeEnum.TreeModel)] + [SourceAnalyzers(EntityTypeEnum.TreeModel)] public class ElectricityMeterTreeModel : IoTEntity { [ATTRIBUTEColumn] @@ -29,7 +30,7 @@ namespace JiShe.CollectBus.Ammeters public double Current { get; set; } [FIELDColumn] - public double Power => Voltage * Current; + public double Power { get; set; } [FIELDColumn] public double? Currentd { get; set; } diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterInfo.cs index 60d6c91..a7792c3 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterInfo.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterInfo.cs @@ -20,7 +20,7 @@ namespace JiShe.CollectBus.IotSystems.Ammeters /// ZSet排序索引分数值,具体值可以根据不同业务场景进行定义,例如时间戳 /// [Column(IsIgnore = true)] - public override long ScoreValue => ((long)FocusId << 32) | (uint)DateTime.Now.Ticks; + public override long ScoreValue => Common.Helpers.CommonHelper.GetFocusScores(FocusAddress,MeteringCode); /// /// 电表名称 @@ -79,12 +79,7 @@ namespace JiShe.CollectBus.IotSystems.Ammeters /// 电表密码 /// public string Password { get; set; } - - /// - /// 采集时间间隔(分钟,如15) - /// - public int TimeDensity { get; set; } - + /// /// 该电表方案下采集项,JSON格式,如:["0D_80","0D_80"] /// diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceInfo.cs new file mode 100644 index 0000000..61fe6f5 --- /dev/null +++ b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceInfo.cs @@ -0,0 +1,180 @@ +using FreeSql.DataAnnotations; +using JiShe.CollectBus.Analyzers.Shared; +using JiShe.CollectBus.Common.Enums; +using JiShe.CollectBus.Common.Models; +using JiShe.CollectBus.IoTDB.Attributes; +using JiShe.CollectBus.IoTDB.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.IotSystems.Devices +{ + /// + /// 设备信息 + /// + public class DeviceInfo : DeviceCacheBasicModel + { + /// + /// 关系映射标识,用于ZSet的Member字段和Set的Value字段,具体值可以根据不同业务场景进行定义 + /// + [Column(IsIgnore = true)] + public override string MemberId => $"{FocusAddress}:{MeteringCode}"; + + /// + /// ZSet排序索引分数值,具体值可以根据不同业务场景进行定义,例如时间戳 + /// + [Column(IsIgnore = true)] + public override long ScoreValue => Common.Helpers.CommonHelper.GetFocusScores(FocusAddress, MeteringCode); + + /// + /// 通讯方案: + /// NB-IOT常德水表、NB-IOT泽联电表、GPRS华立水表、 + /// RS-485、无线、载波 + /// + public string LinkType { get; set; } + + /// + /// HaveValve: 是否带阀 (0 不带阀, 1 带阀) + /// 注意:NULL表示未设置 + /// + public int? HaveValve { get; set; } + + /// + /// 设备类型: 水表\气表、流量计 + /// + public string MeterTypeName { get; set; } + + /// + /// 设备品牌; + /// (当 MeterType = 水表, 如 威铭、捷先 等) + /// (当 MeterType = 流量计, 如 西恩超声波流量计、西恩电磁流量计、涡街流量计 等) + /// + public string MeterBrand { get; set; } + + /// + /// 倍率 + /// + public decimal TimesRate { get; set; } + + /// + /// 电表名称 + /// + public string Name { get; set; } + + /// + /// 集中器地址 + /// + public string Address { get; set; } + + /// + /// 集中器区域代码 + /// + public string AreaCode { get; set; } + + /// + /// 电表类别 (1单相、2三相三线、3三相四线), + /// 07协议: 开合闸指令(1A开闸断电,1C单相表合闸,1B多相表合闸) 645 2007 表 + /// 97协议://true(合闸);false(跳闸) 545 1997 没有单相多相 之分 "true" ? "9966" : "3355" + /// + public int TypeName { get; set; } + + /// + /// 跳合闸状态字段: 0 合闸,1 跳闸 + /// 电表:TripState (0 合闸-通电, 1 断开、跳闸); + /// + public int TripState { get; set; } + + /// + /// 规约 -电表default(30) 1:97协议,30:07协议 + /// + public int? Protocol { get; set; } + + /// + /// 一个集中器下的[MeteringCode]必须唯一。 PN + /// + public int MeteringCode { get; set; } + + /// + /// 表通信地址 + /// + public string MeterAddress { get; set; } + + /// + /// 波特率 default(2400) + /// + public int Baudrate { get; set; } + + /// + /// MeteringPort 端口就几个可以枚举。 + /// + public int MeteringPort { get; set; } + + /// + /// 电表密码 + /// + public string Password { get; set; } + + /// + /// 该电表方案下采集项,JSON格式,如:["0D_80","0D_80"] + /// + public string ItemCodes { get; set; } + + /// + /// State表状态: + /// 0新装(未下发),1运行(档案下发成功时设置状态值1), 2暂停, 100销表(销表后是否重新启用) + /// 特定:State -1 已删除 + /// + public int State { get; set; } + + /// + /// 是否自动采集(0:主动采集,1:自动采集) + /// + public int AutomaticReport { get; set; } + + /// + /// 该电表方案下采集项编号 + /// + public string DataTypes { get; set; } + + /// + /// 品牌型号 + /// + public string BrandType { get; set; } + + /// + /// 采集器编号 + /// + public string GatherCode { get; set; } + + /// + /// 是否特殊表,1是特殊电表 + /// + public int Special { get; set; } + + /// + /// 费率类型,单、多 (SingleRate :单费率(单相表1),多费率(其他0) ,与TypeName字段无关) + /// SingleRate ? "单" : "复" + /// [SingleRate] --0 复费率 false , 1 单费率 true (与PayPlanID保持一致) + ///对应 TB_PayPlan.Type: 1复费率,2单费率 + /// + public bool SingleRate { get; set; } + + /// + /// 项目ID + /// + public int ProjectID { get; set; } + + /// + /// 数据库业务ID + /// + public int DatabaseBusiID { get; set; } + + /// + /// 是否异常集中器 0:正常,1异常 + /// + public int AbnormalState { get; set; } + } +} diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTableModelDataInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTableModelDataInfo.cs new file mode 100644 index 0000000..4ced50b --- /dev/null +++ b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTableModelDataInfo.cs @@ -0,0 +1,22 @@ +using JiShe.CollectBus.Analyzers.Shared; +using JiShe.CollectBus.IoTDB.Attributes; +using JiShe.CollectBus.IoTDB.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.IotSystems.Devices +{ + /// + /// 设备表型数据信息 + /// + [SourceAnalyzers(EntityTypeEnum.TableModel)] + public class DeviceTreeModelDataInfo: IoTEntity + { + + [FIELDColumn] + public bool xfdsa { get; set; } + } +} diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTreeModelDataInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTreeModelDataInfo.cs new file mode 100644 index 0000000..27a59c7 --- /dev/null +++ b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTreeModelDataInfo.cs @@ -0,0 +1,22 @@ +using JiShe.CollectBus.Analyzers.Shared; +using JiShe.CollectBus.IoTDB.Attributes; +using JiShe.CollectBus.IoTDB.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.IotSystems.Devices +{ + /// + /// 设备树模型数据信息 + /// + [SourceAnalyzers(EntityTypeEnum.TableModel)] + public class DeviceTableModelDataInfo : IoTEntity + { + + [FIELDColumn] + public bool xfdsa { get; set; } + } +} diff --git a/services/JiShe.CollectBus.Domain/IotSystems/LogRecord/LogRecords.cs b/services/JiShe.CollectBus.Domain/IotSystems/LogRecord/LogRecords.cs new file mode 100644 index 0000000..2a18a02 --- /dev/null +++ b/services/JiShe.CollectBus.Domain/IotSystems/LogRecord/LogRecords.cs @@ -0,0 +1,99 @@ +using JiShe.CollectBus.Common.Enums; +using MongoDB.Bson.Serialization.Attributes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Domain.Entities; + +namespace JiShe.CollectBus.IotSystems.LogRecord +{ + /// + /// 日志记录集合 + /// + public class LogRecords : AggregateRoot + { + /// + /// 集中器地址 + /// + public string Code { get; set; } = null!; + + /// + /// AFN功能码 + /// + public int AFN { get; set; } + + /// + /// 信息点 + /// + public int Pn { get; set; } + + /// + /// 信息类 + /// + public int Fn { get; set; } + + /// + /// 主站地址 MSA + /// + public int MSA { get; set; } + + /// + /// 响应帧序号 + /// + public int PSEQ { get; set; } + + /// + /// 响应帧 + /// + public string? ReceivedHexMessage { get; set; } = null; + + /// + /// 发送帧 + /// + public string? SendHexMessage { get; set; } = null; + + /// + /// 消息ID + /// + public string? MessageId { get; set; } + + /// + /// 消息时间 + /// + [BsonDateTimeOptions(Kind = DateTimeKind.Local)] + public DateTime? ReceivedTime { get; set; } + + /// + /// 采集密度 + /// + public int TimeDensity { get; set; } + + /// + /// 采集密度单位 + /// + public DensityUnit DensityUnit { get; set; } = DensityUnit.None; + + /// + /// 项目ID + /// + public int ProjectId { get; set; } + + /// + /// 集中器ID + /// + public int FocusId { get; set; } + + /// + /// 数据 + /// + //public object? Data { get; set;} + + /// + /// 创建时间 + /// + [BsonDateTimeOptions(Kind = DateTimeKind.Local)] + public DateTime CreationTime { get; set; }=DateTime.Now; + } +} diff --git a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs index e35d245..c812f56 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs @@ -1,23 +1,14 @@ -using JiShe.CollectBus.Common.Encrypt; -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Models; -using JiShe.CollectBus.IoTDB.Attribute; -using JiShe.CollectBus.IoTDB.Enums; +using JiShe.CollectBus.Analyzers.Shared; +using JiShe.CollectBus.IoTDB.Attributes; using JiShe.CollectBus.IoTDB.Model; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Volo.Abp.Domain.Entities; -using Volo.Abp.Domain.Entities.Auditing; namespace JiShe.CollectBus.IotSystems.MeterReadingRecords { /// /// 抄读任务数据 /// - [EntityType(EntityTypeEnum.TableModel)] + [SourceAnalyzers(EntityTypeEnum.TableModel)] public class MeterReadingTelemetryPacketInfo : IoTEntity { /// @@ -25,7 +16,13 @@ namespace JiShe.CollectBus.IotSystems.MeterReadingRecords /// [FIELDColumn] public string ScoreValue { get; set; } - + + /// + /// 数据包类型 + /// + [FIELDColumn] + public int PacketType { get; set; } + /// /// 是否手动操作 /// @@ -62,12 +59,6 @@ namespace JiShe.CollectBus.IotSystems.MeterReadingRecords /// [FIELDColumn] public string FocusAddress { get; set; } - - /// - /// 表Id - /// - [FIELDColumn] - public int MeterId { get; set; } /// /// 表地址 @@ -96,6 +87,7 @@ namespace JiShe.CollectBus.IotSystems.MeterReadingRecords /// /// 抄读计量点 /// + [FIELDColumn] public int Pn { get; set; } /// @@ -114,6 +106,7 @@ namespace JiShe.CollectBus.IotSystems.MeterReadingRecords /// /// 帧序列域 SEQ /// + [FIELDColumn] public int Seq { get; set; } /// @@ -128,6 +121,18 @@ namespace JiShe.CollectBus.IotSystems.MeterReadingRecords [FIELDColumn] public bool IsSend { get; set; } + /// + /// 发送次数 + /// + [FIELDColumn] + public int? SendNum { get; set; } + + /// + /// 下次发送时间 + /// + [FIELDColumn] + public DateTime? NextSendTime { get; set; } + /// /// 创建时间 /// @@ -174,7 +179,7 @@ namespace JiShe.CollectBus.IotSystems.MeterReadingRecords /// 是否已上报 /// [FIELDColumn] - public bool IsReceived { get; set; } + public bool IsReceived { get; set; } } } diff --git a/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj b/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj index a60ffe1..e69f3b6 100644 --- a/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj +++ b/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj @@ -1,8 +1,8 @@  - - - - + + + + net8.0 enable JiShe.CollectBus @@ -23,11 +23,14 @@ + - + + + diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN10_F66_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN10_F66_AnalysisDto.cs index c3c8306..8a5853a 100644 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN10_F66_AnalysisDto.cs +++ b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN10_F66_AnalysisDto.cs @@ -29,10 +29,6 @@ namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto /// public int CurveRatio { get; set; } - /// - /// 任务号 - /// - public int Pn { get; set; } public List Details { get; set; } = new List(); } diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F129_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F129_AnalysisDto.cs deleted file mode 100644 index 30719e9..0000000 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F129_AnalysisDto.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto -{ - public class AFN12_F129_AnalysisDto : AnalysisBaseDto - { - public DateTime ReadTime { get; set; } - } -} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F130_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F130_AnalysisDto.cs deleted file mode 100644 index 9a9259b..0000000 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F130_AnalysisDto.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto -{ - public class AFN12_F130_AnalysisDto : AnalysisBaseDto - { - public DateTime ReadTime { get; set; } - } -} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F131_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F131_AnalysisDto.cs deleted file mode 100644 index edc5ca7..0000000 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F131_AnalysisDto.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto -{ - public class AFN12_F131_AnalysisDto: AnalysisBaseDto - { - public DateTime ReadTime { get; set; } - } -} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F132_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F132_AnalysisDto.cs deleted file mode 100644 index 1625f15..0000000 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F132_AnalysisDto.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto -{ - public class AFN12_F132_AnalysisDto: AnalysisBaseDto - { - public DateTime ReadTime { get; set; } - } -} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F145_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F145_AnalysisDto.cs deleted file mode 100644 index 96f0c37..0000000 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F145_AnalysisDto.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto -{ - public class AFN12_F145_AnalysisDto : AnalysisBaseDto - { - /// - /// 最大需量时标 - /// - public string TimeSpan { get; set; } - - public DateTime ReadingDate { get; set; } - } - -} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F149_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F149_AnalysisDto.cs deleted file mode 100644 index fb9dafe..0000000 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F149_AnalysisDto.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto -{ - public class AFN12_F149_AnalysisDto : AnalysisBaseDto - { - /// - /// 最大需量时标 - /// - public string TimeSpan { get; set; } - - public DateTime ReadingDate { get; set; } - } -} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F25_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F25_AnalysisDto.cs deleted file mode 100644 index ca8b8ff..0000000 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F25_AnalysisDto.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto -{ - public class AFN12_F25_AnalysisDto: AnalysisBaseDto - { - /// - /// 读取时间 - /// - public DateTime ReadTime { get; set; } - } -} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F49_AnalysisDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F49_AnalysisDto.cs deleted file mode 100644 index ce0aeb7..0000000 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F49_AnalysisDto.cs +++ /dev/null @@ -1,15 +0,0 @@ -using JiShe.CollectBus.Protocol.Dto; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto -{ - public class AFN12_F49_AnalysisDto: AnalysisBaseDto - { - } - - -} diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AnalysisBaseDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AnalysisBaseDto.cs index f637e57..c02ee76 100644 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AnalysisBaseDto.cs +++ b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AnalysisBaseDto.cs @@ -17,9 +17,9 @@ namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto public bool ValidData { get; set; } = true; /// - /// 数据类型 + /// 数据项类型 /// - public string DataType { get; set; } = null!; + public string ItemType { get; set; } = null!; /// /// 错误码信息 @@ -39,12 +39,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto /// /// 数据时标 /// - public DateTime TimeSpan { get; set; } - - /// - /// 数据时间 - /// - public DateTime DataTime { get; set; } + public DateTime? TimeSpan { get; set; } /// /// 项目Id @@ -52,14 +47,14 @@ namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto public int ProjectId { get; set; } /// - /// 电表ID + /// 设备ID(电表ID,水表ID,气表ID,集中器ID等) /// - public int MeterId { get; set; } + public int DeviceId { get; set; } /// - /// 表类型 + /// 设备类型 /// - public MeterTypeEnum MeterType { get; set;} + public MeterTypeEnum DeviceType { get; set;} /// @@ -68,18 +63,22 @@ namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto public int DatabaseBusiID { get; set; } /// - /// 表地址 + /// 设备地址(电表地址,水表地址,气表地址,集中器地址等) /// - public string MeterAddress { get; set; } = null!; + public string DeviceAddress { get; set; } = null!; + /// + /// 集中器ID + /// + public int FocusId { get; set; } } public class AnalysisBaseDto : AnalysisBaseDto { - /// - /// 抄读值 - /// - public T? DataValue { get; set; } + /// + /// 抄读值 + /// + public T? DataValue { get; set; } = default; } } diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/UnitDataAnalysis.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/UnitDataAnalysis.cs index b691b3a..8572819 100644 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/UnitDataAnalysis.cs +++ b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/UnitDataAnalysis.cs @@ -1,4 +1,7 @@ using JiShe.CollectBus.Common.Enums; +using JiShe.CollectBus.Common.Extensions; +using System; +using System.Collections.Generic; namespace JiShe.CollectBus.Protocol.Dto { @@ -37,13 +40,18 @@ namespace JiShe.CollectBus.Protocol.Dto /// /// 响应帧 /// - public string? HexMessage { get; set; } = null; + public string? ReceivedHexMessage { get; set; } = null; /// /// 消息ID /// public string? MessageId { get; set; } + /// + /// 消息时间 + /// + public DateTime? ReceivedTime { get; set; } + /// /// 采集密度 /// @@ -54,6 +62,16 @@ namespace JiShe.CollectBus.Protocol.Dto /// public DensityUnit DensityUnit { get; set; }= DensityUnit.Minute; + /// + /// 数据类型 + /// + public string DataType { get; set; }= null!; + + /// + /// 数据项编码 + /// + public string ItemCode => $"{AFN.HexToDecStr().PadLeft(2, '0')}_{Fn}"; + } public class UnitDataAnalysis: UnitDataAnalysis diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/TB3761.cs b/services/JiShe.CollectBus.Domain/Protocol3761/TB3761.cs index 8f9f776..d4acf61 100644 --- a/services/JiShe.CollectBus.Domain/Protocol3761/TB3761.cs +++ b/services/JiShe.CollectBus.Domain/Protocol3761/TB3761.cs @@ -22,6 +22,11 @@ namespace JiShe.CollectBus.Protocol3761 /// public string? MessageId { get; set; } + /// + /// 消息时间 + /// + public DateTime ReceivedTime { get; set; }=DateTime.Now; + /// /// 控制域C /// diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationApplicationContractsModule.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationApplicationContractsModule.cs new file mode 100644 index 0000000..756ba99 --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationApplicationContractsModule.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Application; +using Volo.Abp.Modularity; +using Volo.Abp.Authorization; + +namespace JiShe.CollectBus.Migration; + +[DependsOn( + typeof(CollectBusDomainSharedModule), + typeof(AbpDddApplicationContractsModule), + typeof(AbpAuthorizationModule) + )] +public class CollectBusMigrationApplicationContractsModule : AbpModule +{ + +} diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationRemoteServiceConsts.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationRemoteServiceConsts.cs new file mode 100644 index 0000000..cc0c233 --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationRemoteServiceConsts.cs @@ -0,0 +1,8 @@ +namespace JiShe.CollectBus.Migration; + +public class CollectBusMigrationRemoteServiceConsts +{ + public const string RemoteServiceName = "CollectBus"; + + public const string ModuleName = "collectBus"; +} diff --git a/services/JiShe.CollectBus.Application.Contracts/DataMigration/IDataMigrationService.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/IDataMigrationService.cs similarity index 90% rename from services/JiShe.CollectBus.Application.Contracts/DataMigration/IDataMigrationService.cs rename to services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/IDataMigrationService.cs index bbfa581..c6fbb96 100644 --- a/services/JiShe.CollectBus.Application.Contracts/DataMigration/IDataMigrationService.cs +++ b/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/IDataMigrationService.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace JiShe.CollectBus.DataMigration +namespace JiShe.CollectBus.Migration { /// /// 数据迁移服务 diff --git a/services/JiShe.CollectBus.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs similarity index 89% rename from services/JiShe.CollectBus.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs rename to services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs index 7174cad..6e70531 100644 --- a/services/JiShe.CollectBus.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs +++ b/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace JiShe.CollectBus.DataMigration.Options +namespace JiShe.CollectBus.Migration { /// /// 数据迁移配置 @@ -19,7 +19,7 @@ namespace JiShe.CollectBus.DataMigration.Options /// /// 批量处理通道容量 /// - public int ChannelCapacity { get; set; } = 100; + public int ChannelCapacity { get; set; } = 100_00; /// /// 数据库 每批处理量 diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/FodyWeavers.xml b/services/JiShe.CollectBus.Migration.Application.Contracts/FodyWeavers.xml new file mode 100644 index 0000000..1715698 --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application.Contracts/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F2_AnalysisDto.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/ICollectWorker.cs similarity index 52% rename from services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F2_AnalysisDto.cs rename to services/JiShe.CollectBus.Migration.Application.Contracts/ICollectWorker.cs index e069382..e2c4fa8 100644 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AFN12_F2_AnalysisDto.cs +++ b/services/JiShe.CollectBus.Migration.Application.Contracts/ICollectWorker.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +namespace JiShe.CollectBus.Migration { - public class AFN12_F2_AnalysisDto: AnalysisBaseDto + public interface ICollectWorker { } } diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/JiShe.CollectBus.Migration.Application.Contracts.csproj b/services/JiShe.CollectBus.Migration.Application.Contracts/JiShe.CollectBus.Migration.Application.Contracts.csproj new file mode 100644 index 0000000..f3ef574 --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application.Contracts/JiShe.CollectBus.Migration.Application.Contracts.csproj @@ -0,0 +1,34 @@ + + + + + + net8.0 + enable + JiShe.CollectBus.Migration + True + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationAppService.cs b/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationAppService.cs new file mode 100644 index 0000000..5ec9a4c --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationAppService.cs @@ -0,0 +1,20 @@ +using JiShe.CollectBus.FreeRedis; +using JiShe.CollectBus.FreeSql; +using JiShe.CollectBus.Localization; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.Application.Services; + +namespace JiShe.CollectBus.Migration; + +[ApiExplorerSettings(GroupName = CollectBusDomainSharedConsts.Business)] +public abstract class CollectBusMigrationAppService : ApplicationService +{ + public IFreeSqlProvider SqlProvider => LazyServiceProvider.LazyGetRequiredService(); + protected IFreeRedisProvider FreeRedisProvider => LazyServiceProvider.LazyGetService()!; + + protected CollectBusMigrationAppService() + { + LocalizationResource = typeof(CollectBusResource); + ObjectMapperContext = typeof(CollectBusMigrationApplicationModule); + } +} diff --git a/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationApplicationModule.cs b/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationApplicationModule.cs new file mode 100644 index 0000000..8a82b7e --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationApplicationModule.cs @@ -0,0 +1,70 @@ +using JiShe.CollectBus.FreeRedis; +using JiShe.CollectBus.FreeSql; +using JiShe.CollectBus.IoTDB; +using Microsoft.Extensions.DependencyInjection; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; + +namespace JiShe.CollectBus.Migration; + +[DependsOn( + typeof(CollectBusDomainModule), + typeof(CollectBusMigrationApplicationContractsModule), + typeof(AbpDddApplicationModule), + typeof(AbpAutoMapperModule), + typeof(CollectBusFreeRedisModule), + typeof(CollectBusFreeSqlModule), + typeof(CollectBusIoTDbModule) +)] +public class CollectBusMigrationApplicationModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + context.Services.AddAutoMapperObjectMapper(); + Configure(options => { options.AddMaps(true); }); + + } + + public override async Task OnApplicationInitializationAsync( + ApplicationInitializationContext context) + { + //var assembly = Assembly.GetExecutingAssembly(); + //var types = assembly.GetTypes().Where(t => typeof(ICollectWorker).IsAssignableFrom(t) && !t.IsInterface) + // .ToList(); + //foreach (var type in types) await context.AddBackgroundWorkerAsync(type); + + //Task.Run(() => + //{ + // //默认初始化表计信息 + // var dbContext = context.ServiceProvider.GetRequiredService(); + // dbContext.InitAmmeterCacheData(); + // //await dbContext.InitWatermeterCacheData(); + //}).ConfigureAwait(false); + + ////下发任务通道构建 + //DataChannelManage.TaskDataChannel = Channel.CreateUnbounded>>(); + + + //// 日志存储通道构建 + //DataChannelManage.LogSaveChannel = Channel.CreateUnbounded(); + + //// 日志刷新通道构建 + //DataChannelManage.LogRefreshChannel = Channel.CreateUnbounded(); + + //// 启动通道任务 + //var _dataChannelManage = context.ServiceProvider.GetRequiredService(); + //_ = _dataChannelManage.LogSaveAsync(DataChannelManage.LogSaveChannel.Reader); + + ////默认初始化表计信息 + //var dbContext = context.ServiceProvider.GetRequiredService(); + //await dbContext.InitAmmeterCacheData(); + } +} \ No newline at end of file diff --git a/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationlicationAutoMapperProfile.cs b/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationlicationAutoMapperProfile.cs new file mode 100644 index 0000000..4e1a5c6 --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationlicationAutoMapperProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; + +namespace JiShe.CollectBus; + +public class CollectBusMigrationlicationAutoMapperProfile : Profile +{ + public CollectBusMigrationlicationAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + } +} diff --git a/services/JiShe.CollectBus.Application/DataMigration/DataMigrationService.cs b/services/JiShe.CollectBus.Migration.Application/DataMigration/DataMigrationService.cs similarity index 96% rename from services/JiShe.CollectBus.Application/DataMigration/DataMigrationService.cs rename to services/JiShe.CollectBus.Migration.Application/DataMigration/DataMigrationService.cs index f1f0c9b..b85d5b0 100644 --- a/services/JiShe.CollectBus.Application/DataMigration/DataMigrationService.cs +++ b/services/JiShe.CollectBus.Migration.Application/DataMigration/DataMigrationService.cs @@ -1,5 +1,4 @@ -using JiShe.CollectBus.DataMigration.Options; -using JiShe.CollectBus.IotSystems.MeterReadingRecords; +using JiShe.CollectBus.IotSystems.MeterReadingRecords; using LiteDB; using Microsoft.Extensions.Options; using System; @@ -9,12 +8,12 @@ using System.Threading.Channels; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; -namespace JiShe.CollectBus.DataMigration +namespace JiShe.CollectBus.Migration.DataMigration { /// /// 数据迁移服务 /// - public class DataMigrationService: CollectBusAppService, IDataMigrationService + public class DataMigrationService: CollectBusMigrationAppService, IDataMigrationService { private readonly IRepository _meterReadingRecordsRepository; private readonly DataMigrationOptions _options; diff --git a/services/JiShe.CollectBus.Migration.Application/FodyWeavers.xml b/services/JiShe.CollectBus.Migration.Application/FodyWeavers.xml new file mode 100644 index 0000000..1715698 --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/services/JiShe.CollectBus.Migration.Application/JiShe.CollectBus.Migration.Application.csproj b/services/JiShe.CollectBus.Migration.Application/JiShe.CollectBus.Migration.Application.csproj new file mode 100644 index 0000000..bce2a34 --- /dev/null +++ b/services/JiShe.CollectBus.Migration.Application/JiShe.CollectBus.Migration.Application.csproj @@ -0,0 +1,35 @@ + + + + + + net8.0 + enable + JiShe.CollectBus.Migration + True + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs b/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs new file mode 100644 index 0000000..523a5df --- /dev/null +++ b/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JiShe.CollectBus.Analyzers.Shared +{ + /// + /// 实体成员信息 + /// + public sealed class EntityMemberInfo + { + /// + /// 名称或者路径 + /// + public string NameOrPath { get; set; } + + /// + /// 声明的类型 + /// + public Type DeclaredType { get; set; } + + /// + /// 声明的类型的名称 + /// + public string DeclaredTypeName { get; } + + /// + /// 获取值 + /// + public Func Getter { get; } + + /// + /// 设置值 + /// + public Action Setter { get; } + + /// + /// 自定义Attribute集合 + /// + public List CustomAttributes { get; set; } + + + public EntityMemberInfo( + string nameOrPath, + Type declaredType, + string declaredTypeName, + Func getter, + Action setter) + { + NameOrPath = nameOrPath; + this.DeclaredType = declaredType; + DeclaredTypeName = declaredTypeName; + Getter = getter; + Setter = setter; + } + + public object GetValue(object entity) => Getter(entity); + public void SetValue(object entity, object value) => Setter(entity, value); + } +} diff --git a/modules/JiShe.CollectBus.IoTDB/EnumInfo/EntityTypeEnum.cs b/shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs similarity index 57% rename from modules/JiShe.CollectBus.IoTDB/EnumInfo/EntityTypeEnum.cs rename to shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs index 26c6645..bddaa86 100644 --- a/modules/JiShe.CollectBus.IoTDB/EnumInfo/EntityTypeEnum.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs @@ -1,24 +1,27 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; -namespace JiShe.CollectBus.IoTDB.Enums +namespace JiShe.CollectBus.Analyzers.Shared { /// - /// IoTDB实体类型枚举 + /// 实体类型枚举 /// public enum EntityTypeEnum { /// - /// 树模型 + /// IoTDB树模型 /// TreeModel = 1, /// - /// 表模型 + /// IoTDB表模型 /// TableModel = 2, + + /// + /// 其他情况 + /// + Other = 3 } } diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs new file mode 100644 index 0000000..2c3a5b0 --- /dev/null +++ b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace JiShe.CollectBus.Analyzers.Shared +{ + public interface ISourceEntityAccessor + { + /// + /// 实体类名称 + /// + string EntityName { get; } + + /// + /// 实体类型 + /// + EntityTypeEnum? EntityType { get;} + + /// + /// 获取属性值 + /// + /// + /// + /// + object GetPropertyValue(T entity, string propertyName); + + /// + /// 设置属性值 + /// + /// + /// + /// + void SetPropertyValue(T entity, string propertyName, object value); + + /// + /// 属性名称集合 + /// + List PropertyNameList { get; } + + /// + /// 属性信息集合 + /// + List MemberList { get; } + } +} diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/JiShe.CollectBus.Analyzers.Shared.csproj b/shared/JiShe.CollectBus.Analyzers.Shared/JiShe.CollectBus.Analyzers.Shared.csproj new file mode 100644 index 0000000..3ae7562 --- /dev/null +++ b/shared/JiShe.CollectBus.Analyzers.Shared/JiShe.CollectBus.Analyzers.Shared.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs b/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs new file mode 100644 index 0000000..ad02607 --- /dev/null +++ b/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs @@ -0,0 +1,19 @@ +using System; + +namespace JiShe.CollectBus.Analyzers.Shared +{ + /// + /// 标记需要生成源码的类 + /// + [AttributeUsage(AttributeTargets.Class)] + public class SourceAnalyzersAttribute : Attribute + { + public EntityTypeEnum EntityType { get; } + + + public SourceAnalyzersAttribute(EntityTypeEnum entityType) + { + EntityType = entityType; + } + } +} diff --git a/shared/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs b/shared/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs index a96c16a..2d815da 100644 --- a/shared/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs +++ b/shared/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs @@ -1362,7 +1362,7 @@ namespace JiShe.CollectBus.Common.BuildSendDatas /// 等待报文超时时间/s /// 等待字节超时时间/ms /// - private static List BuildTransparentForwardingSendDataUnit(int port, int baudRate, List datas, StopBit stopBit = StopBit.Stop1, Parity parity = Parity.Even, DataBit dataBit = DataBit.D8, + public static List BuildTransparentForwardingSendDataUnit(int port, int baudRate, List datas, StopBit stopBit = StopBit.Stop1, Parity parity = Parity.Even, DataBit dataBit = DataBit.D8, int waitContentTimeout = 100, int waitByteTimeout = 100) { var dataUnit = new List(); @@ -1591,7 +1591,7 @@ namespace JiShe.CollectBus.Common.BuildSendDatas //AUX=消息认证码字段(PW,16个字节) - private static List GetPW() + public static List GetPW() { var str = "00"; var pWList = Enumerable.Repeat(str, pWLen).ToList(); @@ -1606,13 +1606,21 @@ namespace JiShe.CollectBus.Common.BuildSendDatas /// private static string GetCS(List userData) { - byte sum = 0; - foreach (var d in userData) + try { - var b = Convert.ToByte(d, 16); - sum += b; + byte sum = 0; + foreach (var d in userData) + { + var b = Convert.ToByte(d, 16); + sum += b; + } + return sum.ToString("X2"); } - return sum.ToString("X2"); + catch(Exception) + { + throw; + } + } /// @@ -1735,6 +1743,8 @@ namespace JiShe.CollectBus.Common.BuildSendDatas return list; } + + /// /// 帧序列域 /// diff --git a/shared/JiShe.CollectBus.Common/Consts/DataFieldConst.cs b/shared/JiShe.CollectBus.Common/Consts/DataFieldConst.cs deleted file mode 100644 index 9cde24b..0000000 --- a/shared/JiShe.CollectBus.Common/Consts/DataFieldConst.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Consts -{ - /// - /// 数据保存字段常量 - /// - public class DataFieldConst - { - public const string ZYGDN = "ZYGDN"; - public const string ZWGDN = "ZWGDN"; - public const string FYGDN = "FYGDN"; - public const string FWGDN = "FWGDN"; - - public const string ZYGDNSZ = "ZYGDNSZ"; - public const string ZWGDNSZ = "ZWGDNSZ"; - public const string FYGDNSZ = "FYGDNSZ"; - public const string FWGDNSZ = "FWGDNSZ"; - - public const string WGDN1 = "WGDN1"; - public const string WGDN2 = "WGDN2"; - public const string WGDN3 = "WGDN3"; - public const string WGDN4 = "WGDN4"; - - public const string WGDNSZ1 = "WGDNSZ1"; - public const string WGDNSZ2 = "WGDNSZ2"; - public const string WGDNSZ3 = "WGDNSZ3"; - public const string WGDNSZ4 = "WGDNSZ4"; - - public const string YGGL = "YGGL"; - public const string AYGGL = "AYGGL"; - public const string BYGGL = "BYGGL"; - public const string CYGGL = "CYGGL"; - - public const string WGGL = "WGGL"; - public const string AWGGL = "AWGGL"; - public const string BWGGL = "BWGGL"; - public const string CWGGL = "CWGGL"; - - public const string GLYS = "GLYS"; - public const string AGLYS = "AGLYS"; - public const string BGLYS = "BGLYS"; - public const string CGLYS = "CGLYS"; - - public const string ADY = "ADY"; - public const string BDY = "BDY"; - public const string CDY = "CDY"; - - public const string ADL = "ADL"; - public const string BDL = "BDL"; - public const string CDL = "CDL"; - public const string LXDL = "LXDL"; - - public const string PowerGridFrequency = "PowerGridFrequency"; - - public const string Ua = "Ua"; - public const string Ub = "Ub"; - public const string Uc = "Uc"; - - public const string Ia = "Ia"; - public const string Ib = "Ib"; - public const string Ic = "Ic"; - - } - - public class ConstGatherDataType - { - public const string ZYGDN = "0D_97"; //正向有功总电能量 - public const string ZWGDN = "0D_98"; //正向无功总电能量曲线 - public const string FYGDN = "0D_99"; //反向有功总电能量曲线 - public const string FWGDN = "0D_100"; //反向无功总电能量曲线 - - public const string ZYGDNSZ = "0D_101"; //正向有功总电能示值曲线 - public const string ZWGDNSZ = "0D_102"; //正向无功总电能示值曲线 - public const string FYGDNSZ = "0D_103"; //反向有功总电能示值曲线 - public const string FWGDNSZ = "0D_104"; //反向无功总电能示值曲线 - - public const string WGDNSZ1 = "0D_145"; //一象限无功总电能示值曲线 - public const string WGDNSZ4 = "0D_146"; //四象限无功总电能示值曲线 - public const string WGDNSZ2 = "0D_147"; //二象限无功总电能示值曲线 - public const string WGDNSZ3 = "0D_148"; //三象限无功总电能示值曲线 - - public const string YGGL = "0D_81"; //有功功率曲线 - public const string AYGGL = "0D_82"; //A相有功功率曲线 - public const string BYGGL = "0D_83"; //B相有功功率曲线 - public const string CYGGL = "0D_84"; //C相有功功率曲线 - - public const string WGGL = "0D_85"; //无功功率曲线 - public const string AWGGL = "0D_86"; //A相无功功率曲线 - public const string BWGGL = "0D_87"; //B相无功功率曲线 - public const string CWGGL = "0D_88"; //C相无功功率曲线 - - public const string GLYS = "0D_105"; // 功率因数曲线 - public const string AGLYS = "0D_106"; // A相功率因数曲线 - public const string BGLYS = "0D_107"; // B相功率因数曲线 - public const string CGLYS = "0D_108"; // C相功率因数曲线 - - public const string ADY = "0D_89"; //A相电压曲线 - public const string BDY = "0D_90"; //B相电压曲线 - public const string CDY = "0D_91"; //C相电压曲线 - - public const string ADL = "0D_92"; //A相电流曲线 - public const string BDL = "0D_93"; //B相电流曲线 - public const string CDL = "0D_94"; //C相电流曲线 - public const string LXDL = "0D_95"; // 零序电流 - - public const string PowerGridFrequency = "10_97"; //电网频率 - - public const string Ua = "0C_49_Uab_Ua"; // 当前电压、电流相位角 - public const string Ub = "0C_49_Ub"; // 当前电压、电流相位角 - public const string Uc = "0C_49_Ucb_Uc"; // 当前电压、电流相位角 - public const string Ia = "0C_49_Ia"; // 当前电压、电流相位角 - public const string Ib = "0C_49_Ib"; // 当前电压、电流相位角 - public const string Ic = "0C_49_Ic"; // 当前电压、电流相位角 - - } - - - public static class DataFieldHelper - { - /// - /// 数据字段映射 - /// - public static Dictionary DataFieldDic = new Dictionary(); - - /// - /// 创建数据字段映射 - /// - /// - public static Dictionary CreateDataFieldMapping() - { - if (DataFieldDic.Count > 0) - return DataFieldDic; - var dataFieldMapping = new Dictionary(); - Type dataType = typeof(ConstGatherDataType); - Type fieldType = typeof(DataFieldConst); - - foreach (FieldInfo gatherField in dataType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)) - { - if (gatherField.IsLiteral && !gatherField.IsInitOnly) - { - // 获取ConstGatherDataType的字段值作为key - string key = (string)gatherField.GetValue(null)!; - - // 查找DataFieldConst中同名字段 - FieldInfo dataField = fieldType.GetField(gatherField.Name, - BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)!; - - if (dataField != null) - { - string value = (string)dataField.GetValue(null)!; - dataFieldMapping[key] = value; - } - } - } - - return dataFieldMapping; - } - - /// - /// 根据采集数据类型获取数据字段 - /// 返回null表示 无效字段 - /// - /// - /// - public static string? GetDataFieldByGatherDataType(this string gatherDataType) - { - if (CreateDataFieldMapping().TryGetValue(gatherDataType, out string? column)) - { - return column; - } - return null; - } - - - } -} diff --git a/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs b/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs new file mode 100644 index 0000000..872c099 --- /dev/null +++ b/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Consts +{ + /// + /// IOTDB数据树类型 + /// + public class IOTDBDataTypeConst + { + /// + /// 数据 + /// + public const string Data = "Data"; + + /// + /// 事件 + /// + public const string Event = "Event"; + + /// + /// 状态 + /// + public const string Status = "Status"; + + /// + /// 日志 + /// + public const string Log = "Log"; + + /// + /// 参数 + /// + public const string Param= "Param"; + } +} diff --git a/shared/JiShe.CollectBus.Common/Consts/MeteringPortConst.cs b/shared/JiShe.CollectBus.Common/Consts/MeteringPortConst.cs new file mode 100644 index 0000000..c65b027 --- /dev/null +++ b/shared/JiShe.CollectBus.Common/Consts/MeteringPortConst.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Consts +{ + /// + /// 计量端口常量 + /// + public class MeteringPortConst + { + /// + /// 计量端口1 + /// + public const int MeteringPortOne = 1; + + /// + /// 计量端口2 + /// + public const int MeteringPortTwo = 2; + } +} diff --git a/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs b/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs index 6af0fd0..0758899 100644 --- a/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs +++ b/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs @@ -65,7 +65,12 @@ namespace JiShe.CollectBus.Common.Consts /// 电表手动抄读 /// public const string AmmeterSubscriberWorkerManualValveReadingIssuedEventName = "issued.manual.reading.ammeter.event"; - + + /// + /// 采集电表数据重试下行消息主题 + /// + public const string AmmeterSubscriberWorkerRetryEventName = "issued.retry.ammeter.event"; + #endregion #region 水表消息主题 @@ -165,5 +170,10 @@ namespace JiShe.CollectBus.Common.Consts /// 测试主题格式 /// public const string TESTTOPIC = "test-topic"; + + /// + /// 测试下发主题格式 + /// + public const string TESTSENDTOPIC = "test-send-topic"; } } diff --git a/shared/JiShe.CollectBus.Common/Consts/RedisConst.cs b/shared/JiShe.CollectBus.Common/Consts/RedisConst.cs index 53ad4f6..bb143ef 100644 --- a/shared/JiShe.CollectBus.Common/Consts/RedisConst.cs +++ b/shared/JiShe.CollectBus.Common/Consts/RedisConst.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -28,22 +29,15 @@ namespace JiShe.CollectBus.Common.Consts /// public const string FifteenMinuteAcquisitionTimeInterval = "Fifteen"; - public const string MeterInfo = "MeterInfo"; /// - /// 缓存表计信息,{0}=>系统类型,{1}=>应用服务部署标记,{2}=>表计类别,{3}=>采集频率 + /// 设备信息缓存数据,{0}=>系统类型,{1}=>应用服务部署标记 /// - public const string CacheMeterInfoHashKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:{MeterInfo}:{"{2}"}:{"{3}"}"; + public const string CacheDeviceInfoHashKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:DeviceInfo"; /// - /// 缓存表计信息索引Set缓存Key,{0}=>系统类型,{1}=>应用服务部署标记,{2}=>表计类别,{3}=>采集频率 + /// 设备信息缓存Set缓存Key,{0}=>系统类型,{1}=>应用服务部署标记 /// - public const string CacheMeterInfoSetIndexKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:{MeterInfo}:{"{2}"}:SetIndex:{"{3}"}"; - - /// - /// 缓存表计信息排序索引ZSET缓存Key,{0}=>系统类型,{1}=>应用服务部署标记,{2}=>表计类别,{3}=>采集频率 - /// - public const string CacheMeterInfoZSetScoresIndexKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:{MeterInfo}:{"{2}"}:ZSetScoresIndex:{"{3}"}"; - + public const string CacheDeviceGroupSetIndexKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:DeviceGroupIndex"; public const string TaskInfo = "TaskInfo"; /// diff --git a/shared/JiShe.CollectBus.Common/Consts/T37612012PacketItemCodeConst.cs b/shared/JiShe.CollectBus.Common/Consts/T37612012PacketItemCodeConst.cs index 6d15e19..47f053d 100644 --- a/shared/JiShe.CollectBus.Common/Consts/T37612012PacketItemCodeConst.cs +++ b/shared/JiShe.CollectBus.Common/Consts/T37612012PacketItemCodeConst.cs @@ -19,6 +19,12 @@ namespace JiShe.CollectBus.Common.Consts /// public const string AFN10HFN01H = $"10_01"; + + /// + /// 电网频率 + /// + public const string AFN10HFN97H = $"10_97"; + /// /// 读取终端信息 /// @@ -36,5 +42,164 @@ namespace JiShe.CollectBus.Common.Consts #endregion #endregion + + #region 数据解析 + + /// + /// 数据保存字段常量 + /// + public class DataFieldConst + { + public const string ZYGDN = "ZYGDN"; + public const string ZWGDN = "ZWGDN"; + public const string FYGDN = "FYGDN"; + public const string FWGDN = "FWGDN"; + + public const string ZYGDNSZ = "ZYGDNSZ"; + public const string ZWGDNSZ = "ZWGDNSZ"; + public const string FYGDNSZ = "FYGDNSZ"; + public const string FWGDNSZ = "FWGDNSZ"; + + public const string WGDN1 = "WGDN1"; + public const string WGDN2 = "WGDN2"; + public const string WGDN3 = "WGDN3"; + public const string WGDN4 = "WGDN4"; + + public const string WGDNSZ1 = "WGDNSZ1"; + public const string WGDNSZ2 = "WGDNSZ2"; + public const string WGDNSZ3 = "WGDNSZ3"; + public const string WGDNSZ4 = "WGDNSZ4"; + + public const string YGGL = "YGGL"; + public const string AYGGL = "AYGGL"; + public const string BYGGL = "BYGGL"; + public const string CYGGL = "CYGGL"; + + public const string WGGL = "WGGL"; + public const string AWGGL = "AWGGL"; + public const string BWGGL = "BWGGL"; + public const string CWGGL = "CWGGL"; + + public const string GLYS = "GLYS"; + public const string AGLYS = "AGLYS"; + public const string BGLYS = "BGLYS"; + public const string CGLYS = "CGLYS"; + + public const string ADY = "ADY"; + public const string BDY = "BDY"; + public const string CDY = "CDY"; + + public const string ADL = "ADL"; + public const string BDL = "BDL"; + public const string CDL = "CDL"; + public const string LXDL = "LXDL"; + + public const string DWPL = "DWPL"; + + public const string Ua = "Ua"; + public const string Ub = "Ub"; + public const string Uc = "Uc"; + + public const string Ia = "Ia"; + public const string Ib = "Ib"; + public const string Ic = "Ic"; + + public const string SZGL = "SZGL"; + public const string ASZGL = "ASZGL"; + public const string BSZGL = "BSZGL"; + public const string CSZGL = "CSZGL"; + } + + public class ConstGatherDataType + { + public const string ZYGDN = "0D_97"; //正向有功总电能量 + public const string ZWGDN = "0D_98"; //正向无功总电能量曲线 + public const string FYGDN = "0D_99"; //反向有功总电能量曲线 + public const string FWGDN = "0D_100"; //反向无功总电能量曲线 + + public const string ZYGDNSZ = "0D_101"; //正向有功总电能示值曲线 + public const string ZWGDNSZ = "0D_102"; //正向无功总电能示值曲线 + public const string FYGDNSZ = "0D_103"; //反向有功总电能示值曲线 + public const string FWGDNSZ = "0D_104"; //反向无功总电能示值曲线 + + public const string WGDNSZ1 = "0D_145"; //一象限无功总电能示值曲线 + public const string WGDNSZ4 = "0D_146"; //四象限无功总电能示值曲线 + public const string WGDNSZ2 = "0D_147"; //二象限无功总电能示值曲线 + public const string WGDNSZ3 = "0D_148"; //三象限无功总电能示值曲线 + + public const string YGGL = "0D_81"; //有功功率曲线 + public const string AYGGL = "0D_82"; //A相有功功率曲线 + public const string BYGGL = "0D_83"; //B相有功功率曲线 + public const string CYGGL = "0D_84"; //C相有功功率曲线 + + public const string WGGL = "0D_85"; //无功功率曲线 + public const string AWGGL = "0D_86"; //A相无功功率曲线 + public const string BWGGL = "0D_87"; //B相无功功率曲线 + public const string CWGGL = "0D_88"; //C相无功功率曲线 + + public const string GLYS = "0D_105"; // 功率因数曲线 + public const string AGLYS = "0D_106"; // A相功率因数曲线 + public const string BGLYS = "0D_107"; // B相功率因数曲线 + public const string CGLYS = "0D_108"; // C相功率因数曲线 + + public const string ADY = "0D_89"; //A相电压曲线 + public const string BDY = "0D_90"; //B相电压曲线 + public const string CDY = "0D_91"; //C相电压曲线 + + public const string ADL = "0D_92"; //A相电流曲线 + public const string BDL = "0D_93"; //B相电流曲线 + public const string CDL = "0D_94"; //C相电流曲线 + public const string LXDL = "0D_95"; // 零序电流 + + public const string DWPL = "10_97"; //电网频率 + + public const string Ua = "0C_49_Uab_Ua"; // 当前电压、电流相位角 + public const string Ub = "0C_49_Ub"; // 当前电压、电流相位角 + public const string Uc = "0C_49_Ucb_Uc"; // 当前电压、电流相位角 + public const string Ia = "0C_49_Ia"; // 当前电压、电流相位角 + public const string Ib = "0C_49_Ib"; // 当前电压、电流相位角 + public const string Ic = "0C_49_Ic"; // 当前电压、电流相位角 + + + public const string SZGL = "0C_25_SZGL"; // 视在功率曲线 + public const string ASZGL = "0C_25_ASZGL"; // A相视在功率曲线 + public const string BSZGL = "0C_25_BSZGL"; // B相视在功率曲线 + public const string CSZGL = "0C_25_CSZGL"; // C相视在功率曲线 + + } + + + /// + /// 集中器状态字段 + /// + public class ConcentratorStatusFieldConst + { + + /// + /// 记录时间 + /// + public const string RecordingTime = "RecordingTime"; + + /// + /// 帧数据 + /// + public const string FrameData = "FrameData"; + + } + #endregion + + /// + /// 特殊645编码关系映射 + /// + /// + /// + public static (string,string) MappingItemCodeTo645SubCodeRelationship(string itemCode) + { + return itemCode switch + { + AFN10HFN97H => (AFN10HFN01H,T6452007PacketItemCodeConst.C1102800002), + _=> (itemCode,""), + }; + } } } diff --git a/shared/JiShe.CollectBus.Common/Consts/T6452007PacketItemCodeConst.cs b/shared/JiShe.CollectBus.Common/Consts/T6452007PacketItemCodeConst.cs index 92da5ba..734bc7a 100644 --- a/shared/JiShe.CollectBus.Common/Consts/T6452007PacketItemCodeConst.cs +++ b/shared/JiShe.CollectBus.Common/Consts/T6452007PacketItemCodeConst.cs @@ -16,37 +16,37 @@ namespace JiShe.CollectBus.Common.Consts /// /// 跳闸 /// - public const string C1C01A = "1C_1A"; + public const string C1C011A = "1C_01_1A"; /// - /// 单相合闸 + /// 合闸允许 /// - public const string C1C01B = "1C_1B"; + public const string C1C011B = "1C_01_1B"; /// - /// 三相合闸 + /// 合闸 /// - public const string C1C01C = "1C_1C"; - + public const string C1C011C = "1C_01_1C"; + /// /// 触发报警 /// - public const string C1C02A = "1C_2A"; + public const string C1C021A = "1C_01_2A"; /// /// 报警解除 /// - public const string C1C02B = "1C_2B"; + public const string C1C012B = "1C_01_2B"; /// /// 保电开始 /// - public const string C1C03A = "1C_3A"; + public const string C1C033A = "1C_03_3A"; /// /// 保电结束 /// - public const string C1C03B = "1C_3B"; + public const string C1C033B = "1C_03_3B"; #endregion #region 广播校时 @@ -56,6 +56,16 @@ namespace JiShe.CollectBus.Common.Consts /// public const string C08 = "08"; #endregion + + #region 读数据 + + + /// + /// 电网频率 + /// + public const string C1102800002 = "11_02_80_00_02"; + #endregion + #endregion } } diff --git a/shared/JiShe.CollectBus.Common/DeviceBalanceControl/DeviceGroupBalanceControl.cs b/shared/JiShe.CollectBus.Common/DeviceBalanceControl/DeviceGroupBalanceControl.cs index aba63e8..470efe7 100644 --- a/shared/JiShe.CollectBus.Common/DeviceBalanceControl/DeviceGroupBalanceControl.cs +++ b/shared/JiShe.CollectBus.Common/DeviceBalanceControl/DeviceGroupBalanceControl.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -192,6 +193,7 @@ namespace JiShe.CollectBus.Common.DeviceBalanceControl int? maxConcurrency = null) { var cache = _currentCache ?? throw new InvalidOperationException("缓存未初始化"); + //var timer = Stopwatch.StartNew(); // 自动计算最佳并发度 int recommendedThreads = CalculateOptimalThreadCount(); @@ -202,6 +204,7 @@ namespace JiShe.CollectBus.Common.DeviceBalanceControl int actualThreads = maxConcurrency ?? recommendedThreads; + // 创建节流器 using var throttler = new SemaphoreSlim(initialCount: actualThreads); @@ -225,6 +228,8 @@ namespace JiShe.CollectBus.Common.DeviceBalanceControl }); await Task.WhenAll(tasks); + //timer.Stop(); + //Console.WriteLine($"任务处理完成,耗时:{timer.ElapsedMilliseconds}ms"); } /// @@ -234,7 +239,7 @@ namespace JiShe.CollectBus.Common.DeviceBalanceControl { int coreCount = Environment.ProcessorCount; return Math.Min( - coreCount * 2, // 超线程优化 + coreCount * 8, // 超线程优化 _currentCache?.CachedGroups.Length ?? 60 ); } diff --git a/shared/JiShe.CollectBus.Common/Enums/376Enums.cs b/shared/JiShe.CollectBus.Common/Enums/376Enums.cs index cff3340..dedeaca 100644 --- a/shared/JiShe.CollectBus.Common/Enums/376Enums.cs +++ b/shared/JiShe.CollectBus.Common/Enums/376Enums.cs @@ -376,15 +376,22 @@ namespace JiShe.CollectBus.Common.Enums /// /// 数据冻结密度 + /// -1、采集项本身无密度位,0、无冻结,1、15分钟,2、30分钟,3、60分钟,245、5分钟,255、1分钟 /// public enum DensityEnums { - Sec_1 = 255, - Sec_5 = 254, - Sec_60 = 3, - Sec_30 = 2, - Sec_15 = 1, - Sec_0 = 0 + [Description("0")] + Second = 0, + [Description("1")] + OneMinute = 255, + [Description("5")] + FiveMinute = 254, + [Description("15")] + FifteenMinute = 1, + [Description("30")] + ThirtyMinute = 2, + [Description("60")] + SixtyMinute = 3, } /// @@ -392,10 +399,14 @@ namespace JiShe.CollectBus.Common.Enums /// public enum DensityUnit { + /// + /// 无 + /// + None = -1, /// /// 秒 /// - Second=0, + Second =0, /// /// 分钟 /// diff --git a/shared/JiShe.CollectBus.Common/Enums/MeterTypeEnum.cs b/shared/JiShe.CollectBus.Common/Enums/MeterTypeEnum.cs index 43cfaae..dc78e45 100644 --- a/shared/JiShe.CollectBus.Common/Enums/MeterTypeEnum.cs +++ b/shared/JiShe.CollectBus.Common/Enums/MeterTypeEnum.cs @@ -49,5 +49,10 @@ namespace JiShe.CollectBus.Common.Enums /// 采集器 /// Collector = 9, + + /// + /// 集中器 + /// + Focus = 10, } } diff --git a/shared/JiShe.CollectBus.Common/Enums/RetryReadingEnum.cs b/shared/JiShe.CollectBus.Common/Enums/RetryReadingEnum.cs new file mode 100644 index 0000000..ee7a388 --- /dev/null +++ b/shared/JiShe.CollectBus.Common/Enums/RetryReadingEnum.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Enums +{ + /// + /// 监控重试类型 + /// + public enum RetryReadingEnum + { + /// + /// 1分钟 + /// + OneMinute, + + /// + /// 5分钟 + /// + FiveMinute, + + /// + /// 15分钟 + /// + FifteenMinute, + + } +} diff --git a/shared/JiShe.CollectBus.Common/Enums/TableTimeStrategyEnum.cs b/shared/JiShe.CollectBus.Common/Enums/TableTimeStrategyEnum.cs new file mode 100644 index 0000000..db065af --- /dev/null +++ b/shared/JiShe.CollectBus.Common/Enums/TableTimeStrategyEnum.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Enums +{ + /// + /// 分表策略枚举 + /// + public enum TableTimeStrategyEnum + { + /// + /// 按分钟分表 + /// + MinuteShardingStrategy = 0, + + /// + /// 按小时分表 + /// + HourShardingStrategy = 1, + /// + /// 按天分表 + /// + DayShardingStrategy = 2, + /// + /// 按月分表 + /// + MonthShardingStrategy = 3, + /// + /// 按年分表 + /// + YearShardingStrategy = 4 + } +} diff --git a/shared/JiShe.CollectBus.Common/Enums/TelemetryPacketTypeEnum.cs b/shared/JiShe.CollectBus.Common/Enums/TelemetryPacketTypeEnum.cs new file mode 100644 index 0000000..837392b --- /dev/null +++ b/shared/JiShe.CollectBus.Common/Enums/TelemetryPacketTypeEnum.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Enums +{ + /// + /// 遥测数据包类型枚举 + /// + public enum TelemetryPacketTypeEnum + { + /// + /// 1分钟密度 + /// + [Description("1分钟密度")] + AmmeterOneMinute = 1, + + /// + /// 5分钟密度 + /// + [Description("5分钟密度")] + AmmeterMeterFiveMinute = 5, + + /// + /// 15分钟密度 + /// + [Description("15分钟密度")] + AmmeterFifteenMinute = 15, + + /// + /// 自动校时 + /// + [Description("自动校时")] + AmmeterAutomaticVerificationTime = 16, + + /// + /// 日冻结 + /// + [Description("日冻结")] + AmmeterDayFreeze = 17, + + /// + /// 月冻结 + /// + [Description("月冻结")] + AmmeterMonthFreeze = 18, + + /// + /// 自动阀控 + /// + [Description("自动阀控")] + AmmeterAutoValveControl = 19, + + /// + /// 集中器终端版本 + /// + [Description("集中器终端版本")] + TerminalVersion = 20, + + /// + /// 集中器通信模块SIM + /// + [Description("集中器通信模块SIM")] + TelematicsModule = 21, + + /// + /// 水表抄读 + /// + [Description("水表抄读")] + WatermeterAutoReadding = 22, + } +} diff --git a/shared/JiShe.CollectBus.Common/Extensions/DateTimeExtensions.cs b/shared/JiShe.CollectBus.Common/Extensions/DateTimeExtensions.cs index 6936ad3..3254edc 100644 --- a/shared/JiShe.CollectBus.Common/Extensions/DateTimeExtensions.cs +++ b/shared/JiShe.CollectBus.Common/Extensions/DateTimeExtensions.cs @@ -1,4 +1,5 @@ -using System; +using JiShe.CollectBus.Common.Enums; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -173,13 +174,24 @@ namespace JiShe.CollectBus.Common.Extensions /// /// /// - public static string GetDataTableShardingStrategy(this DateTime dateTime) + public static string GetDataTableShardingStrategy(this DateTime dateTime, TableTimeStrategyEnum tableStrategy) { -#if DEBUG - return $"{dateTime:yyyyMMddHHmm}"; -#else - return $"{dateTime:yyyyMMddHH}"; -#endif + switch (tableStrategy) + { + case TableTimeStrategyEnum.MinuteShardingStrategy: + return $"{dateTime:yyyyMMddHHmm}"; + case TableTimeStrategyEnum.HourShardingStrategy: + return $"{dateTime:yyyyMMddHH}"; + case TableTimeStrategyEnum.DayShardingStrategy: + return $"{dateTime:yyyyMMdd}"; + case TableTimeStrategyEnum.MonthShardingStrategy: + return $"{dateTime:yyyyMM}"; + case TableTimeStrategyEnum.YearShardingStrategy: + return $"{dateTime:yyyy}"; + default: + return $""; // 默认不分表 + + } } @@ -245,7 +257,7 @@ namespace JiShe.CollectBus.Common.Extensions /// /// /// - public static DateTime ParseIntToDate(long dateLong) + public static DateTime ParseIntToDate(this long dateLong) { if (dateLong < 10000101 || dateLong > 99991231) { diff --git a/shared/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs b/shared/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs index 20ee829..6eb4b36 100644 --- a/shared/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs +++ b/shared/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs @@ -100,14 +100,21 @@ namespace JiShe.CollectBus.Common.Extensions return hexStringList; } - public static List ReduceHex33(this List hexStringList) + /// + /// 字节减33 + /// + /// + /// 是否反转 + /// + public static List ReduceHex33(this List hexStringList,bool isReverse = false) { for (int i = 0; i < hexStringList.Count; i++) { var value = Convert.ToInt32(hexStringList[i], 16) - Convert.ToInt32("33", 16); hexStringList[i] = value.DecToHex().PadLeft(2, '0'); } - + if(isReverse) + hexStringList.Reverse(); return hexStringList; } diff --git a/shared/JiShe.CollectBus.Common/Extensions/StringExtensions.cs b/shared/JiShe.CollectBus.Common/Extensions/StringExtensions.cs index d2cea60..4b24683 100644 --- a/shared/JiShe.CollectBus.Common/Extensions/StringExtensions.cs +++ b/shared/JiShe.CollectBus.Common/Extensions/StringExtensions.cs @@ -1183,10 +1183,10 @@ namespace JiShe.CollectBus.Common.Extensions /// /// /// - public static string HexToDecStr(this int hexString) + public static string HexToDecStr(this int hexString,bool isUpper= true) { var decimalString = Convert.ToString(hexString, 16); - return decimalString; + return isUpper? decimalString.ToUpper(): decimalString; } /// diff --git a/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs b/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs index 59691ce..e6cbafd 100644 --- a/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs +++ b/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs @@ -9,6 +9,9 @@ using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using JiShe.CollectBus.Common.Attributes; +using System.Collections.Specialized; +using JiShe.CollectBus.Common.Enums; +using Newtonsoft.Json.Linq; namespace JiShe.CollectBus.Common.Helpers { @@ -670,6 +673,31 @@ namespace JiShe.CollectBus.Common.Helpers } + /// + /// 根据枚举类型值返回枚举定义Description属性 + /// + /// + /// + /// + public static string GetEnumDescription(this int value, Type enumType) + { + NameValueCollection nameValueCollection = new NameValueCollection(); + Type typeFromHandle = typeof(DescriptionAttribute); + FieldInfo[] fields = enumType.GetFields(); + foreach (FieldInfo fieldInfo in fields) + { + if (fieldInfo.FieldType.IsEnum) + { + string name = ((int)enumType.InvokeMember(fieldInfo.Name, BindingFlags.GetField, null, null, null)).ToString(); + object[] customAttributes = fieldInfo.GetCustomAttributes(typeFromHandle, inherit: true); + string value2 = ((customAttributes.Length == 0) ? "" : ((DescriptionAttribute)customAttributes[0]).Description); + nameValueCollection.Add(name, value2); + } + } + + return nameValueCollection[value.ToString()]; + } + /// /// 将传入的字符串中间部分字符替换成特殊字符 @@ -770,7 +798,7 @@ namespace JiShe.CollectBus.Common.Helpers /// /// /// - public static string GetTaskMark(int afn, int fn, int pn, int msa,int seq) + public static string GetTaskMark(int afn, int fn, int pn, int msa, int seq) { var makstr = $"{afn.ToString().PadLeft(2, '0')}{fn.ToString().PadLeft(2, '0')}{pn.ToString().PadLeft(2, '0')}{msa.ToString().PadLeft(2, '0')}{seq.ToString().PadLeft(2, '0')}"; @@ -807,6 +835,11 @@ namespace JiShe.CollectBus.Common.Helpers /// public static bool JudgeIsGenerate_Day(string eachDayWithout, DateTime curTime) { + if (string.IsNullOrWhiteSpace(eachDayWithout)) + { + return false; + } + var weekName = strWeeks[(int)curTime.DayOfWeek]; var arr = eachDayWithout.Split(','); return !arr.Contains(weekName); @@ -833,6 +866,54 @@ namespace JiShe.CollectBus.Common.Helpers } - + /// + /// 系统采集频率转换为集中器采集密度 + /// + /// + /// + public static int GetFocusDensity(this int timeDensity) => timeDensity switch + { + 0 => 0,//无 + 1 => 255,//1分钟 + 5 => 245,//5分钟 + 15 => 1,//15分钟 + 30 => 2,//30分钟 + 60 => 3,//60分钟 + _ => -1//采集项本身无密度位 + }; + + /// + /// 集中器采集密度转换为系统采集频率 + /// + /// + /// + public static int GetSystemDensity(this int density) => density switch + { + 0 => 0,//无 + 255 => 1,//1分钟 + 245 => 5,//5分钟 + 1 => 15,//15分钟 + 2 => 30,//30分钟 + 3 => 60,//60分钟 + _ => -1//采集项本身无密度位 + }; + + /// + /// 获取集中器ZSet Scores + /// + /// + /// + /// + public static long GetFocusScores(string focusScores, int point) + { + bool hasInvalidChars = focusScores.Any(c => !(c >= '0' && c <= '9')); + if (hasInvalidChars) + { + throw new Exception($"{nameof(GetFocusScores)} 集中器地址格式错误"); + } + var scoresStr = $"{focusScores}{point.ToString().PadLeft(2, '0')}"; + + return Convert.ToInt64(scoresStr); + } } } diff --git a/shared/JiShe.CollectBus.Common/Helpers/DataFieldHelper.cs b/shared/JiShe.CollectBus.Common/Helpers/DataFieldHelper.cs index a9173bb..bcf0bcc 100644 --- a/shared/JiShe.CollectBus.Common/Helpers/DataFieldHelper.cs +++ b/shared/JiShe.CollectBus.Common/Helpers/DataFieldHelper.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; +using static JiShe.CollectBus.Common.Consts.T37612012PacketItemCodeConst; namespace JiShe.CollectBus.Common.Helpers { - public class DataFieldHelper + public static class DataFieldHelper { public static string GetDataField(string dataField) { @@ -22,5 +24,61 @@ namespace JiShe.CollectBus.Common.Helpers return dataField; } + + /// + /// 数据字段映射 + /// + public static Dictionary DataFieldDic = new Dictionary(); + + /// + /// 创建数据字段映射 + /// + /// + public static Dictionary CreateDataFieldMapping() + { + if (DataFieldDic.Count > 0) + return DataFieldDic; + var dataFieldMapping = new Dictionary(); + Type dataType = typeof(ConstGatherDataType); + Type fieldType = typeof(DataFieldConst); + + foreach (FieldInfo gatherField in dataType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)) + { + if (gatherField.IsLiteral && !gatherField.IsInitOnly) + { + // 获取ConstGatherDataType的字段值作为key + string key = (string)gatherField.GetValue(null)!; + + // 查找DataFieldConst中同名字段 + FieldInfo dataField = fieldType.GetField(gatherField.Name, + BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)!; + + if (dataField != null) + { + string value = (string)dataField.GetValue(null)!; + dataFieldMapping[key] = value; + } + } + } + + return dataFieldMapping; + } + + /// + /// 根据采集数据类型获取数据字段 + /// 返回null表示 无效字段 + /// + /// + /// + public static string? GetDataFieldByGatherDataType(this string gatherDataType) + { + if (CreateDataFieldMapping().TryGetValue(gatherDataType, out string? column)) + { + return column; + } + return null; + } + + } } diff --git a/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj b/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj index 05645ef..6cf0246 100644 --- a/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj +++ b/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj @@ -17,7 +17,7 @@ - + @@ -25,8 +25,7 @@ - - + diff --git a/shared/JiShe.CollectBus.Common/Models/DeviceCacheBasicModel.cs b/shared/JiShe.CollectBus.Common/Models/DeviceCacheBasicModel.cs index 1edc46a..178b625 100644 --- a/shared/JiShe.CollectBus.Common/Models/DeviceCacheBasicModel.cs +++ b/shared/JiShe.CollectBus.Common/Models/DeviceCacheBasicModel.cs @@ -1,4 +1,5 @@ -using System; +using JiShe.CollectBus.Common.Enums; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -40,5 +41,16 @@ namespace JiShe.CollectBus.Common.Models /// 集中器地址 /// public string FocusAddress { get; set;} + + /// + /// 采集时间间隔(分钟,如15) + /// + public int TimeDensity { get; set; } + + /// + /// 表计类型 + /// 电表= 1,水表= 2,燃气表= 3,热能表= 4,水表流量计=5,燃气表流量计=6,特殊电表=7 + /// + public MeterTypeEnum MeterType { get; set; } } } diff --git a/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs b/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs index 8aed32b..525b5a2 100644 --- a/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs +++ b/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs @@ -8,31 +8,46 @@ /// /// 服务器标识 /// - public required string ServerTagName { get; set; } + public string ServerTagName { get; set; } /// /// 系统类型 /// - public required string SystemType { get; set; } + public string SystemType { get; set; } /// /// 首次采集时间 /// - public DateTime? FirstCollectionTime { get; set; } + public DateTime? FirstCollectionTime { get; set; } /// /// 自动验证时间 /// - public required string AutomaticVerificationTime { get; set;} + public string AutomaticVerificationTime { get; set; } /// /// 自动获取终端版时间 /// - public required string AutomaticGetTerminalVersionTime { get; set; } + public string AutomaticTerminalVersionTime { get; set; } /// /// 自动获取远程通信模块(SIM)版本时间 /// - public required string AutomaticGetTelematicsModuleTime { get; set; } + public string AutomaticTelematicsModuleTime { get; set; } + + /// + /// 日冻结抄读时间 + /// + public string AutomaticDayFreezeTime { get; set; } + + /// + /// 月冻结抄读时间 + /// + public string AutomaticMonthFreezeTime { get; set; } + + /// + /// 默认协议插件 + /// + public string DefaultProtocolPlugin { get; set; } } } diff --git a/shared/JiShe.CollectBus.Common/Models/TasksToBeIssueModel.cs b/shared/JiShe.CollectBus.Common/Models/TasksToBeIssueModel.cs index 1484ab8..a2a613b 100644 --- a/shared/JiShe.CollectBus.Common/Models/TasksToBeIssueModel.cs +++ b/shared/JiShe.CollectBus.Common/Models/TasksToBeIssueModel.cs @@ -14,10 +14,10 @@ namespace JiShe.CollectBus.Common.Models /// /// 上次下发任务的时间 /// - public DateTime? LastTaskTime { get; set; } + public DateTime LastTaskTime { get; set; } /// - /// 下个任务时间 + /// 下个任务时间,用于构建待采集的 LastTaskTime 任务的时间 /// public DateTime NextTaskTime { get; set; } diff --git a/shared/JiShe.CollectBus.Domain.Shared/CollectBusDomainSharedConsts.cs b/shared/JiShe.CollectBus.Domain.Shared/CollectBusDomainSharedConsts.cs index 8c06a44..63ab843 100644 --- a/shared/JiShe.CollectBus.Domain.Shared/CollectBusDomainSharedConsts.cs +++ b/shared/JiShe.CollectBus.Domain.Shared/CollectBusDomainSharedConsts.cs @@ -14,7 +14,7 @@ namespace JiShe.CollectBus public const string DefaultCultureName = "zh-Hans"; public const string Basic = "Basic"; - public const string Business = "Business"; + public const string Business = "Business"; } } diff --git a/shared/JiShe.CollectBus.Domain.Shared/JiShe.CollectBus.Domain.Shared.csproj b/shared/JiShe.CollectBus.Domain.Shared/JiShe.CollectBus.Domain.Shared.csproj index 874b688..5453712 100644 --- a/shared/JiShe.CollectBus.Domain.Shared/JiShe.CollectBus.Domain.Shared.csproj +++ b/shared/JiShe.CollectBus.Domain.Shared/JiShe.CollectBus.Domain.Shared.csproj @@ -1,38 +1,38 @@ - + - - net8.0 - enable - JiShe.CollectBus - true - + + net8.0 + enable + JiShe.CollectBus + true + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + diff --git a/web/JiShe.CollectBus.Host/CollectBusHostModule.Configure.cs b/web/JiShe.CollectBus.Host/CollectBusHostModule.Configure.cs index e6f1e7e..b00b7b6 100644 --- a/web/JiShe.CollectBus.Host/CollectBusHostModule.Configure.cs +++ b/web/JiShe.CollectBus.Host/CollectBusHostModule.Configure.cs @@ -37,7 +37,7 @@ namespace JiShe.CollectBus.Host Db = context.Services.GetConfiguration().GetValue("Redis:HangfireDB") }; - Configure(options => { options.IsJobExecutionEnabled = true; }); + Configure(options => { options.IsJobExecutionEnabled = false; }); context.Services.AddHangfire(config => { @@ -259,12 +259,12 @@ namespace JiShe.CollectBus.Host .AddMongoDb(configuration.GetConnectionString("Default"), "MongoDB", HealthStatus.Unhealthy) .AddRedis(configuration.GetValue("Redis:Configuration") ?? string.Empty, "Redis", HealthStatus.Unhealthy) - .AddKafka(new Confluent.Kafka.ProducerConfig - { - BootstrapServers = configuration.GetConnectionString("Kafka") - }, "Kafka", failureStatus: HealthStatus.Unhealthy) + //.AddKafka(new Confluent.Kafka.ProducerConfig + //{ + // BootstrapServers = configuration.GetValue("Kafka:BootstrapServers") + //}, "Kafka", failureStatus: HealthStatus.Unhealthy) - .AddCheck("Cassandra") + //.AddCheck("Cassandra") .AddCheck("IoTDB"); context.Services diff --git a/web/JiShe.CollectBus.Host/HealthChecks/IoTDBHealthCheck.cs b/web/JiShe.CollectBus.Host/HealthChecks/IoTDBHealthCheck.cs index d3cb45f..a1cebf2 100644 --- a/web/JiShe.CollectBus.Host/HealthChecks/IoTDBHealthCheck.cs +++ b/web/JiShe.CollectBus.Host/HealthChecks/IoTDBHealthCheck.cs @@ -36,10 +36,11 @@ namespace JiShe.CollectBus.Host.HealthChecks { try { - var ioTDbOptions = new IoTDbOptions(); - _configuration.GetSection("IoTDBOptions").Bind(ioTDbOptions); - var pool = new SessionPoolAdapter(ioTDbOptions); - await pool.OpenAsync(); + // todo 此处需要单独创建连接,并需要在连接打开以后立即关闭,否则会影响整个连接的使用。 + //var ioTDbOptions = new IoTDbOptions(); + //_configuration.GetSection("IoTDBOptions").Bind(ioTDbOptions); + //var pool = new SessionPoolAdapter(ioTDbOptions); + //await pool.OpenAsync(); return HealthCheckResult.Healthy($"IoTDB is healthy."); } catch (Exception ex) diff --git a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj b/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj index 4ebd67d..5501841 100644 --- a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj +++ b/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj @@ -5,7 +5,7 @@ enable enable True - + @@ -55,9 +55,9 @@ - - - + + + diff --git a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Protocol.Test.dll b/web/JiShe.CollectBus.Host/JiShe.CollectBus.Protocol.Test.dll deleted file mode 100644 index 01d6842..0000000 Binary files a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Protocol.Test.dll and /dev/null differ diff --git a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Protocol.dll b/web/JiShe.CollectBus.Host/JiShe.CollectBus.Protocol.dll deleted file mode 100644 index 96cf07b..0000000 Binary files a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Protocol.dll and /dev/null differ diff --git a/web/JiShe.CollectBus.Host/Pages/Monitor.cshtml b/web/JiShe.CollectBus.Host/Pages/Monitor.cshtml index 3a7fbc7..4e13d71 100644 --- a/web/JiShe.CollectBus.Host/Pages/Monitor.cshtml +++ b/web/JiShe.CollectBus.Host/Pages/Monitor.cshtml @@ -5,8 +5,8 @@ @{ Layout = null; -} - +} + @@ -16,8 +16,9 @@ 后端服务 - + +