diff --git a/Directory.Build.JiShe.targets b/Directory.Build.JiShe.targets new file mode 100644 index 0000000..c4b9ff0 --- /dev/null +++ b/Directory.Build.JiShe.targets @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.Microsoft.targets b/Directory.Build.Microsoft.targets new file mode 100644 index 0000000..9e2203b --- /dev/null +++ b/Directory.Build.Microsoft.targets @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.Volo.targets b/Directory.Build.Volo.targets new file mode 100644 index 0000000..17d91a7 --- /dev/null +++ b/Directory.Build.Volo.targets @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..64df1da --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,12 @@ + + + + + 1.0.5.08 + + 9.1.1 + + + 9.0.0 + + \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000..4333da3 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,155 @@ + + + + + + + + latest + 1.0.1 + JiShe Service Pro + $(NoWarn);CS1591;CS0436;NU1504 + app + true + 湖南集社电子技术有限公司 + true + icon.png + bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 8030845..95839ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,21 @@ -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base WORKDIR /app EXPOSE 8080 EXPOSE 10500 ENV TZ=Asia/Shanghai ENV ASPNETCORE_ENVIRONMENT=Production -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build # WORKDIR /src COPY ["JiShe.CollectBus.Main.sln", "."] COPY ["common.props", "."] +COPY ["Directory.Build.JiShe.targets", "."] +COPY ["Directory.Build.Microsoft.targets", "."] +COPY ["Directory.Build.props", "."] +COPY ["Directory.Build.targets", "."] +COPY ["Directory.Build.Volo.targets", "."] COPY ["NuGet.Config", "."] COPY ["web/", "web/"] -COPY ["modules/", "modules/"] COPY ["services/", "services/"] COPY ["shared/", "shared/"] COPY ["protocols/", "protocols/"] diff --git a/JiShe.CollectBus.Main.sln b/JiShe.CollectBus.Main.sln index 46d2db3..3fa5f95 100644 --- a/JiShe.CollectBus.Main.sln +++ b/JiShe.CollectBus.Main.sln @@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Applicatio 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}" @@ -21,23 +19,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Common", " 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}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4.Protocols", "4.Protocols", "{3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2.Services", "2.Services", "{BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23}" EndProject @@ -54,6 +40,11 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0.Docs", "0.Docs", "{D8346C4C-55B8-43E8-A6B8-E59D56FE6D92}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore + Directory.Build.JiShe.targets = Directory.Build.JiShe.targets + Directory.Build.Microsoft.targets = Directory.Build.Microsoft.targets + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + Directory.Build.Volo.targets = Directory.Build.Volo.targets Dockerfile = Dockerfile NuGet.Config = NuGet.Config PackageAndPublish.bat = PackageAndPublish.bat @@ -61,10 +52,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0.Docs", "0.Docs", "{D8346C 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 @@ -87,10 +74,6 @@ Global {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 @@ -107,30 +90,10 @@ Global {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 @@ -147,14 +110,6 @@ 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 - {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 @@ -164,23 +119,15 @@ Global {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} diff --git a/JiShe.CollectBus.sln b/JiShe.CollectBus.sln index c32791b..ffc3d0d 100644 --- a/JiShe.CollectBus.sln +++ b/JiShe.CollectBus.sln @@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Applicatio 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}" @@ -21,30 +19,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Common", " 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}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4.Protocols", "4.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.Kafka.Test", "modules\JiShe.CollectBus.Kafka.Test\JiShe.CollectBus.Kafka.Test.csproj", "{6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B}" -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}" @@ -56,44 +40,17 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0.Docs", "0.Docs", "{D8346C4C-55B8-43E8-A6B8-E59D56FE6D92}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore + Directory.Build.JiShe.targets = Directory.Build.JiShe.targets + Directory.Build.Microsoft.targets = Directory.Build.Microsoft.targets + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + Directory.Build.Volo.targets = Directory.Build.Volo.targets Dockerfile = Dockerfile NuGet.Config = NuGet.Config PackageAndPublish.bat = PackageAndPublish.bat 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 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MainService", "MainService", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EPOService", "EPOService", "{18207368-3C39-4346-85F7-A8B499B0B458}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MigrationService", "MigrationService", "{A31EC18C-956B-4FD2-AED6-609C33B467E9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBusEPO.Application.Contracts", "services\JiShe.CollectBusEPO.Application.Contracts\JiShe.CollectBusEPO.Application.Contracts.csproj", "{3B32D838-33BF-C08A-C447-3172CA62D42F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBusEPO.Application", "services\JiShe.CollectBusEPO.Application\JiShe.CollectBusEPO.Application.csproj", "{C71FF348-FB47-67E6-AF0D-6A8E48C5EDEA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBusEPO.HttpApi", "web\JiShe.CollectBusEPO.HttpApi\JiShe.CollectBusEPO.HttpApi.csproj", "{98FE468D-0C34-83D9-31BD-F59C44D00357}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBusEPO.HttpApi.Host", "web\JiShe.CollectBusEPO.HttpApi.Host\JiShe.CollectBusEPO.HttpApi.Host.csproj", "{A2DDA6F0-C760-0633-D576-E23A186504E4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MainHost", "MainHost", "{A38B5EB3-2F55-44A2-944B-31A73DE91402}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MigrationHost", "MigrationHost", "{C61007F8-51F5-409C-9FAF-DEF6A24DCDED}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EPOHost", "EPOHost", "{8D1FD3D9-3FF0-4581-ACF0-45AF9D595774}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -116,10 +73,6 @@ Global {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 @@ -136,34 +89,10 @@ Global {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 - {6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B}.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 @@ -180,46 +109,6 @@ 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 - {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 - {3B32D838-33BF-C08A-C447-3172CA62D42F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B32D838-33BF-C08A-C447-3172CA62D42F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3B32D838-33BF-C08A-C447-3172CA62D42F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B32D838-33BF-C08A-C447-3172CA62D42F}.Release|Any CPU.Build.0 = Release|Any CPU - {C71FF348-FB47-67E6-AF0D-6A8E48C5EDEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C71FF348-FB47-67E6-AF0D-6A8E48C5EDEA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C71FF348-FB47-67E6-AF0D-6A8E48C5EDEA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C71FF348-FB47-67E6-AF0D-6A8E48C5EDEA}.Release|Any CPU.Build.0 = Release|Any CPU - {98FE468D-0C34-83D9-31BD-F59C44D00357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {98FE468D-0C34-83D9-31BD-F59C44D00357}.Debug|Any CPU.Build.0 = Debug|Any CPU - {98FE468D-0C34-83D9-31BD-F59C44D00357}.Release|Any CPU.ActiveCfg = Release|Any CPU - {98FE468D-0C34-83D9-31BD-F59C44D00357}.Release|Any CPU.Build.0 = Release|Any CPU - {A2DDA6F0-C760-0633-D576-E23A186504E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A2DDA6F0-C760-0633-D576-E23A186504E4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A2DDA6F0-C760-0633-D576-E23A186504E4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A2DDA6F0-C760-0633-D576-E23A186504E4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -227,40 +116,17 @@ Global 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} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} - {78040F9E-3501-4A40-82DF-00A597710F35} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} - {F1C58097-4C08-4D88-8976-6B3389391481} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59} - {077AA5F8-8B61-420C-A6B5-0150A66FDB34} = {A38B5EB3-2F55-44A2-944B-31A73DE91402} - {35829A15-4127-4F69-8BDE-9405DEAACA9A} = {A38B5EB3-2F55-44A2-944B-31A73DE91402} + {BD65D04F-08D5-40C1-8C24-77CA0BACB877} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23} + {78040F9E-3501-4A40-82DF-00A597710F35} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23} + {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} - {6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B} = {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} - {E01625B5-B5B7-7A4B-468F-EC12C1BDBA2A} = {A31EC18C-956B-4FD2-AED6-609C33B467E9} - {B955C5DA-3C20-35D2-0770-8FE473C41C44} = {A31EC18C-956B-4FD2-AED6-609C33B467E9} - {995D3D91-7221-D4A3-A7B2-FEC202328A18} = {C61007F8-51F5-409C-9FAF-DEF6A24DCDED} - {8A113DE5-7D50-6E6B-739F-B6EEAD5E13B4} = {C61007F8-51F5-409C-9FAF-DEF6A24DCDED} - {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23} - {18207368-3C39-4346-85F7-A8B499B0B458} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23} - {A31EC18C-956B-4FD2-AED6-609C33B467E9} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23} - {3B32D838-33BF-C08A-C447-3172CA62D42F} = {18207368-3C39-4346-85F7-A8B499B0B458} - {C71FF348-FB47-67E6-AF0D-6A8E48C5EDEA} = {18207368-3C39-4346-85F7-A8B499B0B458} - {98FE468D-0C34-83D9-31BD-F59C44D00357} = {8D1FD3D9-3FF0-4581-ACF0-45AF9D595774} - {A2DDA6F0-C760-0633-D576-E23A186504E4} = {8D1FD3D9-3FF0-4581-ACF0-45AF9D595774} - {A38B5EB3-2F55-44A2-944B-31A73DE91402} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94} - {C61007F8-51F5-409C-9FAF-DEF6A24DCDED} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94} - {8D1FD3D9-3FF0-4581-ACF0-45AF9D595774} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD} diff --git a/NuGet.Config b/NuGet.Config index 44f8e7f..370bfce 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -1,7 +1,8 @@ - - - - \ No newline at end of file + + + + + diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..d8e6f12 Binary files /dev/null and b/icon.png differ diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs deleted file mode 100644 index c0ce66c..0000000 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ /dev/null @@ -1,734 +0,0 @@ -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)!; - }); - } - - public static object GetAccessor(Type type) - { - MethodInfo getAccessorMethod = typeof(SourceEntityAccessorFactory) - .GetMethod( - name: nameof(GetAccessor), - bindingAttr: BindingFlags.Public | BindingFlags.Static, - - types: Type.EmptyTypes - ); - - MethodInfo genericMethod = getAccessorMethod.MakeGenericMethod(type); - return genericMethod.Invoke(null, null); - } - } - """; - } - - /// - /// 属性访问生成逻辑 - /// - /// 属性集合 - /// - /// - /// - 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 deleted file mode 100644 index 66b1fcf..0000000 --- a/modules/JiShe.CollectBus.Analyzers/JiShe.CollectBus.Analyzers.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - netstandard2.0 - true - true - false - bin - false - latest - true - true - - - - - - - - - diff --git a/modules/JiShe.CollectBus.Cassandra/CassandraConfig.cs b/modules/JiShe.CollectBus.Cassandra/CassandraConfig.cs deleted file mode 100644 index c14171e..0000000 --- a/modules/JiShe.CollectBus.Cassandra/CassandraConfig.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Cassandra -{ - public class CassandraConfig - { - public Node[] Nodes { get; set; } - public string Username { get; set; } - public string Password { get; set; } - public string Keyspace { get; set; } - public string ConsistencyLevel { get; set; } - public Pooling PoolingOptions { get; set; } - public Socket SocketOptions { get; set; } - public Query QueryOptions { get; set; } - - public ReplicationStrategy ReplicationStrategy { get; set; } - } - - public class Pooling - { - public int CoreConnectionsPerHost { get; set; } - public int MaxConnectionsPerHost { get; set; } - public int MaxRequestsPerConnection { get; set; } - } - - public class Socket - { - public int ConnectTimeoutMillis { get; set; } - public int ReadTimeoutMillis { get; set; } - } - - public class Query - { - public string ConsistencyLevel { get; set; } - public string SerialConsistencyLevel { get; set; } - public bool DefaultIdempotence { get; set; } - } - - public class ReplicationStrategy - { - public string Class { get; set; } - public DataCenter[] DataCenters { get; set; } - } - - public class DataCenter - { - public string Name { get; set; } - public int ReplicationFactor { get; set; } - public string Strategy { get; set; } - } - - public class Node - { - public string Host { get; set; } - public int Port { get; set; } - public string DataCenter { get; set; } - public string Rack { get; set; } - } - -} diff --git a/modules/JiShe.CollectBus.Cassandra/CassandraProvider.cs b/modules/JiShe.CollectBus.Cassandra/CassandraProvider.cs deleted file mode 100644 index dc3e0ee..0000000 --- a/modules/JiShe.CollectBus.Cassandra/CassandraProvider.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Text; -using Cassandra; -using Cassandra.Mapping; -using Cassandra.Data.Linq; -using System.ComponentModel.DataAnnotations; -using System.Diagnostics; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -using JiShe.CollectBus.Common.Attributes; - -namespace JiShe.CollectBus.Cassandra -{ - public class CassandraProvider : IDisposable, ICassandraProvider, ISingletonDependency - { - private readonly ILogger _logger; - - public Cluster Instance { get; set; } - - public ISession Session { get; set; } - - public CassandraConfig CassandraConfig { get; set; } - /// - /// - /// - /// - /// - public CassandraProvider( - IOptions options, - ILogger logger) - { - CassandraConfig = options.Value; - _logger = logger; - } - - public Task InitClusterAndSessionAsync() - { - InitClusterAndSession(); - return Task.CompletedTask; - } - - public void InitClusterAndSession() - { - GetCluster((keyspace) => - { - GetSession(keyspace); - }); - } - - public Cluster GetCluster(Action? callback=null) - { - var clusterBuilder = Cluster.Builder(); - - // 添加多个节点 - foreach (var node in CassandraConfig.Nodes) - { - clusterBuilder.AddContactPoint(node.Host) - .WithPort(node.Port); - } - - clusterBuilder.WithCredentials(CassandraConfig.Username, CassandraConfig.Password); - - // 优化连接池配置 - var poolingOptions = new PoolingOptions() - .SetCoreConnectionsPerHost(HostDistance.Local, CassandraConfig.PoolingOptions.CoreConnectionsPerHost) - .SetMaxConnectionsPerHost(HostDistance.Local, CassandraConfig.PoolingOptions.MaxConnectionsPerHost) - .SetMaxRequestsPerConnection(CassandraConfig.PoolingOptions.MaxRequestsPerConnection) - .SetHeartBeatInterval(30000); // 30秒心跳 - - clusterBuilder.WithPoolingOptions(poolingOptions); - - // 优化Socket配置 - var socketOptions = new SocketOptions() - .SetConnectTimeoutMillis(CassandraConfig.SocketOptions.ConnectTimeoutMillis) - .SetReadTimeoutMillis(CassandraConfig.SocketOptions.ReadTimeoutMillis) - .SetTcpNoDelay(true) // 启用Nagle算法 - .SetKeepAlive(true) // 启用TCP保活 - .SetReceiveBufferSize(32768) // 32KB接收缓冲区 - .SetSendBufferSize(32768); // 32KB发送缓冲区 - - clusterBuilder.WithSocketOptions(socketOptions); - - // 优化查询选项 - var queryOptions = new QueryOptions() - .SetConsistencyLevel((ConsistencyLevel)Enum.Parse(typeof(ConsistencyLevel), CassandraConfig.QueryOptions.ConsistencyLevel)) - .SetSerialConsistencyLevel((ConsistencyLevel)Enum.Parse(typeof(ConsistencyLevel), CassandraConfig.QueryOptions.SerialConsistencyLevel)) - .SetDefaultIdempotence(CassandraConfig.QueryOptions.DefaultIdempotence) - .SetPageSize(5000); // 增加页面大小 - - clusterBuilder.WithQueryOptions(queryOptions); - - // 启用压缩 - clusterBuilder.WithCompression(CompressionType.LZ4); - - // 配置重连策略 - clusterBuilder.WithReconnectionPolicy(new ExponentialReconnectionPolicy(1000, 10 * 60 * 1000)); - Instance = clusterBuilder.Build(); - callback?.Invoke(null); - return Instance; - } - - public ISession GetSession(string? keyspace = null) - { - if (string.IsNullOrEmpty(keyspace)) - { - keyspace = CassandraConfig.Keyspace; - } - Session = Instance.Connect(); - var replication = GetReplicationStrategy(); - Session.CreateKeyspaceIfNotExists(keyspace, replication); - Session.ChangeKeyspace(keyspace); - return Session; - } - - private Dictionary GetReplicationStrategy() - { - var strategy = CassandraConfig.ReplicationStrategy.Class; - var dataCenters = CassandraConfig.ReplicationStrategy.DataCenters; - - switch (strategy) - { - case "NetworkTopologyStrategy": - var networkDic = new Dictionary { { "class", "NetworkTopologyStrategy" } }; - foreach (var dataCenter in dataCenters) - { - networkDic.Add(dataCenter.Name, dataCenter.ReplicationFactor.ToString()); - } - return networkDic; - case "SimpleStrategy": - var dic = new Dictionary { { "class", "SimpleStrategy" } }; - if (dataCenters.Length >= 1) - { - dic.Add("replication_factor", dataCenters[0].ReplicationFactor.ToString()); - } - else - { - _logger.LogError("SimpleStrategy 不支持多个数据中心!"); - } - return dic; - default: - throw new ArgumentNullException($"Strategy", "Strategy配置错误!"); - } - } - - public void Dispose() - { - Instance.Dispose(); - Session.Dispose(); - } - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Cassandra/CassandraRepository.cs b/modules/JiShe.CollectBus.Cassandra/CassandraRepository.cs deleted file mode 100644 index 1d6cc3c..0000000 --- a/modules/JiShe.CollectBus.Cassandra/CassandraRepository.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Linq.Expressions; -using Cassandra.Mapping; -using JiShe.CollectBus.Cassandra.Extensions; -using Volo.Abp.Domain.Entities; - -namespace JiShe.CollectBus.Cassandra -{ - public class CassandraRepository - : ICassandraRepository - where TEntity : class, ICassandraEntity - { - private readonly ICassandraProvider _cassandraProvider; - public CassandraRepository(ICassandraProvider cassandraProvider, MappingConfiguration mappingConfig) - { - _cassandraProvider = cassandraProvider; - Mapper = new Mapper(cassandraProvider.Session, mappingConfig); - cassandraProvider.Session.CreateTable(cassandraProvider.CassandraConfig.Keyspace); - } - - public readonly IMapper Mapper; - - public virtual async Task GetAsync(TKey id) - { - return await GetAsync("WHERE id = ?", id); - } - - public virtual async Task GetAsync(string cql, params object[] args) - { - return await Mapper.SingleAsync(cql, args); - } - - - public virtual async Task FirstOrDefaultAsync(TKey id) - { - return await FirstOrDefaultAsync("WHERE id = ?", id); - } - - public virtual async Task FirstOrDefaultAsync(string cql, params object[] args) - { - return await Mapper.FirstOrDefaultAsync(cql, args); - } - - - public virtual async Task?> GetListAsync(string? cql = null, params object[] args) - { - return cql.IsNullOrWhiteSpace() ? (await Mapper.FetchAsync()).ToList() : (await Mapper.FetchAsync(cql, args)).ToList(); - } - - public virtual async Task InsertAsync(TEntity entity) - { - await Mapper.InsertAsync(entity); - return entity; - } - - public virtual async Task UpdateAsync(TEntity entity) - { - await Mapper.UpdateAsync(entity); - return entity; - } - - public virtual async Task DeleteAsync(TEntity entity) - { - await Mapper.DeleteAsync(entity); - } - - public virtual async Task DeleteAsync(TKey id) - { - await Mapper.DeleteAsync("WHERE id = ?", id); - } - - public virtual async Task> GetPagedListAsync( - int skipCount, - int maxResultCount, - string sorting) - { - var cql = $"SELECT * FROM {typeof(TEntity).Name.ToLower()}"; - if (!string.IsNullOrWhiteSpace(sorting)) - { - cql += $" ORDER BY {sorting}"; - } - cql += $" LIMIT {maxResultCount} OFFSET {skipCount}"; - - return (await Mapper.FetchAsync(cql)).ToList(); - } - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Cassandra/CollectBusCassandraModule.cs b/modules/JiShe.CollectBus.Cassandra/CollectBusCassandraModule.cs deleted file mode 100644 index bf57bce..0000000 --- a/modules/JiShe.CollectBus.Cassandra/CollectBusCassandraModule.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp; -using Volo.Abp.Autofac; -using Volo.Abp.Modularity; - -namespace JiShe.CollectBus.Cassandra -{ - [DependsOn( - typeof(AbpAutofacModule) - )] - public class CollectBusCassandraModule : AbpModule - { - public override Task ConfigureServicesAsync(ServiceConfigurationContext context) - { - Configure(context.Services.GetConfiguration().GetSection("Cassandra")); - context.AddCassandra(); - return Task.CompletedTask; - } - - public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context) - { - await context.UseCassandra(); - } - } -} diff --git a/modules/JiShe.CollectBus.Cassandra/Extensions/ServiceCollectionExtensions.cs b/modules/JiShe.CollectBus.Cassandra/Extensions/ServiceCollectionExtensions.cs deleted file mode 100644 index c9ec0de..0000000 --- a/modules/JiShe.CollectBus.Cassandra/Extensions/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using JiShe.CollectBus.Cassandra; -using Volo.Abp; -using Volo.Abp.Modularity; - -// ReSharper disable once CheckNamespace -namespace Microsoft.Extensions.DependencyInjection -{ - public static class ApplicationInitializationContextExtensions - { - public static async Task UseCassandra(this ApplicationInitializationContext context) - { - var service = context.ServiceProvider; - var cassandraProvider = service.GetRequiredService(); - await cassandraProvider.InitClusterAndSessionAsync(); - } - } - - public static class ServiceCollectionExtensions - { - public static void AddCassandra(this ServiceConfigurationContext context) - { - context.Services.AddTransient(typeof(ICassandraRepository<,>), typeof(CassandraRepository<,>)); - } - } -} diff --git a/modules/JiShe.CollectBus.Cassandra/Extensions/SessionExtension.cs b/modules/JiShe.CollectBus.Cassandra/Extensions/SessionExtension.cs deleted file mode 100644 index dd0ff66..0000000 --- a/modules/JiShe.CollectBus.Cassandra/Extensions/SessionExtension.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Reflection; -using System.Text; -using Cassandra; -using System.ComponentModel.DataAnnotations; -using JiShe.CollectBus.Common.Attributes; -using Volo.Abp.Data; - -namespace JiShe.CollectBus.Cassandra.Extensions -{ - public static class SessionExtension - { - public static void CreateTable(this ISession session,string? defaultKeyspace=null) where TEntity : class - { - var type = typeof(TEntity); - var tableAttribute = type.GetCustomAttribute(); - var tableName = tableAttribute?.Name ?? type.Name.ToLower(); - var tableKeyspace = session.Keyspace; - - var properties = type.GetProperties(); - - // 分区键设置 - var primaryKey = properties.FirstOrDefault(p => p.GetCustomAttribute() != null); - - if (primaryKey == null) - { - throw new InvalidOperationException($"No primary key defined for type {type.Name}"); - } - - // 集群键设置 - var clusteringKeys = properties.Where(p => p.GetCustomAttribute() != null).Select(a=>a.Name).ToList(); - var clusteringKeyCql = string.Empty; - if (clusteringKeys.Any()) - { - clusteringKeyCql = $", {string.Join(", ", clusteringKeys)}"; - } - - var cql = new StringBuilder(); - cql.Append($"CREATE TABLE IF NOT EXISTS {tableKeyspace}.{tableName} ("); - - foreach (var prop in properties) - { - var ignoreAttribute = prop.GetCustomAttribute(); - if (ignoreAttribute != null) continue; - var columnName = prop.Name.ToLower(); - var cqlType = GetCassandraType(prop.PropertyType); - - cql.Append($"{columnName} {cqlType}, "); - } - cql.Length -= 2; // Remove last comma and space - cql.Append($", PRIMARY KEY (({primaryKey.Name.ToLower()}){clusteringKeyCql}))"); - - session.Execute(cql.ToString()); - } - - private static string GetCassandraType(Type type) - { - // 基础类型处理 - switch (Type.GetTypeCode(type)) - { - case TypeCode.String: return "text"; - case TypeCode.Int32: return "int"; - case TypeCode.Int64: return "bigint"; - case TypeCode.Boolean: return "boolean"; - case TypeCode.DateTime: return "timestamp"; - case TypeCode.Byte: return "tinyint"; - } - - if (type == typeof(Guid)) return "uuid"; - if (type == typeof(DateTimeOffset)) return "timestamp"; - if (type == typeof(Byte[])) return "blob"; - if (type == typeof(ExtraPropertyDictionary)) return "map"; - - // 处理集合类型 - if (type.IsGenericType) - { - var genericType = type.GetGenericTypeDefinition(); - var elementType = type.GetGenericArguments()[0]; - - if (genericType == typeof(List<>)) - return $"list<{GetCassandraType(elementType)}>"; - if (genericType == typeof(HashSet<>)) - return $"set<{GetCassandraType(elementType)}>"; - if (genericType == typeof(Nullable<>)) - return GetCassandraType(elementType); - if (genericType == typeof(Dictionary<,>)) - { - var keyType = type.GetGenericArguments()[0]; - var valueType = type.GetGenericArguments()[1]; - return $"map<{GetCassandraType(keyType)}, {GetCassandraType(valueType)}>"; - } - } - - throw new NotSupportedException($"不支持的类型: {type.Name}"); - } - - - } -} diff --git a/modules/JiShe.CollectBus.Cassandra/ICassandraProvider.cs b/modules/JiShe.CollectBus.Cassandra/ICassandraProvider.cs deleted file mode 100644 index 8b1f87a..0000000 --- a/modules/JiShe.CollectBus.Cassandra/ICassandraProvider.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Cassandra; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Cassandra -{ - public interface ICassandraProvider - { - Cluster Instance { get;} - - ISession Session { get;} - - CassandraConfig CassandraConfig { get; } - - ISession GetSession(string? keyspace = null); - - Cluster GetCluster(Action? callback = null); - - void InitClusterAndSession(); - - Task InitClusterAndSessionAsync(); - } -} diff --git a/modules/JiShe.CollectBus.Cassandra/ICassandraRepository.cs b/modules/JiShe.CollectBus.Cassandra/ICassandraRepository.cs deleted file mode 100644 index 5f3b862..0000000 --- a/modules/JiShe.CollectBus.Cassandra/ICassandraRepository.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Volo.Abp.Domain.Entities; - -namespace JiShe.CollectBus.Cassandra -{ - public interface ICassandraRepository where TEntity : class - { - Task GetAsync(TKey id); - Task GetAsync(string cql, params object[] args); - Task FirstOrDefaultAsync(TKey id); - Task FirstOrDefaultAsync(string cql, params object[] args); - Task?> GetListAsync(string? cql = null, params object[] args); - Task InsertAsync(TEntity entity); - Task UpdateAsync(TEntity entity); - Task DeleteAsync(TEntity entity); - Task DeleteAsync(TKey id); - Task> GetPagedListAsync(int skipCount, int maxResultCount, string sorting); - } -} diff --git a/modules/JiShe.CollectBus.Cassandra/JiShe.CollectBus.Cassandra.csproj b/modules/JiShe.CollectBus.Cassandra/JiShe.CollectBus.Cassandra.csproj deleted file mode 100644 index a3360e3..0000000 --- a/modules/JiShe.CollectBus.Cassandra/JiShe.CollectBus.Cassandra.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - - - - - - - - diff --git a/modules/JiShe.CollectBus.FreeRedis/CollectBusFreeRedisModule.cs b/modules/JiShe.CollectBus.FreeRedis/CollectBusFreeRedisModule.cs deleted file mode 100644 index fb86fdd..0000000 --- a/modules/JiShe.CollectBus.FreeRedis/CollectBusFreeRedisModule.cs +++ /dev/null @@ -1,25 +0,0 @@ -using JiShe.CollectBus.FreeRedis.Options; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; - -namespace JiShe.CollectBus.FreeRedis -{ - public class CollectBusFreeRedisModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - - Configure(options => - { - configuration.GetSection("Redis").Bind(options); - }); - - - } - } -} - - - diff --git a/modules/JiShe.CollectBus.FreeRedis/FreeRedisProvider.cs b/modules/JiShe.CollectBus.FreeRedis/FreeRedisProvider.cs deleted file mode 100644 index b2cf9e5..0000000 --- a/modules/JiShe.CollectBus.FreeRedis/FreeRedisProvider.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Diagnostics; -using FreeRedis; -using JiShe.CollectBus.Common.Helpers; -using JiShe.CollectBus.FreeRedis.Options; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; - -namespace JiShe.CollectBus.FreeRedis -{ - - public class FreeRedisProvider : IFreeRedisProvider, ISingletonDependency - { - - private readonly FreeRedisOptions _option; - - /// - /// FreeRedis - /// - public FreeRedisProvider(IOptions options) - { - _option = options.Value; - GetInstance(); - } - - public RedisClient Instance { get; set; } = new(string.Empty); - - /// - /// 获取 FreeRedis 客户端 - /// - /// - public IRedisClient GetInstance() - { - - var connectionString = $"{_option.Configuration},defaultdatabase={_option.DefaultDB},MaxPoolSize={_option.MaxPoolSize}"; - Instance = new RedisClient(connectionString); - Instance.Serialize = obj => BusJsonSerializer.Serialize(obj); - Instance.Deserialize = (json, type) => BusJsonSerializer.Deserialize(json, type); - Instance.Notice += (s, e) => Trace.WriteLine(e.Log); - return Instance; - } - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.FreeRedis/IFreeRedisProvider.cs b/modules/JiShe.CollectBus.FreeRedis/IFreeRedisProvider.cs deleted file mode 100644 index e9e8a40..0000000 --- a/modules/JiShe.CollectBus.FreeRedis/IFreeRedisProvider.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FreeRedis; - -namespace JiShe.CollectBus.FreeRedis -{ - public interface IFreeRedisProvider - { - /// - /// 获取客户端 - /// - /// - RedisClient Instance { get; set; } - } -} - diff --git a/modules/JiShe.CollectBus.FreeRedis/JiShe.CollectBus.FreeRedis.csproj b/modules/JiShe.CollectBus.FreeRedis/JiShe.CollectBus.FreeRedis.csproj deleted file mode 100644 index 92b3223..0000000 --- a/modules/JiShe.CollectBus.FreeRedis/JiShe.CollectBus.FreeRedis.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - diff --git a/modules/JiShe.CollectBus.FreeRedis/Options/FreeRedisOptions.cs b/modules/JiShe.CollectBus.FreeRedis/Options/FreeRedisOptions.cs deleted file mode 100644 index 331da88..0000000 --- a/modules/JiShe.CollectBus.FreeRedis/Options/FreeRedisOptions.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace JiShe.CollectBus.FreeRedis.Options -{ - public class FreeRedisOptions - { - /// - /// 连接字符串 - /// - public string? Configuration { get; set; } - - /// - /// 最大连接数 - /// - public string? MaxPoolSize { get; set; } - - /// - /// 默认数据库 - /// - public string? DefaultDB { get; set; } - - /// - /// HangfireDB - /// - public string? HangfireDB { get; set; } - } -} - diff --git a/modules/JiShe.CollectBus.FreeSql/CollectBusFreeSqlModule.cs b/modules/JiShe.CollectBus.FreeSql/CollectBusFreeSqlModule.cs deleted file mode 100644 index 309e22c..0000000 --- a/modules/JiShe.CollectBus.FreeSql/CollectBusFreeSqlModule.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FreeSql; -using FreeSql.SqlServer; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; - -namespace JiShe.CollectBus.FreeSql -{ - public class CollectBusFreeSqlModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } - } -} diff --git a/modules/JiShe.CollectBus.FreeSql/DbEnum.cs b/modules/JiShe.CollectBus.FreeSql/DbEnum.cs deleted file mode 100644 index 81bb094..0000000 --- a/modules/JiShe.CollectBus.FreeSql/DbEnum.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace JiShe.CollectBus.FreeSql -{ - /// - /// 数据库枚举 - /// - public enum DbEnum - { - /// - /// 微服务默认数据库,MySQL - /// - Default, - - /// - /// 预付费数据库,SQLSERVER - /// - PrepayDB, - - /// - /// 能耗数据库,SQLSERVER - /// - EnergyDB - } -} diff --git a/modules/JiShe.CollectBus.FreeSql/FreeSqlProvider.cs b/modules/JiShe.CollectBus.FreeSql/FreeSqlProvider.cs deleted file mode 100644 index e7e7191..0000000 --- a/modules/JiShe.CollectBus.FreeSql/FreeSqlProvider.cs +++ /dev/null @@ -1,37 +0,0 @@ -using FreeSql; -using Microsoft.Extensions.Configuration; -using Volo.Abp.DependencyInjection; - -namespace JiShe.CollectBus.FreeSql -{ - public class FreeSqlProvider : IFreeSqlProvider, ISingletonDependency - { - /// - /// Initializes a new instance of the class. - /// - /// The configuration. - public FreeSqlProvider(IConfiguration configuration) - { - GetInstance(configuration); - } - - public FreeSqlCloud Instance { get; set; } = new(); - public FreeSqlCloud GetInstance(IConfiguration configuration) - { - Instance = new FreeSqlCloud - { - DistributeTrace = log => Console.WriteLine(log.Split('\n')[0].Trim()) - }; - - Instance.Register(DbEnum.EnergyDB, () => new FreeSqlBuilder() - .UseConnectionString(DataType.SqlServer, configuration.GetConnectionString(DbEnum.EnergyDB.ToString())) - .Build()); - - Instance.Register(DbEnum.PrepayDB, () => new FreeSqlBuilder() - .UseConnectionString(DataType.SqlServer, configuration.GetConnectionString(DbEnum.PrepayDB.ToString())) - .Build()); - return Instance; - } - - } -} diff --git a/modules/JiShe.CollectBus.FreeSql/IFreeSqlProvider.cs b/modules/JiShe.CollectBus.FreeSql/IFreeSqlProvider.cs deleted file mode 100644 index e4250d6..0000000 --- a/modules/JiShe.CollectBus.FreeSql/IFreeSqlProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -using FreeSql; - -namespace JiShe.CollectBus.FreeSql -{ - /// - /// FreeSqlProvider服务 - /// - public interface IFreeSqlProvider - { - FreeSqlCloud Instance { get; set; } - } -} diff --git a/modules/JiShe.CollectBus.FreeSql/JiShe.CollectBus.FreeSql.csproj b/modules/JiShe.CollectBus.FreeSql/JiShe.CollectBus.FreeSql.csproj deleted file mode 100644 index 9b40553..0000000 --- a/modules/JiShe.CollectBus.FreeSql/JiShe.CollectBus.FreeSql.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs deleted file mode 100644 index 7ef13f3..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace JiShe.CollectBus.IoTDB.Attributes -{ - /// - /// Column分类标记特性(ATTRIBUTE字段),也就是属性字段 - /// - [AttributeUsage(AttributeTargets.Property)] - public class ATTRIBUTEColumnAttribute : System.Attribute - { - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs deleted file mode 100644 index 43d699f..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace JiShe.CollectBus.IoTDB.Attributes -{ - /// - /// Column分类标记特性(FIELD字段),数据列字段 - /// - [AttributeUsage(AttributeTargets.Property)] - public class FIELDColumnAttribute : System.Attribute - { - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/IgnoreInitTableAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/IgnoreInitTableAttribute.cs deleted file mode 100644 index bd6006c..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Attributes/IgnoreInitTableAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace JiShe.CollectBus.IoTDB.Attributes -{ - /// - /// 需要忽略表模型初始化,有此特性无需初始化 - /// - [AttributeUsage(AttributeTargets.Class)] - public class IgnoreInitTableAttribute : System.Attribute - { - - public IgnoreInitTableAttribute() - { - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs deleted file mode 100644 index 481bfa2..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace JiShe.CollectBus.IoTDB.Attributes -{ - /// - /// 用于标识当前实体为单侧点模式,单侧点模式只有一个Filed标识字段,类型是Tuple,Item1=>测点名称,Item2=>测点值,泛型 - /// - [AttributeUsage(AttributeTargets.Property)] - public class SingleMeasuringAttribute : System.Attribute - { - public string FieldName { get; set;} - - public SingleMeasuringAttribute(string fieldName) - { - FieldName = fieldName; - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs deleted file mode 100644 index 48a3830..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace JiShe.CollectBus.IoTDB.Attributes -{ - /// - /// Column分类标记特性(TAG字段),标签字段 - /// - [AttributeUsage(AttributeTargets.Property)] - public class TAGColumnAttribute : System.Attribute - { - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs deleted file mode 100644 index 5f986b5..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ - -namespace JiShe.CollectBus.IoTDB.Attributes -{ - /// - /// IoTDB实体存储路径或表名称,一般用于已经明确的存储路径或表名称,例如日志存储 - /// - [AttributeUsage(AttributeTargets.Class)] - public class TableNameOrTreePathAttribute : System.Attribute - { - public string TableNameOrTreePath { get; } - - public TableNameOrTreePathAttribute(string tableNameOrTreePath) - { - TableNameOrTreePath = tableNameOrTreePath; - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/CollectBusIoTDBModule.cs b/modules/JiShe.CollectBus.IoTDB/CollectBusIoTDBModule.cs deleted file mode 100644 index 6d26bdc..0000000 --- a/modules/JiShe.CollectBus.IoTDB/CollectBusIoTDBModule.cs +++ /dev/null @@ -1,22 +0,0 @@ -using JiShe.CollectBus.IoTDB.Context; -using JiShe.CollectBus.IoTDB.Options; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; - -namespace JiShe.CollectBus.IoTDB; - -/// -/// CollectBusIoTDBModule -/// -public class CollectBusIoTDbModule : AbpModule -{ - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - Configure(options => { configuration.GetSection(nameof(IoTDbOptions)).Bind(options); }); - - //// 注册上下文为Scoped - //context.Services.AddScoped(); - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.IoTDB/Context/IoTDBRuntimeContext.cs b/modules/JiShe.CollectBus.IoTDB/Context/IoTDBRuntimeContext.cs deleted file mode 100644 index 7384716..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Context/IoTDBRuntimeContext.cs +++ /dev/null @@ -1,33 +0,0 @@ -using JiShe.CollectBus.IoTDB.Options; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; - -namespace JiShe.CollectBus.IoTDB.Context -{ - /// - /// IoTDB SessionPool 运行时上下文 - /// - public class IoTDBRuntimeContext: IScopedDependency//ITransientDependency - { - private readonly bool _defaultValue; - - public IoTDBRuntimeContext(IOptions options) - { - _defaultValue = options.Value.UseTableSessionPoolByDefault; - UseTableSessionPool = _defaultValue; - } - - /// - /// 存储模型切换标识,是否使用table模型存储, 默认为false,标识tree模型存储 - /// - public bool UseTableSessionPool { get; set; } - - /// - /// 重置为默认值 - /// - public void ResetToDefault() - { - UseTableSessionPool = _defaultValue; - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs b/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs deleted file mode 100644 index 93bed4f..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 index 08454b2..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs +++ /dev/null @@ -1,75 +0,0 @@ -using JiShe.CollectBus.Common.Models; -using JiShe.CollectBus.IoTDB.Model; -using JiShe.CollectBus.IoTDB.Options; -using JiShe.CollectBus.IoTDB.Provider; - -namespace JiShe.CollectBus.IoTDB.Interface -{ - /// - /// IoTDB数据源,数据库能同时存多个时序模型,但数据是完全隔离的,不能跨时序模型查询,通过连接字符串配置 - /// - public interface IIoTDbProvider - { - /// - /// 切换 SessionPool - /// - /// 是否使用表模型 - /// - IIoTDbProvider GetSessionPool(bool sessionpolType); - - /// - /// 插入数据 - /// - /// - /// - /// - Task InsertAsync(T entity) where T : IoTEntity; - - /// - /// 批量插入数据 - /// - /// - /// - /// - Task BatchInsertAsync(IEnumerable entities) where T : IoTEntity; - - /// - /// 批量插入数据 - /// - /// - /// 设备元数据 - /// - /// - Task BatchInsertAsync(DeviceMetadata deviceMetadata,IEnumerable entities) where T : IoTEntity; - - - /// - /// 删除数据 - /// - /// - /// - /// - Task DeleteAsync(IoTDBQueryOptions options) where T : IoTEntity; - - /// - /// 获取设备元数据 - /// - /// - /// - Task GetMetadata() where T : IoTEntity; - - /// - /// 查询数据 - /// - /// - /// - /// - Task> QueryAsync(IoTDBQueryOptions options) where T : IoTEntity, new(); - - /// - /// 初始化表模型 - /// - /// - Task InitTableSessionModelAsync(); - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionFactory.cs b/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionFactory.cs deleted file mode 100644 index c2337ea..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionFactory.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace JiShe.CollectBus.IoTDB.Interface -{ - /// - /// Session 工厂接口 - /// - public interface IIoTDbSessionFactory:IDisposable - { - IIoTDbSessionPool GetSessionPool(bool useTableSession); - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionPool.cs b/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionPool.cs deleted file mode 100644 index d183099..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionPool.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Apache.IoTDB.DataStructure; - -namespace JiShe.CollectBus.IoTDB.Interface -{ - /// - /// Session 连接池 - /// - public interface IIoTDbSessionPool : IDisposable - { - /// - /// 打开连接池 - /// - /// - Task OpenAsync(); - - /// - /// 关闭连接池 - /// - /// - Task CloseAsync(); - - /// - /// 插入数据 - /// - /// - /// - Task InsertAsync(Tablet tablet); - - /// - /// 查询数据 - /// - /// - /// - Task ExecuteQueryStatementAsync(string sql); - - /// - /// 执行无返回结果SQL - /// - /// - /// - Task ExecuteNonQueryStatementAsync(string sql); - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj b/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj deleted file mode 100644 index 78b81e3..0000000 --- a/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - - - - - diff --git a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs deleted file mode 100644 index a8163d8..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs +++ /dev/null @@ -1,72 +0,0 @@ -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,新增字段只能现有字段末尾添加,否则会导致数据写入失败。 - /// - public abstract class IoTEntity - { - /// - /// 系统名称 - /// - [TAGColumn] - public string SystemName { get; set; } - - /// - /// 项目编码 - /// - [TAGColumn] - public string ProjectId { get; set; } - - /// - /// 数据类型 - /// - [TAGColumn] - public string DataType { get; set; } = IOTDBDataTypeConst.Data; - - /// - /// 设备类型集中器、电表、水表、流量计、传感器等 - /// - [TAGColumn] - public string DeviceType { get; set; } - - /// - /// 设备ID,数据生成者,例如集中器ID,电表ID、水表ID、流量计ID、传感器ID等 - /// - [TAGColumn] - public string DeviceId { get; set; } - - /// - /// 时标,也就是业务时间戳,单位毫秒,必须通过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 deleted file mode 100644 index 89ea088..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs +++ /dev/null @@ -1,19 +0,0 @@ -using JiShe.CollectBus.Analyzers.Shared; -using JiShe.CollectBus.IoTDB.Attributes; - -namespace JiShe.CollectBus.IoTDB.Model -{ - /// - /// Table模型单项数据实体 - /// - [SourceAnalyzers(EntityTypeEnum.TableModel)] - [IgnoreInitTable] - public class TableModelSingleMeasuringEntity : IoTEntity - { - /// - /// 单项数据键值对 - /// - [SingleMeasuring(nameof(SingleColumn))] - public required ValueTuple SingleColumn { get; set; } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs deleted file mode 100644 index 56a6c54..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs +++ /dev/null @@ -1,18 +0,0 @@ -using JiShe.CollectBus.Analyzers.Shared; -using JiShe.CollectBus.IoTDB.Attributes; - -namespace JiShe.CollectBus.IoTDB.Model -{ - /// - /// Tree模型单项数据实体 - /// - [SourceAnalyzers(EntityTypeEnum.TreeModel)] - public class TreeModelSingleMeasuringEntity : IoTEntity - { - /// - /// 单项数据键值对 - /// - [SingleMeasuring(nameof(SingleMeasuring))] - public required ValueTuple SingleMeasuring { get; set; } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Options/IoTDBOptions.cs b/modules/JiShe.CollectBus.IoTDB/Options/IoTDBOptions.cs deleted file mode 100644 index 68b2770..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Options/IoTDBOptions.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace JiShe.CollectBus.IoTDB.Options -{ - /// - /// IOTDB配置 - /// - public class IoTDbOptions - { - /// - /// 数据库名称,表模型才有,树模型为空 - /// - public string DataBaseName { get; set; } - - /// - /// 集群列表 - /// - public List ClusterList { get; set; } - /// - /// 用户名 - /// - public string UserName { get; set; } - /// - /// 密码 - /// - public string Password { get; set; } - - /// - /// 连接池大小 - /// - public int PoolSize { get; set; } = 8; - - /// - /// 查询时,每次查询的数据量,默认1024 - /// - public int FetchSize { get; set; } = 1024; - - /// - /// 是否开启调试模式,生产环境请关闭,因为底层的实现方式,可能会导致内存持续增长。 - /// - public bool OpenDebugMode { get; set;} - - /// - /// 是否使用表模型存储, 默认false,使用tree模型存储 - /// - public bool UseTableSessionPoolByDefault { get; set; } = false; - - /// - /// 时区,默认为:"UTC+08:00" - /// - public string ZoneId { get; set; } = "UTC+08:00"; - - /// - /// 请求超时时间,单位毫秒,默认为:50000 - /// - public long Timeout { get; set; } = 50000; - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Options/IoTDBQueryOptions.cs b/modules/JiShe.CollectBus.IoTDB/Options/IoTDBQueryOptions.cs deleted file mode 100644 index bff4641..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Options/IoTDBQueryOptions.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace JiShe.CollectBus.IoTDB.Options -{ - /// - /// 查询条件 - /// - public class IoTDBQueryOptions - { - /// - /// 表模型的表名称或者树模型的设备路径 - /// - public required string TableNameOrTreePath { get; set; } - - /// - /// 分页 - /// - public int PageIndex { get; set; } - - /// - /// 分页大小 - /// - public int PageSize { get; set; } - - /// - /// 查询条件 - /// - public List Conditions { get; set; } = new(); - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Options/QueryCondition.cs b/modules/JiShe.CollectBus.IoTDB/Options/QueryCondition.cs deleted file mode 100644 index bccf017..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Options/QueryCondition.cs +++ /dev/null @@ -1,64 +0,0 @@ -using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Common.Helpers; - -namespace JiShe.CollectBus.IoTDB.Options -{ - /// - /// 查询条件 - /// - public class QueryCondition - { - /// - /// 字段 - /// - public string Field { get; set; } - - /// - /// 操作符,>,=,< - /// - public string Operator { get; set; } - - /// - /// 是否数值,如果是数值,则进行数值比较,否则进行字符串比较 - /// - public bool IsNumber { get; set; } = false; - - private object _rawValue; - /// - /// 值 - /// - 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 deleted file mode 100644 index a93ba35..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Apache.IoTDB; -using JiShe.CollectBus.Analyzers.Shared; - -namespace JiShe.CollectBus.IoTDB.Provider -{ - /// - /// 设备元数据 - /// - public sealed class DeviceMetadata - { - /// - /// 实体类名称 - /// - public string EntityName { get; set; } - - /// - /// 设备表名或树路径,如果实体没有添加TableNameOrTreePath,此处为空 - /// - public string TableNameOrTreePath { get; set; } - - /// - /// 实体类型枚举 - /// - public EntityTypeEnum? EntityType { get; set; } - - /// - /// 是否有单测量值 - /// - public bool IsSingleMeasuring { get; set; } - - /// - /// 测量值集合,用于构建Table的测量值,也就是columnNames参数 - /// - public List ColumnNames { get; set; } = new(); - - /// - /// 列类型集合,用于构建Table的列类型,也就是columnCategories参数 - /// - public List ColumnCategories { get; } = new(); - - /// - /// 值类型集合,用于构建Table的值类型,也就是dataTypes参数 - /// - 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 deleted file mode 100644 index 57e1b09..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs +++ /dev/null @@ -1,46 +0,0 @@ -using JiShe.CollectBus.IoTDB.Model; - -namespace JiShe.CollectBus.IoTDB.Provider -{ - /// - /// 设备路径构建器 - /// - public static class DevicePathBuilder - { - /// - /// 构建设备路径,由于路径的层级约束规范不能是纯数字字符,所以需要做特殊处理。 - /// - /// - /// - /// - public static string GetDevicePath(T entity) where T : IoTEntity - { - return $"root.{entity.SystemName.ToLower()}.`{entity.ProjectId}`.`{entity.DeviceType}`.{entity.DataType}.`{entity.DeviceId}`"; - } - - - /// - /// 获取表名称 - /// - /// - /// - /// - public static string GetTableName() where T : IoTEntity - { - var type = typeof(T); - return $"{type.Name.ToLower()}"; - } - - /// - /// 获取表名称,用作单侧点表模型特殊处理。 - /// - /// - /// - /// - public static string GetDeviceTableName(T entity) where T : IoTEntity - { - return $"{entity.SystemName.ToLower()}.`{entity.ProjectId}`.`{entity.DeviceType}`.`{entity.DeviceId}`"; - } - } - -} diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs deleted file mode 100644 index 1d22c33..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs +++ /dev/null @@ -1,1133 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.ComponentModel.DataAnnotations; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Metadata.Ecma335; -using System.Text; -using System.Threading.Tasks; -using Apache.IoTDB; -using Apache.IoTDB.DataStructure; -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Common.Helpers; -using JiShe.CollectBus.Common.Models; -using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Context; -using JiShe.CollectBus.IoTDB.Interface; -using JiShe.CollectBus.IoTDB.Model; -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; -using System.Xml.Linq; -using System.Linq; - -namespace JiShe.CollectBus.IoTDB.Provider -{ - /// - /// IoTDB数据源 - /// - public class IoTDbProvider : IIoTDbProvider, ITransientDependency - { - private static readonly ConcurrentDictionary MetadataCache = new(); - private readonly ILogger _logger; - 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; - } - - - /// - /// IoTDbProvider - /// - /// - /// - /// - public IoTDbProvider( - ILogger logger, - IIoTDbSessionFactory sessionFactory) - { - _logger = logger; - _sessionFactory = sessionFactory; - - } - - /// - /// 插入数据 - /// - /// - /// - /// - public async Task InsertAsync(T entity) where T : IoTEntity - { - try - { - 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.LogWarning($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 路径为 {tablet.First().InsertTargetName}"); - - await CurrentSession.InsertAsync(tablet.First()); - } - catch (Exception ex) - { - _logger.LogError(ex, $"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时发生异常"); - throw; - } - } - - /// - /// 批量插入数据 - /// - /// - /// - public async Task BatchInsertAsync(IEnumerable entities) where T : IoTEntity - { - try - { - if (entities == null || entities.Count() <= 0) - { - _logger.LogError($"{nameof(BatchInsertAsync)} 参数异常,-101"); - return; - } - var metadata = await GetMetadata(); - - var batchSize = 1000; - var batches = entities.Chunk(batchSize); - - foreach (var batch in batches) - { - var tablet = BuildTablet(batch, metadata); - if (tablet == null || tablet.Count <= 0) - { - _logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 tablet 为null"); - return; - } - - foreach (var item in tablet) - { - _logger.LogWarning($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 路径为 {item.InsertTargetName}"); - - await CurrentSession.InsertAsync(item); - } - } - } - catch (Exception ex) - { - _logger.LogError(ex, $"{nameof(BatchInsertAsync)} IoTDB批量插入{typeof(T).Name}的数据时发生异常"); - throw; - } - } - - /// - /// 批量插入数据 - /// - /// - /// 设备元数据 - /// - /// - 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); - 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)} IoTDB批量插入{typeof(T).Name}的数据时发生异常"); - throw; - } - } - - - /// - /// 删除数据 - /// - /// - /// - /// - public async Task DeleteAsync(IoTDBQueryOptions options) where T : IoTEntity - { - try - { - var query = await BuildDeleteSQL(options); - var result = await CurrentSession.ExecuteQueryStatementAsync(query); - - if (result == null) - { - return 0; - } - - if (!result.HasNext()) - { - _logger.LogWarning($"{typeof(T).Name} IoTDB删除{typeof(T).Name}的数据时,没有返回受影响记录数量。"); - return 0; - } - - //获取唯一结果行 - var row = result.Next(); - await result.Close(); - var dataResult = row.Values[0]; - return dataResult; - } - catch (Exception ex) - { - _logger.LogError(ex, $"{nameof(DeleteAsync)} IoTDB删除{typeof(T).Name}的数据时发生异常"); - throw; - } - } - - /// - /// 获取设备元数据 - /// - /// - /// - public async Task GetMetadata() where T : IoTEntity - { - 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 => tmpMetadata, // 如果键不存在,用此值添加 - updateValueFactory: (t, existingValue) => - { - 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); - } - - /// - /// 查询数据 - /// - /// - /// - /// - public async Task> QueryAsync(IoTDBQueryOptions options) where T : IoTEntity, new() - { - try - { - var stopwatch2 = Stopwatch.StartNew(); - - var query = await BuildQuerySQL(options); - var sessionDataSet = await CurrentSession.ExecuteQueryStatementAsync(query); - - - var result = new BusPagedResult - { - TotalCount = await GetTotalCount(options), - Items = await ParseResults(sessionDataSet, options.PageSize), - PageIndex = options.PageIndex, - PageSize = options.PageSize, - - }; - stopwatch2.Stop(); - - //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查询{typeof(T).Name}的数据时发生异常"); - throw; - } - } - - /// - /// 构建Tablet - /// - /// - /// 表实体 - /// 设备元数据 - /// - private List BuildTablet(IEnumerable entities, DeviceMetadata metadata) where T : IoTEntity - { - var entitiyList = entities.ToList(); - if (entitiyList == null || entitiyList.Count <= 0) - { - return null; - } - - - if (metadata.EntityType == null) - { - throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 没有指定,属于异常情况,-101"); - } - - if (metadata.EntityType == EntityTypeEnum.Other) - { - throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 不属于IoTDB数据模型实体,属于异常情况,-102"); - } - - if (metadata.EntityType == EntityTypeEnum.TreeModel && UseTableSessionPool == true) - { - throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 tree模型不能使用table模型Session连接,属于异常情况,-103"); - } - else if (metadata.EntityType == EntityTypeEnum.TableModel && UseTableSessionPool == false) - { - throw new Exception($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接,属于异常情况,-104"); - } - string tableNameOrTreePath = string.Empty; - if ( UseTableSessionPool)//表模型 - { - //如果指定了路径 - if (!string.IsNullOrWhiteSpace(metadata.TableNameOrTreePath)) - { - tableNameOrTreePath = metadata.TableNameOrTreePath; - } - else if(metadata.IsSingleMeasuring && string.IsNullOrWhiteSpace(metadata.TableNameOrTreePath) == true)//单侧点时,且路径没有指定,取默认实体名称和第一个列名组合。 - { - tableNameOrTreePath = $"{metadata.EntityName}_{metadata.ColumnNames.First()}"; - } - else - { - tableNameOrTreePath = DevicePathBuilder.GetTableName(); - } - - return new List() { BuildTablet(entitiyList, metadata, tableNameOrTreePath) }; - } - else - { - //树模型的时候,实体的设备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]; - } - - 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 columns, List> values, List timestamps) - { - //todo 树模型需要去掉TAG类型和ATTRIBUTE类型的字段,只需要保留FIELD类型字段即可 - - return new Tablet( - devicePath, - columns, - metadata.DataTypes, - values, - timestamps - ); - } - - /// - /// 构建表模型的Tablet - /// - /// 已解析的设备数据元数据 - /// 表名称 - /// 数据列集合 - /// 数据集合 - /// 时间戳集合 - /// - private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List columns, List> values, List timestamps) - { - var tablet = new Tablet( - tableName, - columns, - metadata.ColumnCategories, - metadata.DataTypes, - values, - timestamps - ); - - return tablet; - } - - /// - /// 构建查询语句 - /// - /// - /// - /// - private async Task BuildQuerySQL(IoTDBQueryOptions options) where T : IoTEntity - { - var metadata = await GetMetadata(); - var sb = new StringBuilder("SELECT "); - sb.AppendJoin(", ", metadata.ColumnNames); - sb.Append($" FROM {options.TableNameOrTreePath}"); - - if (options.Conditions.Any()) - { - sb.Append(" WHERE "); - sb.AppendJoin(" AND ", options.Conditions.Select(TranslateCondition)); - } - - sb.Append($" LIMIT {options.PageSize} OFFSET {options.PageIndex * options.PageSize}"); - return sb.ToString(); - } - - /// - /// 构建删除语句 - /// - /// - /// - /// - private async Task BuildDeleteSQL(IoTDBQueryOptions options) where T : IoTEntity - { - var metadata = await GetMetadata(); - var sb = new StringBuilder(); - - if (!UseTableSessionPool) - { - sb.Append("DELETE "); - } - else - { - sb.Append("DROP "); - } - - sb.Append($" FROM {options.TableNameOrTreePath}"); - - sb.AppendJoin(", ", metadata.ColumnNames); - - if (options.Conditions.Any()) - { - sb.Append(" WHERE "); - sb.AppendJoin(" AND ", options.Conditions.Select(TranslateCondition)); - } - - return sb.ToString(); - } - - /// - /// 将查询条件转换为SQL语句 - /// - /// - /// - /// - private string TranslateCondition(QueryCondition condition) - { - return condition.Operator switch - { - ">" => $"{condition.Field} > {condition.Value}", - "<" => $"{condition.Field} < {condition.Value}", - "=" => $"{condition.Field} = {condition.Value}", - _ => throw new NotSupportedException($"{nameof(TranslateCondition)} 将查询条件转换为SQL语句时操作符 {condition.Operator} 属于异常情况") - }; - } - - /// - /// 获取查询条件的总数量 - /// - /// - /// - /// - private async Task GetTotalCount(IoTDBQueryOptions options) where T : IoTEntity - { - var countQuery = $"SELECT COUNT(*) FROM {options.TableNameOrTreePath}"; - if (options.Conditions.Any()) - { - countQuery += " WHERE " + string.Join(" AND ", options.Conditions.Select(TranslateCondition)); - } - - var result = await CurrentSession.ExecuteQueryStatementAsync(countQuery); - if (result == null) - { - return 0; - } - - if (!result.HasNext()) - { - return 0; - } - - - var count = Convert.ToInt32(result.Next().Values[0]); - await result.Close(); - - return count; - } - - /// - /// 解析查询结果 - /// - /// - /// - /// - /// - private async Task> ParseResults(SessionDataSet dataSet, int pageSize) where T : IoTEntity, new() - { - var results = new List(); - var metadata = await GetMetadata(); - - var accessor = SourceEntityAccessorFactory.GetAccessor(); - var memberCache = BuildMemberCache(accessor); - - - while (dataSet.HasNext() && results.Count < pageSize) - { - var record = dataSet.Next(); - var entity = new T - { - Timestamps = record.Timestamps - }; - - for (int i = 0; i < metadata.Processors.Count; i++) - { - var value = record.Values[i]; - if (!(value is System.DBNull)) - { - metadata.Processors[i].ValueSetter(entity, value); - } - } - - results.Add(entity); - - } - await dataSet.Close(); - return results; - } - - /// - /// 获取设备元数据的列 - /// - /// - /// - private List CollectColumnMetadata(ISourceEntityAccessor accessor) - { - var columns = new List(); - var memberCache = BuildMemberCache(accessor); - - foreach (var member in accessor.MemberList) - { - // 过滤元组子项 - if (member.NameOrPath.Contains(".Item")) continue; - - // 特性查询优化 - 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) - { - column = new ColumnInfo(member.NameOrPath, ColumnCategory.TAG, GetDataTypeFromTypeName(member.DeclaredTypeName), false, member.DeclaredTypeName); - } - else if (attrColumn != null) - { - 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); - } - - // 单测模式处理 - if (singleMeasuringAttr != null && column == null) - { - 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); - } - return columns; - } - - /// - /// 构建设备元数据 - /// - /// 待解析的类 - /// 已处理好的数据列 - /// - private DeviceMetadata BuildDeviceMetadata(List columns, ISourceEntityAccessor accessor) where T : IoTEntity - { - var metadata = new DeviceMetadata(); - - //先检查是不是单侧点模型 - if (columns.Any(c => c.IsSingleMeasuring)) - { - metadata.IsSingleMeasuring = true; - } - - //按业务逻辑顺序处理(TAG -> ATTRIBUTE -> FIELD) - var groupedColumns = columns - .GroupBy(c => c.Category) - .ToDictionary(g => g.Key, g => g.ToList()); - - ProcessCategory(groupedColumns, ColumnCategory.TAG, metadata); - ProcessCategory(groupedColumns, ColumnCategory.ATTRIBUTE, metadata); - ProcessCategory(groupedColumns, ColumnCategory.FIELD, metadata); - - // 新增处理器初始化 - foreach (var item in metadata.ColumnNames) - { - ColumnInfo column = columns.FirstOrDefault(d => d.Name == item); - - 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; - - /// - /// 处理不同列类型的逻辑 - /// - /// - /// - /// - private void ProcessCategory(IReadOnlyDictionary> groupedColumns, ColumnCategory category, DeviceMetadata metadata) - { - if (groupedColumns.TryGetValue(category, out var cols)) - { - metadata.ColumnNames.AddRange(cols.Select(c => c.Name)); - metadata.ColumnCategories.AddRange(cols.Select(c => c.Category)); - metadata.DataTypes.AddRange(cols.Select(c => c.DataType)); - } - } - - /// - /// 处理不同列类型的逻辑 - /// - /// - /// - private string ProcessCategory(IReadOnlyDictionary> groupedColumns, ColumnCategory category) - { - if (groupedColumns.TryGetValue(category, out var cols)) - { - List tempColumnInfos = new List(); - foreach (var item in cols) - { - tempColumnInfos.Add($" {item.Name} {item.DataType} {item.Category}"); - } - return string.Join(",", tempColumnInfos); - } - return string.Empty; - } - - /// - /// 数据列结构 - /// - private readonly struct ColumnInfo - { - /// - /// 列名 - /// - public string Name { get; } - - /// - /// 声明的类型的名称 - /// - public string DeclaredTypeName { get; } - - /// - /// 是否是单测点 - /// - public bool IsSingleMeasuring { get; } - - /// - /// 列类型 - /// - public ColumnCategory Category { get; } - - /// - /// 数据类型 - /// - public TSDataType DataType { get; } - - public ColumnInfo(string name, ColumnCategory category, TSDataType dataType, bool isSingleMeasuring, string declaredTypeName) - { - Name = name; - Category = category; - DataType = dataType; - IsSingleMeasuring = isSingleMeasuring; - DeclaredTypeName = declaredTypeName; - } - } - - /// - /// 根据类型名称获取对应的 IoTDB 数据类型 - /// - /// 类型名称(不区分大小写) - /// 对应的 TSDataType,默认返回 TSDataType.STRING - private TSDataType GetDataTypeFromTypeName(string typeName) - { - if (string.IsNullOrWhiteSpace(typeName)) - return TSDataType.STRING; - - return DataTypeMap.TryGetValue(typeName.Trim(), out var dataType) - ? dataType - : TSDataType.STRING; - } - - /// - /// 根据类型名称获取 IoTDB 数据类型 - /// - private readonly IReadOnlyDictionary DataTypeMap = - new Dictionary(StringComparer.OrdinalIgnoreCase) - { - ["BOOLEAN"] = TSDataType.BOOLEAN, - ["INT32"] = TSDataType.INT32, - ["INT64"] = TSDataType.INT64, - ["FLOAT"] = TSDataType.FLOAT, - ["DOUBLE"] = TSDataType.DOUBLE, - ["TEXT"] = TSDataType.TEXT, - ["NULLTYPE"] = TSDataType.NONE, - ["DATETIME"] = TSDataType.TIMESTAMP, - ["DATE"] = TSDataType.DATE, - ["BLOB"] = TSDataType.BLOB, - ["DECIMAL"] = TSDataType.DOUBLE, - ["STRING"] = TSDataType.STRING - }; - - /// - /// 根据类型名称获取 IoTDB 数据默认值 - /// - private readonly IReadOnlyDictionary DataTypeDefaultValueMap = - new Dictionary(StringComparer.OrdinalIgnoreCase) - { - ["BOOLEAN"] = false, - ["INT32"] = 0, - ["INT64"] = 0, - ["FLOAT"] = 0.0f, - ["DOUBLE"] = 0.0d, - ["TEXT"] = string.Empty, - ["NULLTYPE"] = null, - ["DATETIME"] = null, - ["DATE"] = null, - ["BLOB"] = null, - ["DECIMAL"] = "0.0", - ["STRING"] = string.Empty - }; - - /// - /// IoTDB 数据类型与.net类型映射 - /// - /// - /// - /// - private dynamic GetTSDataValue(TSDataType tSDataType, object value) => - tSDataType switch - { - TSDataType.BOOLEAN => Convert.ToBoolean(value), - TSDataType.INT32 => Convert.ToInt32(value), - TSDataType.INT64 => Convert.ToInt64(value), - TSDataType.FLOAT => Convert.ToSingle(value), - TSDataType.DOUBLE => Convert.ToDouble(value), - TSDataType.TEXT => Convert.ToString(value), - TSDataType.NONE => null, - TSDataType.TIMESTAMP => Convert.ToInt64(value), - TSDataType.DATE => Convert.ToDateTime(value), - TSDataType.BLOB => Convert.ToByte(value), - 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; - } - - - - /// - /// 初始化表模型 - /// - /// - public async Task InitTableSessionModelAsync() - { - //获取JiShe.CollectBus.IoTDB程序集和JiShe.CollectBus.Domain程序集中的所有 [SourceAnalyzers(EntityTypeEnum.TableModel)] 的实体 - var assemblyNames = new[] { "JiShe.CollectBus.IoTDB", "JiShe.CollectBus.Domain" }; - var assemblies = CommonHelper.LoadAssemblies(assemblyNames); - - var targetTypes = CollectTargetTypes(assemblies); - if (targetTypes == null || targetTypes.Count <= 0) - { - _logger.LogError($"{nameof(InitTableSessionModelAsync)} 初始化表模型时没有找到对应的实体类信息。"); - return; - } - -// @"CREATE TABLE table1( -// time TIMESTAMP TIME, -// region STRING TAG, -// plant_id STRING TAG, -// device_id STRING TAG, -// model_id STRING ATTRIBUTE, -// maintenance STRING ATTRIBUTE, -// temperature FLOAT FIELD, -// humidity FLOAT FIELD, -// status Boolean FIELD, -// arrival_time TIMESTAMP FIELD -//) COMMENT 'table1' WITH(TTL = 31536000000);"; - - - foreach (var item in targetTypes) - { - var accessor = SourceEntityAccessorFactory.GetAccessor(item); - //通过 dynamic 简化操作 - dynamic dynamicAccessor = accessor; - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.Append("CREATE TABLE IF NOT EXISTS "); - stringBuilder.Append(dynamicAccessor.EntityName); - stringBuilder.Append("( time TIMESTAMP TIME, "); - var columns = new List(); - foreach (var member in dynamicAccessor.MemberList) - { - // 过滤元组子项 - if (member.NameOrPath.Contains(".Item")) continue; - - // 特性查询优化 - var attributes = (IEnumerable)(member.CustomAttributes ?? Enumerable.Empty()); - var tagAttr = attributes.OfType().FirstOrDefault(); - var attrColumn = attributes.OfType().FirstOrDefault(); - var fieldColumn = attributes.OfType().FirstOrDefault(); - - // 构建ColumnInfo - ColumnInfo? column = null; - if (tagAttr != null) - { - column = new ColumnInfo(member.NameOrPath, ColumnCategory.TAG, GetDataTypeFromTypeName(member.DeclaredTypeName), false, member.DeclaredTypeName); - } - else if (attrColumn != null) - { - 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); - } - - if (!column.HasValue) - { - _logger.LogError($"{nameof(InitTableSessionModelAsync)} 初始化表模型时实体类{dynamicAccessor.EntityName}的{member.NameOrPath}列的ColumnInfo构建失败。"); - continue; - } - columns.Add(column.Value); - } - - //按业务逻辑顺序处理(TAG -> ATTRIBUTE -> FIELD) - var groupedColumns = columns - .GroupBy(c => c.Category) - .ToDictionary(g => g.Key, g => g.ToList()); - List tempColumInfos = new List(); - - tempColumInfos.Add( ProcessCategory(groupedColumns, ColumnCategory.TAG)); - tempColumInfos.Add(ProcessCategory(groupedColumns, ColumnCategory.ATTRIBUTE)); - tempColumInfos.Add(ProcessCategory(groupedColumns, ColumnCategory.FIELD)); - stringBuilder.Append(string.Join(",", tempColumInfos.Where(d => !string.IsNullOrWhiteSpace(d)))); - stringBuilder.Append($" ) COMMENT '{item.Name}' "); - - _logger.LogWarning($"{dynamicAccessor.EntityName} 初始化语句:{stringBuilder.ToString()}"); - - await CurrentSession.ExecuteNonQueryStatementAsync($"{stringBuilder.ToString()}"); - } - - } - - - /// - /// 获取程序集中的所有 [SourceAnalyzers(EntityTypeEnum.TableModel)] 的实体 - /// - /// - /// - private List CollectTargetTypes(List assemblies) - { - var targetTypes = new List(); - foreach (var assembly in assemblies) - { - try - { - foreach (var type in assembly.GetExportedTypes()) - { - //获取表模型特性的类 - var sourceAnalyzersAttribute = type.GetCustomAttribute(); - - //需要忽略表模型初始化,有此特性无需初始化 - var ignoreInitTableAttribute = type.GetCustomAttribute(); - - if (sourceAnalyzersAttribute?.EntityType == EntityTypeEnum.TableModel && ignoreInitTableAttribute == null) - { - if (type.GetConstructor(Type.EmptyTypes) != null) - targetTypes.Add(type); - } - } - } - catch (ReflectionTypeLoadException ex) - { - _logger.LogError($"加载 {assembly} 失败: {string.Join(", ", ex.LoaderExceptions.Select(e => e.Message))}"); - } - } - return targetTypes; - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBSessionFactory.cs b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBSessionFactory.cs deleted file mode 100644 index 27b9200..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBSessionFactory.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Concurrent; -using JiShe.CollectBus.IoTDB.Interface; -using JiShe.CollectBus.IoTDB.Options; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; - -namespace JiShe.CollectBus.IoTDB.Provider -{ - - /// - /// 实现带缓存的Session工厂 - /// - public class IoTDbSessionFactory : IIoTDbSessionFactory, ISingletonDependency - { - private readonly IoTDbOptions _options; - private readonly ConcurrentDictionary _pools = new(); - private bool _disposed; - - /// - /// IoTDbSessionFactory - /// - /// - public IoTDbSessionFactory(IOptions options) - { - _options = options.Value; - } - - public IIoTDbSessionPool GetSessionPool(bool useTableSession) - { - if (_disposed) throw new ObjectDisposedException(nameof(IoTDbSessionFactory)); - - return _pools.GetOrAdd(useTableSession, key => - { - var pool = key - ? (IIoTDbSessionPool)new TableSessionPoolAdapter(_options) - : new SessionPoolAdapter(_options); - - pool.OpenAsync().ConfigureAwait(false).GetAwaiter().GetResult(); ; - return pool; - }); - } - - public void Dispose() - { - foreach (var pool in _pools.Values) - { - pool.Dispose(); - } - _pools.Clear(); - _disposed = true; - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs b/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs deleted file mode 100644 index a6d2cf5..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs +++ /dev/null @@ -1,105 +0,0 @@ -using Apache.IoTDB; -using Apache.IoTDB.DataStructure; -using JiShe.CollectBus.IoTDB.Interface; -using JiShe.CollectBus.IoTDB.Options; -using Microsoft.Extensions.Logging; - -namespace JiShe.CollectBus.IoTDB.Provider -{ - /// - /// 树模型连接池 - /// - public class SessionPoolAdapter : IIoTDbSessionPool - { - private readonly SessionPool _sessionPool; - private readonly IoTDbOptions _options; - - /// - /// SessionPoolAdapter - /// - /// - public SessionPoolAdapter(IoTDbOptions options) - { - _options = options; - _sessionPool = new SessionPool.Builder() - .SetNodeUrl(options.ClusterList) - .SetUsername(options.UserName) - .SetPassword(options.Password) - .SetZoneId(options.ZoneId) - .SetFetchSize(options.FetchSize) - .SetPoolSize(options.PoolSize) - .Build(); - } - - /// - /// 打开连接池 - /// - /// - public async Task OpenAsync() - { - await _sessionPool.Open(false); - if (_options.OpenDebugMode) - { - _sessionPool.OpenDebugMode(builder => - { - builder.AddConsole(); - }); - } - } - - /// - /// 关闭连接池 - /// - /// - public async Task CloseAsync() - { - if (_sessionPool == null) - { - return; - } - await _sessionPool.Close(); - } - - /// - /// 批量插入对齐时间序列数据 - /// - /// - /// - public async Task InsertAsync(Tablet tablet) - { - var result = await _sessionPool.InsertAlignedTabletAsync(tablet); - if (result != 0) - { - throw new Exception($"{nameof(SessionPoolAdapter)} Tree模型数据入库没有成功,返回结果为:{result},请检查IoTEntity继承子类属性索引是否有变动。"); - } - return result; - } - - /// - /// 查询数据 - /// - /// - /// - public async Task ExecuteQueryStatementAsync(string sql) - { - var result = await _sessionPool.ExecuteQueryStatementAsync(sql, _options.Timeout); - return result; - } - - /// - /// 执行无返回结果SQL - /// - /// - /// - public async Task ExecuteNonQueryStatementAsync(string sql) - { - var result = await _sessionPool.ExecuteNonQueryStatementAsync(sql); - return result; - } - - public void Dispose() - { - _sessionPool?.Close().ConfigureAwait(false).GetAwaiter().GetResult(); - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs b/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs deleted file mode 100644 index 5708de6..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs +++ /dev/null @@ -1,104 +0,0 @@ -using Apache.IoTDB; -using Apache.IoTDB.DataStructure; -using JiShe.CollectBus.IoTDB.Interface; -using JiShe.CollectBus.IoTDB.Options; -using Microsoft.Extensions.Logging; - -namespace JiShe.CollectBus.IoTDB.Provider -{ - /// - /// 表模型Session连接池 - /// - public class TableSessionPoolAdapter : IIoTDbSessionPool - { - private readonly TableSessionPool _sessionPool; - private readonly IoTDbOptions _options; - - /// - /// TableSessionPoolAdapter - /// - /// - public TableSessionPoolAdapter(IoTDbOptions options) - { - _options = options; - _sessionPool = new TableSessionPool.Builder() - .SetNodeUrls(options.ClusterList) - .SetUsername(options.UserName) - .SetPassword(options.Password) - .SetZoneId(options.ZoneId) - .SetFetchSize(options.FetchSize) - .SetPoolSize(options.PoolSize) - .SetDatabase(options.DataBaseName) - .Build(); - } - - /// - /// 打开连接池 - /// - /// - public async Task OpenAsync() - { - await _sessionPool.Open(false); - if (_options.OpenDebugMode) - { - _sessionPool.OpenDebugMode(builder => builder.AddConsole()); - } - } - - /// - /// 关闭连接池 - /// - /// - public async Task CloseAsync() - { - if (_sessionPool == null) - { - return; - } - await _sessionPool.Close(); - } - - /// - /// 批量插入 - /// - /// - /// - public async Task InsertAsync(Tablet tablet) - { - var result = await _sessionPool.InsertAsync(tablet); - if (result != 0) - { - throw new Exception($"{nameof(TableSessionPoolAdapter)} table模型数据入库没有成功,返回结果为:{result},请检查IoTEntity继承子类属性索引是否有变动。"); - } - - return result; - } - - /// - /// 查询数据 - /// - /// - /// - public async Task ExecuteQueryStatementAsync(string sql) - { - var result = await _sessionPool.ExecuteQueryStatementAsync(sql,_options.Timeout); - return result; - } - - /// - /// 执行无返回结果SQL - /// - /// - /// - public async Task ExecuteNonQueryStatementAsync(string sql) - { - var result = await _sessionPool.ExecuteNonQueryStatementAsync(sql); - return result; - } - - public void Dispose() - { - _sessionPool?.Close().ConfigureAwait(false).GetAwaiter().GetResult(); - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/SourceEntityAccessorFactory3.cs b/modules/JiShe.CollectBus.IoTDB/SourceEntityAccessorFactory3.cs deleted file mode 100644 index 4712b67..0000000 --- a/modules/JiShe.CollectBus.IoTDB/SourceEntityAccessorFactory3.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Reflection; - -namespace JiShe.CollectBus.Analyzers.Shared; - -public static class SourceEntityAccessorFactory3 -{ - 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)!; - }); - } - - public static object GetAccessor(Type type) - { - MethodInfo getAccessorMethod = typeof(SourceEntityAccessorFactory) - .GetMethod( - name: nameof(GetAccessor), - bindingAttr: BindingFlags.Public | BindingFlags.Static, - - types: Type.EmptyTypes - ); - - MethodInfo genericMethod = getAccessorMethod.MakeGenericMethod(type); - return genericMethod.Invoke(null, null); - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka.Test/ConsoleApplicationBuilder.cs b/modules/JiShe.CollectBus.Kafka.Test/ConsoleApplicationBuilder.cs deleted file mode 100644 index f6b0891..0000000 --- a/modules/JiShe.CollectBus.Kafka.Test/ConsoleApplicationBuilder.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Kafka.Test -{ - public class ConsoleApplicationBuilder: IApplicationBuilder - { - public IServiceProvider ApplicationServices { get; set; } - public IDictionary Properties { get; set; } = new Dictionary(); - - public IFeatureCollection ServerFeatures => throw new NotImplementedException(); - - private readonly List> _middlewares = new(); - - public IApplicationBuilder Use(Func middleware) - { - _middlewares.Add(middleware); - return this; - } - - public RequestDelegate Build() - { - RequestDelegate app = context => Task.CompletedTask; - foreach (var middleware in _middlewares) - { - app = middleware(app); - } - return app; - } - - public IApplicationBuilder New() - { - return new ConsoleApplicationBuilder - { - ApplicationServices = this.ApplicationServices, - Properties = new Dictionary(this.Properties) - }; - } - } - - - public static class HostBuilderExtensions - { - public static IHostBuilder ConfigureConsoleAppBuilder( - this IHostBuilder hostBuilder, - Action configure) - { - hostBuilder.ConfigureServices((context, services) => - { - // 注册 ConsoleApplicationBuilder 到 DI 容器 - services.AddSingleton(provider => - { - var appBuilder = new ConsoleApplicationBuilder - { - ApplicationServices = provider // 注入服务提供者 - }; - configure(appBuilder); // 执行配置委托 - return appBuilder; - }); - }); - return hostBuilder; - } - } -} diff --git a/modules/JiShe.CollectBus.Kafka.Test/JiShe.CollectBus.Kafka.Test.csproj b/modules/JiShe.CollectBus.Kafka.Test/JiShe.CollectBus.Kafka.Test.csproj deleted file mode 100644 index c312740..0000000 --- a/modules/JiShe.CollectBus.Kafka.Test/JiShe.CollectBus.Kafka.Test.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - Exe - net8.0 - enable - enable - - - - - Always - true - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - diff --git a/modules/JiShe.CollectBus.Kafka.Test/KafkaProduceBenchmark.cs b/modules/JiShe.CollectBus.Kafka.Test/KafkaProduceBenchmark.cs deleted file mode 100644 index 4152a33..0000000 --- a/modules/JiShe.CollectBus.Kafka.Test/KafkaProduceBenchmark.cs +++ /dev/null @@ -1,121 +0,0 @@ -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; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Serilog; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Kafka.Test -{ - [SimpleJob(RuntimeMoniker.Net80)] - //[SimpleJob(RuntimeMoniker.NativeAot80)] - [RPlotExporter] - public class KafkaProduceBenchmark - { - - // 每批消息数量 - [Params(1000, 10000, 100000, 1000000)] - public int N; - public ServiceProvider _serviceProvider; - public IConsumerService _consumerService; - public IProducerService _producerService; - public string topic = "test-topic1"; - - [GlobalSetup] - public void Setup() - { - // 构建配置 - var config = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json") - .Build(); - // 直接读取配置项 - 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 读取配置 - .CreateLogger(); - - // 配置日志系统 - services.AddLogging(logging => - { - logging.ClearProviders(); - logging.AddSerilog(); - }); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddTransient(); - - // 构建ServiceProvider - _serviceProvider = services.BuildServiceProvider(); - - // 获取日志记录器工厂 - var loggerFactory = _serviceProvider.GetRequiredService(); - var logger = loggerFactory.CreateLogger(); - logger.LogInformation("程序启动"); - - var adminClientService = _serviceProvider.GetRequiredService(); - - - //await adminClientService.DeleteTopicAsync(topic); - // 创建 topic - //adminClientService.CreateTopicAsync(topic, 3, 3).ConfigureAwait(false).GetAwaiter(); - - _consumerService = _serviceProvider.GetRequiredService(); - - _producerService = _serviceProvider.GetRequiredService(); - } - - [Benchmark] - public async Task UseAsync() - { - List tasks = new(); - for (int i = 0; i < N; ++i) - { - var task = _producerService.ProduceAsync(topic, i.ToString()); - tasks.Add(task); - } - await Task.WhenAll(tasks); - } - - [Benchmark] - public async Task UseLibrd() - { - List tasks = new(); - for (int i = 0; i < N; ++i) - { - var task = _producerService.ProduceAsync(topic, i.ToString(), null); - } - await Task.WhenAll(tasks); - } - } -} diff --git a/modules/JiShe.CollectBus.Kafka.Test/KafkaSubscribeTest.cs b/modules/JiShe.CollectBus.Kafka.Test/KafkaSubscribeTest.cs deleted file mode 100644 index c7ad309..0000000 --- a/modules/JiShe.CollectBus.Kafka.Test/KafkaSubscribeTest.cs +++ /dev/null @@ -1,70 +0,0 @@ -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Models; -using JiShe.CollectBus.IotSystems.MessageReceiveds; -using JiShe.CollectBus.Kafka.Attributes; -using JiShe.CollectBus.Kafka.Internal; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; -using Volo.Abp.Timing; - -namespace JiShe.CollectBus.Kafka.Test -{ - public class KafkaSubscribeTest: IKafkaSubscribe - { - [KafkaSubscribe(ProtocolConst.TESTTOPIC, EnableBatch = false, BatchSize = 10)] - - public async Task KafkaSubscribeAsync(TestTopic obj) - //public async Task KafkaSubscribeAsync(IEnumerable obj) - { - Console.WriteLine($"收到订阅消息: {JsonSerializer.Serialize(obj)}"); - return SubscribeAck.Success(); - } - - - //[KafkaSubscribe(ProtocolConst.SubscriberLoginIssuedEventName)] - ////[CapSubscribe(ProtocolConst.SubscriberLoginIssuedEventName)] - //public async Task LoginIssuedEvent(IssuedEventMessage issuedEventMessage) - //{ - // Console.WriteLine($"收到订阅消息: {JsonSerializer.Serialize(issuedEventMessage)}"); - // return SubscribeAck.Success(); - //} - - //[KafkaSubscribe(ProtocolConst.SubscriberHeartbeatIssuedEventName)] - ////[CapSubscribe(ProtocolConst.SubscriberHeartbeatIssuedEventName)] - //public async Task HeartbeatIssuedEvent(IssuedEventMessage issuedEventMessage) - //{ - // Console.WriteLine($"收到订阅消息: {JsonSerializer.Serialize(issuedEventMessage)}"); - // return SubscribeAck.Success(); - //} - - //[KafkaSubscribe(ProtocolConst.SubscriberReceivedEventName)] - ////[CapSubscribe(ProtocolConst.SubscriberReceivedEventName)] - //public async Task ReceivedEvent(MessageReceived receivedMessage) - //{ - // Console.WriteLine($"收到订阅消息: {JsonSerializer.Serialize(receivedMessage)}"); - // return SubscribeAck.Success(); - //} - - //[KafkaSubscribe(ProtocolConst.SubscriberHeartbeatReceivedEventName)] - ////[CapSubscribe(ProtocolConst.SubscriberHeartbeatReceivedEventName)] - //public async Task ReceivedHeartbeatEvent(MessageReceivedHeartbeat receivedHeartbeatMessage) - //{ - // Console.WriteLine($"收到订阅消息: {JsonSerializer.Serialize(receivedHeartbeatMessage)}"); - // return SubscribeAck.Success(); - //} - - //[KafkaSubscribe(ProtocolConst.SubscriberLoginReceivedEventName)] - ////[CapSubscribe(ProtocolConst.SubscriberLoginReceivedEventName)] - //public async Task ReceivedLoginEvent(MessageReceivedLogin receivedLoginMessage) - //{ - // Console.WriteLine($"收到订阅消息: {JsonSerializer.Serialize(receivedLoginMessage)}"); - // return SubscribeAck.Success(); - //} - } -} diff --git a/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Common.dll b/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Common.dll deleted file mode 100644 index 5d9bd8d..0000000 Binary files a/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Common.dll and /dev/null differ diff --git a/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Kafka.dll b/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Kafka.dll deleted file mode 100644 index 7ca63d6..0000000 Binary files a/modules/JiShe.CollectBus.Kafka.Test/Lib/JiShe.CollectBus.Kafka.dll and /dev/null differ diff --git a/modules/JiShe.CollectBus.Kafka.Test/Program.cs b/modules/JiShe.CollectBus.Kafka.Test/Program.cs deleted file mode 100644 index d932806..0000000 --- a/modules/JiShe.CollectBus.Kafka.Test/Program.cs +++ /dev/null @@ -1,197 +0,0 @@ -// See https://aka.ms/new-console-template for more information -using JiShe.CollectBus.Common; -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Kafka; -using JiShe.CollectBus.Kafka.AdminClient; -using JiShe.CollectBus.Kafka.Consumer; -using JiShe.CollectBus.Kafka.Internal; -using JiShe.CollectBus.Kafka.Producer; -using JiShe.CollectBus.Kafka.Test; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Serilog; - -#region 基准测试 -//var summary = BenchmarkRunner.Run(); -//Console.WriteLine("压测完成"); -//return; -#endregion 基准测试 - - -var host = Host.CreateDefaultBuilder(args) - .ConfigureServices(services => - { - // 构建配置 - var config = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json") - .Build(); - // 直接读取配置项 - var greeting = config["ServerApplicationOptions:ServerTagName"]; - Console.WriteLine(greeting); // 输出: Hello, World! - - - // 创建服务容器 - //var services = new ServiceCollection(); - // 注册 IConfiguration 实例 - services.AddSingleton(config); - - // 初始化日志 - Log.Logger = new LoggerConfiguration() - .ReadFrom.Configuration(config) // 从 appsettings.json 读取配置 - .CreateLogger(); - - // 配置日志系统 - services.AddLogging(logging => - { - logging.ClearProviders(); - logging.AddSerilog(); - }); - //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(); - services.AddSingleton(); - services.AddSingleton(); - services.AddTransient(); - - }) - .ConfigureConsoleAppBuilder(appBuilder => - { - - }) - .Build(); - - - await host.StartAsync(); - var appBuilder = host.Services.GetRequiredService(); - appBuilder.ApplicationServices.UseKafkaSubscribe(); - - -// 构建ServiceProvider -//var serviceProvider = services.BuildServiceProvider(); - -// 获取日志记录器工厂 -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 -//await adminClientService.CreateTopicAsync(topic, configuration.GetValue(CommonConst.NumPartitions), 3); - -var consumerService = host.Services.GetRequiredService(); -var producerService = host.Services.GetRequiredService(); -//var kafkaOptions = host.Services.GetRequiredService>(); -//await consumerService.SubscribeAsync(topic, (message) => -//{ -// try -// { -// logger.LogInformation($"消费消息:{message}"); -// return Task.FromResult(true); - -// } -// catch (ConsumeException ex) -// { -// // 处理消费错误 -// logger.LogError($"kafka消费异常:{ex.Message}"); -// } -// return Task.FromResult(false); -//}, "default"); - -//Stopwatch stopwatch = Stopwatch.StartNew(); - -//for (int i = 0; i < 3; i++) -//{ -//await consumerService.SubscribeBatchAsync(topic, (message) => -//{ -// try -// { -// int index = 0; -// logger.LogInformation($"消费消息_{index}消费总数:{message.Count()}:{JsonSerializer.Serialize(message)}"); -// return Task.FromResult(true); - -// } -// catch (ConsumeException ex) -// { -// // 处理消费错误 -// logger.LogError($"kafka消费异常:{ex.Message}"); -// } -// return Task.FromResult(false); -//}); -//} -//stopwatch.Stop(); -//Console.WriteLine($"耗时: {stopwatch.ElapsedMilliseconds} 毫秒,{stopwatch.ElapsedMilliseconds/1000} 秒"); - - -int num = 1; -while (num <= 6) -{ - await producerService.ProduceAsync(topic, new TestTopic { Topic = topic, Val = num }); - num++; -} - -//int num = 2; -//while (num <= 4) -//{ -// await producerService.ProduceAsync(topic, num.ToString()); -// num++; -//} -//await Task.Factory.StartNew(async() => { -// int num = 0; -// while (true) -// { -// //await producerService.ProduceAsync(topic, new TestTopic { Topic = topic, Val = i }); -// await producerService.ProduceAsync(topic, num.ToString()); -// num++; -// } -//}); -Console.WriteLine("\n按Esc键退出"); -while (true) -{ - var key = Console.ReadKey(intercept: true); // intercept:true 隐藏按键显示 - - if (key.Key == ConsoleKey.Escape) - { - await host.StopAsync(); - Console.WriteLine("\n程序已退出"); - break; - } -} -(host.Services as IDisposable)?.Dispose(); - - -public class TestTopic -{ - public string Topic { get; set; } - public int Val { get; set; } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka.Test/Properties/launchSettings.json b/modules/JiShe.CollectBus.Kafka.Test/Properties/launchSettings.json deleted file mode 100644 index 33504c9..0000000 --- a/modules/JiShe.CollectBus.Kafka.Test/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "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 deleted file mode 100644 index 0734e89..0000000 --- a/modules/JiShe.CollectBus.Kafka.Test/appsettings.json +++ /dev/null @@ -1,155 +0,0 @@ -{ - "Serilog": { - "Using": [ - "Serilog.Sinks.Console", - "Serilog.Sinks.File" - ], - "MinimumLevel": { - "Default": "Information", - "Override": { - "Microsoft": "Warning", - "Volo.Abp": "Warning", - "Hangfire": "Warning", - "DotNetCore.CAP": "Warning", - "Serilog.AspNetCore": "Information", - "Microsoft.EntityFrameworkCore": "Warning", - "Microsoft.AspNetCore": "Warning", - "Microsoft.AspNetCore.Diagnostics.HealthChecks": "Warning" - } - }, - "WriteTo": [ - { - "Name": "Console" - }, - { - "Name": "File", - "Args": { - "path": "logs/logs-.txt", - "rollingInterval": "Day" - } - } - ] - }, - "App": { - "SelfUrl": "http://localhost:44315", - "CorsOrigins": "http://localhost:4200,http://localhost:3100" - }, - "ConnectionStrings": { - "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" - }, - "Redis": { - "Configuration": "192.168.1.9:6380,password=1q2w3e!@#,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true", - "MaxPoolSize": "50", - "DefaultDB": "14", - "HangfireDB": "13" - }, - "Jwt": { - "Audience": "JiShe.CollectBus", - "SecurityKey": "dzehzRz9a8asdfasfdadfasdfasdfafsdadfasbasdf=", - "Issuer": "JiShe.CollectBus", - "ExpirationTime": 2 - }, - "HealthChecks": { - "IsEnable": true, - "HealthCheckDatabaseName": "HealthChecks", - "EvaluationTimeInSeconds": 10, - "MinimumSecondsBetweenFailureNotifications": 60 - }, - "SwaggerConfig": [ - { - "GroupName": "Basic", - "Title": "【后台管理】基础模块", - "Version": "V1" - }, - { - "GroupName": "Business", - "Title": "【后台管理】业务模块", - "Version": "V1" - } - ], - "Kafka": { - "BootstrapServers": "192.168.1.9:29092,192.168.1.9:39092,192.168.1.9:49092", - "EnableFilter": true, - "EnableAuthorization": false, - "SecurityProtocol": "SaslPlaintext", - "SaslMechanism": "Plain", - "SaslUserName": "lixiao", - "SaslPassword": "lixiao1980", - "KafkaReplicationFactor": 3, - "NumPartitions": 30, - "FirstCollectionTime": "2025-04-22 16:07:00" - }, - "IoTDBOptions": { - "UserName": "root", - "Password": "root", - "ClusterList": [ "192.168.1.9:6667" ], - "PoolSize": 32, - "DataBaseName": "energy", - "OpenDebugMode": true, - "UseTableSessionPoolByDefault": false - }, - "Cassandra": { - "ReplicationStrategy": { - "Class": "NetworkTopologyStrategy", //策略为NetworkTopologyStrategy时才会有多个数据中心,SimpleStrategy用在只有一个数据中心的情况下 - "DataCenters": [ - { - "Name": "dc1", - "ReplicationFactor": 3 - } - ] - }, - "Nodes": [ - { - "Host": "192.168.1.9", - "Port": 9042, - "DataCenter": "dc1", - "Rack": "RAC1" - }, - { - "Host": "192.168.1.9", - "Port": 9043, - "DataCenter": "dc1", - "Rack": "RAC2" - }, - { - "Host": "192.168.1.9", - "Port": 9044, - "DataCenter": "dc1", - "Rack": "RAC2" - } - ], - "Username": "admin", - "Password": "lixiao1980", - "Keyspace": "jishecollectbus", - "ConsistencyLevel": "Quorum", - "PoolingOptions": { - "CoreConnectionsPerHost": 4, - "MaxConnectionsPerHost": 8, - "MaxRequestsPerConnection": 2000 - }, - "SocketOptions": { - "ConnectTimeoutMillis": 10000, - "ReadTimeoutMillis": 20000 - }, - "QueryOptions": { - "ConsistencyLevel": "Quorum", - "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 deleted file mode 100644 index 3ec24ef..0000000 --- a/modules/JiShe.CollectBus.Kafka/AdminClient/AdminClientService.cs +++ /dev/null @@ -1,187 +0,0 @@ -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; - -public class AdminClientService : IAdminClientService, ISingletonDependency -{ - private readonly ILogger _logger; - private readonly KafkaOptionConfig _kafkaOptionConfig; - private readonly Lazy _lazyAdminClient; - /// - /// Initializes a new instance of the class. - /// - /// - /// - public AdminClientService(IConfiguration configuration, ILogger logger, IOptions kafkaOptionConfig) - { - _logger = logger; - _kafkaOptionConfig = kafkaOptionConfig.Value; - //Instance = GetInstance(); - _lazyAdminClient = new Lazy(() => GetInstance()); - } - - /// - /// Gets or sets the instance. - /// - /// - /// The instance. - /// - public IAdminClient Instance => _lazyAdminClient.Value; - - /// - /// 创建Kafka主题 - /// - /// - /// - /// - /// - public async Task CreateTopicAsync(string topic, int numPartitions, short replicationFactor) - { - try - { - if (await CheckTopicAsync(topic)) return; - - - await Instance.CreateTopicsAsync(new[] - { - new TopicSpecification - { - Name = topic, - NumPartitions = numPartitions, - ReplicationFactor = replicationFactor - } - }); - } - catch (CreateTopicsException e) - { - if (e.Results[0].Error.Code != ErrorCode.TopicAlreadyExists) throw; - } - } - - /// - /// 删除Kafka主题 - /// - /// - /// - public async Task DeleteTopicAsync(string topic) - { - await Instance.DeleteTopicsAsync(new[] { topic }); - } - - /// - /// 获取Kafka主题列表 - /// - /// - public async Task> ListTopicsAsync() - { - var metadata = Instance.GetMetadata(TimeSpan.FromSeconds(10)); - return await Task.FromResult(new List(metadata.Topics.Select(t => t.Topic))); - } - - /// - /// 判断Kafka主题是否存在 - /// - /// - /// - public async Task TopicExistsAsync(string topic) - { - var metadata = Instance.GetMetadata(TimeSpan.FromSeconds(10)); - return await Task.FromResult(metadata.Topics.Any(t => t.Topic == topic)); - } - - /// - /// 检测分区是否存在 - /// - /// - /// - /// - public Dictionary CheckPartitionsExists(string topic, int[] partitions) - { - var result = new Dictionary(); - var metadata = Instance.GetMetadata(topic, TimeSpan.FromSeconds(10)); - if (metadata.Topics.Count == 0) - return partitions.ToDictionary(p => p, p => false); - var existingPartitions = metadata.Topics[0].Partitions.Select(p => p.PartitionId).ToHashSet(); - return partitions.ToDictionary(p => p, p => existingPartitions.Contains(p)); - } - - /// - /// 检测分区是否存在 - /// - /// - /// - /// - public bool CheckPartitionsExist(string topic, int targetPartition) - { - var metadata = Instance.GetMetadata(topic, TimeSpan.FromSeconds(10)); - if (metadata.Topics.Count == 0) - return false; - var partitions = metadata.Topics[0].Partitions; - return partitions.Any(p => p.PartitionId == targetPartition); - } - - /// - /// 获取主题的分区数量 - /// - /// - /// - public int GetTopicPartitionsNum(string topic) - { - var metadata = Instance.GetMetadata(topic, TimeSpan.FromSeconds(10)); - if (metadata.Topics.Count == 0) - return 0; - return metadata.Topics[0].Partitions.Count; - } - - /// - /// Gets the instance. - /// - /// - public IAdminClient GetInstance() - { - var adminClientConfig = new AdminClientConfig - { - BootstrapServers = _kafkaOptionConfig.BootstrapServers - }; - if (_kafkaOptionConfig.EnableAuthorization) - { - adminClientConfig.SecurityProtocol = _kafkaOptionConfig.SecurityProtocol; - adminClientConfig.SaslMechanism = _kafkaOptionConfig.SaslMechanism; - adminClientConfig.SaslUsername = _kafkaOptionConfig.SaslUserName; - adminClientConfig.SaslPassword = _kafkaOptionConfig.SaslPassword; - } - return new AdminClientBuilder(adminClientConfig).Build(); - } - - /// - /// Checks the topic asynchronous. - /// - /// The topic. - /// - public async Task CheckTopicAsync(string topic) - { - var metadata = Instance.GetMetadata(TimeSpan.FromSeconds(5)); - return await Task.FromResult(metadata.Topics.Exists(a => a.Topic == topic)); - } - - /// - /// 判断Kafka主题是否存在 - /// - /// 主题名称 - /// 副本数量,不能高于Brokers数量 - /// - public async Task CheckTopicAsync(string topic, int numPartitions) - { - var metadata = Instance.GetMetadata(TimeSpan.FromSeconds(5)); - if (numPartitions > metadata.Brokers.Count) - throw new Exception($"{nameof(CheckTopicAsync)} 主题检查时,副本数量大于了节点数量。"); - - return await Task.FromResult(metadata.Topics.Exists(a => a.Topic == topic)); - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/AdminClient/IAdminClientService.cs b/modules/JiShe.CollectBus.Kafka/AdminClient/IAdminClientService.cs deleted file mode 100644 index 92121c5..0000000 --- a/modules/JiShe.CollectBus.Kafka/AdminClient/IAdminClientService.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Kafka.AdminClient -{ - public interface IAdminClientService - { - /// - /// 创建Kafka主题 - /// - /// 主题名称 - /// 主题分区数量 - /// 副本数量,不能高于Brokers数量 - /// - Task CreateTopicAsync(string topic, int numPartitions, short replicationFactor); - - /// - /// 删除Kafka主题 - /// - /// - /// - Task DeleteTopicAsync(string topic); - - /// - /// 获取Kafka主题列表 - /// - /// - Task> ListTopicsAsync(); - - /// - /// 判断Kafka主题是否存在 - /// - /// - /// - Task TopicExistsAsync(string topic); - - /// - /// 检测分区是否存在 - /// - /// - /// - /// - Dictionary CheckPartitionsExists(string topic, int[] partitions); - - /// - /// 检测分区是否存在 - /// - /// - /// - /// - bool CheckPartitionsExist(string topic, int targetPartition); - - /// - /// 获取主题的分区数量 - /// - /// - /// - int GetTopicPartitionsNum(string topic); - } -} diff --git a/modules/JiShe.CollectBus.Kafka/Attributes/KafkaSubscribeAttribute.cs b/modules/JiShe.CollectBus.Kafka/Attributes/KafkaSubscribeAttribute.cs deleted file mode 100644 index 3b2cfae..0000000 --- a/modules/JiShe.CollectBus.Kafka/Attributes/KafkaSubscribeAttribute.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace JiShe.CollectBus.Kafka.Attributes; - -[AttributeUsage(AttributeTargets.Method)] -public class KafkaSubscribeAttribute : Attribute -{ - /// - /// 订阅主题 - /// - /// - public KafkaSubscribeAttribute(string topic) - { - Topic = topic; - } - - /// - /// 订阅主题 - /// - public KafkaSubscribeAttribute(string topic, int partition) - { - Topic = topic; - Partition = partition; - } - - /// - /// 订阅的主题 - /// - public string Topic { get; set; } = null!; - - /// - /// 分区 - /// - public int Partition { get; set; } = -1; - - /// - /// 消费者组 - /// - public string? GroupId { get; set; } = null; //"default" - - /// - /// 任务数(默认是多少个分区多少个任务) - /// 如设置订阅指定Partition则任务数始终为1 - /// - public int TaskCount { get; set; } = -1; - - /// - /// 批量处理数量 - /// - public int BatchSize { get; set; } = 100; - - /// - /// 是否启用批量处理 - /// - public bool EnableBatch { get; set; } = false; - - /// - /// 批次超时时间 - /// 格式:("00:05:00") - /// - public TimeSpan? BatchTimeout { get; set; } = null; -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/Attributes/TopicAttribute.cs b/modules/JiShe.CollectBus.Kafka/Attributes/TopicAttribute.cs deleted file mode 100644 index a023edb..0000000 --- a/modules/JiShe.CollectBus.Kafka/Attributes/TopicAttribute.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace JiShe.CollectBus.Kafka.Attributes; - -[AttributeUsage(AttributeTargets.Class, Inherited = false)] -public class TopicAttribute : Attribute -{ - /// - /// Initializes a new instance of the class. - /// - /// The name. - public TopicAttribute(string name = "Default") - { - Name = name; - } - - /// - /// Gets or sets the name. - /// - /// - /// The name. - /// - public string Name { get; set; } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/CollectBusKafkaModule.cs b/modules/JiShe.CollectBus.Kafka/CollectBusKafkaModule.cs deleted file mode 100644 index d7190b2..0000000 --- a/modules/JiShe.CollectBus.Kafka/CollectBusKafkaModule.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Confluent.Kafka; -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Kafka.Consumer; -using JiShe.CollectBus.Kafka.Internal; -using JiShe.CollectBus.Kafka.Producer; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using System.Reflection; -using Volo.Abp; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Modularity; -using static Confluent.Kafka.ConfigPropertyNames; - -namespace JiShe.CollectBus.Kafka -{ - public class CollectBusKafkaModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - //var kafkaSection = configuration.GetSection(CommonConst.Kafka); - //KafkaOptionConfig kafkaOptionConfig = new KafkaOptionConfig(); - //kafkaSection.Bind(kafkaOptionConfig); - //Configure(kafkaSection); - Configure(options => - { - configuration.GetSection(CommonConst.Kafka).Bind(options); - }); - - // 注册Producer - context.Services.AddSingleton(); - // 注册Consumer - context.Services.AddSingleton(); - - // 注册Polly - context.Services.AddSingleton(); - - var topics = ProtocolConstExtensions.GetAllTopicNamesByIssued(); - topics.AddRange(ProtocolConstExtensions.GetAllTopicNamesByReceived()); - - // 注册任务调度 - context.Services.AddSingleton(); - - //context.Services.AddHostedService(); - } - - /// - /// 在初始化之前,初始化Kafka Topic - /// - /// - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - var app = context.GetApplicationBuilder(); - app.ApplicationServices.UseInitKafkaTopic(); - } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var app = context.GetApplicationBuilder(); - // 注册Subscriber - app.ApplicationServices.UseKafkaSubscribe(); - - // 获取程序集 - //app.UseKafkaSubscribers(Assembly.Load("JiShe.CollectBus.Application")); - } - } -} diff --git a/modules/JiShe.CollectBus.Kafka/Consumer/ConsumerService.cs b/modules/JiShe.CollectBus.Kafka/Consumer/ConsumerService.cs deleted file mode 100644 index 685915d..0000000 --- a/modules/JiShe.CollectBus.Kafka/Consumer/ConsumerService.cs +++ /dev/null @@ -1,718 +0,0 @@ -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; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.Collections.Concurrent; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using YamlDotNet.Core.Tokens; - -namespace JiShe.CollectBus.Kafka.Consumer -{ - public class ConsumerService : IConsumerService, IDisposable - { - private readonly ILogger _logger; - /// - /// 消费者存储 - /// Key 格式:{groupId}_{topic}_{TKey}_{TValue} - /// - private readonly ConcurrentDictionary - _consumerStore = new(); - - /// - /// 消费完或者无数据时的延迟时间 - /// - private static TimeSpan DelayTime => TimeSpan.FromMilliseconds(100); - - private readonly KafkaOptionConfig _kafkaOptionConfig; - - private readonly ServerApplicationOptions _applicationOptions; - - private readonly KafkaPollyPipeline _kafkaPollyPipeline; - - - private readonly KafkaTaskScheduler _kafkaTaskScheduler; - - /// - /// ConsumerService - /// - /// - /// - public ConsumerService(ILogger logger, IOptions kafkaOptionConfig, KafkaPollyPipeline kafkaPollyPipeline, IOptions applicationOptions, KafkaTaskScheduler kafkaTaskScheduler) - { - _logger = logger; - _kafkaOptionConfig = kafkaOptionConfig.Value; - _applicationOptions = applicationOptions.Value; - _kafkaPollyPipeline = kafkaPollyPipeline; - _kafkaTaskScheduler = kafkaTaskScheduler; - } - - #region private 私有方法 - - /// - /// 创建消费者 - /// - /// - /// - /// - private IConsumer CreateConsumer(string? groupId = null) where TKey : notnull where TValue : class - { - var config = BuildConsumerConfig(groupId); - return new ConsumerBuilder(config) - .SetValueDeserializer(new JsonSerializer()) - .SetLogHandler((_, log) => _logger.LogInformation($"消费者Log: {log.Message}")) - .SetErrorHandler((_, e) => _logger.LogError($"消费者错误: {e.Reason}")) - .Build(); - } - - private ConsumerConfig BuildConsumerConfig(string? groupId = null) - { - var config = new ConsumerConfig - { - BootstrapServers = _kafkaOptionConfig.BootstrapServers, - GroupId = groupId ?? _applicationOptions.ServerTagName, - AutoOffsetReset = AutoOffsetReset.Earliest, - EnableAutoCommit = false, // 禁止AutoCommit - EnablePartitionEof = true, // 启用分区末尾标记 - //AllowAutoCreateTopics = true, // 启用自动创建 - FetchMaxBytes = 1024 * 1024 * 50 // 增加拉取大小(50MB) - }; - - if (_kafkaOptionConfig.EnableAuthorization) - { - config.SecurityProtocol = _kafkaOptionConfig.SecurityProtocol; - config.SaslMechanism = _kafkaOptionConfig.SaslMechanism; - config.SaslUsername = _kafkaOptionConfig.SaslUserName; - config.SaslPassword = _kafkaOptionConfig.SaslPassword; - } - - return config; - } - #endregion - - /// - /// 订阅消息 - /// - /// - /// - /// - /// - /// - public async Task SubscribeAsync(string topic, Func> messageHandler, string? groupId = null) where TKey : notnull where TValue : class - { - await SubscribeAsync(new[] { topic }, messageHandler, groupId); - } - - - /// - /// 订阅消息 - /// - /// - /// - /// - /// - public async Task SubscribeAsync(string topic, Func> messageHandler, string? groupId = null) where TValue : class - { - await SubscribeAsync(new[] { topic }, messageHandler, groupId); - } - - /// - /// 订阅消息 - /// - /// - /// - /// - /// - /// - public async Task SubscribeAsync(string[] topics, Func> messageHandler, string? groupId = null) where TKey : notnull where TValue : class - { - try - { - // 扩展独立线程,避免阻塞 - _kafkaTaskScheduler.WorkerThreadExpansion(); - await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token => - { - var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}"; - var consumerStore = _consumerStore.GetOrAdd(consumerKey, _ => - ( - CreateConsumer(groupId), - new CancellationTokenSource() - )); - if (consumerStore.Consumer == null) - { - _logger.LogWarning($"{string.Join("、", topics)}创建消息消费失败或消费组已被释放"); - return; - } - var consumer = consumerStore.Consumer as IConsumer; - var cts = consumerStore.CTS; - - consumer!.Subscribe(topics); - _= Task.Factory.StartNew(async () => - { - 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) - { - 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 (ObjectDisposedException) - { - _logger.LogError($"{string.Join("、", topics)}消费者被释放"); - break; - } - catch (Exception ex) - { - _logger.LogError(ex, "处理消息时发生未知错误"); - } - } - }, cts.Token, TaskCreationOptions.None, _kafkaTaskScheduler); - await Task.CompletedTask; - }); - - } - catch (Exception ex) - { - - throw; - } - } - - - - /// - /// 订阅消息 - /// - /// - /// - /// - /// - /// - public async Task SubscribeAsync(string[] topics, Func> messageHandler, string? groupId) where TValue : class - { - try - { - // 扩展独立线程,避免阻塞 - _kafkaTaskScheduler.WorkerThreadExpansion(); - await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token => - { - var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(Ignore).Name}_{typeof(TValue).Name}"; - - var consumerStore = _consumerStore.GetOrAdd(consumerKey, _ => - ( - CreateConsumer(groupId), - new CancellationTokenSource() - )); - if (consumerStore.Consumer == null) - { - _logger.LogWarning($"{string.Join("、", topics)}创建消息消费失败或消费组已被释放"); - return; - } - var consumer = consumerStore.Consumer as IConsumer; - var cts = consumerStore.CTS; - - consumer!.Subscribe(topics); - - _ = Task.Factory.StartNew(async () => - { - 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; - } - - 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 (ObjectDisposedException) - { - _logger.LogError($"{string.Join("、", topics)}消费者被释放"); - break; - } - catch (Exception ex) - { - _logger.LogError(ex, "处理消息时发生未知错误"); - } - } - }, cts.Token, TaskCreationOptions.None, _kafkaTaskScheduler); - await Task.CompletedTask; - }); - } - catch (Exception ex) - { - - throw; - } - } - - - /// - /// 批量订阅消息 - /// - /// 消息Key类型 - /// 消息Value类型 - /// 主题 - /// 批量消息处理函数 - /// 消费组ID - /// 批次大小 - /// 批次超时时间 - public async Task SubscribeBatchAsync(string topic, Func, Task> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null) where TKey : notnull where TValue : class - { - try - { - await SubscribeBatchAsync(new[] { topic }, messageBatchHandler, groupId, batchSize, batchTimeout); - } - catch (Exception ex) - { - - throw; - } - } - - /// - /// 批量订阅消息 - /// - /// 消息Key类型 - /// 消息Value类型 - /// 主题列表 - /// 批量消息处理函数 - /// 消费组ID - /// 批次大小 - /// 批次超时时间 - public async Task SubscribeBatchAsync(string[] topics, Func, Task> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null) where TKey : notnull where TValue : class - { - try - { - // 扩展独立线程,避免阻塞 - _kafkaTaskScheduler.WorkerThreadExpansion(); - await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token => - { - - var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}"; - - var consumerStore = _consumerStore.GetOrAdd(consumerKey, _ => - ( - CreateConsumer(groupId), - new CancellationTokenSource() - )); - if (consumerStore.Consumer == null) - { - _logger.LogWarning($"{string.Join("、", topics)}创建消息消费失败或消费组已被释放"); - return; - } - var consumer = consumerStore.Consumer as IConsumer; - var cts = consumerStore.CTS; - - consumer!.Subscribe(topics); - - var timeout = batchTimeout ?? TimeSpan.FromSeconds(5); // 默认超时时间调整为5秒 - - _ = Task.Factory.StartNew(async () => - { - var messages = new List<(TValue Value, TopicPartitionOffset Offset)>(); - var startTime = DateTime.UtcNow; - - while (!cts.IsCancellationRequested) - { - try - { - // 非阻塞快速累积消息 - while (messages.Count < batchSize && (DateTime.UtcNow - startTime) < timeout) - { - var result = consumer.Consume(TimeSpan.Zero); // 非阻塞调用 - - if (result != null) - { - if (result.IsPartitionEOF) - { -#if DEBUG - _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); - } - } - - // 处理批次 - if (messages.Count > 0) - { - 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(); - } - - startTime = DateTime.UtcNow; - } - 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 (ObjectDisposedException) - { - _logger.LogError($"{string.Join("、", topics)}消费者被释放"); - break; - } - catch (Exception ex) - { - _logger.LogError(ex, "处理批量消息时发生未知错误"); - } - } - }, cts.Token, TaskCreationOptions.None, _kafkaTaskScheduler); - - await Task.CompletedTask; - }); - } - catch (Exception ex) - { - - throw; - } - } - - - /// - /// 批量订阅消息 - /// - /// 消息Value类型 - /// 主题列表 - /// 批量消息处理函数 - /// 消费组ID - /// 批次大小 - /// 批次超时时间 - /// 消费等待时间 - public async Task SubscribeBatchAsync(string topic, Func, Task> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null, TimeSpan? consumeTimeout = null) where TValue : class - { - try - { - await SubscribeBatchAsync(new[] { topic }, messageBatchHandler, groupId, batchSize, batchTimeout, consumeTimeout); - } - catch (Exception ex) - { - - throw; - } - - } - - - /// - /// 批量订阅消息 - /// - /// 消息Value类型 - /// 主题列表 - /// 批量消息处理函数 - /// 消费组ID - /// 批次大小 - /// 批次超时时间 - /// 消费等待时间 - public async Task SubscribeBatchAsync(string[] topics, Func, Task> messageBatchHandler, string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null, TimeSpan? consumeTimeout = null) where TValue : class - { - try - { - // 扩展独立线程,避免阻塞 - _kafkaTaskScheduler.WorkerThreadExpansion(); - await _kafkaPollyPipeline.KafkaPipeline.ExecuteAsync(async token => - { - - var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(Ignore).Name}_{typeof(TValue).Name}"; - var consumerStore = _consumerStore.GetOrAdd(consumerKey, _ => - ( - CreateConsumer(groupId), - new CancellationTokenSource() - )); - if (consumerStore.Consumer == null) - { - _logger.LogWarning($"{string.Join("、", topics)}创建消息消费失败或消费组已被释放"); - return; - } - var consumer = consumerStore.Consumer as IConsumer; - var cts = consumerStore.CTS; - - consumer!.Subscribe(topics); - - var timeout = batchTimeout ?? TimeSpan.FromSeconds(5); // 默认超时时间调整为5秒 - - _ = Task.Factory.StartNew(async () => - { - var messages = new List<(TValue Value, TopicPartitionOffset Offset)>(); - var startTime = DateTime.UtcNow; - - while (!cts.IsCancellationRequested) - { - try - { - // 非阻塞快速累积消息 - while (messages.Count < batchSize && (DateTime.UtcNow - startTime) < timeout) - { - var result = consumer.Consume(TimeSpan.Zero); // 非阻塞调用 - - if (result != null) - { - 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); - } - } - - // 处理批次 - if (messages.Count > 0) - { - 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(); - } - - startTime = DateTime.UtcNow; - } - catch (ConsumeException ex) when (KafkaPollyPipeline.IsRecoverableError(ex)) - { - _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 (ObjectDisposedException) - { - _logger.LogError($"{string.Join("、", topics)}消费者被释放"); - break; - } - catch (Exception ex) - { - _logger.LogError(ex, "处理批量消息时发生未知错误"); - } - } - }, cts.Token, TaskCreationOptions.None, _kafkaTaskScheduler); - - await Task.CompletedTask; - }); - } - catch (Exception ex) - { - - throw; - } - } - - - /// - /// 取消消息订阅 - /// - /// - /// - public void Unsubscribe(string[] topics, string? groupId) where TKey : notnull where TValue : class - { - try - { - var consumerKey = $"{groupId}_{string.Join("_", topics)}_{typeof(TKey).Name}_{typeof(TValue).Name}"; - if (_consumerStore.TryGetValue(consumerKey, out var entry)) - { - entry.CTS.Cancel(); - (entry.Consumer as IDisposable)?.Dispose(); - entry.CTS.Dispose(); - // 从字典中移除 - _consumerStore.TryRemove(consumerKey, out entry); - } - } - catch (Exception ex) - { - - throw; - } - } - - /// - /// 释放资源 - /// - public void Dispose() - { - foreach (var entry in _consumerStore.Values) - { - entry.CTS.Cancel(); - (entry.Consumer as IDisposable)?.Dispose(); - entry.CTS.Dispose(); - } - _consumerStore.Clear(); - } - } -} diff --git a/modules/JiShe.CollectBus.Kafka/Consumer/IConsumerService.cs b/modules/JiShe.CollectBus.Kafka/Consumer/IConsumerService.cs deleted file mode 100644 index b4b4274..0000000 --- a/modules/JiShe.CollectBus.Kafka/Consumer/IConsumerService.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace JiShe.CollectBus.Kafka.Consumer; - -public interface IConsumerService -{ - Task SubscribeAsync(string topic, Func> messageHandler, - string? groupId = null) where TKey : notnull where TValue : class; - - /// - /// 订阅消息 - /// - /// - /// - /// - /// - Task SubscribeAsync(string topic, Func> messageHandler, string? groupId = null) - where TValue : class; - - Task SubscribeAsync(string[] topics, Func> messageHandler, string? groupId) - where TKey : notnull where TValue : class; - - - /// - /// 订阅消息 - /// - /// - /// - /// - /// - /// - Task SubscribeAsync(string[] topics, Func> messageHandler, string? groupId = null) - where TValue : class; - - Task SubscribeBatchAsync(string[] topics, Func, Task> messageBatchHandler, - string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null) - where TKey : notnull where TValue : class; - - Task SubscribeBatchAsync(string topic, Func, Task> messageBatchHandler, - string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null) - where TKey : notnull where TValue : class; - - Task SubscribeBatchAsync(string topic, Func, Task> messageBatchHandler, - string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null, TimeSpan? consumeTimeout = null) - where TValue : class; - - Task SubscribeBatchAsync(string[] topics, Func, Task> messageBatchHandler, - string? groupId = null, int batchSize = 100, TimeSpan? batchTimeout = null, TimeSpan? consumeTimeout = null) - where TValue : class; - - void Unsubscribe(string[] topics, string groupId) where TKey : notnull where TValue : class; -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/HostedService.cs b/modules/JiShe.CollectBus.Kafka/HostedService.cs deleted file mode 100644 index c2e672c..0000000 --- a/modules/JiShe.CollectBus.Kafka/HostedService.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Kafka -{ - public class HostedService : IHostedService, IDisposable - { - private readonly ILogger _logger; - private readonly IServiceProvider _provider; - public HostedService(ILogger logger, IServiceProvider provider) - { - _logger = logger; - _provider = provider; - } - - public Task StartAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("程序启动"); - Task.Run(() => - { - _provider.UseKafkaSubscribe(); - }); - return Task.CompletedTask; - } - - public Task StopAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("结束"); - return Task.CompletedTask; - } - - public void Dispose() - { - - } - } -} diff --git a/modules/JiShe.CollectBus.Kafka/Internal/HeadersFilter.cs b/modules/JiShe.CollectBus.Kafka/Internal/HeadersFilter.cs deleted file mode 100644 index 8bcdcdc..0000000 --- a/modules/JiShe.CollectBus.Kafka/Internal/HeadersFilter.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Confluent.Kafka; - -namespace JiShe.CollectBus.Kafka.Internal; - -/// -/// 消息头过滤器 -/// -public class HeadersFilter : Dictionary -{ - /// - /// 判断Headers是否匹配 - /// - /// - /// - public bool Match(Headers headers) - { - foreach (var kvp in this) - if (!headers.TryGetLastBytes(kvp.Key, out var value) || !value.SequenceEqual(kvp.Value)) - return false; - return true; - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/Internal/IKafkaSubscribe.cs b/modules/JiShe.CollectBus.Kafka/Internal/IKafkaSubscribe.cs deleted file mode 100644 index 5345f1b..0000000 --- a/modules/JiShe.CollectBus.Kafka/Internal/IKafkaSubscribe.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace JiShe.CollectBus.Kafka.Internal; - -/// -/// Kafka订阅者 -/// -/// 订阅者需要继承此接口并需要依赖注入,并使用标记 -/// -/// -public interface IKafkaSubscribe -{ -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/Internal/ISubscribeAck.cs b/modules/JiShe.CollectBus.Kafka/Internal/ISubscribeAck.cs deleted file mode 100644 index 27512f7..0000000 --- a/modules/JiShe.CollectBus.Kafka/Internal/ISubscribeAck.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace JiShe.CollectBus.Kafka.Internal; - -public interface ISubscribeAck -{ - /// - /// 是否成功标记 - /// - bool Ack { get; set; } - - /// - /// 消息 - /// - string? Msg { get; set; } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/Internal/KafkaOptionConfig.cs b/modules/JiShe.CollectBus.Kafka/Internal/KafkaOptionConfig.cs deleted file mode 100644 index 3b053c8..0000000 --- a/modules/JiShe.CollectBus.Kafka/Internal/KafkaOptionConfig.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Confluent.Kafka; - -namespace JiShe.CollectBus.Kafka.Internal; - -public class KafkaOptionConfig -{ - /// - /// kafka地址 - /// - public string BootstrapServers { get; set; } = null!; - - /// - /// kafka主题副本数量 - /// - public short KafkaReplicationFactor { get; set; } - - /// - /// kafka主题分区数量 - /// - public int NumPartitions { get; set; } - - /// - /// 是否开启过滤器 - /// - public bool EnableFilter { get; set; } = true; - - /// - /// 是否开启认证 - /// - public bool EnableAuthorization { get; set; } = false; - - /// - /// 安全协议 - /// - public SecurityProtocol SecurityProtocol { get; set; } = SecurityProtocol.SaslPlaintext; - - /// - /// 认证方式 - /// - public SaslMechanism SaslMechanism { get; set; } = SaslMechanism.Plain; - - /// - /// 用户名 - /// - public string? SaslUserName { get; set; } - - /// - /// 密码 - /// - public string? SaslPassword { get; set; } - - /// - /// 订阅任务线程数量 - /// 当主题未指定时,订阅任务线程数量默认为:-1 - /// 优先级低于订阅任务特性TaskCount值 - /// - public int TaskThreadCount { get; set; } = -1; - -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/Internal/KafkaPollyPipeline.cs b/modules/JiShe.CollectBus.Kafka/Internal/KafkaPollyPipeline.cs deleted file mode 100644 index fd4bb1b..0000000 --- a/modules/JiShe.CollectBus.Kafka/Internal/KafkaPollyPipeline.cs +++ /dev/null @@ -1,105 +0,0 @@ -using Confluent.Kafka; -using Microsoft.Extensions.Logging; -using Polly; -using Polly.CircuitBreaker; -using Polly.Retry; - -namespace JiShe.CollectBus.Kafka.Internal -{ - public class KafkaPollyPipeline - { - - private readonly ILogger _logger; - public KafkaPollyPipeline(ILogger logger) - { - _logger= logger; - } - - /// - /// 判断是否可恢复的异常 - /// - /// - /// - public static bool IsRecoverableError(Exception ex) - { - var errorList= new List - { - ErrorCode.GroupLoadInProgress, - ErrorCode.Local_Retry, - ErrorCode.Local_MaxPollExceeded, - ErrorCode.RequestTimedOut, - ErrorCode.LeaderNotAvailable, - ErrorCode.NotLeaderForPartition, - ErrorCode.RebalanceInProgress, - ErrorCode.NotCoordinatorForGroup, - ErrorCode.NetworkException, - ErrorCode.GroupCoordinatorNotAvailable, - ErrorCode.InvalidGroupId, - ErrorCode.IllegalGeneration - }; - return ex switch - { - ConsumeException kafkaEx => errorList.Contains(kafkaEx.Error.Code), - KafkaException kafkaEx =>kafkaEx.Error.IsFatal && errorList.Contains(kafkaEx.Error.Code), - _ => false - }; - - } - - /// - /// 创建重试 + 断路器 - /// - /// - public ResiliencePipeline KafkaPipeline - { - get - { - // 组合重试 + 断路器 - ResiliencePipeline pipeline = new ResiliencePipelineBuilder() - .AddRetry(new RetryStrategyOptions - { - ShouldHandle = args => args.Outcome.Exception switch - { - not null when IsRecoverableError(args.Outcome.Exception) => - PredicateResult.True(), - _ => PredicateResult.False() - }, - Delay = TimeSpan.FromSeconds(2), - OnRetry = args => - { - _logger.LogWarning($"重试中... 第 {args.AttemptNumber} 次,原因: {args.Outcome.Exception?.Message}"); - return default; - } - }) - .AddCircuitBreaker(new CircuitBreakerStrategyOptions - { - ShouldHandle = args => args.Outcome.Exception switch - { - not null when IsRecoverableError(args.Outcome.Exception) => - PredicateResult.True(), - _ => PredicateResult.False() - }, - FailureRatio = 0.8, // 80% 失败触发熔断 - SamplingDuration = TimeSpan.FromSeconds(10), - MinimumThroughput = 4, // 至少4次调用才计算失败率 - BreakDuration = TimeSpan.FromSeconds(10), - OnOpened = args => - { - _logger.LogWarning($"熔断器开启,等待 {args.BreakDuration} 后重试"); - return default; - }, - OnClosed = _ => - { - _logger.LogWarning("熔断器关闭,再次开始重试"); - return default; - } - }) - .Build(); - return pipeline; - } - - } - - - } -} diff --git a/modules/JiShe.CollectBus.Kafka/Internal/KafkaTaskScheduler.cs b/modules/JiShe.CollectBus.Kafka/Internal/KafkaTaskScheduler.cs deleted file mode 100644 index 9afe7fa..0000000 --- a/modules/JiShe.CollectBus.Kafka/Internal/KafkaTaskScheduler.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Collections.Concurrent; - -namespace JiShe.CollectBus.Kafka.Internal -{ - public class KafkaTaskScheduler : TaskScheduler, IDisposable - { - private readonly BlockingCollection _tasksCollection=new BlockingCollection (); - private readonly List _workerThreads; - private readonly object _disposeLock = new object(); - private bool _isDisposed; - - /// - /// 当前队列中的任务数 - /// - public int QueuedTasks => _tasksCollection.Count; - - /// - /// 当前工作线程数 - /// - public int WorkerThreads => _workerThreads.Count; - - /// - /// 初始化任务调度器 - /// - public KafkaTaskScheduler() - { - // 默认最大并发线程数为CPU核心数 - int MaxConcurrencyLevel = Environment.ProcessorCount; - _workerThreads = new List(MaxConcurrencyLevel); - for (int i = 0; i < MaxConcurrencyLevel; i++) - { - var thread = new Thread(ExecuteScheduledTasks) - { - IsBackground = true, - Name = $"KafkaWorkerTask-{i + 1}" - }; - thread.Start(); - _workerThreads.Add(thread); - } - - } - - /// - /// 扩容工作线程调度 - /// 可以启动多个工作线程来处理任务 - /// - /// 扩展独立线程数(默认为1) - public void WorkerThreadExpansion(int taskNum = 1) - { - int currCount = WorkerThreads+1; - Parallel.For(0, taskNum, (index) => - { - var thread = new Thread(ExecuteScheduledTasks) - { - IsBackground = true, - Name = $"KafkaWorkerTask-{index+ currCount}" - }; - thread.Start(); - _workerThreads.Add(thread); - }); - } - - /// - /// 工作线程执行循环 - /// - private void ExecuteScheduledTasks() - { - try - { - foreach (var task in _tasksCollection.GetConsumingEnumerable()) - { - TryExecuteTaskSafely(task); - } - } - catch (OperationCanceledException) { } - catch (ObjectDisposedException) { } - } - - /// - /// 安全执行任务并处理异常 - /// - private void TryExecuteTaskSafely(Task task) - { - try - { - TryExecuteTask(task); - } - catch (OperationCanceledException){} - catch (Exception ex) - { - OnExceptionOccurred(ex); - } - } - - #region TaskScheduler 重写方法 - protected override IEnumerable GetScheduledTasks() - { - ThrowIfDisposed(); - return _tasksCollection.ToList(); - } - - protected override void QueueTask(Task task) - { - ThrowIfDisposed(); - _tasksCollection.Add(task); - } - - protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) - { - // 禁止内联执行以强制所有任务在专用线程执行 - return false; - } - #endregion - - #region 释放资源 - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - lock (_disposeLock) - { - if (_isDisposed) return; - - if (disposing) - { - // 停止接收新任务 - _tasksCollection.CompleteAdding(); - - // 等待所有工作线程退出 - foreach (var thread in _workerThreads) - { - if (thread.IsAlive) - { - thread.Join(TimeSpan.FromSeconds(5)); - } - } - // 释放资源 - _tasksCollection.Dispose(); - } - _isDisposed = true; - } - } - - private void ThrowIfDisposed() - { - if (_isDisposed) - { - throw new ObjectDisposedException(GetType().Name); - } - } - #endregion - - #region 异常事件处理 - /// - /// 任务执行异常时触发 - /// - public event Action? ExceptionEvent; - - private void OnExceptionOccurred(Exception ex) - { - ExceptionEvent?.Invoke(ex); - } - #endregion - } -} diff --git a/modules/JiShe.CollectBus.Kafka/Internal/ReflectionHelper.cs b/modules/JiShe.CollectBus.Kafka/Internal/ReflectionHelper.cs deleted file mode 100644 index a39db81..0000000 --- a/modules/JiShe.CollectBus.Kafka/Internal/ReflectionHelper.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Collections; -using System.Reflection; - -namespace JiShe.CollectBus.Kafka.Internal; - -/// -/// 反射辅助类 -/// -public static class ReflectionHelper -{ - /// - /// 集合类型 - /// Item1:参数类型 - /// Item2:集合元素类型 - /// - public static Tuple GetParameterTypeInfo(this MethodInfo method, int parameterIndex = 0) - { - // 参数校验 - if (method == null) throw new ArgumentNullException(nameof(method)); - var parameters = method.GetParameters(); - if (parameterIndex < 0 || parameterIndex >= parameters.Length) - throw new ArgumentOutOfRangeException(nameof(parameterIndex)); - - var param = parameters[parameterIndex]; - var paramType = param.ParameterType; - Type? elementType = null; - - // 判断是否是集合类型(排除字符串) - if (paramType != typeof(string) && IsEnumerableType(paramType)) - elementType = GetEnumerableElementType(paramType); - - return Tuple.Create(paramType, elementType); - } - - /// - /// 判断是否是集合类型(排除字符串) - /// - public static bool IsEnumerableType(this Type type) - { - return type.IsArray - || (type.IsGenericType && type.GetInterfaces() - .Any(t => t.IsGenericType - && t.GetGenericTypeDefinition() == typeof(IEnumerable<>))) - || type.GetInterfaces().Any(t => t == typeof(IEnumerable)); - } - - /// - /// 获取集合元素的类型 - /// - public static Type? GetEnumerableElementType(this Type type) - { - // 处理数组类型 - if (type.IsArray) - return type.GetElementType(); - - // 处理直接实现IEnumerable的类型(如IEnumerable本身) - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - return type.GetGenericArguments()[0]; - - // 处理通过接口实现IEnumerable的泛型集合(如List) - var genericEnumerable = type.GetInterfaces() - .FirstOrDefault(t => t.IsGenericType - && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)); - if (genericEnumerable != null) - return genericEnumerable.GetGenericArguments()[0]; - - // 处理非泛型集合类型(如 ArrayList) - if (typeof(IEnumerable).IsAssignableFrom(type) && type == typeof(ArrayList)) - return typeof(ArrayList); - // 返回null表示无法确定元素类型 - return null; - } - - - /// - /// 判断是否使用强转换 - /// - /// - /// - public static bool IsConvertType(this Type targetType) - { - // 处理可空类型 - var underlyingType = Nullable.GetUnderlyingType(targetType) ?? targetType; - // 情况1:值类型或基元类型(如 int、DateTime) - if (underlyingType.IsValueType || underlyingType.IsPrimitive) - return true; - // 情况2:字符串类型直接赋值 - if (underlyingType == typeof(string)) - return true; - - // 情况3:枚举类型处理 - //else if (underlyingType.IsEnum) - //{ - // if (Enum.IsDefined(underlyingType, msg)) - // { - // convertedValue = Enum.Parse(underlyingType, msg.ToString()); - // return true; - // } - // return false; - //} - return false; - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/Internal/SubscribeResult.cs b/modules/JiShe.CollectBus.Kafka/Internal/SubscribeResult.cs deleted file mode 100644 index d3fbcf6..0000000 --- a/modules/JiShe.CollectBus.Kafka/Internal/SubscribeResult.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace JiShe.CollectBus.Kafka.Internal; - -public class SubscribeResult : ISubscribeAck -{ - /// - /// 是否成功 - /// - public bool Ack { get; set; } - - /// - /// 消息 - /// - public string? Msg { get; set; } - - - /// - /// 成功 - /// - /// 消息 - public SubscribeResult Success(string? msg = null) - { - Ack = true; - Msg = msg; - return this; - } - - /// - /// 失败 - /// - /// - /// - public SubscribeResult Fail(string? msg = null) - { - Msg = msg; - Ack = false; - return this; - } -} - -public static class SubscribeAck -{ - /// - /// 成功 - /// - /// 消息 - /// - public static ISubscribeAck Success(string? msg = null) - { - return new SubscribeResult().Success(msg); - } - - - /// - /// 失败 - /// - /// 消息 - /// - public static ISubscribeAck Fail(string? msg = null) - { - return new SubscribeResult().Fail(msg); - } -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.Kafka/JiShe.CollectBus.Kafka.csproj b/modules/JiShe.CollectBus.Kafka/JiShe.CollectBus.Kafka.csproj deleted file mode 100644 index a0fd2f7..0000000 --- a/modules/JiShe.CollectBus.Kafka/JiShe.CollectBus.Kafka.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - - - - - - - diff --git a/modules/JiShe.CollectBus.Kafka/KafkaSubscribeExtensions.cs b/modules/JiShe.CollectBus.Kafka/KafkaSubscribeExtensions.cs deleted file mode 100644 index 15eb60d..0000000 --- a/modules/JiShe.CollectBus.Kafka/KafkaSubscribeExtensions.cs +++ /dev/null @@ -1,435 +0,0 @@ -using Confluent.Kafka; -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Common.Helpers; -using JiShe.CollectBus.Kafka.AdminClient; -using JiShe.CollectBus.Kafka.Attributes; -using JiShe.CollectBus.Kafka.Consumer; -using JiShe.CollectBus.Kafka.Internal; -using JiShe.CollectBus.Kafka.Serialization; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.Collections; -using System.ComponentModel; -using System.Reflection; - -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) - { - //初始化主题信息 - var kafkaAdminClient = provider.GetRequiredService(); - var kafkaOptions = provider.GetRequiredService>(); - - var topics = ProtocolConstExtensions.GetAllTopicNamesByIssued(); - topics.AddRange(ProtocolConstExtensions.GetAllTopicNamesByReceived()); - foreach (var item in topics) - { - kafkaAdminClient.CreateTopicAsync(item, kafkaOptions.Value.NumPartitions, kafkaOptions.Value.KafkaReplicationFactor).ConfigureAwait(false).GetAwaiter().GetResult(); - } - - } - - /// - /// 添加Kafka订阅 - /// - public static void UseKafkaSubscribe(this IServiceProvider provider) - { - var lifetime = provider.GetRequiredService(); - var kafkaOptions = provider.GetRequiredService>(); - lifetime.ApplicationStarted.Register(() => - { - var logger = provider.GetRequiredService>(); - //var threadCount = 0; - //var topicCount = 0; - var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); - if (string.IsNullOrWhiteSpace(assemblyPath)) - { - logger.LogWarning($"kafka订阅未能找到程序路径"); - return; - } - var dllFiles = Directory.GetFiles(assemblyPath, "*.dll"); - foreach (var file in dllFiles) - { - // 跳过已加载的程序集 - var assemblyName = AssemblyName.GetAssemblyName(file); - var existingAssembly = AppDomain.CurrentDomain.GetAssemblies() - .FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName); - var assembly = existingAssembly ?? Assembly.LoadFrom(file); - // 实现IKafkaSubscribe接口 - var subscribeTypes = assembly.GetTypes().Where(type => - typeof(IKafkaSubscribe).IsAssignableFrom(type) && - !type.IsAbstract && !type.IsInterface).ToList(); - if (subscribeTypes.Count == 0) - continue; - - // 并行处理 - Parallel.ForEach(subscribeTypes, subscribeType => - { - var subscribes = provider.GetServices(subscribeType).ToList(); - Parallel.ForEach(subscribes, subscribe => - { - if (subscribe != null) - { - Tuple tuple = BuildKafkaSubscribe(subscribe, provider, logger, kafkaOptions.Value); - //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.LogWarning($"kafka订阅主题:{_topicSubscribeCount}数,共启动:{_threadCount}线程"); - - var kafkaTaskScheduler = provider.GetRequiredService(); - kafkaTaskScheduler.ExceptionEvent += (ex) => - { - logger.LogError(ex, "Kafka任务调度异常"); - }; - //logger.LogWarning($"kafka订阅工作线程数:{kafkaTaskScheduler.WorkerThreads},队列任务:{kafkaTaskScheduler.QueuedTasks}数"); - // - // 订阅调度监控测试可打开 - //_ = Task.Factory.StartNew(async () => - // { - // while (true) - // { - // logger.LogWarning($"kafka订阅工作线程数:{kafkaTaskScheduler.WorkerThreads},队列任务:{kafkaTaskScheduler.QueuedTasks}数"); - // await Task.Delay(TimeSpan.FromSeconds(5)); - // } - // }); - - }); - - } - - /// - /// 添加Kafka订阅 - /// - public static void UseKafkaSubscribersAsync(this IApplicationBuilder app, Assembly assembly) - { - var provider = app.ApplicationServices; - var lifetime = provider.GetRequiredService(); - var kafkaOptions = provider.GetRequiredService>(); - lifetime.ApplicationStarted.Register(() => - { - var logger = provider.GetRequiredService>(); - int threadCount = 0; - int topicCount = 0; - var subscribeTypes = assembly.GetTypes() - .Where(t => typeof(IKafkaSubscribe).IsAssignableFrom(t)) - .ToList(); - - if (subscribeTypes.Count == 0) return; - - Parallel.ForEach(subscribeTypes, subscribeType => - { - var subscribes = provider.GetServices(subscribeType).ToList(); - Parallel.ForEach(subscribes, subscribe => - { - if (subscribe != null) - { - Tuple tuple = BuildKafkaSubscribe(subscribe, provider, logger, kafkaOptions.Value); - //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}线程"); - }); - } - - /// - /// 构建Kafka订阅 - /// - private static Tuple BuildKafkaSubscribe(object subscribe, IServiceProvider provider, ILogger logger, KafkaOptionConfig kafkaOptionConfig) - { - var subscribedMethods = subscribe.GetType().GetMethods() - .Select(m => new { Method = m, Attribute = m.GetCustomAttribute() }) - .Where(x => x.Attribute != null) - .ToArray(); - //var configuration = provider.GetRequiredService(); - int threadCount = 0; - - Parallel.ForEach(subscribedMethods, sub => - { - Interlocked.Increment(ref _topicSubscribeCount); - var adminClientService = provider.GetRequiredService(); - int topicCount = adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic); - // 可以根据配置文件TaskThreadCount来配置线程数 - int partitionCount = sub.Attribute!.TaskCount == -1 ? (kafkaOptionConfig.TaskThreadCount==-1? topicCount: kafkaOptionConfig.TaskThreadCount) : 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; - Parallel.For(0,partitionCount, async (partition) => - { - 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); - } - - /// - /// 启动后台消费线程 - /// - private static async Task StartConsumerAsync(IServiceProvider provider, KafkaSubscribeAttribute attr, MethodInfo method, object subscribe, ILogger logger) - { - var consumerService = provider.GetRequiredService(); - - if (attr.EnableBatch) - { - Interlocked.Increment(ref _threadStartCount); - logger.LogInformation($"kafka开启线程消费:{_threadStartCount}"); - await consumerService.SubscribeBatchAsync(attr.Topic, async (message) => - { - try - { -#if DEBUG - logger.LogInformation($"kafka批量消费消息:{message.Serialize()}"); -#endif - // 处理消息 - return await ProcessMessageAsync(message.ToList(), method, subscribe); - } - catch (ConsumeException ex) - { - // 处理消费错误 - 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 - { -#if DEBUG - logger.LogInformation($"kafka消费消息:{message}"); -#endif - // 处理消息 - return await ProcessMessageAsync(new List() { message }, method, subscribe); - } - catch (ConsumeException ex) - { - // 处理消费错误 - logger.LogError($"kafka消费异常:{ex.Message}"); - } - catch (Exception ex) - { - // 处理消费错误 - logger.LogError($"kafka批量消费异常:{ex.Message}"); - } - return await Task.FromResult(false); - }, attr.GroupId); - } - - } - - - /// - /// 处理消息 - /// - private static async Task ProcessMessageAsync(List messages, MethodInfo method, object subscribe) - { - try - { - var parameters = method.GetParameters(); - bool isGenericTask = method.ReturnType.IsGenericType - && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>); - bool existParameters = parameters.Length > 0; - object[]? executeParameters = null; - - if (existParameters) - { - 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) - { - - object? tempParameter = null; - var parameterDescriptor = parameterDescriptors[i]; - if (KafkaSerialization.IsJsonType(item)) - { - tempParameter = KafkaSerialization.Deserialize(item, tuple.Item2 != null ? tuple.Item2 : parameterDescriptor.ParameterType); - } - else - { - - 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; - } - catch (Exception ex) - { - - throw; - } - } - } - - -} diff --git a/modules/JiShe.CollectBus.Kafka/Producer/IProducerService.cs b/modules/JiShe.CollectBus.Kafka/Producer/IProducerService.cs deleted file mode 100644 index 8cbe665..0000000 --- a/modules/JiShe.CollectBus.Kafka/Producer/IProducerService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Confluent.Kafka; - -namespace JiShe.CollectBus.Kafka.Producer -{ - public interface IProducerService - { - Task ProduceAsync(string topic, TKey key, TValue value) where TKey : notnull where TValue : class; - - Task ProduceAsync(string topic, TValue value) where TValue : class; - - Task ProduceAsync(string topic, TKey key, TValue value, int? partition, Action>? deliveryHandler = null) where TKey : notnull where TValue : class; - - Task ProduceAsync(string topic, TValue value, int? partition = null, Action>? deliveryHandler = null) where TValue : class; - } -} diff --git a/modules/JiShe.CollectBus.Kafka/Producer/ProducerService.cs b/modules/JiShe.CollectBus.Kafka/Producer/ProducerService.cs deleted file mode 100644 index 72e9096..0000000 --- a/modules/JiShe.CollectBus.Kafka/Producer/ProducerService.cs +++ /dev/null @@ -1,265 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -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; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -using YamlDotNet.Serialization; - -namespace JiShe.CollectBus.Kafka.Producer -{ - public class ProducerService: IProducerService, IDisposable - { - private readonly ILogger _logger; - private readonly IConfiguration _configuration; - private readonly ConcurrentDictionary _producerCache = new(); - private class KafkaProducer where TKey : notnull where TValue : class { } - private readonly KafkaOptionConfig _kafkaOptionConfig; - private readonly ServerApplicationOptions _applicationOptions; - /// - /// ProducerService - /// - /// - /// - /// - public ProducerService(IConfiguration configuration,ILogger logger, IOptions kafkaOptionConfig, IOptions applicationOptions) - { - _configuration = configuration; - _logger = logger; - _kafkaOptionConfig = kafkaOptionConfig.Value; - _applicationOptions = applicationOptions.Value; - } - - #region private 私有方法 - /// - /// 创建生产者实例 - /// - /// - /// - /// - private IProducer GetProducer(Type typeKey) - { - return (IProducer)_producerCache.GetOrAdd(typeKey, _ => - { - var config = BuildProducerConfig(); - return new ProducerBuilder(config) - .SetValueSerializer(new JsonSerializer()) // Value 使用自定义 JSON 序列化 - .SetLogHandler((_, msg) => _logger.Log(ConvertLogLevel(msg.Level), msg.Message)) - .Build(); - }); - } - - /// - /// 配置 - /// - /// - private ProducerConfig BuildProducerConfig() - { - var config = new ProducerConfig - { - BootstrapServers = _kafkaOptionConfig.BootstrapServers, - //AllowAutoCreateTopics = true, - 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,默认为5ms - Acks = Acks.All, // 表明只有所有副本Broker都收到消息才算提交成功, 可以 Acks.Leader - MessageSendMaxRetries = 50, // 消息发送失败最大重试50次 - MessageTimeoutMs = 120000, // 消息发送超时时间为2分钟,设置值MessageTimeoutMs > LingerMs - }; - - if (_kafkaOptionConfig.EnableAuthorization) - { - config.SecurityProtocol = _kafkaOptionConfig.SecurityProtocol; - config.SaslMechanism = _kafkaOptionConfig.SaslMechanism; - config.SaslUsername = _kafkaOptionConfig.SaslUserName; - config.SaslPassword = _kafkaOptionConfig.SaslPassword; - } - - return config; - } - - private static LogLevel ConvertLogLevel(SyslogLevel level) => level switch - { - SyslogLevel.Emergency => LogLevel.Critical, - SyslogLevel.Alert => LogLevel.Critical, - SyslogLevel.Critical => LogLevel.Critical, - SyslogLevel.Error => LogLevel.Error, - SyslogLevel.Warning => LogLevel.Warning, - SyslogLevel.Notice => LogLevel.Information, - SyslogLevel.Info => LogLevel.Information, - SyslogLevel.Debug => LogLevel.Debug, - _ => LogLevel.None - }; - - #endregion - - /// - /// 发布消息 - /// - /// - /// - /// - /// - /// - /// - public async Task ProduceAsync(string topic, TKey key, TValue value)where TKey : notnull where TValue : class - { - try - { - 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); - } - catch (Exception ex) - { - - throw; - } - } - - /// - /// 发布消息 - /// - /// - /// - /// - /// - public async Task ProduceAsync(string topic, TValue value) where TValue : class - { - try - { - 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); - } - catch (Exception ex) - { - - throw; - } - } - - /// - /// 发布消息 - /// - /// - /// - /// - /// - /// - /// - /// - /// - public async Task ProduceAsync(string topic,TKey key,TValue value,int? partition=null, Action>? deliveryHandler = null)where TKey : notnull where TValue : class - { - try - { - 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, new Partition(partition.Value)); - producer.Produce(topicPartition, message, deliveryHandler); - } - else - { - producer.Produce(topic, message, deliveryHandler); - } - await Task.CompletedTask; - } - catch (Exception ex) - { - - throw; - } - - } - - /// - /// 发布消息 - /// - /// - /// - /// - /// - /// - /// - /// - public async Task ProduceAsync(string topic, TValue value, int? partition=null, Action>? deliveryHandler = null) where TValue : class - { - try - { - 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, new Partition(partition.Value)); - //_logger.LogError($"push消息:{topic}-{partition.Value}"); - producer.Produce(topicPartition, message, deliveryHandler); - } - else - { - producer.Produce(topic, message, deliveryHandler); - } - await Task.CompletedTask; - } - catch (Exception ex) - { - - throw; - } - } - - public void Dispose() - { - foreach (var producer in _producerCache.Values.OfType()) - { - producer.Dispose(); - } - _producerCache.Clear(); - } - } -} diff --git a/modules/JiShe.CollectBus.Kafka/Serialization/JsonSerializer.cs b/modules/JiShe.CollectBus.Kafka/Serialization/JsonSerializer.cs deleted file mode 100644 index 98fda49..0000000 --- a/modules/JiShe.CollectBus.Kafka/Serialization/JsonSerializer.cs +++ /dev/null @@ -1,139 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Text.Json; -using Confluent.Kafka; -using System.Text.Json.Serialization; -using System.Text.Encodings.Web; - -namespace JiShe.CollectBus.Kafka.Serialization -{ - /// - /// JSON 序列化器(支持泛型) - /// - public class JsonSerializer : ISerializer, IDeserializer - { - private static readonly JsonSerializerOptions _options = 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() } // 注册你的自定义转换器, - }; - - public byte[] Serialize(T data, SerializationContext context) - { - if (data == null) - return null; - - try - { - return JsonSerializer.SerializeToUtf8Bytes(data, _options); - } - catch (Exception ex) - { - throw new InvalidOperationException("Kafka序列化失败", ex); - } - } - - public T Deserialize(ReadOnlySpan data, bool isNull, SerializationContext context) - { - if (isNull) - return default; - try - { - if (data.IsEmpty) - return default; - return JsonSerializer.Deserialize(data, _options)!; - } - catch (Exception ex) - { - throw new InvalidOperationException("Kafka反序列化失败", ex); - } - } - } - - - public class DateTimeJsonConverter : JsonConverter - { - private readonly string _dateFormatString; - public DateTimeJsonConverter() - { - _dateFormatString = "yyyy-MM-dd HH:mm:ss"; - } - - public DateTimeJsonConverter(string dateFormatString) - { - _dateFormatString = dateFormatString; - } - - public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return DateTime.Parse(reader.GetString()); - } - - public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) - { - writer.WriteStringValue(value.ToString(_dateFormatString)); - } - } - - - public static class KafkaSerialization - { - - /// - /// 判断是否是json类型 - /// - /// - /// - public static bool IsJsonType(this object jsonObject) - { - return jsonObject is JsonElement; - } - public static object? Deserialize(object value, Type valueType) - { - try - { - 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); - return JsonSerializer.Deserialize(jsonElement, valueType, _jsonSerializerOptions); - } - - return null; - } - catch (Exception ex) - { - - throw; - } - } - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/FodyWeavers.xml b/modules/JiShe.CollectBus.MongoDB/FodyWeavers.xml deleted file mode 100644 index 1715698..0000000 --- a/modules/JiShe.CollectBus.MongoDB/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/modules/JiShe.CollectBus.MongoDB/JiShe.CollectBus.MongoDB.abppkg b/modules/JiShe.CollectBus.MongoDB/JiShe.CollectBus.MongoDB.abppkg deleted file mode 100644 index 8b23fd1..0000000 --- a/modules/JiShe.CollectBus.MongoDB/JiShe.CollectBus.MongoDB.abppkg +++ /dev/null @@ -1,3 +0,0 @@ -{ - "role": "lib.mongodb" -} \ No newline at end of file diff --git a/modules/JiShe.CollectBus.MongoDB/JiShe.CollectBus.MongoDB.csproj b/modules/JiShe.CollectBus.MongoDB/JiShe.CollectBus.MongoDB.csproj deleted file mode 100644 index 2987d33..0000000 --- a/modules/JiShe.CollectBus.MongoDB/JiShe.CollectBus.MongoDB.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - net8.0 - enable - JiShe.CollectBus - - - - - - - - - - - - - - - diff --git a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusDbSchemaMigrator.cs b/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusDbSchemaMigrator.cs deleted file mode 100644 index 28dbd19..0000000 --- a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusDbSchemaMigrator.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using JiShe.CollectBus.Data; -using Microsoft.Extensions.DependencyInjection; -using MongoDB.Driver; -using Volo.Abp.Data; -using Volo.Abp.DependencyInjection; -using Volo.Abp.MongoDB; -using Volo.Abp.MultiTenancy; - -namespace JiShe.CollectBus.MongoDB -{ - public class CollectBusDbSchemaMigrator : ICollectBusDbSchemaMigrator, ITransientDependency - { - private readonly IServiceProvider _serviceProvider; - - public CollectBusDbSchemaMigrator(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public async Task MigrateAsync() - { - var dbContexts = _serviceProvider.GetServices(); - var connectionStringResolver = _serviceProvider.GetRequiredService(); - - if (_serviceProvider.GetRequiredService().IsAvailable) - { - dbContexts = dbContexts.Where(x => !x.GetType().IsDefined(typeof(IgnoreMultiTenancyAttribute))); - } - - foreach (var dbContext in dbContexts) - { - var connectionString = - await connectionStringResolver.ResolveAsync( - ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType())); - var mongoUrl = new MongoUrl(connectionString); - var databaseName = mongoUrl.DatabaseName; - var client = new MongoClient(mongoUrl); - - if (databaseName.IsNullOrWhiteSpace()) - { - databaseName = ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType()); - } - - (dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName)); - } - } - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContext.cs b/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContext.cs deleted file mode 100644 index c0ddd77..0000000 --- a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContext.cs +++ /dev/null @@ -1,94 +0,0 @@ -using JiShe.CollectBus.IotSystems.Devices; -using JiShe.CollectBus.IotSystems.MessageReceiveds; -using JiShe.CollectBus.IotSystems.MeterReadingRecords; -using JiShe.CollectBus.IotSystems.Protocols; -using JiShe.CollectBus.ShardingStrategy; -using MongoDB.Bson; -using MongoDB.Bson.Serialization; -using MongoDB.Driver; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -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; - -[IgnoreMultiTenancy] -[ConnectionStringName(CollectBusDbProperties.MongoDbConnectionStringName)] -public class CollectBusMongoDbContext : AbpMongoDbContext, ICollectBusMongoDbContext -{ - /* Add mongo collections here. Example: - * public IMongoCollection Questions => Collection(); - */ - - public IMongoCollection MessageReceiveds => Collection(); - public IMongoCollection MessageReceivedLogins => Collection(); - public IMongoCollection MessageReceivedHeartbeats => Collection(); - public IMongoCollection Devices => Collection(); - public IMongoCollection ProtocolInfos => Collection(); - - public IMongoCollection MessageIssueds => Collection(); - - - protected override void CreateModel(IMongoModelBuilder modelBuilder) - { - //modelBuilder.Entity(builder => - //{ - // builder.CreateCollectionOptions.Collation = new Collation(locale: "en_US", strength: CollationStrength.Secondary); - // builder.ConfigureIndexes(indexes => - // { - // indexes.CreateOne( - // new CreateIndexModel( - // Builders.IndexKeys.Ascending("MyProperty"), - // new CreateIndexOptions { Unique = true } - // ) - // ); - // } - // ); - - // //// 创建索引 - // //builder.ConfigureIndexes(index => - // //{ - - - // // //List> createIndexModels = new List>(); - // // //createIndexModels.Add(new CreateIndexModel( - // // // Builders.IndexKeys.Ascending(nameof(MeterReadingRecords)), - // // // new CreateIndexOptions - // // // { - // // // Unique = true - // // // } - // // // )); - - - // // //var indexKeys = Builders.IndexKeys - // // //.Ascending("CreationTime") - // // //.Ascending("OrderNumber"); - - // // //var indexOptions = new CreateIndexOptions - // // //{ - // // // Background = true, - // // // Name = "IX_CreationTime_OrderNumber" - // // //}; - // // //index.CreateOne( - // // //new CreateIndexModel(indexKeys, indexOptions)); - - // // //index.CreateOne(new CreateIndexModel( - // // // Builders.IndexKeys.Ascending(nameof(MeterReadingRecords)), - // // // new CreateIndexOptions - // // // { - // // // Unique = true - // // // } - // // // )); - // //}); - - //}); - - base.CreateModel(modelBuilder); - modelBuilder.ConfigureCollectBus(); - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContextExtensions.cs b/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContextExtensions.cs deleted file mode 100644 index 891bfb5..0000000 --- a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbContextExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Volo.Abp; -using Volo.Abp.MongoDB; - -namespace JiShe.CollectBus.MongoDB; - -public static class CollectBusMongoDbContextExtensions -{ - public static void ConfigureCollectBus( - this IMongoModelBuilder builder) - { - Check.NotNull(builder, nameof(builder)); - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbModule.cs b/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbModule.cs deleted file mode 100644 index 89fd079..0000000 --- a/modules/JiShe.CollectBus.MongoDB/MongoDB/CollectBusMongoDbModule.cs +++ /dev/null @@ -1,54 +0,0 @@ -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; -using Microsoft.Extensions.DependencyInjection.Extensions; -using System; -using Volo.Abp; -using Volo.Abp.AuditLogging.MongoDB; -using Volo.Abp.BackgroundJobs.MongoDB; -using Volo.Abp.Domain.Repositories; -using Volo.Abp.Domain.Repositories.MongoDB; -using Volo.Abp.Modularity; -using Volo.Abp.MongoDB; -using Volo.Abp.Uow; - -namespace JiShe.CollectBus.MongoDB; - -[DependsOn( - typeof(CollectBusDomainModule), - typeof(AbpMongoDbModule), - typeof(AbpBackgroundJobsMongoDbModule), - typeof(AbpAuditLoggingMongoDbModule) - )] -public class CollectBusMongoDbModule : AbpModule -{ - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddMongoDbContext(options => - { - options.AddDefaultRepositories(includeAllEntities: true); - - // 注册分表策略 - context.Services.AddTransient( - typeof(IShardingStrategy<>), - typeof(DayShardingStrategy<>)); - - - context.Services.AddTransient(typeof(HourShardingStrategy<>)); - - //// 分表策略仓储 替换默认仓储 - //options.AddRepository(); - - options.AddRepository(); - }); - context.Services.AddAlwaysDisableUnitOfWorkTransaction(); - Configure(options => - { - options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; - }); - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/MongoDB/ICollectBusMongoDbContext.cs b/modules/JiShe.CollectBus.MongoDB/MongoDB/ICollectBusMongoDbContext.cs deleted file mode 100644 index 2b554be..0000000 --- a/modules/JiShe.CollectBus.MongoDB/MongoDB/ICollectBusMongoDbContext.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Volo.Abp.Data; -using Volo.Abp.MongoDB; - -namespace JiShe.CollectBus.MongoDB; - -[ConnectionStringName(CollectBusDbProperties.MongoDbConnectionStringName)] -public interface ICollectBusMongoDbContext : IAbpMongoDbContext -{ - /* Define mongo collections here. Example: - * IMongoCollection Questions { get; } - */ -} diff --git a/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/ILogRecordRepository.cs b/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/ILogRecordRepository.cs deleted file mode 100644 index 8d1c203..0000000 --- a/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/ILogRecordRepository.cs +++ /dev/null @@ -1,57 +0,0 @@ -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 deleted file mode 100644 index 415ad06..0000000 --- a/modules/JiShe.CollectBus.MongoDB/Repository/LogRecord/LogRecordRepository.cs +++ /dev/null @@ -1,166 +0,0 @@ -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/Repository/MeterReadingRecord/IMeterReadingRecordRepository.cs b/modules/JiShe.CollectBus.MongoDB/Repository/MeterReadingRecord/IMeterReadingRecordRepository.cs deleted file mode 100644 index 20b7809..0000000 --- a/modules/JiShe.CollectBus.MongoDB/Repository/MeterReadingRecord/IMeterReadingRecordRepository.cs +++ /dev/null @@ -1,60 +0,0 @@ -using JiShe.CollectBus.IotSystems.MeterReadingRecords; -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.Domain.Repositories; - -namespace JiShe.CollectBus.Repository.MeterReadingRecord -{ - /// - /// 抄读仓储接口 - /// - public interface IMeterReadingRecordRepository : IRepository - { - /// - /// 批量插入 - /// - /// - /// - /// - Task InsertManyAsync(List entities, - DateTime? dateTime); - - /// - /// 单个插入 - /// - /// - /// - /// - Task InsertAsync(MeterReadingRecords entity, DateTime? dateTime); - - /// - /// 单条更新 - /// - /// 过滤条件,示例:Builders.Filter.Eq(x => x.Id, filter.Id) - /// 包含待更新的内容,示例:Builders.Update.Set(x => x.Processed, true).Set(x => x.ProcessedTime, Clock.Now) - /// 数据实体,用于获取对应的分片库 - /// - Task UpdateOneAsync(FilterDefinition filter, UpdateDefinition update, MeterReadingRecords entity); - - /// - /// 单个获取 - /// - /// - /// - /// - Task FirOrDefaultAsync(MeterReadingRecords entity, DateTime? dateTime); - - /// - /// 多集合数据查询 - /// - /// - /// - /// - Task> ParallelQueryAsync(DateTime startTime, DateTime endTime); - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/Repository/MeterReadingRecord/MeterReadingRecordRepository.cs b/modules/JiShe.CollectBus.MongoDB/Repository/MeterReadingRecord/MeterReadingRecordRepository.cs deleted file mode 100644 index cb35b5c..0000000 --- a/modules/JiShe.CollectBus.MongoDB/Repository/MeterReadingRecord/MeterReadingRecordRepository.cs +++ /dev/null @@ -1,173 +0,0 @@ -using JiShe.CollectBus.IotSystems.MeterReadingRecords; -using JiShe.CollectBus.MongoDB; -using JiShe.CollectBus.ShardingStrategy; -using MongoDB.Bson; -using MongoDB.Driver; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Volo.Abp.Domain.Entities; -using Volo.Abp.Domain.Repositories.MongoDB; -using Volo.Abp.MongoDB; -using Volo.Abp.MongoDB.DistributedEvents; -using Volo.Abp.Timing; -using static System.Net.Mime.MediaTypeNames; - -namespace JiShe.CollectBus.Repository.MeterReadingRecord -{ - /// - /// 抄读记录仓储 - /// - public class MeterReadingRecordRepository : MongoDbRepository, IMeterReadingRecordRepository - { - - private readonly IShardingStrategy _shardingStrategy; - private readonly IMongoDbContextProvider _dbContextProvider; - - public MeterReadingRecordRepository( - IMongoDbContextProvider dbContextProvider, - IShardingStrategy shardingStrategy - ) - : base(dbContextProvider) - { - _dbContextProvider = dbContextProvider; - _shardingStrategy = shardingStrategy; - } - - /// - /// 批量插入 - /// - /// - /// - /// - 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(MeterReadingRecords entity, bool autoSave = false, CancellationToken cancellationToken = default(CancellationToken)) - { - var collection = await GetShardedCollection(DateTime.Now); - await collection.InsertOneAsync(entity); - return entity; - } - - - /// - /// 单条插入 - /// - /// - /// - /// - public async Task InsertAsync(MeterReadingRecords 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.Processed, true).Set(x => x.ProcessedTime, Clock.Now) - /// 数据实体,用于获取对应的分片库 - /// - public async Task UpdateOneAsync(FilterDefinition filter, UpdateDefinition update, MeterReadingRecords entity) - { - var collection = await GetShardedCollection(entity.CreationTime); - - await collection.UpdateOneAsync(filter, update); - return entity; - } - - - /// - /// 单个获取 - /// - /// - /// - /// - /// - public async Task FirOrDefaultAsync(MeterReadingRecords entity, DateTime? dateTime) - { - var collection = await GetShardedCollection(dateTime); - var query = await collection.FindAsync(d => d.CreationTime == dateTime.Value && d.AFN == entity.AFN && d.Fn == entity.Fn && d.FocusAddress == entity.FocusAddress); - return await query.FirstOrDefaultAsync(); - } - - /// - /// 多集合数据查询 - /// - /// - /// - /// - public async Task> ParallelQueryAsync(DateTime startTime, DateTime endTime) - { - var collectionNames = _shardingStrategy.GetQueryCollectionNames(startTime, endTime); - var database = await GetDatabaseAsync(); - - - var tasks = collectionNames.Select(async name => - { - var collection = 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 database = await GetDatabaseAsync(); - string collectionName = string.Empty; - - if (dateTime != null) - { - collectionName = _shardingStrategy.GetCollectionName(dateTime.Value); - } - else - { - collectionName = _shardingStrategy.GetCurrentCollectionName(); - } - - return database.GetCollection(collectionName); - } - - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/DayShardingStrategy.cs b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/DayShardingStrategy.cs deleted file mode 100644 index 0c721a5..0000000 --- a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/DayShardingStrategy.cs +++ /dev/null @@ -1,61 +0,0 @@ -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Extensions; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; - -namespace JiShe.CollectBus.ShardingStrategy -{ - /// - /// 按天分表策略 - /// - /// - public class DayShardingStrategy : IShardingStrategy - { - /// - /// 获取指定时间对应的集合名 - /// - /// - /// - public string GetCollectionName(DateTime dateTime) - { - var baseName = typeof(TEntity).Name; - return $"{baseName}_{dateTime.GetDataTableShardingStrategy(TableTimeStrategyEnum.DayShardingStrategy)}"; - } - - /// - /// 获取当前时间对应的集合名 - /// - /// - public string GetCurrentCollectionName() - { - var baseName = typeof(TEntity).Name; - return $"{baseName}_{DateTime.Now.GetDataTableShardingStrategy(TableTimeStrategyEnum.DayShardingStrategy)}"; - } - - /// - /// 用于查询时确定目标集合 - /// - /// - /// - /// - public IEnumerable GetQueryCollectionNames(DateTime? startTime, DateTime? endTime) - { - var months = new List(); - var current = startTime ?? DateTime.MinValue; - var end = endTime ?? DateTime.MaxValue; - var baseName = typeof(TEntity).Name; - - while (current <= end) - { - months.Add($"{baseName}_{current.GetDataTableShardingStrategy(TableTimeStrategyEnum.DayShardingStrategy)}"); - current = current.AddMonths(1); - } - - return months.Distinct(); - } - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/HourShardingStrategy.cs b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/HourShardingStrategy.cs deleted file mode 100644 index 20f65de..0000000 --- a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/HourShardingStrategy.cs +++ /dev/null @@ -1,58 +0,0 @@ -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/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IHourShardingStrategy.cs b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IHourShardingStrategy.cs deleted file mode 100644 index ad0654c..0000000 --- a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IHourShardingStrategy.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.ShardingStrategy -{ - public interface IHourShardingStrategy : IShardingStrategy - { - } -} diff --git a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IShardingStrategy.cs b/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IShardingStrategy.cs deleted file mode 100644 index 151d5df..0000000 --- a/modules/JiShe.CollectBus.MongoDB/ShardingStrategy/IShardingStrategy.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.ShardingStrategy -{ - /// - /// 数据存储分片策略 - /// - /// - public interface IShardingStrategy - { - /// - /// 获取指定时间对应的集合名 - /// - /// - string GetCollectionName(DateTime dateTime); - - /// - /// 获取当前时间对应的集合名 - /// - /// - string GetCurrentCollectionName(); - - /// - /// 用于查询时确定目标集合 - /// - /// - /// - /// - IEnumerable GetQueryCollectionNames(DateTime? startTime = null, - DateTime? endTime = null); - } -} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/ProtocolPools/IPluginContainer.cs b/protocols/JiShe.CollectBus.Protocol.Contracts/ProtocolPools/IPluginContainer.cs deleted file mode 100644 index c34a1eb..0000000 --- a/protocols/JiShe.CollectBus.Protocol.Contracts/ProtocolPools/IPluginContainer.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace JiShe.CollectBus.Protocol.Contracts.ProtocolPools -{ - public interface IPluginContainer - { - } -} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/ProtocolPools/PluginContainer.cs b/protocols/JiShe.CollectBus.Protocol.Contracts/ProtocolPools/PluginContainer.cs deleted file mode 100644 index 116eccc..0000000 --- a/protocols/JiShe.CollectBus.Protocol.Contracts/ProtocolPools/PluginContainer.cs +++ /dev/null @@ -1,26 +0,0 @@ -using JiShe.CollectBus.Interfaces; - -namespace JiShe.CollectBus.Protocol.Contracts.ProtocolPools -{ - public class PluginContainer: IPluginContainer - { - public Dictionary ProtocolPools; - - public PluginContainer() - { - - - } - - - } - - public static class ServiceProviderKeyedServiceExtensions - { - //public static Task AddKeyedSingleton(this IServiceProvider provider, string key) - //{ - // //var aa = Activator.CreateInstance(); - - //} - } -} diff --git a/protocols/JiShe.CollectBus.Protocol.T1882018/GlobalUsings.cs b/protocols/JiShe.CollectBus.Protocol.T1882018/GlobalUsings.cs new file mode 100644 index 0000000..d1b32ae --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/GlobalUsings.cs @@ -0,0 +1,9 @@ +// Global using directives + +global using System.Text; +global using Volo.Abp.Modularity; +global using JiShe.ServicePro.Enums; +global using JiShe.ServicePro.FreeRedisProvider; +global using JiShe.ServicePro.Consts; +global using JiShe.ServicePro.Core; +global using JiShe.ServicePro.ServerOptions; \ No newline at end of file diff --git a/protocols/JiShe.CollectBus.Protocol.T1882018/JiShe.CollectBus.Protocol.T1882018.csproj b/protocols/JiShe.CollectBus.Protocol.T1882018/JiShe.CollectBus.Protocol.T1882018.csproj index 4866985..400c849 100644 --- a/protocols/JiShe.CollectBus.Protocol.T1882018/JiShe.CollectBus.Protocol.T1882018.csproj +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/JiShe.CollectBus.Protocol.T1882018.csproj @@ -1,14 +1,16 @@  - net8.0 + net9.0 enable enable - - + + + + 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 6fd96e1..81f187e 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 @@ -8,6 +8,8 @@ using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto; using JiShe.CollectBus.Protocol.Dto; using JiShe.CollectBus.Protocol.Interfaces; using JiShe.CollectBus.Protocol3761; +using JiShe.ServicePro.Enums; +using JiShe.ServicePro.FreeRedisProvider; using Microsoft.Extensions.Logging; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_00H @@ -39,10 +41,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_00H ItemType= $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询电表信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 2e465b8..8a76b57 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 @@ -36,10 +36,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_00H ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询电表信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 index 686d027..c2cfaba 100644 --- 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 @@ -38,10 +38,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_02H ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 index 6428063..2f26ae1 100644 --- 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 @@ -38,10 +38,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_02H ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 index 1c3027b..b157325 100644 --- 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 @@ -38,10 +38,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_02H ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 5011b4e..dc99c5c 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 @@ -8,7 +8,7 @@ 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 JiShe.CollectBus.Protocol3761; using Microsoft.Extensions.Logging; namespace JiShe.CollectBus.Protocol.AnalysisData.AFN_09H @@ -45,10 +45,10 @@ namespace JiShe.CollectBus.Protocol.AnalysisData.AFN_09H ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 7547662..fa8c753 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 @@ -39,10 +39,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_09H ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 7e36e11..ad00f2c 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 @@ -44,10 +44,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 5305476..7dbaa7a 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 @@ -43,10 +43,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 48aa519..e096978 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 @@ -38,10 +38,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0AH ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; 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 35c258f..229c735 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,17 +1,12 @@ -using Apache.IoTDB; -using JiShe.CollectBus.Common.Consts; +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 { @@ -58,12 +53,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code,input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code,input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 3f28d97..5ae6d70 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 @@ -41,12 +41,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 887e982..c9d9cbb 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 @@ -42,12 +42,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 55ab674..9cdb741 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 @@ -8,7 +8,7 @@ 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 JiShe.CollectBus.Protocol3761; using Microsoft.Extensions.Logging; using YamlDotNet.Core.Tokens; @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 13541e3..9cf2c32 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 @@ -44,10 +44,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH AnalysisBaseDto data = GenerateFinalResult(datas, "当月正向有功最大需量及发生时间", itemType); // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; 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 1a32132..b261ac6 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 @@ -44,10 +44,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH AnalysisBaseDto data = GenerateFinalResult(datas, itemType,"上月(上一结算日)正向有功最大需量及发生时间"); // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; 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 a95bd09..1c624d1 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 @@ -44,10 +44,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH 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); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; 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 e6e6096..85fdf43 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 @@ -71,12 +71,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 a54db8c..48d798c 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 @@ -43,10 +43,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH var data = await GenerateFinalResultAsync(input.UnitData.HexMessageList, itemType); // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; 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 fd7dd30..861c256 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 @@ -49,10 +49,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH ItemType= $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; 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 257a666..7d6c448 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 @@ -66,12 +66,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 8fbad80..128e522 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 10f52b2..9bfb4fe 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 e40c2e8..5e38127 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 ed7d4c1..8a2333f 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 6b0585e..8d45257 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 78eadd8..a34572c 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 ff5e8e6..24d7589 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 6f26aa9..996ba77 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 ced6c30..3d423d9 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 becaf19..214d9e5 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 7ffa444..07d99b2 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 e5d011f..a41f93d 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 4ec9e9f..9aad2fe 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 d10dcce..4310d04 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 382134e..3890010 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 90991c9..01a3cac 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 e2bb0b0..10be34e 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 c636e4c..b9abaf5 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 d69b3a1..dedd9a7 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 b02c99b..1d58fcf 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 fb99e97..cabe4ea 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 4b7d39a..bc30e29 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 e147c17..bb7c1e6 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 @@ -43,12 +43,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 d60bd89..d7807df 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 b685ec3..9a670dd 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 9c42518..9852016 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 @@ -43,12 +43,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 24c4195..d89f147 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 820dfc1..54510e5 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 45307ce..29214c4 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 @@ -43,12 +43,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 7714ed2..cc0f2f2 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 @@ -44,12 +44,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 c826ffb..687167d 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 @@ -45,12 +45,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 d6bf837..54adf41 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 @@ -42,10 +42,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH AnalysisBaseDto data = GenerateFinalResult(datas, "抄表日冻结正向无功最大需量及发生时间", dataType); // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; 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 f6d698e..3180e03 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 @@ -43,10 +43,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH AnalysisBaseDto data = GenerateFinalResult(datas, "月冻结正向有功最大需量及发生时间", dataType); // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; 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 ceda00c..043ce9c 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 @@ -43,10 +43,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH AnalysisBaseDto data = GenerateFinalResult(datas, "月冻结反向有功最大需量及发生时间", dataType); // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; 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 531b234..13dfd15 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 7ed137e..bd7484b 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 @@ -49,12 +49,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 c99a894..c3bfbcf 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 @@ -48,12 +48,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 4bf1e2e..f395291 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 0c4aa75..0166d4d 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 ef77a80..eeaeb74 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 66216bc..25c96a4 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 b9103b8..e4a9ad0 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 1748a3d..c2d5d09 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 26dfcd1..66a3367 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 29fb978..5858719 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 330cf0a..e480a9b 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 3033c76..c06829d 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 b18d244..aa0077b 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 @@ -46,12 +46,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 1d1bff5..a556c5e 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 bbd8f0d..a73763e 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 19e6d2f..cd7447f 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 842496f..b2406af 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 8ce25e1..731ee4d 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 6da01d5..b7d81fb 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 33b8560..64451ad 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 @@ -47,12 +47,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 7dc7275..bec9102 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 @@ -49,12 +49,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0EH if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; 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 627b1da..19c1fa5 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 @@ -69,10 +69,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_10H ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.FocusId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.FocusAddress; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F101_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F101_Analysis.cs index 6066e26..ebea790 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F101_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F101_Analysis.cs @@ -40,10 +40,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_10H.Ammeter ItemType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}" }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F97_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F97_Analysis.cs index bab56d2..0da01ca 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F97_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F97_Analysis.cs @@ -1,5 +1,4 @@ -using DeviceDetectorNET.Parser.Device; -using GatherService.WattMeter.AnalysisData.AFN_10H; +using DeviceDetectorNET.Parser.Device; using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; @@ -47,10 +46,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_10H.Ammeter AnalysisBaseDto data = GenerateFinalResult(datas); // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn, datas[1]); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn, datas[1]); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F98_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F98_Analysis.cs index ae0512f..36d9c66 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F98_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Ammeter/AFN16_F98_Analysis.cs @@ -47,10 +47,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_10H.Ammeter }; // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn); if (deviceInfo != null) { - data.ProjectId = deviceInfo.ProjectID; + data.ProjectId = deviceInfo.ProjectId; data.DeviceId = deviceInfo.MeterId; data.DatabaseBusiID = deviceInfo.DatabaseBusiID; data.DeviceAddress = deviceInfo.MeterAddress; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Watermeter/ES190DC_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Watermeter/ES190DC_Analysis.cs index e831c9c..4c75999 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Watermeter/ES190DC_Analysis.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_10H/Watermeter/ES190DC_Analysis.cs @@ -42,12 +42,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_10H.Watermeter if (list.Count > 0) { // 查询设备信息 - DeviceInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn, list[0].DeviceAddress); + DeviceCacheInfo? deviceInfo = await _dataStorage.GetDeviceInfoAsync(input.A.Code, input.DA.Pn, list[0].DeviceAddress); if (deviceInfo != null) { list.ForEach(item => { - item.ProjectId = deviceInfo.ProjectID; + item.ProjectId = deviceInfo.ProjectId; item.DeviceId = deviceInfo.MeterId; item.DatabaseBusiID = deviceInfo.DatabaseBusiID; item.DeviceAddress = deviceInfo.MeterAddress; diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs index ea11af8..aa80d1f 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs @@ -1,36 +1,23 @@ -using Confluent.Kafka; -using FreeRedis; +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 JiShe.ServicePro.Consts; +using JiShe.ServicePro.Core; +using JiShe.ServicePro.Encrypt; +using JiShe.ServicePro.IoTDBManagement.Model; +using JiShe.ServicePro.IoTDBManagement.Options; +using JiShe.ServicePro.IoTDBManagement.SessionPools; +using JiShe.ServicePro.IoTDBManagement.TableModels; +using JiShe.ServicePro.IoTDBManagement.TreeModels; 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 IClientRPCService; using static JiShe.CollectBus.Common.Consts.T37612012PacketItemCodeConst; namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData @@ -38,13 +25,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData public class DataStorage:ITransientDependency { private readonly IGuidGenerator _guidGenerator; - private readonly IIoTDbProvider _dbProvider; + private readonly IoTDBSessionPoolProvider _dbProvider; 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, + private IRedisClient Instance { get; set; } + public DataStorage(IoTDBSessionPoolProvider dbProvider, IOptions applicationOptions, IGuidGenerator guidGenerator, ILogger logger, IMemoryCache memoryCache, IFreeRedisProvider freeRedisProvider) { _dbProvider= dbProvider; @@ -81,13 +68,13 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData /// /// /// - public async Task GetDeviceInfoAsync(string code,int pn=1,string meterAddress=null) + public async Task GetDeviceInfoAsync(string code,int pn=1,string meterAddress=null) { 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(); + 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)); @@ -101,7 +88,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData string deviceAddressKey = $"{code}:{meterAddress}"; deviceInfo = await _imemoryCache.GetOrCreateAsync(deviceAddressKey, async entry => { - List devices = await Instance.HGetAsync>(redisCacheDeviceInfoHashKey, code) ?? new List(); + 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)); @@ -155,7 +142,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{data.DeviceId}", DeviceType = $"{data.DeviceType.ToString()}", ProjectId = $"{data.ProjectId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, Timestamps = data.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity).GetDateTimeOffset().ToUnixTimeNanoseconds(), SingleMeasuring = (data.FiledName ?? string.Empty, data.DataValue ?? default) }; @@ -182,7 +169,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData ProjectId = $"{data.ProjectId}", DeviceType = $"{data.DeviceType}", DeviceId = $"{data.DeviceId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, FocusId = data.FocusId, FocusAddress = analysisBaseDto.Code, Timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(), @@ -220,7 +207,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{data.DeviceId}", DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, Timestamps = meter.Timestamps, SingleMeasuring = (IotDbFieldConst.IsSync, false) }; @@ -233,7 +220,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{data.DeviceId}", DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, Timestamps = meter.Timestamps, SingleMeasuring = (IotDbFieldConst.DatabaseBusiID, data.DatabaseBusiID) }; @@ -293,7 +280,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{item.DeviceId}", DeviceType = $"{item.DeviceType}", ProjectId = $"{item.ProjectId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, Timestamps = item.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity).GetDateTimeOffset().ToUnixTimeNanoseconds(), // TODO:这里暂时格式化15分钟数据,需要进行调整 SingleMeasuring =(item.FiledName ?? string.Empty, item.DataValue ?? default) }; @@ -319,7 +306,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData ProjectId = $"{item.ProjectId}", DeviceType = $"{item.DeviceType}", DeviceId = $"{item.DeviceId}", - DataType = IOTDBDataTypeConst.Log, // 匹配不到下发记录标记为LOG + IoTDataType = IOTDBDataTypeConst.Log, // 匹配不到下发记录标记为LOG Timestamps = DateTime.Now.CheckTimePoint().GetDateTimeOffset().ToUnixTimeNanoseconds(), DatabaseBusiID = item.DatabaseBusiID, PendingCopyReadTime = item.TimeSpan.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity), @@ -347,7 +334,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData } meterReadingTelemetryPacketInfos.Add(taskData); //如果无字段名,则不保存数据,如saveData=false 也不保存数据 - if (!string.IsNullOrWhiteSpace(item.FiledName) && item.ProjectId>0) + if (!string.IsNullOrWhiteSpace(item.FiledName) && !string.IsNullOrWhiteSpace(item.ProjectId)) { treeModelSingleMeasuringEntities.Add(meter); @@ -358,11 +345,11 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{item.DeviceId}", DeviceType = $"{item.DeviceType}", ProjectId = $"{item.ProjectId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, Timestamps = meter.Timestamps, SingleMeasuring = (IotDbFieldConst.IsSync, false) }; - if(!meterIsSyncs.Any(a=> a.DataType == meterIsSync.DataType && a.ProjectId == meterIsSync.ProjectId && a.SystemName== meterIsSync.SystemName && a.DeviceId== meterIsSync.DeviceId && a.Timestamps== meterIsSync.Timestamps)) + if(!meterIsSyncs.Any(a=> a.IoTDataType == meterIsSync.IoTDataType && a.ProjectId == meterIsSync.ProjectId && a.SystemName== meterIsSync.SystemName && a.DeviceId== meterIsSync.DeviceId && a.Timestamps== meterIsSync.Timestamps)) meterIsSyncs.Add(meterIsSync); // 数据库业务ID @@ -372,11 +359,11 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{item.DeviceId}", DeviceType = $"{item.DeviceType}", ProjectId = $"{item.ProjectId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, Timestamps = meter.Timestamps, SingleMeasuring = (IotDbFieldConst.DatabaseBusiID, item.DatabaseBusiID) }; - if (!meterDataBaseIDs.Any(a => a.DataType == meterIsSync.DataType && a.ProjectId == meterIsSync.ProjectId && a.SystemName == meterIsSync.SystemName && a.DeviceId == meterIsSync.DeviceId && a.Timestamps == meterIsSync.Timestamps)) + if (!meterDataBaseIDs.Any(a => a.IoTDataType == meterIsSync.IoTDataType && a.ProjectId == meterIsSync.ProjectId && a.SystemName == meterIsSync.SystemName && a.DeviceId == meterIsSync.DeviceId && a.Timestamps == meterIsSync.Timestamps)) meterDataBaseIDs.Add(meterIsDatabaseBusiID); } @@ -412,7 +399,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData if (!data.TimeSpan.HasValue) data.TimeSpan = analysisBaseDto.ReceivedTime; // 类型(心跳,登录,上电,掉电) - if (data.ProjectId > 0) + if (!string.IsNullOrWhiteSpace(data.ProjectId)) { long timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(); var treeData = new TreeModelSingleMeasuringEntity() @@ -421,7 +408,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{data.DeviceId}", DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", - DataType = IOTDBDataTypeConst.Status, + IoTDataType = IOTDBDataTypeConst.Status, Timestamps = timestamps, SingleMeasuring = (data.FiledName!, data.DataValue!) }; @@ -433,7 +420,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{data.DeviceId}", DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", - DataType = IOTDBDataTypeConst.Status, + IoTDataType = IOTDBDataTypeConst.Status, Timestamps = timestamps, SingleMeasuring = (IotDbFieldConst.FrameData, analysisBaseDto.ReceivedHexMessage ?? string.Empty) }; @@ -447,7 +434,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", Timestamps = timestamps, - DataType = IOTDBDataTypeConst.Status, + IoTDataType = IOTDBDataTypeConst.Status, SingleMeasuring = (IotDbFieldConst.RecordingTime, data.TimeSpan.HasValue ? data.TimeSpan.Value : DateTime.Now) }; await _dbProvider.GetSessionPool(false).InsertAsync(treeRecordingTimeData); @@ -464,7 +451,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData ProjectId = $"{data.ProjectId}", DeviceType = $"{data.DeviceType}", DeviceId = $"{data.DeviceId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, FocusId = data.FocusId, FocusAddress = analysisBaseDto.Code, Timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(), @@ -514,7 +501,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData if (!item.TimeSpan.HasValue) item.TimeSpan = analysisBaseDto.ReceivedTime; // 类型(心跳,登录,上电,掉电) - if (item.ProjectId > 0) + if (!string.IsNullOrWhiteSpace(item.ProjectId)) { long timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(); var treeData = new TreeModelSingleMeasuringEntity() @@ -523,7 +510,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceId = $"{item.DeviceId}", DeviceType = $"{item.DeviceType}", ProjectId = $"{item.ProjectId}", - DataType = IOTDBDataTypeConst.Status, + IoTDataType = IOTDBDataTypeConst.Status, Timestamps = timestamps, SingleMeasuring = (item.FiledName!, item.DataValue!) }; @@ -534,7 +521,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData SystemName = _applicationOptions.SystemType, DeviceType = $"{item.DeviceType}", ProjectId = $"{item.ProjectId}", - DataType = IOTDBDataTypeConst.Status, + IoTDataType = IOTDBDataTypeConst.Status, Timestamps = timestamps, SingleMeasuring = (IotDbFieldConst.FrameData, analysisBaseDto.ReceivedHexMessage ?? string.Empty) }; @@ -547,7 +534,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData SystemName = _applicationOptions.SystemType, DeviceType = $"{item.DeviceType}", ProjectId = $"{item.ProjectId}", - DataType = IOTDBDataTypeConst.Status, + IoTDataType = IOTDBDataTypeConst.Status, Timestamps = timestamps, SingleMeasuring = (IotDbFieldConst.RecordingTime, item.TimeSpan.HasValue ? item.TimeSpan.Value : DateTime.Now) }; @@ -566,7 +553,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData ProjectId = $"{item.ProjectId}", DeviceType = $"{item.DeviceType}", DeviceId = $"{item.DeviceId}", - DataType = analysisBaseDto.DataType, + IoTDataType = analysisBaseDto.DataType, Timestamps = DateTime.Now.GetDateTimeOffset().ToUnixTimeNanoseconds(), DatabaseBusiID = item.DatabaseBusiID, PendingCopyReadTime = item.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity), diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/GlobalUsings.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/GlobalUsings.cs new file mode 100644 index 0000000..d1b32ae --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/GlobalUsings.cs @@ -0,0 +1,9 @@ +// Global using directives + +global using System.Text; +global using Volo.Abp.Modularity; +global using JiShe.ServicePro.Enums; +global using JiShe.ServicePro.FreeRedisProvider; +global using JiShe.ServicePro.Consts; +global using JiShe.ServicePro.Core; +global using JiShe.ServicePro.ServerOptions; \ No newline at end of file diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/JiShe.CollectBus.Protocol.T37612012.csproj b/protocols/JiShe.CollectBus.Protocol.T37612012/JiShe.CollectBus.Protocol.T37612012.csproj index e83c165..ce34bdf 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/JiShe.CollectBus.Protocol.T37612012.csproj +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/JiShe.CollectBus.Protocol.T37612012.csproj @@ -1,18 +1,18 @@  - net8.0 + net9.0 enable enable - - + + + - diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs index ed82fa0..addfb17 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs @@ -1,23 +1,21 @@ using JiShe.CollectBus.Common.BuildSendDatas; -using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.Common.Models; -using JiShe.CollectBus.Enums; -using JiShe.CollectBus.IotSystems.Devices; using JiShe.CollectBus.IotSystems.MessageReceiveds; using JiShe.CollectBus.IotSystems.Protocols; -using JiShe.CollectBus.Kafka.Producer; using JiShe.CollectBus.Protocol.Abstracts; using JiShe.CollectBus.Protocol.Models; using JiShe.CollectBus.Protocol.T37612012.SendData; using JiShe.CollectBus.Protocol3761; +using JiShe.ServicePro.Kafka.Consts; +using JiShe.ServicePro.Kafka.Extensions; +using JiShe.ServicePro.Kafka.Producer; using Mapster; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using TouchSocket.Sockets; -using Volo.Abp.Domain.Repositories; namespace JiShe.CollectBus.Protocol.T37612012 { @@ -27,7 +25,6 @@ namespace JiShe.CollectBus.Protocol.T37612012 private readonly IProducerService _producerService; - private readonly IRepository _deviceRepository; private readonly ITcpService _tcpService; public readonly Dictionary T3761AFNHandlers; @@ -41,7 +38,6 @@ namespace JiShe.CollectBus.Protocol.T37612012 _logger = logger; //_logger = serviceProvider.GetRequiredService>(); _producerService = serviceProvider.GetRequiredService(); - _deviceRepository = serviceProvider.GetRequiredService>(); _tcpService = tcpService; T3761AFNHandlers = Telemetry3761PacketBuilder.T3761AFNHandlers; } @@ -94,9 +90,9 @@ namespace JiShe.CollectBus.Protocol.T37612012 /// private async Task OnTcpNormalReceived(ITcpSessionClient tcpSessionClient, TB3761 tB3761) { - //string topicName = string.Format(ProtocolConst.AFNTopicNameFormat, aFn); + //string topicName = string.Format(KafkaTopicConsts.AFNTopicNameFormat, aFn); //todo 如何确定时标?目前集中器的采集频率,都是固定,数据上报的时候,根据当前时间,往后推测出应当采集的时间点作为时标。但是如果由于网络问题,数据一直没上报的情况改怎么计算? - //await _producerBus.PublishAsync(ProtocolConst.SubscriberReceivedEventName, new MessageReceived + //await _producerBus.PublishAsync(KafkaTopicConsts.SubscriberReceivedEventName, new MessageReceived //{ // ClientId = client.Id, // ClientIp = client.IP, @@ -112,7 +108,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 return; } //TODO:根据AFN进行分流推送到kafka - string topicName = string.Format(ProtocolConst.AFNTopicNameFormat, tB3761.AFN_FC.AFN.ToString().PadLeft(2, '0')); + string topicName = string.Format(KafkaTopicConsts.AFNTopicNameFormat, tB3761.AFN_FC.AFN.ToString().PadLeft(2, '0')); tB3761.MessageId = Guid.NewGuid().ToString(); tB3761.ReceivedTime = DateTime.Now; MessageProtocolAnalysis messageReceivedAnalysis = new MessageProtocolAnalysis() @@ -127,13 +123,12 @@ namespace JiShe.CollectBus.Protocol.T37612012 Data = tB3761 }; - List topics = ProtocolConstExtensions.GetAllTopicNamesByReceived(); + List topics = KafkaTopicConstExtensions.GetAllTopicNamesByReceived(); if (topics.Contains(topicName)) await _producerService.ProduceAsync(topicName, messageReceivedAnalysis); else { _logger.LogError($"不支持的上报kafka主题:{topicName}"); - await _producerService.ProduceAsync(ProtocolConst.SubscriberReceivedEventName, messageReceivedAnalysis); } } @@ -151,15 +146,15 @@ 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) + //var DeviceCacheInfoList = await _deviceRepository.GetListAsync(a => a.Number == code); + //if (DeviceCacheInfoList != null && DeviceCacheInfoList.Count > 1) //{ // //todo 推送集中器编号重复预警 // _logger.LogError($"集中器编号:{code},存在多个集中器,请检查集中器编号是否重复"); // return; //} - //var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code); + //var entity = DeviceCacheInfoList?.FirstOrDefault(a => a.Number == code); //if (entity == null) //{ // await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online)); @@ -181,7 +176,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 MessageId = Guid.NewGuid().ToString(), ReceivedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; - //await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginReceivedEventName, messageReceivedLoginEvent); + //await _producerService.ProduceAsync(KafkaTopicConsts.SubscriberLoginReceivedEventName, messageReceivedLoginEvent); var reqParam = new ReqParameter2 { @@ -213,7 +208,7 @@ namespace JiShe.CollectBus.Protocol.T37612012 { await _tcpService.SendAsync(issuedEventMessage.ClientId, issuedEventMessage.Message); _logger.LogWarning($"集中器地址{issuedEventMessage.ClientId} 登录回复下发内容:{Convert.ToHexString(bytes)}"); - // await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginIssuedEventName, issuedEventMessage); + // await _producerService.ProduceAsync(KafkaTopicConsts.SubscriberLoginIssuedEventName, issuedEventMessage); } } @@ -230,15 +225,15 @@ 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) + //var DeviceCacheInfoList = await _deviceRepository.GetListAsync(a => a.Number == code); + //if (DeviceCacheInfoList != null && DeviceCacheInfoList.Count > 1) //{ // //todo 推送集中器编号重复预警 // _logger.LogError($"集中器编号:{code},存在多个集中器,请检查集中器编号是否重复"); // return; //} - //var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code); + //var entity = DeviceCacheInfoList?.FirstOrDefault(a => a.Number == code); //if (entity == null) //没有登录帧的设备,只有心跳帧 //{ await client.ResetIdAsync(clientId); @@ -268,7 +263,7 @@ 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(KafkaTopicConsts.SubscriberHeartbeatReceivedEventName, messageReceivedHeartbeatEvent); var reqParam = new ReqParameter2() { @@ -301,7 +296,7 @@ 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(KafkaTopicConsts.SubscriberHeartbeatIssuedEventName, issuedEventMessage); } diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/GlobalUsings.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/GlobalUsings.cs new file mode 100644 index 0000000..d1b32ae --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/GlobalUsings.cs @@ -0,0 +1,9 @@ +// Global using directives + +global using System.Text; +global using Volo.Abp.Modularity; +global using JiShe.ServicePro.Enums; +global using JiShe.ServicePro.FreeRedisProvider; +global using JiShe.ServicePro.Consts; +global using JiShe.ServicePro.Core; +global using JiShe.ServicePro.ServerOptions; \ No newline at end of file diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/JiShe.CollectBus.Protocol.T6452007.csproj b/protocols/JiShe.CollectBus.Protocol.T6452007/JiShe.CollectBus.Protocol.T6452007.csproj index e19a7e0..1876a75 100644 --- a/protocols/JiShe.CollectBus.Protocol.T6452007/JiShe.CollectBus.Protocol.T6452007.csproj +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/JiShe.CollectBus.Protocol.T6452007.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable @@ -10,8 +10,8 @@ - - + + diff --git a/protocols/JiShe.CollectBus.Protocol.Test/JiShe.CollectBus.Protocol.Test.csproj b/protocols/JiShe.CollectBus.Protocol.Test/JiShe.CollectBus.Protocol.Test.csproj index e798bdb..5eceed5 100644 --- a/protocols/JiShe.CollectBus.Protocol.Test/JiShe.CollectBus.Protocol.Test.csproj +++ b/protocols/JiShe.CollectBus.Protocol.Test/JiShe.CollectBus.Protocol.Test.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable @@ -10,8 +10,8 @@ - - + + diff --git a/protocols/JiShe.CollectBus.Protocol.Test/JiSheCollectBusTestProtocolModule.cs b/protocols/JiShe.CollectBus.Protocol.Test/JiSheCollectBusTestProtocolModule.cs index 6c3ebdc..f35b00e 100644 --- a/protocols/JiShe.CollectBus.Protocol.Test/JiSheCollectBusTestProtocolModule.cs +++ b/protocols/JiShe.CollectBus.Protocol.Test/JiSheCollectBusTestProtocolModule.cs @@ -1,5 +1,7 @@ using JiShe.CollectBus.Protocol.Interfaces; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System.Reflection; using Volo.Abp; using Volo.Abp.Modularity; diff --git a/protocols/JiShe.CollectBus.Protocol.Test/TestServer.cs b/protocols/JiShe.CollectBus.Protocol.Test/TestServer.cs new file mode 100644 index 0000000..23a8703 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.Test/TestServer.cs @@ -0,0 +1,27 @@ +using JiShe.CollectBus.Protocol.Interfaces; +using JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_00H; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Test +{ + public class TestServer: IAnalysisStrategy + { + private readonly ILogger _logger; + public TestServer (ILogger logger) + { + _logger= logger; + } + + public Task ExecuteAsync(string input, Action? result = null) + { + _logger.LogWarning("测试插件动态加载"); + return Task.FromResult(true); + } + + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Abstracts/ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol/Abstracts/ProtocolPlugin.cs index c6779e5..a9add3f 100644 --- a/protocols/JiShe.CollectBus.Protocol/Abstracts/ProtocolPlugin.cs +++ b/protocols/JiShe.CollectBus.Protocol/Abstracts/ProtocolPlugin.cs @@ -1,12 +1,10 @@ -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.FreeRedis; -using JiShe.CollectBus.IotSystems.Protocols; +using JiShe.CollectBus.IotSystems.Protocols; using JiShe.CollectBus.Protocol.Interfaces; using JiShe.CollectBus.Protocol.Models; +using JiShe.ServicePro.FreeRedisProvider; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using TouchSocket.Sockets; -using Volo.Abp.Domain.Repositories; namespace JiShe.CollectBus.Protocol.Abstracts { @@ -20,13 +18,11 @@ namespace JiShe.CollectBus.Protocol.Abstracts public const string errorData = "EE"; private readonly ILogger _logger; - private readonly IRepository _protocolInfoRepository; private readonly IFreeRedisProvider _redisProvider; public ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger) { _logger = logger; - _protocolInfoRepository = serviceProvider.GetRequiredService>(); _redisProvider = serviceProvider.GetRequiredService(); } @@ -40,10 +36,8 @@ namespace JiShe.CollectBus.Protocol.Abstracts if (Info == null) { throw new ArgumentNullException(nameof(Info)); - } + } - await _protocolInfoRepository.DeleteDirectAsync(a => a.Name == Info.Name); - await _protocolInfoRepository.InsertAsync(Info); await _redisProvider.Instance.HDelAsync($"{RedisConst.ProtocolKey}", Info.Name); await _redisProvider.Instance.HSetAsync($"{RedisConst.ProtocolKey}", Info.Name, Info); } diff --git a/protocols/JiShe.CollectBus.Protocol/GlobalUsings.cs b/protocols/JiShe.CollectBus.Protocol/GlobalUsings.cs new file mode 100644 index 0000000..b6f2092 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/GlobalUsings.cs @@ -0,0 +1,9 @@ +// Global using directives + +global using System.Text; +global using Volo.Abp.Modularity; +global using JiShe.ServicePro.Enums; +global using JiShe.ServicePro.FreeRedisProvider; +global using JiShe.ServicePro.Consts; +global using JiShe.ServicePro.Core; +global using JiShe.ServicePro.ServerOptions; diff --git a/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj b/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj index 7fead27..e9a8214 100644 --- a/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj +++ b/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable @@ -18,13 +18,14 @@ - - + + + + + - - diff --git a/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs b/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs index d51b7be..99bb314 100644 --- a/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs +++ b/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs @@ -1,9 +1,9 @@ using System.Text.RegularExpressions; using JiShe.CollectBus.Common; -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.FreeRedis; +using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.IotSystems.Protocols; using JiShe.CollectBus.Protocol.Interfaces; +using JiShe.ServicePro.FreeRedisProvider; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/services/JiShe.CollectBus.Application.Contracts/CollectBusApplicationContractsModule.cs b/services/JiShe.CollectBus.Application.Contracts/CollectBusApplicationContractsModule.cs index 932231c..9fd14ae 100644 --- a/services/JiShe.CollectBus.Application.Contracts/CollectBusApplicationContractsModule.cs +++ b/services/JiShe.CollectBus.Application.Contracts/CollectBusApplicationContractsModule.cs @@ -1,12 +1,14 @@ using Volo.Abp.Application; using Volo.Abp.Modularity; using Volo.Abp.Authorization; +using JiShe.ServicePro.IoTDBManagement; namespace JiShe.CollectBus; [DependsOn( typeof(CollectBusDomainSharedModule), typeof(AbpDddApplicationContractsModule), + typeof(IoTDBManagementApplicationContractsModule), typeof(AbpAuthorizationModule) )] public class CollectBusApplicationContractsModule : AbpModule diff --git a/services/JiShe.CollectBus.Application.Contracts/DataChannels/IDataChannelManageService.cs b/services/JiShe.CollectBus.Application.Contracts/DataChannels/IDataChannelManageService.cs index a126910..a2df329 100644 --- a/services/JiShe.CollectBus.Application.Contracts/DataChannels/IDataChannelManageService.cs +++ b/services/JiShe.CollectBus.Application.Contracts/DataChannels/IDataChannelManageService.cs @@ -1,5 +1,5 @@ using JiShe.CollectBus.IotSystems.MeterReadingRecords; -using Microsoft.AspNetCore.Mvc; +using JiShe.ServicePro.IoTDBManagement.TableModels; using System; using System.Collections.Generic; using System.Linq; diff --git a/services/JiShe.CollectBus.Application.Contracts/GlobalUsings.cs b/services/JiShe.CollectBus.Application.Contracts/GlobalUsings.cs new file mode 100644 index 0000000..6b81fc0 --- /dev/null +++ b/services/JiShe.CollectBus.Application.Contracts/GlobalUsings.cs @@ -0,0 +1,13 @@ +// Global using directives + +global using System.Text; +global using Volo.Abp.Modularity; +global using JiShe.ServicePro.Enums; +global using JiShe.ServicePro.FreeRedisProvider; +global using JiShe.ServicePro.IoTDBManagement.Options; +global using JiShe.ServicePro.IoTDBManagement.SessionPools; +global using JiShe.ServicePro.IoTDBManagement.TableModels; +global using JiShe.ServicePro.Kafka.Consts; +global using JiShe.ServicePro.Kafka.Internal; +global using JiShe.ServicePro.Consts; +global using JiShe.ServicePro.Core; \ No newline at end of file diff --git a/services/JiShe.CollectBus.Application.Contracts/JiShe.CollectBus.Application.Contracts.csproj b/services/JiShe.CollectBus.Application.Contracts/JiShe.CollectBus.Application.Contracts.csproj index fedbafd..11df2da 100644 --- a/services/JiShe.CollectBus.Application.Contracts/JiShe.CollectBus.Application.Contracts.csproj +++ b/services/JiShe.CollectBus.Application.Contracts/JiShe.CollectBus.Application.Contracts.csproj @@ -3,7 +3,7 @@ - net8.0 + net9.0 enable JiShe.CollectBus True @@ -21,12 +21,15 @@ - - - + + + + + + + - diff --git a/services/JiShe.CollectBus.Application.Contracts/Permissions/CollectBusPermissions.cs b/services/JiShe.CollectBus.Application.Contracts/Permissions/CollectBusPermissions.cs index 7d71651..d6d633a 100644 --- a/services/JiShe.CollectBus.Application.Contracts/Permissions/CollectBusPermissions.cs +++ b/services/JiShe.CollectBus.Application.Contracts/Permissions/CollectBusPermissions.cs @@ -8,6 +8,6 @@ public class CollectBusPermissions public static string[] GetAll() { - return ReflectionHelper.GetPublicConstantsRecursively(typeof(CollectBusPermissions)); + return Volo.Abp.Reflection.ReflectionHelper.GetPublicConstantsRecursively(typeof(CollectBusPermissions)); } } diff --git a/services/JiShe.CollectBus.Application.Contracts/RedisDataCache/IRedisDataCacheService.cs b/services/JiShe.CollectBus.Application.Contracts/RedisDataCache/IRedisDataCacheService.cs deleted file mode 100644 index e28417b..0000000 --- a/services/JiShe.CollectBus.Application.Contracts/RedisDataCache/IRedisDataCacheService.cs +++ /dev/null @@ -1,174 +0,0 @@ -using JiShe.CollectBus.Common.Models; -using JiShe.CollectBus.IotSystems.Ammeters; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Application.Contracts -{ - /// - /// 数据缓存服务接口 - /// - public interface IRedisDataCacheService - { - /// - /// 单个添加数据 - /// - /// - /// Set索引缓存Key - /// hash缓存Key - /// 待缓存数据 - /// - Task InsertDataAsync( - string redisSetIndexCacheKey, - string redisDeviceInfoHashCacheKey, - T data) where T : DeviceCacheBasicModel; - - - /// - /// 批量添加数据 - /// - /// - /// Set索引缓存Key - /// hash缓存Key - /// 待缓存数据集合 - /// - Task BatchInsertDataAsync( - string redisSetIndexCacheKey, - string redisDeviceInfoHashCacheKey, - Dictionary> items) where T : DeviceCacheBasicModel; - - - /// - /// 删除缓存信息 - /// - /// - /// Set索引缓存Key - /// hash缓存Key - /// 已缓存数据 - /// - Task RemoveCacheDataAsync( - string redisSetIndexCacheKey, - string redisDeviceInfoHashCacheKey, - T data) where T : DeviceCacheBasicModel; - - /// - /// 修改缓存信息,映射关系未发生改变 - /// - /// - /// 主数据存储Hash缓存Key - /// Set索引缓存Key - /// ZSET索引缓存Key - /// 待修改缓存数据 - /// - Task ModifyDataAsync( - string redisHashCacheKey, - string redisSetIndexCacheKey, - string redisZSetScoresIndexCacheKey, - T newData) where T : DeviceCacheBasicModel; - - - /// - /// 修改缓存信息,映射关系已改变 - /// - /// - /// 主数据存储Hash缓存Key - /// Set索引缓存Key - /// 旧的映射关系 - /// ZSET索引缓存Key - /// 待修改缓存数据 - /// - Task ModifyDataAsync( - string redisHashCacheKey, - string redisSetIndexCacheKey, - string oldMemberId, - 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 - /// ZSET索引的原始数据,例如集中地址和点位的组合 - /// 分页尺寸 - /// 最后一个索引 - /// 最后一个唯一标识 - /// 排序方式 - /// - Task> GetSingleData( - string redisHashCacheKey, - string redisZSetScoresIndexCacheKey, - string scoreValueRawData, - int pageSize = 10, - decimal? lastScore = null, - string lastMember = null, - bool descending = true) - where T : DeviceCacheBasicModel; - - - /// - /// 通过ZSET索引获取数据,支持10万级别数据处理,控制在13秒以内。 - /// - /// - /// 主数据存储Hash缓存Key - /// ZSET索引缓存Key - /// 分页尺寸 - /// 最后一个索引 - /// 最后一个唯一标识 - /// 排序方式 - /// - Task> GetAllPagedData( - string redisHashCacheKey, - string redisZSetScoresIndexCacheKey, - int pageSize = 1000, - decimal? lastScore = null, - string lastMember = null, - bool descending = true) - where T : DeviceCacheBasicModel; - - /// - /// 通过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/ScheduledMeterReading/IScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs index b82feab..4173f76 100644 --- a/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs @@ -7,6 +7,8 @@ using JiShe.CollectBus.IotSystems.Ammeters; using JiShe.CollectBus.IotSystems.Devices; using JiShe.CollectBus.IotSystems.MeterReadingRecords; using JiShe.CollectBus.IotSystems.Watermeter; +using JiShe.ServicePro.FreeRedisProvider; +using JiShe.ServicePro.IoTDBManagement.TableModels; using Volo.Abp.Application.Services; namespace JiShe.CollectBus.ScheduledMeterReading @@ -35,7 +37,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// /// 采集端Code /// - Task> GetAmmeterInfoList(string gatherCode = ""); + Task> GetAmmeterInfoList(string gatherCode = ""); /// /// 初始化电表缓存数据 @@ -44,23 +46,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// Task InitAmmeterCacheData(string gatherCode = ""); - /// - /// 1分钟采集电表数据,只获取任务数据下发,不构建任务 - /// - /// - Task AmmeterScheduledMeterOneMinuteReading(); - - /// - /// 5分钟采集电表数据,只获取任务数据下发,不构建任务 - /// - /// - Task AmmeterScheduledMeterFiveMinuteReading(); - - /// - /// 15分钟采集电表数据,只获取任务数据下发,不构建任务 - /// - /// - Task AmmeterScheduledMeterFifteenMinuteReading(); + /// /// 获取电表阀控配置 @@ -83,7 +69,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - Task> AmmeterScheduledAutomaticVerificationTime(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); + Task> AmmeterScheduledAutomaticVerificationTime(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps); /// /// 日冻结抄读 @@ -93,7 +79,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - Task> AmmeterScheduledGetAutomaticDayFreezeData(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); + Task> AmmeterScheduledGetAutomaticDayFreezeData(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps); /// /// 月冻结数据抄读 @@ -103,7 +89,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - Task> AmmeterScheduledGetAutomaticMonthFreezeData(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); + Task> AmmeterScheduledGetAutomaticMonthFreezeData(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps); #endregion @@ -113,7 +99,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// /// 采集端Code /// - Task> GetWatermeterInfoList(string gatherCode = ""); + Task> GetWatermeterInfoList(string gatherCode = ""); /// /// 初始化水表缓存数据,只获取任务数据下发,不构建任务 @@ -122,12 +108,6 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// Task InitWatermeterCacheData(string gatherCode = ""); - /// - /// 水表数据采集 - /// - /// - Task WatermeterScheduledMeterAutoReadding(); - #endregion #region 集中器处理 @@ -140,7 +120,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - Task> ConcentratorScheduledAutomaticGetTerminalVersion(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); + Task> ConcentratorScheduledAutomaticGetTerminalVersion(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps); /// /// 自动获取远程通信模块(SIM)版本信息 @@ -150,7 +130,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - Task> ConcentratorScheduledAutomaticGetTelematicsModule(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps); + Task> ConcentratorScheduledAutomaticGetTelematicsModule(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps); #endregion diff --git a/services/JiShe.CollectBus.Application.Contracts/Subscribers/IServiceCommunicationChannelSubscriberService.cs b/services/JiShe.CollectBus.Application.Contracts/Subscribers/IServiceCommunicationChannelSubscriberService.cs new file mode 100644 index 0000000..fc448b9 --- /dev/null +++ b/services/JiShe.CollectBus.Application.Contracts/Subscribers/IServiceCommunicationChannelSubscriberService.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace JiShe.CollectBus.Subscribers +{ + /// + /// 数据通讯通道订阅者服务 + /// + public interface IServiceCommunicationChannelSubscriberService:IApplicationService + { + /// + /// 数据通讯通道消息消费订阅 + /// + /// + /// + Task ServiceCommunicationChannelIssuedEvent(Dictionary issuedMessage); + } +} diff --git a/services/JiShe.CollectBus.Application.Contracts/Subscribers/ISubscriberAppService.cs b/services/JiShe.CollectBus.Application.Contracts/Subscribers/ISubscriberAppService.cs index 63594c8..1f227fa 100644 --- a/services/JiShe.CollectBus.Application.Contracts/Subscribers/ISubscriberAppService.cs +++ b/services/JiShe.CollectBus.Application.Contracts/Subscribers/ISubscriberAppService.cs @@ -1,9 +1,6 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using JiShe.CollectBus.Common.Models; +using JiShe.CollectBus.Common.Models; using JiShe.CollectBus.IotSystems.MessageReceiveds; -using JiShe.CollectBus.Kafka.Internal; -using JiShe.CollectBus.Protocol3761; +using JiShe.ServicePro.Kafka.Internal; using Volo.Abp.Application.Services; namespace JiShe.CollectBus.Subscribers @@ -12,7 +9,6 @@ namespace JiShe.CollectBus.Subscribers { Task LoginIssuedEvent(List issuedEventMessage); Task HeartbeatIssuedEvent(List issuedEventMessage); - Task ReceivedEvent(MessageProtocolAnalysis receivedMessage); Task ReceivedHeartbeatEvent(List receivedHeartbeatMessage); Task ReceivedLoginEvent(List receivedLoginMessage); } diff --git a/services/JiShe.CollectBus.Application.Contracts/Subscribers/IWorkerSubscriberAppService.cs b/services/JiShe.CollectBus.Application.Contracts/Subscribers/IWorkerSubscriberAppService.cs index e899ce4..7ab7f03 100644 --- a/services/JiShe.CollectBus.Application.Contracts/Subscribers/IWorkerSubscriberAppService.cs +++ b/services/JiShe.CollectBus.Application.Contracts/Subscribers/IWorkerSubscriberAppService.cs @@ -1,11 +1,5 @@ -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; +using JiShe.ServicePro.IoTDBManagement.TableModels; +using JiShe.ServicePro.Kafka.Internal; using Volo.Abp.Application.Services; namespace JiShe.CollectBus.Subscribers diff --git a/services/JiShe.CollectBus.Application/CollectBusAppService.cs b/services/JiShe.CollectBus.Application/CollectBusAppService.cs index bd4a232..c2e621a 100644 --- a/services/JiShe.CollectBus.Application/CollectBusAppService.cs +++ b/services/JiShe.CollectBus.Application/CollectBusAppService.cs @@ -1,17 +1,8 @@ -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Common.Helpers; -using JiShe.CollectBus.FreeSql; -using JiShe.CollectBus.Localization; +using JiShe.CollectBus.Localization; +using JiShe.ServicePro.FreeRedisProvider; +using JiShe.ServicePro.FreeSqlProvider; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using JiShe.CollectBus.FreeRedis; using Volo.Abp.Application.Services; -using Volo.Abp.Timing; namespace JiShe.CollectBus; diff --git a/services/JiShe.CollectBus.Application/CollectBusApplicationModule.cs b/services/JiShe.CollectBus.Application/CollectBusApplicationModule.cs index 942befc..5a9f7a2 100644 --- a/services/JiShe.CollectBus.Application/CollectBusApplicationModule.cs +++ b/services/JiShe.CollectBus.Application/CollectBusApplicationModule.cs @@ -1,30 +1,20 @@ -using Cassandra.Mapping; -using JiShe.CollectBus.Cassandra; -using JiShe.CollectBus.DataChannels; -using JiShe.CollectBus.FreeRedis; -using JiShe.CollectBus.FreeSql; +using JiShe.CollectBus.DataChannels; 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.ScheduledMeterReading; +using JiShe.CollectBus.Workers; +using JiShe.ServicePro.FreeRedisProvider; +using JiShe.ServicePro.FreeSqlProvider; +using JiShe.ServicePro.IoTDBManagement; +using JiShe.ServicePro.IoTDBManagement.TableModels; +using JiShe.ServicePro.Kafka; 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.AuditLogging; using Volo.Abp.Autofac; using Volo.Abp.AutoMapper; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.BackgroundWorkers; -using Volo.Abp.BackgroundWorkers.Hangfire; using Volo.Abp.Modularity; namespace JiShe.CollectBus; @@ -34,16 +24,12 @@ namespace JiShe.CollectBus; typeof(CollectBusApplicationContractsModule), typeof(AbpDddApplicationModule), typeof(AbpAutoMapperModule), + typeof(ServiceProFreeRedisProviderModule), + typeof(ServiceProFreeSqlProviderModule), + typeof(ServiceProKafkaModule), + typeof(IoTDBManagementApplicationModule), typeof(AbpAutofacModule), - typeof(AbpBackgroundWorkersHangfireModule), - typeof(CollectBusFreeRedisModule), - typeof(CollectBusFreeSqlModule), - typeof(CollectBusKafkaModule), - typeof(CollectBusIoTDbModule), typeof(CollectBusDomainSharedModule), - typeof(AbpAuditLoggingDomainModule), - typeof(AbpBackgroundJobsDomainModule), - typeof(CollectBusCassandraModule), typeof(CollectBusProtocolModule) )] public class CollectBusApplicationModule : AbpModule @@ -55,8 +41,10 @@ public class CollectBusApplicationModule : AbpModule context.Services.AddAutoMapperObjectMapper(); Configure(options => { options.AddMaps(true); }); - context.Services.AddSingleton(new MappingConfiguration() - .Define(new CollectBusMapping())); + context.Services.AddHostedService(); + + //context.Services.AddSingleton(new MappingConfiguration() + // .Define(new CollectBusMapping())); // 注册拦截器 context.Services.OnRegistered(ctx => @@ -65,38 +53,17 @@ public class CollectBusApplicationModule : AbpModule var any = methods.Any(a => a.GetCustomAttribute() != null); if (any) ctx.Interceptors.TryAdd(); }); + } 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("V4-Gather-8890"); diff --git a/services/JiShe.CollectBus.Application/DataChannels/DataChannelManage.cs b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManage.cs index 6130a25..1eb8c4c 100644 --- a/services/JiShe.CollectBus.Application/DataChannels/DataChannelManage.cs +++ b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManage.cs @@ -1,5 +1,6 @@ using JiShe.CollectBus.IotSystems.MeterReadingRecords; using JiShe.CollectBus.Protocol.Dto; +using JiShe.ServicePro.IoTDBManagement.TableModels; using System; using System.Collections.Generic; using System.Linq; diff --git a/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs index 5fe49f2..c45c242 100644 --- a/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs +++ b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs @@ -1,29 +1,10 @@ -using Amazon.Runtime.Internal.Transform; -using DnsClient.Protocol; -using JiShe.CollectBus.Common; +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; -using ZstdSharp; namespace JiShe.CollectBus.DataChannels { @@ -33,26 +14,23 @@ namespace JiShe.CollectBus.DataChannels public class DataChannelManageService : IDataChannelManageService, ITransientDependency { private readonly ILogger _logger; - private readonly IIoTDbProvider _dbProvider; + private readonly IoTDBSessionPoolProvider _dbProvider; private readonly IProducerService _producerService; private readonly KafkaOptionConfig _kafkaOptions; - private readonly ServerApplicationOptions _applicationOptions; - private readonly ILogRecordRepository _logRecordRepository; + private readonly ServerApplicationOptions _applicationOptions; public DataChannelManageService( ILogger logger, - IIoTDbProvider dbProvider, + IoTDBSessionPoolProvider dbProvider, IProducerService producerService, IOptions kafkaOptions, - IOptions applicationOptions, - ILogRecordRepository logRecordRepository) + IOptions applicationOptions) { _logger = logger; _dbProvider = dbProvider; _producerService = producerService; _kafkaOptions = kafkaOptions.Value; - _applicationOptions = applicationOptions.Value; - _logRecordRepository= logRecordRepository; + _applicationOptions = applicationOptions.Value; } /// @@ -204,131 +182,6 @@ namespace JiShe.CollectBus.DataChannels 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/EnergySystem/CacheAppService.cs b/services/JiShe.CollectBus.Application/EnergySystem/CacheAppService.cs index 6e2034a..b8f5ca0 100644 --- a/services/JiShe.CollectBus.Application/EnergySystem/CacheAppService.cs +++ b/services/JiShe.CollectBus.Application/EnergySystem/CacheAppService.cs @@ -1,18 +1,4 @@ -using JiShe.CollectBus.IotSystems.Records; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.EnergySystems.TableViews; -using JiShe.CollectBus.FreeSql; -using Volo.Abp.Domain.Repositories; -using JiShe.CollectBus.IotSystems.PrepayModel; -using JiShe.CollectBus.Ammeters; -using JiShe.CollectBus.Common.BuildSendDatas; -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.EnergySystems.TableViews; namespace JiShe.CollectBus.EnergySystem { diff --git a/services/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs b/services/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs index 19a1296..305162f 100644 --- a/services/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs +++ b/services/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs @@ -1,26 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using DeviceDetectorNET.Class.Device; -using JiShe.CollectBus.Common.BuildSendDatas; -using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.Common.BuildSendDatas; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.Common.Models; using JiShe.CollectBus.EnergySystem.Dto; -using JiShe.CollectBus.FreeSql; using JiShe.CollectBus.IotSystems.PrepayModel; using JiShe.CollectBus.IotSystems.Records; -using JiShe.CollectBus.Kafka.Producer; -using JiShe.CollectBus.Protocol.Contracts; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Volo.Abp.Domain.Repositories; -using YamlDotNet.Core; namespace JiShe.CollectBus.EnergySystem { @@ -71,7 +58,7 @@ namespace JiShe.CollectBus.EnergySystem if (bytes == null) return result; - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -80,7 +67,7 @@ namespace JiShe.CollectBus.EnergySystem // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -117,7 +104,7 @@ namespace JiShe.CollectBus.EnergySystem foreach (var bytes in bytesList) { - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -126,7 +113,7 @@ namespace JiShe.CollectBus.EnergySystem // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -168,7 +155,7 @@ namespace JiShe.CollectBus.EnergySystem }).ToList(); var bytes = Build3761SendData.BuildAmmeterParameterSetSendCmd(address, meterParameters); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -176,7 +163,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -206,7 +193,7 @@ namespace JiShe.CollectBus.EnergySystem var dataUnit = Build645SendData.BuildReadMeterAddressSendDataUnit(detail.MeterAddress); var bytes =Build3761SendData.BuildTransparentForwardingSendCmd(address, detail.Port, detail.BaudRate.ToString(), dataUnit, StopBit.Stop1, Parity.None); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -214,7 +201,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -297,7 +284,7 @@ namespace JiShe.CollectBus.EnergySystem if (bytes != null) { - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -306,7 +293,7 @@ namespace JiShe.CollectBus.EnergySystem // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -365,7 +352,7 @@ namespace JiShe.CollectBus.EnergySystem var bytes = Build3761SendData.BuildCommunicationParametersSetSendCmd(address, masterIP, materPort, backupIP, backupPort, input.Data.APN); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -374,7 +361,7 @@ namespace JiShe.CollectBus.EnergySystem // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -402,7 +389,7 @@ namespace JiShe.CollectBus.EnergySystem var bytes = Build3761SendData.BuildTerminalCalendarClockSendCmd(address); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -410,7 +397,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -438,7 +425,7 @@ namespace JiShe.CollectBus.EnergySystem bool isManual = !input.AreaCode.Equals("5110");//低功耗集中器不是长连接,在连接的那一刻再发送 var bytes = Build3761SendData.BuildConrCheckTimeSendCmd(address,DateTime.Now, isManual); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -446,7 +433,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -473,7 +460,7 @@ namespace JiShe.CollectBus.EnergySystem var address = $"{input.AreaCode}{input.Address}"; var bytes = Build3761SendData.BuildConrRebootSendCmd(address); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -481,7 +468,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -509,7 +496,7 @@ namespace JiShe.CollectBus.EnergySystem var address = $"{input.AreaCode}{input.Address}"; var pnList = input.Data.Split(',').Select(it => int.Parse(it)).ToList(); var bytes = Build3761SendData.BuildAmmeterParameterReadingSendCmd(address, pnList); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -517,7 +504,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -566,7 +553,7 @@ namespace JiShe.CollectBus.EnergySystem foreach (var bytes in bytesList) { - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -575,7 +562,7 @@ namespace JiShe.CollectBus.EnergySystem // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -644,7 +631,7 @@ namespace JiShe.CollectBus.EnergySystem foreach (var bytes in bytesList) { - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -652,7 +639,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -681,7 +668,7 @@ namespace JiShe.CollectBus.EnergySystem var address = $"{code.AreaCode}{code.Address}"; var bytes = Build3761SendData.BuildAmmeterReportCollectionItemsSetSendCmd(address,input.Detail.Pn, input.Detail.Unit,input.Detail.Cycle,input.Detail.BaseTime, input.Detail.CurveRatio,input.Detail.Details.Select(it => new PnFn(it.Pn,it.Fn)).ToList()); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -689,7 +676,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -717,7 +704,7 @@ namespace JiShe.CollectBus.EnergySystem { var address = $"{code.AreaCode}{code.Address}"; var bytes = Build3761SendData.BuildAmmeterAutoUpSwitchSetSendCmd(address, input.Detail.Pn,input.Detail.IsOpen); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -725,7 +712,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -751,7 +738,7 @@ namespace JiShe.CollectBus.EnergySystem var result = new BaseResultDto(); var address = $"{input.AreaCode}{input.Address}"; var bytes = Build3761SendData.BuildAmmeterReadAutoUpSwitchSendCmd(address, input.Detail.Pn); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -759,7 +746,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -786,7 +773,7 @@ namespace JiShe.CollectBus.EnergySystem { var address = $"{data.AreaCode}{data.Address}"; var bytes = Build3761SendData.BuildTerminalVersionInfoReadingSendCmd(address); - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -794,7 +781,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, @@ -849,7 +836,7 @@ namespace JiShe.CollectBus.EnergySystem foreach (var bytes in bytesList) { - //await _capBus.PublishAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + //await _capBus.PublishAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage //{ // //ClientId = messageReceived.ClientId, // DeviceNo = address, @@ -857,7 +844,7 @@ namespace JiShe.CollectBus.EnergySystem // Type = IssuedEventType.Data, // MessageId = Guid.NewGuid().ToString() //}); - await _producerService.ProduceAsync(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage + await _producerService.ProduceAsync(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, DeviceNo = address, diff --git a/services/JiShe.CollectBus.Application/GlobalUsings.cs b/services/JiShe.CollectBus.Application/GlobalUsings.cs new file mode 100644 index 0000000..4c0d3a4 --- /dev/null +++ b/services/JiShe.CollectBus.Application/GlobalUsings.cs @@ -0,0 +1,17 @@ +// Global using directives + +global using System.Text; +global using Volo.Abp.Modularity; +global using JiShe.ServicePro.Enums; +global using JiShe.ServicePro.FreeRedisProvider; +global using JiShe.ServicePro.IoTDBManagement.Options; +global using JiShe.ServicePro.IoTDBManagement.SessionPools; +global using JiShe.ServicePro.IoTDBManagement.TableModels; +global using JiShe.ServicePro.Kafka.Consts; +global using JiShe.ServicePro.Kafka.Internal; +global using JiShe.ServicePro.Kafka.Attributes; +global using JiShe.ServicePro.FreeSqlProvider; +global using JiShe.ServicePro.Kafka.Producer; +global using JiShe.ServicePro.Consts; +global using JiShe.ServicePro.Core; +global using JiShe.ServicePro.ServerOptions; diff --git a/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj b/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj index 01878c2..96ad2e7 100644 --- a/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj +++ b/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj @@ -3,34 +3,37 @@ - net8.0 + net9.0 enable JiShe.CollectBus True + + + + + + - - - - - - - - + + + + + + + + + + + - - - - - - diff --git a/services/JiShe.CollectBus.Application/Mappers/CollectBusMapping.cs b/services/JiShe.CollectBus.Application/Mappers/CollectBusMapping.cs deleted file mode 100644 index a4d4ef4..0000000 --- a/services/JiShe.CollectBus.Application/Mappers/CollectBusMapping.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Cassandra.Mapping; -using JiShe.CollectBus.IotSystems.Devices; -using JiShe.CollectBus.IotSystems.MessageIssueds; - -namespace JiShe.CollectBus.Mappers -{ - public class CollectBusMapping: Mappings - { - public CollectBusMapping() - { - For() - .Column(e => e.Type, cm => cm.WithName("type").WithDbType()); - For() - .Column(e => e.Status, cm => cm.WithName("status").WithDbType()); - } - } -} diff --git a/services/JiShe.CollectBus.Application/Plugins/TcpMonitor.cs b/services/JiShe.CollectBus.Application/Plugins/TcpMonitor.cs index 0e92ff6..f84dd55 100644 --- a/services/JiShe.CollectBus.Application/Plugins/TcpMonitor.cs +++ b/services/JiShe.CollectBus.Application/Plugins/TcpMonitor.cs @@ -1,13 +1,11 @@ using JiShe.CollectBus.Common; +using JiShe.CollectBus.Common.Enums; 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; using TouchSocket.Sockets; using Volo.Abp.Caching; @@ -20,37 +18,37 @@ namespace JiShe.CollectBus.Plugins { private readonly IProducerService _producerService; private readonly ILogger _logger; - private readonly IRepository _deviceRepository; private readonly IDistributedCache _ammeterInfoCache; private readonly IServiceProvider _serviceProvider; private readonly IProtocolService _protocolService; private readonly ServerApplicationOptions _serverApplicationOptions; + private readonly IFreeRedisProvider _freeRedisProvider; /// /// /// /// /// - /// /// /// /// /// + /// public TcpMonitor(IProducerService producerService, ILogger logger, - IRepository deviceRepository, IDistributedCache ammeterInfoCache, IServiceProvider serviceProvider, IOptions serverApplicationOptions, - IProtocolService protocolService) + IProtocolService protocolService, + IFreeRedisProvider freeRedisProvider) { _producerService = producerService; _logger = logger; - _deviceRepository = deviceRepository; _ammeterInfoCache = ammeterInfoCache; _serviceProvider= serviceProvider; _protocolService = protocolService; _serverApplicationOptions = serverApplicationOptions.Value; + _freeRedisProvider = freeRedisProvider; } public async Task OnTcpReceived(ITcpSession client, ReceivedDataEventArgs e) @@ -74,6 +72,61 @@ namespace JiShe.CollectBus.Plugins _logger.LogError($"指令初步解析失败,指令内容:{messageHexString}"); } + ////登录和心跳的时候,需要过滤TCP连接 + //if (tB3761.DT?.Fn == (int)FN.登录 || tB3761.DT?.Fn == (int)FN.心跳) + //{ + // string focusAddress = tB3761.A.Code; + // if (string.IsNullOrWhiteSpace(focusAddress))//集中器地址为空,主动关闭连接 + // { + // await tcpSessionClient.CloseAsync(); + // _logger.LogError($"指令解析失败,没有找到集中器地址,指令内容:{messageHexString}"); + // return; + // } + + // //查找Redis缓存的集中器信息 + // var focusCacheInfos = _freeRedisProvider.Instance.HGet(RedisConst.CacheAllFocusInfoHashKey, focusAddress); + // if (focusCacheInfos == null) + // { + // await tcpSessionClient.CloseAsync(); + // _logger.LogError($"TCP连接关闭,没有找到集中器地址{focusAddress}的缓存信息"); + // return; + // } + + // //检查集中器的信息的服务器标记是否为空,如果不为空,需要检查是否与当前服务器的标记一致 + // if (!string.IsNullOrWhiteSpace(focusCacheInfos.ServerTagName) && focusCacheInfos.ServerTagName != _serverApplicationOptions.ServerTagName) + // { + // await tcpSessionClient.CloseAsync(); + // _logger.LogError($"TCP连接关闭,集中器地址{focusAddress}的服务器标记为:{focusCacheInfos.ServerTagName},当前服务器的标记为:{_serverApplicationOptions.ServerTagName},不一致拒绝连接。"); + // return; + // } + + // int currentTCPConnectionCount = tcpSessionClient.Service.Count; + // int configTCPConnectionCount = _serverApplicationOptions.TCPConnectionCount;//配置TCP连接数量 + + // _logger.LogWarning($"当前配置连接数量为:{configTCPConnectionCount},当前连接数量为:{currentTCPConnectionCount}"); + + // if (currentTCPConnectionCount >= configTCPConnectionCount) + // { + // _logger.LogError($"当前连接数量为:{currentTCPConnectionCount},大于配置连接数量{configTCPConnectionCount},将拒绝集中{focusAddress}连接"); + // await tcpSessionClient.CloseAsync(); + // return; + // } + + // //缓存更新状态 + // focusCacheInfos.LastSurvivalTime = DateTime.Now; + // focusCacheInfos.ServerTagName = _serverApplicationOptions.ServerTagName; + // focusCacheInfos.OnLineStatus = true; + + // _freeRedisProvider.Instance.HSet(RedisConst.CacheAllFocusInfoHashKey, focusAddress, focusCacheInfos); + + // //连接成功以后,通知信息到后台 + // Dictionary channelMessage = new Dictionary(); + // channelMessage.Add(ServiceCommunicationTypeEnum.FocusStatusReceived, focusCacheInfos.Serialize()); + // _= _producerService.ProduceAsync(KafkaTopicConsts.ServiceCommunicationChannelTopic, channelMessage); + //} + + //todo 后续可以考虑Redis的bitmap做日活签到。 + // TODO:要注意保存树模型的时时标字段,如果没有时标,则取接受时间做兼容 await e.InvokeNext(); } @@ -97,21 +150,23 @@ namespace JiShe.CollectBus.Plugins } 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 tcpSessionClient = (ITcpSessionClient)client; _logger.LogWarning($"[TCP] ID:{tcpSessionClient.Id} IP:{client.GetIPPort()}已关闭连接"); + //查找Redis缓存的集中器信息 + var focusCacheInfos = _freeRedisProvider.Instance.HGet(RedisConst.CacheAllFocusInfoHashKey, tcpSessionClient.Id); + if (focusCacheInfos != null) + { + + //缓存更新状态 + focusCacheInfos.LastSurvivalTime = DateTime.Now; + focusCacheInfos.ServerTagName = _serverApplicationOptions.ServerTagName; + focusCacheInfos.OnLineStatus = false; + + _freeRedisProvider.Instance.HSet(RedisConst.CacheAllFocusInfoHashKey, tcpSessionClient.Id, focusCacheInfos); + } + await e.InvokeNext(); } diff --git a/services/JiShe.CollectBus.Application/RedisDataCache/RedisDataCacheService.cs b/services/JiShe.CollectBus.Application/RedisDataCache/RedisDataCacheService.cs deleted file mode 100644 index c59fb4f..0000000 --- a/services/JiShe.CollectBus.Application/RedisDataCache/RedisDataCacheService.cs +++ /dev/null @@ -1,994 +0,0 @@ -using Confluent.Kafka; -using FreeRedis; -using JiShe.CollectBus.Application.Contracts; -using JiShe.CollectBus.Common.Extensions; -using JiShe.CollectBus.Common.Helpers; -using JiShe.CollectBus.Common.Models; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using JiShe.CollectBus.FreeRedis; -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; -using System.IO.Pipelines; - -namespace JiShe.CollectBus.RedisDataCache -{ - /// - /// 数据缓存服务接口 - /// - public class RedisDataCacheService : IRedisDataCacheService, ITransientDependency - { - private readonly IFreeRedisProvider _freeRedisProvider; - private readonly ILogger _logger; - private RedisClient Instance { get; set; } - - /// - /// 数据缓存服务接口 - /// - /// - /// - public RedisDataCacheService(IFreeRedisProvider freeRedisProvider, - ILogger logger) - { - this._freeRedisProvider = freeRedisProvider; - this._logger = logger; - - Instance = _freeRedisProvider.Instance; - } - - /// - /// 单个添加数据 - /// - /// - /// Set索引缓存Key - /// hash缓存Key - /// 待缓存数据 - /// - public async Task InsertDataAsync( - string redisSetIndexCacheKey, - string redisDeviceInfoHashCacheKey, - T data) where T : DeviceCacheBasicModel - { - // 参数校验增强 - if (data == null || string.IsNullOrWhiteSpace(redisSetIndexCacheKey) - || string.IsNullOrWhiteSpace(redisDeviceInfoHashCacheKey)) - { - _logger.LogError($"{nameof(InsertDataAsync)} 参数异常,-101"); - return; - } - - // 使用事务保证原子性 - using (var trans = Instance.Multi()) - { - // Set索引缓存 - trans.SAdd(redisSetIndexCacheKey, $"{data.TimeDensity.ToString().PadLeft(2, '0')}:{data.FocusAddress}"); - - //检查HSet是否存在对应的信息,如果存在,需要进一步检查value是否已经存在,如果存在则更新,不存在则添加 - var oldValue = Instance.HGet>(redisDeviceInfoHashCacheKey, data.FocusAddress); - if (oldValue == null || oldValue.Count <= 0)//直接添加 - { - //设备信息缓存 - trans.HSet(redisDeviceInfoHashCacheKey, data.FocusAddress, data); - } - else - { - // 移除缓存中同类型旧数据 - oldValue.RemoveAll(device => device.MeterType == data.MeterType); - - //添加新数据 - oldValue.Add(data); - - //设备信息缓存 - trans.HSet(redisDeviceInfoHashCacheKey, data.FocusAddress, oldValue); - } - - var results = trans.Exec(); - - if (results == null || results.Length <= 0) - { - _logger.LogError($"{nameof(InsertDataAsync)} 添加事务提交失败,-102"); - } - } - - await Task.CompletedTask; - } - - /// - /// 批量添加数据 - /// - /// - /// Set索引缓存Key - /// hash缓存Key - /// 待缓存数据集合 - /// - public async Task BatchInsertDataAsync( - string redisSetIndexCacheKey, - string redisDeviceInfoHashCacheKey, - Dictionary> items) where T : DeviceCacheBasicModel - { - if (items == null - || items.Count() <= 0 - || string.IsNullOrWhiteSpace(redisSetIndexCacheKey) - || string.IsNullOrWhiteSpace(redisDeviceInfoHashCacheKey) - ) - { - _logger.LogError($"{nameof(BatchInsertDataAsync)} 参数异常,-101"); - return; - } - - 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) - { - // Set索引缓存 - pipe.SAdd(redisSetIndexCacheKey, $"{item.Value.First().TimeDensity.ToString().PadLeft(2, '0')}:{item.Value.First().FocusAddress}"); - - //检查HSet是否存在对应的信息,如果存在,需要进一步检查value是否已经存在,如果存在则更新,不存在则添加 - var oldValue = Instance.HGet>(redisDeviceInfoHashCacheKey, item.Key); - if (oldValue == null || oldValue.Count <= 0)//直接添加 - { - //设备信息缓存 - pipe.HSet(redisDeviceInfoHashCacheKey, item.Key, item.Value); - } - else - { - // 移除缓存中同类型旧数据 - oldValue.RemoveAll(device => device.MeterType == item.Value[0].MeterType); - - //添加新数据 - oldValue.AddRange(item.Value); - - //设备信息缓存 - pipe.HSet(redisDeviceInfoHashCacheKey, item.Key, oldValue); - } - } - pipe.EndPipe(); - } - semaphore.Release(); - }); - } - - await Task.CompletedTask; - } - - /// - /// 删除缓存信息 - /// - /// - /// Set索引缓存Key - /// hash缓存Key - /// 已缓存数据 - /// - public async Task RemoveCacheDataAsync( - string redisSetIndexCacheKey, - string redisDeviceInfoHashCacheKey, - T data) where T : DeviceCacheBasicModel - { - if (data == null - || string.IsNullOrWhiteSpace(redisDeviceInfoHashCacheKey) - || string.IsNullOrWhiteSpace(redisSetIndexCacheKey) ) - { - _logger.LogError($"{nameof(RemoveCacheDataAsync)} 参数异常,-101"); - return; - } - - const string luaScript = @" - local hashCacheKey = KEYS[1] - local setIndexCacheKey = KEYS[2] - local focusAddress = ARGV[1] - local scoreValue = ARGV[2] - - local deleted = 0 - if redis.call('HDEL', hashCacheKey, focusAddress) > 0 then - deleted = 1 - end - - redis.call('SREM', setIndexCacheKey, scoreValue) - return deleted - "; - - var keys = new[] - { - redisDeviceInfoHashCacheKey, - redisSetIndexCacheKey - }; - - var result = await Instance.EvalAsync(luaScript, keys, new object[] { data.FocusAddress , data.ScoreValue}); - - if ((int)result == 0) - { - _logger.LogError($"{nameof(RemoveCacheDataAsync)} 删除指定Key{redisDeviceInfoHashCacheKey}的{data.MemberId}数据失败,-102"); - } - } - - /// - /// 修改缓存信息,映射关系未发生改变 - /// - /// - /// 主数据存储Hash缓存Key - /// Set索引缓存Key - /// ZSET索引缓存Key - /// 待修改缓存数据 - /// - public async Task ModifyDataAsync( - string redisHashCacheKey, - string redisSetIndexCacheKey, - string redisZSetScoresIndexCacheKey, - T newData) where T : DeviceCacheBasicModel - { - if (newData == null - || string.IsNullOrWhiteSpace(redisHashCacheKey) - || string.IsNullOrWhiteSpace(redisSetIndexCacheKey) - || string.IsNullOrWhiteSpace(redisZSetScoresIndexCacheKey)) - { - _logger.LogError($"{nameof(ModifyDataAsync)} 参数异常,-101"); - return; - } - - var luaScript = @" - local hashCacheKey = KEYS[1] - local member = ARGV[1] - local newData = ARGV[2] - - -- 校验存在性 - if redis.call('HEXISTS', hashCacheKey, member) == 0 then - return 0 - end - - -- 更新主数据 - redis.call('HSET', hashCacheKey, member, newData) - - return 1 - "; - - - var result = await Instance.EvalAsync(luaScript, - new[] - { - redisHashCacheKey - }, - new object[] - { - newData.MemberId, - newData.Serialize() - }); - - if ((int)result == 0) - { - _logger.LogError($"{nameof(ModifyDataAsync)} 更新指定Key{redisHashCacheKey}的{newData.MemberId}数据失败,-102"); - } - } - - /// - /// 修改缓存信息,映射关系已经改变 - /// - /// - /// 主数据存储Hash缓存Key - /// Set索引缓存Key - /// 旧的映射关系 - /// ZSET索引缓存Key - /// 待修改缓存数据 - /// - public async Task ModifyDataAsync( - string redisHashCacheKey, - string redisSetIndexCacheKey, - string oldMemberId, - string redisZSetScoresIndexCacheKey, - T newData) where T : DeviceCacheBasicModel - { - if (newData == null - || string.IsNullOrWhiteSpace(redisHashCacheKey) - || string.IsNullOrWhiteSpace(redisSetIndexCacheKey) - || string.IsNullOrWhiteSpace(oldMemberId) - || string.IsNullOrWhiteSpace(redisZSetScoresIndexCacheKey)) - { - _logger.LogError($"{nameof(ModifyDataAsync)} 参数异常,-101"); - return; - } - - var luaScript = @" - local hashCacheKey = KEYS[1] - local setIndexCacheKey = KEYS[2] - local zsetScoresIndexCacheKey = KEYS[3] - local member = ARGV[1] - local oldMember = ARGV[2] - local newData = ARGV[3] - local newScore = ARGV[4] - - -- 校验存在性 - if redis.call('HEXISTS', hashCacheKey, oldMember) == 0 then - return 0 - end - - -- 删除旧数据 - redis.call('HDEL', hashCacheKey, oldMember) - - -- 插入新主数据 - redis.call('HSET', hashCacheKey, member, newData) - - -- 处理变更 - if newScore ~= '' then - -- 删除旧索引 - redis.call('SREM', setIndexCacheKey, oldMember) - redis.call('ZREM', zsetScoresIndexCacheKey, oldMember) - - -- 添加新索引 - redis.call('SADD', setIndexCacheKey, member) - redis.call('ZADD', zsetScoresIndexCacheKey, newScore, member) - end - - return 1 - "; - - var result = await Instance.EvalAsync(luaScript, - new[] - { - redisHashCacheKey, - redisSetIndexCacheKey, - redisZSetScoresIndexCacheKey - }, - new object[] - { - newData.MemberId, - oldMemberId, - newData.Serialize(), - newData.ScoreValue.ToString() ?? "", - }); - - if ((int)result == 0) - { - _logger.LogError($"{nameof(ModifyDataAsync)} 更新指定Key{redisHashCacheKey}的{newData.MemberId}数据失败,-102"); - } - } - - - /// - /// 通过集中器与表计信息排序索引获取指定集中器号集合数据 - /// - /// - /// 主数据存储Hash缓存Key - /// 集中器与表计信息排序索引ZSET缓存Key - /// 集中器Id - /// 分页尺寸 - /// 最后一个索引 - /// 最后一个唯一标识 - /// 排序方式 - /// - public async Task> GetPagedData( - string redisCacheKey, - string redisCacheFocusScoresIndexKey, - IEnumerable focusIds, - int pageSize = 10, - decimal? lastScore = null, - string lastMember = null, - bool descending = true) - where T : DeviceCacheBasicModel - { - 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秒以内。 - /// - /// - /// 主数据存储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 new BusCacheGlobalPagedResult { Items = new List() }; - } - - pageSize = Math.Clamp(pageSize, 1, 10000); - - 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] - - -- 获取原始数据 - 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[] { redisZSetScoresIndexCacheKey, redisHashCacheKey }, - 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(redisZSetScoresIndexCacheKey), - PageSize = pageSize, - }; - } - - - /// - /// 通过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() }; - } - - pageSize = Math.Clamp(pageSize, 1, 10000); - - 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] - - -- 获取原始数据 - 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, - }; - } - - - /// - /// 游标分页查询 - /// - /// 排序索引ZSET缓存Key - /// 分页数量 - /// 上一个索引 - /// 上一个标识 - /// 排序方式 - /// - private async Task<(List Members, bool HasNext, decimal? NextScore, string NextMember)> GetPagedMembers( - string redisZSetScoresIndexCacheKey, - int pageSize, - decimal? lastScore, - string lastMember, - bool descending) - { - // 根据排序方向初始化参数 - long initialScore = descending ? long.MaxValue : 0; - decimal? currentScore = lastScore ?? initialScore; - string currentMember = lastMember; - var members = new List(pageSize + 1); - - // 使用游标分页查询 - while (members.Count < pageSize + 1 && currentScore.HasValue) - { - var (batch, hasMore) = await GetNextBatch( - redisZSetScoresIndexCacheKey, - pageSize + 1 - members.Count, - currentScore.Value, - currentMember, - descending); - - if (!batch.Any()) break; - - members.AddRange(batch); - - // 更新游标 - currentMember = batch.LastOrDefault(); - currentScore = await GetNextScore(redisZSetScoresIndexCacheKey, currentMember, descending); - } - - // 处理分页结果 - bool hasNext = members.Count > pageSize; - var resultMembers = members.Take(pageSize).ToList(); - - return ( - resultMembers, - hasNext, - currentScore, - currentMember - ); - } - - /// - /// 批量获取指定分页的数据 - /// - /// - /// Hash表缓存key - /// Hash表字段集合 - /// - private async Task> BatchGetData( - string redisHashCacheKey, - IEnumerable members) - where T : DeviceCacheBasicModel - { - using var pipe = Instance.StartPipe(); - - foreach (var member in members) - { - pipe.HGet(redisHashCacheKey, member); - } - - var results = pipe.EndPipe(); - return await Task.FromResult(members.Zip(results, (k, v) => new { k, v }) - .ToDictionary(x => x.k, x => (T)x.v)); - } - - /// - /// 处理下一个分页数据 - /// - /// - /// - /// - /// - /// - /// - private async Task<(string[] Batch, bool HasMore)> GetNextBatch( - string zsetKey, - int limit, - decimal score, - string excludeMember, - bool descending) - { - var query = descending - ? await Instance.ZRevRangeByScoreAsync( - zsetKey, - max: score, - min: 0, - offset: 0, - count: limit) - : await Instance.ZRangeByScoreAsync( - zsetKey, - min: score, - max: long.MaxValue, - offset: 0, - count: limit); - - return (query, query.Length >= limit); - } - - /// - /// 获取下一页游标 - /// - /// 排序索引ZSET缓存Key - /// 最后一个唯一标识 - /// 排序方式 - /// - private async Task GetNextScore( - string redisZSetScoresIndexCacheKey, - string lastMember, - bool descending) - { - if (string.IsNullOrEmpty(lastMember)) return null; - - var score = await Instance.ZScoreAsync(redisZSetScoresIndexCacheKey, lastMember); - if (!score.HasValue) return null; - - // 根据排序方向调整score - return descending - ? score.Value - 1 // 降序时下页查询小于当前score - : score.Value + 1; // 升序时下页查询大于当前score - } - - /// - /// 获取指定ZSET区间内的总数量 - /// - /// - /// - /// - /// - public async Task GetCount(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; - } - - /// - /// 获取指定ZSET的总数量 - /// - /// - /// - private async Task GetTotalCount(string redisZSetScoresIndexCacheKey) - { - // 缓存计数优化 - var cacheKey = $"{redisZSetScoresIndexCacheKey}_total_count"; - var cached = await Instance.GetAsync(cacheKey); - - if (cached.HasValue) - return cached.Value; - - var count = await Instance.ZCountAsync(redisZSetScoresIndexCacheKey, 0, decimal.MaxValue); - await Instance.SetExAsync(cacheKey, 30, count); // 缓存30秒 - return count; - } - } -} diff --git a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs index c6340ed..19fe3d7 100644 --- a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs +++ b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs @@ -1,59 +1,39 @@ -using Confluent.Kafka; -using DeviceDetectorNET.Parser.Device; -using FreeSql.Internal.CommonProvider; -using JiShe.CollectBus.Ammeters; -using JiShe.CollectBus.Application.Contracts; +using JiShe.CollectBus.Ammeters; using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.Common.DeviceBalanceControl; -using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Helpers; -using JiShe.CollectBus.FreeSql; -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 JiShe.ServicePro.FreeSqlProvider; +using JiShe.ServicePro.IoTDBManagement.Options; +using JiShe.ServicePro.IoTDBManagement.SessionPools; +using JiShe.ServicePro.Kafka.Internal; +using JiShe.ServicePro.Kafka.Producer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.Metrics; -using System.Threading.Tasks; -using TouchSocket.Core; using TouchSocket.Sockets; -using static IdentityModel.ClaimComparer; namespace JiShe.CollectBus.Samples; public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaSubscribe { private readonly ILogger _logger; - private readonly IIoTDbProvider _iotDBProvider; - private readonly IoTDBRuntimeContext _dbContext; + private readonly IoTDBSessionPoolProvider _iotDBProvider; 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, IProducerService producerService, ITcpService tcpService) + public SampleAppService(IoTDBSessionPoolProvider iotDBProvider, IOptions options, + ILogger logger, IRedisDataCacheService redisDataCacheService, IProducerService producerService, ITcpService tcpService) { _iotDBProvider = iotDBProvider; _options = options.Value; - _dbContext = dbContext; _logger = logger; _redisDataCacheService = redisDataCacheService; _producerService = producerService; @@ -73,26 +53,14 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS List values = new List() { $"{dataTime:yy}", $"{dataTime:MM}", $"{dataTime:dd}", $"{dataTime:HH}", $"{dataTime:mm}", }; - ElectricityMeterTreeModel meter = new ElectricityMeterTreeModel() - { - SystemName = "energy", - DeviceId = "402440506s", - DeviceType = "Ammeter", - Current = 10, - MeterModel = "DDZY-1980", - ProjectId = "10059", - Voltage = 10, - 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); + //ElectricityMeterAccessor } /// @@ -103,51 +71,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS public async Task UseTableSessionPool(DateTime time) { var testTime = time; - ElectricityMeterTreeModel meter2 = new ElectricityMeterTreeModel() - { - SystemName = "energy", - DeviceId = "402440506", - DeviceType = "Ammeter", - Current = 10, - MeterModel = "DDZY-1980", - ProjectId = "10059", - Voltage = 10, - Timestamps = DateTimeOffset.Now.ToUnixTimeNanoseconds(), - }; - - await _iotDBProvider.GetSessionPool(false).InsertAsync(meter2); - - ElectricityMeter meter = new ElectricityMeter() - { - SystemName = "energy", - DeviceId = "402440506", - DeviceType = "Ammeter", - Current = 10, - MeterModel = "DDZY-1980", - ProjectId = "10059", - Voltage = 10, - CurrentdDateTime = DateTime.Now, - Timestamps = DateTimeOffset.Now.ToUnixTimeNanoseconds(), - }; - 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); + } @@ -159,42 +83,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS public async Task UseTableSessionPool3(DateTime time) { var testTime = time; - ElectricityMeterTreeModel meter2 = new ElectricityMeterTreeModel() - { - SystemName = "energy", - DeviceId = "402440506", - DeviceType = "Ammeter", - Current = 10, - MeterModel = "DDZY-1980", - ProjectId = "10059", - Voltage = 10, - IssuedMessageHexString = "dsdfsfd", - Timestamps = DateTimeOffset.UtcNow.ToUnixTimeNanoseconds(), - - }; - - await _iotDBProvider.InsertAsync(meter2); - - - ElectricityMeter meter3 = new ElectricityMeter() - { - SystemName = "energy", - DeviceId = "402440506", - DeviceType = "Ammeter", - Current = 10, - MeterModel = "DDZY-1980", - ProjectId = "10059", - Voltage = 10, - Currentd = 22, - IssuedMessageHexString = "dsdfsfd", - Timestamps = DateTimeOffset.Now.ToUnixTimeNanoseconds(), - }; - - //var dd = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - //var dd3 = DateTimeOffset.Now.ToUnixTimeMicroseconds(); - //var dd2 = DateTimeOffset.Now.ToUnixTimeNanoseconds(); - - await _iotDBProvider.InsertAsync(meter3); + } /// @@ -205,20 +94,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTreeModelSingleMeasuringEntity(string measuring, string value, DateTime time) { - 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 = (measuring, 34.534m) - }; - await _iotDBProvider.InsertAsync(meter); + } /// @@ -229,17 +105,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTreeModelSingleMeasuringEntity2(string measuring, int value, DateTime time) { - time = DateTime.Now; - var meter = new TreeModelSingleMeasuringEntity() - { - SystemName = "energy", - DeviceId = "402440506", - DeviceType = "Ammeter", - ProjectId = "10059", - Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleMeasuring = (measuring, true) - }; - await _iotDBProvider.InsertAsync(meter); + } /// @@ -251,37 +117,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS 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); + } /// @@ -294,17 +130,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS { time = DateTime.Now; - var meter = new TableModelSingleMeasuringEntity() - { - SystemName = "energy", - DeviceId = "402440506", - DeviceType = "Ammeter", - ProjectId = "10059", - Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleColumn = (measuring, value) - }; - _dbContext.UseTableSessionPool = true; - await _iotDBProvider.InsertAsync(meter); + } /// @@ -317,46 +143,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS { time = DateTime.Now; - var meter = new TableModelSingleMeasuringEntity() - { - SystemName = "energy", - DeviceId = "402440506", - DeviceType = "Ammeter", - ProjectId = "10059", - Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - 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); + } /// @@ -512,7 +299,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS return aa == null; } - [KafkaSubscribe(ProtocolConst.TESTTOPIC)] + [KafkaSubscribe(KafkaTopicConsts.TESTTOPIC)] public async Task KafkaSubscribeAsync(object obj) { @@ -531,7 +318,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS ArgumentException.ThrowIfNullOrWhiteSpace(input.Address); ArgumentException.ThrowIfNullOrWhiteSpace(input.Frame); input.Frame = input.Frame.Replace(" ", ""); - await _producerService.ProduceAsync(ProtocolConst.TESTSENDTOPIC, input); + await _producerService.ProduceAsync(KafkaTopicConsts.TESTSENDTOPIC, input); return await Task.FromResult(true); } @@ -541,7 +328,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS /// /// /// - [KafkaSubscribe(ProtocolConst.TESTSENDTOPIC), ApiExplorerSettings(IgnoreApi = true)] + [KafkaSubscribe(KafkaTopicConsts.TESTSENDTOPIC), ApiExplorerSettings(IgnoreApi = true)] public async Task KafkaSubscribeTestSendAsync(KafkaSendDto dto) { diff --git a/services/JiShe.CollectBus.Application/Samples/TestAppService.cs b/services/JiShe.CollectBus.Application/Samples/TestAppService.cs index 1975d5a..af8bbde 100644 --- a/services/JiShe.CollectBus.Application/Samples/TestAppService.cs +++ b/services/JiShe.CollectBus.Application/Samples/TestAppService.cs @@ -1,19 +1,24 @@ -using Cassandra; -using JiShe.CollectBus.Cassandra; +using IdentityModel.Client; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.DynamicModule; using JiShe.CollectBus.Interceptors; using JiShe.CollectBus.IotSystems.MessageIssueds; using JiShe.CollectBus.IotSystems.Protocols; +using JiShe.CollectBus.Protocol; using JiShe.CollectBus.Protocol.Interfaces; +using JiShe.CollectBus.Protocol3761; using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using TouchSocket.Sockets; +using Volo.Abp; using Volo.Abp.Modularity; namespace JiShe.CollectBus.Samples; @@ -22,102 +27,104 @@ namespace JiShe.CollectBus.Samples; public class TestAppService : CollectBusAppService { private readonly ILogger _logger; - private readonly ICassandraRepository _messageReceivedCassandraRepository; - private readonly ICassandraProvider _cassandraProvider; + //private readonly ICassandraRepository _messageReceivedCassandraRepository; + //private readonly ICassandraProvider _cassandraProvider; private readonly IProtocolService _protocolService; private readonly IServiceProvider _serviceProvider; private readonly IDynamicModuleManager _dynamicModuleManager; - + private readonly IServiceCollection _serviceDescriptors; public TestAppService( ILogger logger, - ICassandraRepository messageReceivedCassandraRepository, - ICassandraProvider cassandraProvider, IProtocolService protocolService,IServiceProvider serviceProvider, IDynamicModuleManager dynamicModuleManager) + //ICassandraRepository messageReceivedCassandraRepository, + //ICassandraProvider cassandraProvider, + IProtocolService protocolService,IServiceProvider serviceProvider, IDynamicModuleManager dynamicModuleManager, IServiceCollection serviceDescriptors) { _logger = logger; - _messageReceivedCassandraRepository = messageReceivedCassandraRepository; - _cassandraProvider = cassandraProvider; + //_messageReceivedCassandraRepository = messageReceivedCassandraRepository; + //_cassandraProvider = cassandraProvider; _protocolService = protocolService; _serviceProvider = serviceProvider; _dynamicModuleManager = dynamicModuleManager; + _serviceDescriptors = serviceDescriptors; } public async Task AddMessageOfCassandra() { - var stopwatch = Stopwatch.StartNew(); - for (int i = 1; i <= 10000; i++) - { - var str = Guid.NewGuid().ToString(); - await _messageReceivedCassandraRepository.InsertAsync(new MessageIssued - { - ClientId = str, - DeviceNo = i.ToString(), - MessageId = str, - Type = IssuedEventType.Data, - Id = str, - Message = str.GetBytes() - }); - } - stopwatch.Stop(); - _logger.LogWarning($"插入 {10000} 条记录完成,耗时: {stopwatch.ElapsedMilliseconds} 毫秒"); + //var stopwatch = Stopwatch.StartNew(); + //for (int i = 1; i <= 10000; i++) + //{ + // var str = Guid.NewGuid().ToString(); + // await _messageReceivedCassandraRepository.InsertAsync(new MessageIssued + // { + // ClientId = str, + // DeviceNo = i.ToString(), + // MessageId = str, + // Type = IssuedEventType.Data, + // Id = str, + // Message = str.GetBytes() + // }); + //} + //stopwatch.Stop(); + //_logger.LogWarning($"插入 {10000} 条记录完成,耗时: {stopwatch.ElapsedMilliseconds} 毫秒"); } public async Task AddMessageOfBulkInsertCassandra() { - var records = new List(); - var prepared = await _cassandraProvider.Session.PrepareAsync( - $"INSERT INTO {_cassandraProvider.CassandraConfig.Keyspace}.{nameof(MessageIssued)} (id, clientid, message, deviceno,type,messageid) VALUES (?, ?, ?, ?, ?, ?)"); + //var records = new List(); + //var prepared = await _cassandraProvider.Session.PrepareAsync( + // $"INSERT INTO {_cassandraProvider.CassandraConfig.Keyspace}.{nameof(MessageIssued)} (id, clientid, message, deviceno,type,messageid) VALUES (?, ?, ?, ?, ?, ?)"); - for (int i = 1; i <= 100000; i++) - { - var str = Guid.NewGuid().ToString(); - records.Add(new MessageIssued - { - ClientId = str, - DeviceNo = i.ToString(), - MessageId = str, - Type = IssuedEventType.Data, - Id = str, - Message = str.GetBytes() - }); - } - var stopwatch = Stopwatch.StartNew(); - await BulkInsertAsync(_cassandraProvider.Session, prepared, records); - stopwatch.Stop(); - _logger.LogWarning($"插入 {100000} 条记录完成,耗时: {stopwatch.ElapsedMilliseconds} 毫秒"); + //for (int i = 1; i <= 100000; i++) + //{ + // var str = Guid.NewGuid().ToString(); + // records.Add(new MessageIssued + // { + // ClientId = str, + // DeviceNo = i.ToString(), + // MessageId = str, + // Type = IssuedEventType.Data, + // Id = str, + // Message = str.GetBytes() + // }); + //} + //var stopwatch = Stopwatch.StartNew(); + //await BulkInsertAsync(_cassandraProvider.Session, prepared, records); + //stopwatch.Stop(); + //_logger.LogWarning($"插入 {100000} 条记录完成,耗时: {stopwatch.ElapsedMilliseconds} 毫秒"); } - private static async Task BulkInsertAsync(ISession session, PreparedStatement prepared, List records) - { - var tasks = new List(); - var batch = new BatchStatement(); + //private static async Task BulkInsertAsync(ISession session, PreparedStatement prepared, List records) + //{ + // var tasks = new List(); + // var batch = new BatchStatement(); - for (int i = 0; i < records.Count; i++) - { - var record = records[i]; - var boundStatement = prepared.Bind( - record.Id, - record.ClientId, - record.Message, - record.DeviceNo, - (int)record.Type, - record.MessageId); + // for (int i = 0; i < records.Count; i++) + // { + // var record = records[i]; + // var boundStatement = prepared.Bind( + // record.Id, + // record.ClientId, + // record.Message, + // record.DeviceNo, + // (int)record.Type, + // record.MessageId); - // 设置一致性级别为ONE以提高性能 - boundStatement.SetConsistencyLevel(ConsistencyLevel.One); + // // 设置一致性级别为ONE以提高性能 + // boundStatement.SetConsistencyLevel(ConsistencyLevel.One); - batch.Add(boundStatement); + // batch.Add(boundStatement); - // 当达到批处理大小时执行 - if (batch.Statements.Count() >= 1000 || i == records.Count - 1) - { - tasks.Add(session.ExecuteAsync(batch)); - batch = new BatchStatement(); - } - } + // // 当达到批处理大小时执行 + // if (batch.Statements.Count() >= 1000 || i == records.Count - 1) + // { + // tasks.Add(session.ExecuteAsync(batch)); + // batch = new BatchStatement(); + // } + // } - // 等待所有批处理完成 - await Task.WhenAll(tasks); - } + // // 等待所有批处理完成 + // await Task.WhenAll(tasks); + //} [LogIntercept] public virtual Task LogInterceptorTest(string str) @@ -136,8 +143,76 @@ public class TestAppService : CollectBusAppService public async Task ReloadPluginsAsync() { var aa = Assembly.LoadFile( - @"D:\Codes\CollectBusV5\JiShe.CollectBus\web\JiShe.CollectBus.Host\bin\Debug\net8.0\Plugins\JiShe.CollectBus.Protocol.Test.dll"); + @"E:\Devlopment\JiShe.CollectBusDev01\web\JiShe.CollectBus.Host\bin\Debug\net8.0\Plugins\JiShe.CollectBus.Protocol.Test.dll"); var module = aa.GetTypes().First(a=> typeof(IAbpModule).IsAssignableFrom(a)); - await _dynamicModuleManager.ReinitializeModuleAsync(module); + await _dynamicModuleManager.LoadModuleAsync(module); + } + + + public async Task TestPlugins() + { + var executor = _serviceProvider.GetRequiredService(); + return await executor.ExecuteAsync("TestServer", "TestServer"); + + } + + /// + /// 注册策略 + /// + public void RegisterProtocolAnalysis() + { + // 扫描并注册所有策略 + var strategyMetadata = new Dictionary<(string, Type), Type>(); + _serviceDescriptors.AddTransient(); + + // 批量注册 + var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); + if (string.IsNullOrWhiteSpace(assemblyPath)) + { + return; + } + var dllFiles = Directory.GetFiles(Path.Combine(assemblyPath, "Plugins"), "*.dll"); + foreach (var file in dllFiles) + { + // 跳过已加载的程序集 + var assemblyName = AssemblyName.GetAssemblyName(file); + var existingAssembly = AppDomain.CurrentDomain.GetAssemblies() + .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<>))); + if (!analysisStrategyTypes.Any()) + continue; + foreach (var analysisStrategyType in analysisStrategyTypes) + { + // 通过反射获取静态元数据 + var strategyType = analysisStrategyType.Name; + var genericArgs = analysisStrategyType.GetInterface($"IAnalysisStrategy`1")!.GetGenericArguments(); + var inputType = genericArgs[0]; + // 注册策略实现 + _serviceDescriptors.AddTransient(analysisStrategyType); + strategyMetadata[(strategyType, inputType)] = analysisStrategyType; + + } + } + + // 注册元数据字典 + _serviceDescriptors.AddSingleton(strategyMetadata); + + // 注册策略解析工厂 + _serviceDescriptors.AddTransient>(provider => (name, inputType) => + { + 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}"); + return null; + } + }); } } diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs index 85a71d8..8e04734 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs @@ -1,37 +1,21 @@ -using JiShe.CollectBus.Application.Contracts; -using JiShe.CollectBus.Common; +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.Common.Models; using JiShe.CollectBus.DataChannels; -using JiShe.CollectBus.EnergySystems.Entities; using JiShe.CollectBus.GatherItem; -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.Kafka.Internal; using JiShe.CollectBus.Protocol.Interfaces; using JiShe.CollectBus.Protocol.Models; +using JiShe.ServicePro.Core; +using JiShe.ServicePro.Encrypt; using Mapster; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; using Volo.Abp.Guids; -using static FreeSql.Internal.GlobalFilter; -using static Microsoft.AspNetCore.Razor.Language.TagHelperMetadata; -using static Thrift.Protocol.Utilities.TJSONProtocolConstants; namespace JiShe.CollectBus.ScheduledMeterReading { @@ -41,7 +25,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading public abstract class BasicScheduledMeterReadingService : CollectBusAppService, IScheduledMeterReadingService { private readonly ILogger _logger; - private readonly IIoTDbProvider _dbProvider; + private readonly IoTDBSessionPoolProvider _dbProvider; private readonly IDataChannelManageService _dataChannelManage; private readonly IRedisDataCacheService _redisDataCacheService; private readonly IProtocolService _protocolService; @@ -55,7 +39,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading ILogger logger, IDataChannelManageService dataChannelManage, IRedisDataCacheService redisDataCacheService, - IIoTDbProvider dbProvider, + IoTDBSessionPoolProvider dbProvider, IProtocolService protocolService, IGuidGenerator guidGenerator, IOptions kafkaOptions, @@ -141,7 +125,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading //_logger.LogInformation($"{nameof(AmmeterScheduledAutomaticVerificationTime)} 电表自动校时,非自动校时时间"); //return; - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTime, meterType: MeterTypeEnum.Ammeter, @@ -154,12 +138,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"电表自动校时 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (KafkaTopicConsts.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); }); } else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticTerminalVersionTime, StringComparison.CurrentCultureIgnoreCase))//集中器版本号读取 { - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTime, meterType: MeterTypeEnum.Ammeter, @@ -171,12 +155,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"集中器终端版本信息 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (KafkaTopicConsts.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); }); } else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticTelematicsModuleTime, StringComparison.CurrentCultureIgnoreCase))//SIM卡读取 { - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTime, meterType: MeterTypeEnum.Ammeter, @@ -188,12 +172,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"集中器SIM卡读取 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (KafkaTopicConsts.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); }); } else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticMonthFreezeTime, StringComparison.CurrentCultureIgnoreCase))//月冻结 { - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTime, meterType: MeterTypeEnum.Ammeter, @@ -205,12 +189,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"电表月冻结 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (KafkaTopicConsts.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); }); } else if (string.Equals(currentTimeStr, _applicationOptions.AutomaticDayFreezeTime, StringComparison.CurrentCultureIgnoreCase))//日冻结 { - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTime, meterType: MeterTypeEnum.Ammeter, @@ -222,7 +206,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"电表日冻结 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (KafkaTopicConsts.AmmeterSubscriberWorkerOtherIssuedEventName, tempTask)); }); } else @@ -248,7 +232,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading timeDensity = 15; } - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTaskTime, meterType: MeterTypeEnum.Ammeter, @@ -260,13 +244,13 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, tempTask)); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (KafkaTopicConsts.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, tempTask)); }); } else if (meteryType == MeterTypeEnum.WaterMeter.ToString()) { - _ = CreateMeterPublishTask( + _ = CreateMeterPublishTask( timeDensity: timeDensity, nextTaskTime: currentTaskTime, meterType: MeterTypeEnum.WaterMeter, @@ -279,7 +263,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogWarning($"水表 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.WatermeterSubscriberWorkerAutoReadingIssuedEventName, tempTask)); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (KafkaTopicConsts.WatermeterSubscriberWorkerAutoReadingIssuedEventName, tempTask)); }); } else @@ -305,7 +289,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading // _logger.LogWarning($"{nameof(AmmeterScheduledAutoValveControl)}电表定时阀控没有可操作的任务"); // return; //} - //_ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, autoValveControlTask)); + //_ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, (KafkaTopicConsts.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, autoValveControlTask)); } #region 电表采集处理 @@ -315,7 +299,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// /// 采集端Code /// - public virtual Task> GetAmmeterInfoList(string gatherCode = "") + public virtual Task> GetAmmeterInfoList(string gatherCode = "") { throw new NotImplementedException($"{nameof(GetAmmeterInfoList)}请根据不同系统类型进行实现"); } @@ -332,19 +316,17 @@ namespace JiShe.CollectBus.ScheduledMeterReading try { // 创建取消令牌源 - //var cts = new CancellationTokenSource(); - - await _dbProvider.GetSessionPool(true).InitTableSessionModelAsync(); + //var cts = new CancellationTokenSource(); _ = _dataChannelManage.ScheduledMeterTaskReadingAsync(DataChannelManage.TaskDataChannel.Reader); // //此处代码不要删除 //#if DEBUG - // var redisCacheDeviceInfoHashKeyTemp = $"CollectBus:Energy:JiSheCollectBus2:DeviceInfo"; + // var redisCacheDeviceCacheInfoHashKeyTemp = $"CollectBus:Energy:JiSheCollectBus2:DeviceCacheInfo"; // var timer1 = Stopwatch.StartNew(); - // Dictionary> keyValuePairsTemps = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceInfoHashKeyTemp); - // List meterInfos = new List(); + // Dictionary> keyValuePairsTemps = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceCacheInfoHashKeyTemp); + // List meterInfos = new List(); // List focusAddressDataLista = new List(); // foreach (var item in keyValuePairsTemps) // { @@ -410,12 +392,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading } //设备hash缓存key - string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; + string redisCacheDeviceCacheInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; //设备分组集合key string redisCacheDeviceGroupSetIndexKey = $"{string.Format(RedisConst.CacheDeviceGroupSetIndexKey, SystemType, ServerTagName)}"; - Dictionary> keyValuePairs = new Dictionary>(); + Dictionary> keyValuePairs = new Dictionary>(); //处理设备缓存信息 foreach (var ammeter in meterInfos) @@ -466,17 +448,17 @@ namespace JiShe.CollectBus.ScheduledMeterReading if (!keyValuePairs.ContainsKey(ammeter.FocusAddress)) { - keyValuePairs[ammeter.FocusAddress] = new List() { ammeter.Adapt() }; + keyValuePairs[ammeter.FocusAddress] = new List() { ammeter.Adapt() }; } else { - keyValuePairs[ammeter.FocusAddress].Add(ammeter.Adapt()); + keyValuePairs[ammeter.FocusAddress].Add(ammeter.Adapt()); } } - await _redisDataCacheService.BatchInsertDataAsync( + await _redisDataCacheService.BatchInsertDataAsync( redisCacheDeviceGroupSetIndexKey, - redisCacheDeviceInfoHashKey, + redisCacheDeviceCacheInfoHashKey, keyValuePairs); //初始化设备组负载控制 @@ -500,116 +482,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading throw ex; } } - - /// - /// 1分钟采集电表数据,只获取任务数据下发,不构建任务 - /// - /// - public virtual async Task AmmeterScheduledMeterOneMinuteReading() - { - int timeDensity = 5; - var redisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity); - var taskInfo = await FreeRedisProvider.Instance.GetAsync(redisCacheKey); - - if (taskInfo == null) - { - _logger.LogError($"{nameof(AmmeterScheduledMeterFifteenMinuteReading)} {timeDensity}分钟获取任务下发信息失败,请检查Redis中是否有对应的任务下发信息"); - return; - } - - var pendingCopyReadTime = taskInfo.LastTaskTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); - - var conditions = new List(); - conditions.Add(new QueryCondition() - { - Field = "PendingCopyReadTime", - Operator = "=", - IsNumber = true, - Value = pendingCopyReadTime - }); - - _ = CreateMeterKafkaTaskMessage(ProtocolConst.AmmeterSubscriberWorkerOneMinuteIssuedEventName, new IoTDBQueryOptions() - { - TableNameOrTreePath = DevicePathBuilder.GetTableName(), - PageIndex = 1, - PageSize = pageSize, - Conditions = conditions, - }); - - } - - /// - /// 5分钟采集电表数据 - /// - /// - public virtual async Task AmmeterScheduledMeterFiveMinuteReading() - { - int timeDensity = 5; - var redisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity); - var taskInfo = await FreeRedisProvider.Instance.GetAsync(redisCacheKey); - - if (taskInfo == null) - { - _logger.LogError($"{nameof(AmmeterScheduledMeterFifteenMinuteReading)} {timeDensity}分钟获取任务下发信息失败,请检查Redis中是否有对应的任务下发信息"); - return; - } - - var pendingCopyReadTime = taskInfo.LastTaskTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); - - var conditions = new List(); - conditions.Add(new QueryCondition() - { - Field = "PendingCopyReadTime", - Operator = "=", - IsNumber = true, - Value = pendingCopyReadTime - }); - - _ = CreateMeterKafkaTaskMessage(ProtocolConst.AmmeterSubscriberWorkerFiveMinuteIssuedEventName, new IoTDBQueryOptions() - { - TableNameOrTreePath = DevicePathBuilder.GetTableName(), - PageIndex = 1, - PageSize = pageSize, - Conditions = conditions, - }); - } - - /// - /// 15分钟采集电表数据 - /// - /// - public virtual async Task AmmeterScheduledMeterFifteenMinuteReading() - { - int timeDensity = 15; - var redisCacheKey = string.Format(RedisConst.CacheTasksToBeIssuedKey, SystemType, ServerTagName, MeterTypeEnum.Ammeter, timeDensity); - var taskInfo = await FreeRedisProvider.Instance.GetAsync(redisCacheKey); - - if (taskInfo == null) - { - _logger.LogError($"{nameof(AmmeterScheduledMeterFifteenMinuteReading)} {timeDensity}分钟获取任务下发信息失败,请检查Redis中是否有对应的任务下发信息"); - return; - } - - var pendingCopyReadTime = taskInfo.LastTaskTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); - - var conditions = new List(); - conditions.Add(new QueryCondition() - { - Field = "PendingCopyReadTime", - Operator = "=", - IsNumber = true, - Value = pendingCopyReadTime - }); - - _ = CreateMeterKafkaTaskMessage(ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, new IoTDBQueryOptions() - { - TableNameOrTreePath = DevicePathBuilder.GetTableName(), - PageIndex = 1, - PageSize = pageSize, - Conditions = conditions, - }); - } - + /// /// 创建电表待发送的任务数据 /// @@ -618,7 +491,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - private async Task> AmmerterCreatePublishTaskAction(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) + private async Task> AmmerterCreatePublishTaskAction(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; @@ -802,7 +675,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - public virtual async Task> AmmeterScheduledAutomaticVerificationTime(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) + public virtual async Task> AmmeterScheduledAutomaticVerificationTime(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm:00}"; @@ -883,7 +756,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - public virtual async Task> AmmeterScheduledGetAutomaticDayFreezeData(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) + public virtual async Task> AmmeterScheduledGetAutomaticDayFreezeData(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm:00}"; @@ -964,7 +837,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - public virtual async Task> AmmeterScheduledGetAutomaticMonthFreezeData(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) + public virtual async Task> AmmeterScheduledGetAutomaticMonthFreezeData(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm:00}"; @@ -1098,7 +971,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading IsNumber = false, Value = false }); - //await CreateMeterKafkaTaskMessage(ProtocolConst.AmmeterSubscriberWorkerRetryEventName, new IoTDBQueryOptions() + //await CreateMeterKafkaTaskMessage(KafkaTopicConsts.AmmeterSubscriberWorkerRetryEventName, new IoTDBQueryOptions() //{ // TableNameOrTreePath = DevicePathBuilder.GetTableName(), // PageIndex = 1, @@ -1128,7 +1001,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// /// 采集端Code /// - public virtual Task> GetWatermeterInfoList(string gatherCode = "") + public virtual Task> GetWatermeterInfoList(string gatherCode = "") { throw new NotImplementedException($"{nameof(GetWatermeterInfoList)}请根据不同系统类型进行实现"); } @@ -1217,19 +1090,19 @@ namespace JiShe.CollectBus.ScheduledMeterReading } //设备hash缓存key - string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; + string redisCacheDeviceCacheInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; //设备分组集合key string redisCacheDeviceGroupSetIndexKey = $"{string.Format(RedisConst.CacheDeviceGroupSetIndexKey, SystemType, ServerTagName)}"; - Dictionary> keyValuePairs = new Dictionary>(); + Dictionary> keyValuePairs = new Dictionary>(); foreach (var subItem in meterInfos) { deviceIds.Add(subItem.MeterId.ToString()); if (!keyValuePairs.ContainsKey(subItem.FocusAddress)) { - keyValuePairs[subItem.FocusAddress] = new List() { subItem }; + keyValuePairs[subItem.FocusAddress] = new List() { subItem }; } else { @@ -1239,9 +1112,9 @@ namespace JiShe.CollectBus.ScheduledMeterReading - await _redisDataCacheService.BatchInsertDataAsync( + await _redisDataCacheService.BatchInsertDataAsync( redisCacheDeviceGroupSetIndexKey, - redisCacheDeviceInfoHashKey, + redisCacheDeviceCacheInfoHashKey, keyValuePairs); //初始化设备组负载控制 @@ -1258,46 +1131,8 @@ namespace JiShe.CollectBus.ScheduledMeterReading _logger.LogInformation($"{nameof(InitAmmeterCacheData)} 初始化水表缓存数据完成"); } - - /// - /// 水表数据采集 - /// - /// - 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) - { - _logger.LogError($"{nameof(AmmeterScheduledMeterFifteenMinuteReading)} {timeDensity}分钟获取任务下发信息失败,请检查Redis中是否有对应的任务下发信息"); - return; - } - - var pendingCopyReadTime = taskInfo.LastTaskTime.GetDateTimeOffset().ToUnixTimeNanoseconds(); - - var conditions = new List(); - conditions.Add(new QueryCondition() - { - Field = "PendingCopyReadTime", - Operator = "=", - IsNumber = true, - Value = pendingCopyReadTime - }); - - //_ = CreateMeterKafkaTaskMessage(ProtocolConst.WatermeterSubscriberWorkerAutoReadingIssuedEventName, new IoTDBQueryOptions() - //{ - // TableNameOrTreePath = DevicePathBuilder.GetTableName(), - // PageIndex = 1, - // PageSize = pageSize, - // Conditions = conditions, - //}); - - _logger.LogInformation($"{nameof(WatermeterScheduledMeterAutoReadding)} {timeDensity}分钟采集水表数据处理完成"); - } - + + /// /// 创建水表待发送的任务数据 /// @@ -1307,7 +1142,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 时间格式的任务批次名称 /// private async Task> WatermeterCreatePublishTaskAction(int timeDensity - , DeviceInfo watermeter, int groupIndex, DateTime timestamps) + , DeviceCacheInfo watermeter, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; @@ -1414,7 +1249,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - public virtual async Task> ConcentratorScheduledAutomaticGetTerminalVersion(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) + public virtual async Task> ConcentratorScheduledAutomaticGetTerminalVersion(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm:00}"; @@ -1493,7 +1328,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 集中器所在分组 /// 采集频率对应的时间戳 /// - public virtual async Task> ConcentratorScheduledAutomaticGetTelematicsModule(int timeDensity, DeviceInfo ammeterInfo, int groupIndex, DateTime timestamps) + public virtual async Task> ConcentratorScheduledAutomaticGetTelematicsModule(int timeDensity, DeviceCacheInfo ammeterInfo, int groupIndex, DateTime timestamps) { var currentTime = DateTime.Now; string currentTimeStr = $"{currentTime:HH:mm:00}"; @@ -1591,7 +1426,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading //获取对应频率中的所有电表信息 //设备hash缓存key - string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; + string redisCacheDeviceCacheInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; //设备分组集合key string redisCacheDeviceGroupSetIndexKey = $"{string.Format(RedisConst.CacheDeviceGroupSetIndexKey, SystemType, ServerTagName)}"; @@ -1604,7 +1439,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading //{ // var page = await _redisDataCacheService.GetAllPagedData2( // redisCacheDeviceGroupSetIndexKey, - // redisCacheDeviceInfoHashKey, + // redisCacheDeviceCacheInfoHashKey, // pageSize: 1000, // lastScore: cursor, // lastMember: member); @@ -1634,7 +1469,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading // return; //} - Dictionary> keyValuePairs = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceInfoHashKey); + Dictionary> keyValuePairs = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceCacheInfoHashKey); timer.Stop(); @@ -1667,70 +1502,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading timer.Stop(); _logger.LogError($"{nameof(CreateMeterPublishTask)} {meterType} {timeDensity}分钟采集待下发任务创建完成,耗时{timer.ElapsedMilliseconds}毫秒,总共{meterInfos.Count}表计信息"); } - - - /// - /// 创建Kafka消息 - /// - /// - /// kafka主题名称 - /// 任务查询条件 - /// - protected async Task CreateMeterKafkaTaskMessage(string kafkaTopicName, IoTDBQueryOptions options) where T : IoTEntity, new() - { - if (string.IsNullOrWhiteSpace(kafkaTopicName)) - { - _logger.LogInformation($"{nameof(CreateMeterKafkaTaskMessage)} Kafka消息推送主题不能为空,-101"); - return; - } - 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; - - _ = DeviceGroupBalanceControl.ProcessWithThrottleAsync( - items: pageResult.Items.ToList(), - deviceIdSelector: data => data.DeviceId, - processor: (data, groupIndex) => - { - _ = KafkaProducerIssuedMessageAction(kafkaTopicName, data, groupIndex); - } - ); - stopwatch2.Stop(); - _logger.LogWarning($"{nameof(CreateMeterKafkaTaskMessage)} {kafkaTopicName}主题的任务 {options.TableNameOrTreePath} 路径批次{options.PageIndex}任务数据读取完成,共消耗{stopwatch2.ElapsedMilliseconds}毫秒。"); - } while (hasNext); - - stopwatch.Stop(); - _logger.LogWarning($"{nameof(CreateMeterKafkaTaskMessage)} {kafkaTopicName}主题的任务 {options.TableNameOrTreePath} 路径任务推送完成,共消耗{stopwatch.ElapsedMilliseconds}毫秒。"); - } - - /// - /// 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"); - } - - // await _dataChannelManage.ProduceAsync(topicName, taskRecord, partition); - } - + /// /// 构建报文保存对象 /// @@ -1744,7 +1516,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// 数据包类型 /// Guid生成器 /// - protected MeterReadingTelemetryPacketInfo CreateAmmeterPacketInfo(DeviceInfo ammeterInfo, long timestamps, ProtocolBuildResponse builderResponse, string itemCode, string subItemCode, DateTime pendingCopyReadTime, DateTime creationTime, TelemetryPacketTypeEnum packetType, IGuidGenerator guidGenerator) + protected MeterReadingTelemetryPacketInfo CreateAmmeterPacketInfo(DeviceCacheInfo ammeterInfo, long timestamps, ProtocolBuildResponse builderResponse, string itemCode, string subItemCode, DateTime pendingCopyReadTime, DateTime creationTime, TelemetryPacketTypeEnum packetType, IGuidGenerator guidGenerator) { try { @@ -1752,7 +1524,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading return new MeterReadingTelemetryPacketInfo() { SystemName = SystemType, - ProjectId = $"{ammeterInfo.ProjectID}", + ProjectId = $"{ammeterInfo.ProjectId}", DeviceType = $"{MeterTypeEnum.Ammeter}", DeviceId = $"{ammeterInfo.MeterId}", Timestamps = timestamps, diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs index 762d001..a76c551 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs @@ -1,26 +1,17 @@ -using JiShe.CollectBus.Application.Contracts; -using JiShe.CollectBus.Common; +using JiShe.CollectBus.Common; using JiShe.CollectBus.Common.Consts; 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.Interface; using JiShe.CollectBus.IotSystems.Ammeters; -using JiShe.CollectBus.IotSystems.Devices; -using JiShe.CollectBus.IotSystems.MeterReadingRecords; -using JiShe.CollectBus.Kafka.Internal; using JiShe.CollectBus.Protocol.Interfaces; using JiShe.CollectBus.Protocol.Models; +using JiShe.ServicePro.Consts; +using JiShe.ServicePro.Core; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Volo.Abp.Guids; @@ -43,7 +34,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading ILogger logger, IDataChannelManageService dataChannelManage, IRedisDataCacheService redisDataCacheService, - IIoTDbProvider dbProvider, + IoTDBSessionPoolProvider dbProvider, IProtocolService protocolService, IGuidGenerator guidGenerator, IOptions kafkaOptions, @@ -94,17 +85,17 @@ 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"; + var redisCacheDeviceCacheInfoHashKeyTemp = $"CollectBus:Energy:JiSheCollectBus109:DeviceCacheInfo"; - List ammeterInfos = FreeRedisProvider.Instance.Get>(redisCacheDeviceInfoHashKeyTemp);//542400504 + List ammeterInfos = FreeRedisProvider.Instance.Get>(redisCacheDeviceCacheInfoHashKeyTemp);//542400504 if (ammeterInfos == null || ammeterInfos.Count <= 0) { - ammeterInfos = new List(); - //ammeterInfos.Add(new DeviceInfo() + ammeterInfos = new List(); + //ammeterInfos.Add(new DeviceCacheInfo() //{ // Baudrate = 2400, // FocusAddress = "442400040", @@ -124,7 +115,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading // Password = "000000", //}); - //ammeterInfos.Add(new DeviceInfo() + //ammeterInfos.Add(new DeviceCacheInfo() //{ // Baudrate = 2400, // FocusAddress = "442400039", @@ -144,7 +135,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading // Password = "000000", //}); - //ammeterInfos.Add(new DeviceInfo() + //ammeterInfos.Add(new DeviceCacheInfo() //{ // Baudrate = 2400, // FocusAddress = "402440506", @@ -165,7 +156,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading //}); - //ammeterInfos.Add(new DeviceInfo() + //ammeterInfos.Add(new DeviceCacheInfo() //{ // Baudrate = 2400, // FocusAddress = "942411321", @@ -186,7 +177,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading //}); - //ammeterInfos.Add(new DeviceInfo() + //ammeterInfos.Add(new DeviceCacheInfo() //{ // Baudrate = 2400, // FocusAddress = "942411319", @@ -206,7 +197,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading // MeteringPort = MeteringPortConst.MeteringPortTwo, //}); - ammeterInfos.Add(new DeviceInfo() + ammeterInfos.Add(new DeviceCacheInfo() { Baudrate = 2400, FocusAddress = "322011149", @@ -221,12 +212,17 @@ namespace JiShe.CollectBus.ScheduledMeterReading TimeDensity = 15, BrandType = "DTS1980", Password = "000000", - ProjectID = 1, MeterType = MeterTypeEnum.Ammeter, MeteringPort = MeteringPortConst.MeteringPortTwo, + SystemName = SystemType, + IoTDataType = IOTDBDataTypeConst.Data, + ProjectId = "1", + DeviceType = JiShe.ServicePro.Enums.MeterTypeEnum.Ammeter.ToString(), + DeviceId = "78973", + }); - FreeRedisProvider.Instance.Set(redisCacheDeviceInfoHashKeyTemp, ammeterInfos); + FreeRedisProvider.Instance.Set(redisCacheDeviceCacheInfoHashKeyTemp, ammeterInfos); } return ammeterInfos; @@ -285,7 +281,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading } return await SqlProvider.Instance.Change(DbEnum.EnergyDB) .Ado - .QueryAsync(sql); + .QueryAsync(sql); } catch (Exception ex) { @@ -425,7 +421,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading FreeRedisProvider.Instance.Set(redisCacheDeviceSettingInfoHashKey, settingInfos); } - List meterInfos = await GetAmmeterInfoList(); + List meterInfos = await GetAmmeterInfoList(); #else //获取电表阀控配置 var settingInfos = await GetAmmeterAutoValveControlSetting(currentTimeStr); @@ -436,10 +432,10 @@ namespace JiShe.CollectBus.ScheduledMeterReading } //设备hash缓存key - string redisCacheDeviceInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; + string redisCacheDeviceCacheInfoHashKey = $"{string.Format(RedisConst.CacheDeviceInfoHashKey, SystemType, ServerTagName)}"; - Dictionary> keyValuePairsTemps = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceInfoHashKey); - List meterInfos = new List(); + Dictionary> keyValuePairsTemps = FreeRedisProvider.Instance.HGetAll>(redisCacheDeviceCacheInfoHashKey); + List meterInfos = new List(); List focusAddressDataLista = new List(); foreach (var item in keyValuePairsTemps) { @@ -575,19 +571,19 @@ 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") { try { #if DEBUG - var redisCacheDeviceInfoHashKeyTemp = $"CollectBus:Energy:JiSheCollectBus119:DeviceInfo"; + var redisCacheDeviceCacheInfoHashKeyTemp = $"CollectBus:Energy:JiSheCollectBus119:DeviceCacheInfo"; - List deviceInfos = FreeRedisProvider.Instance.Get>(redisCacheDeviceInfoHashKeyTemp); + List DeviceCacheInfos = FreeRedisProvider.Instance.Get>(redisCacheDeviceCacheInfoHashKeyTemp); - if (deviceInfos == null || deviceInfos.Count <= 0) + if (DeviceCacheInfos == null || DeviceCacheInfos.Count <= 0) { - deviceInfos = new List(); - deviceInfos.Add(new DeviceInfo() + DeviceCacheInfos = new List(); + DeviceCacheInfos.Add(new DeviceCacheInfo() { Baudrate = 2400, FocusAddress = "322011149", @@ -602,18 +598,22 @@ namespace JiShe.CollectBus.ScheduledMeterReading BrandType = "云集", MeterTypeName = "水表", MeterType = MeterTypeEnum.WaterMeter, - ProjectID = 1, MeteringPort = MeteringPortConst.MeteringPortTwo, Password = "000000", LinkType = "RS-485", TimesRate = 1.0000m, Protocol = 30, + SystemName = SystemType, + IoTDataType = IOTDBDataTypeConst.Data, + ProjectId = "1", + DeviceType = JiShe.ServicePro.Enums.MeterTypeEnum.WaterMeter.ToString(), + DeviceId = "1025", }); - FreeRedisProvider.Instance.Set(redisCacheDeviceInfoHashKeyTemp, deviceInfos); + FreeRedisProvider.Instance.Set(redisCacheDeviceCacheInfoHashKeyTemp, DeviceCacheInfos); } - - return deviceInfos; + + return DeviceCacheInfos; #else string sql = $@"SELECT A.ID as MeterId, @@ -656,7 +656,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading } return await SqlProvider.Instance.Change(DbEnum.EnergyDB) .Ado - .QueryAsync(sql); + .QueryAsync(sql); #endif } catch (Exception) diff --git a/services/JiShe.CollectBus.Application/Subscribers/ServiceCommunicationChannelSubscriberService.cs b/services/JiShe.CollectBus.Application/Subscribers/ServiceCommunicationChannelSubscriberService.cs new file mode 100644 index 0000000..8ee60e6 --- /dev/null +++ b/services/JiShe.CollectBus.Application/Subscribers/ServiceCommunicationChannelSubscriberService.cs @@ -0,0 +1,91 @@ +using JiShe.CollectBus.Protocol.Interfaces; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TouchSocket.Sockets; + +namespace JiShe.CollectBus.Subscribers +{ + public class ServiceCommunicationChannelSubscriberService : CollectBusAppService, IServiceCommunicationChannelSubscriberService, IKafkaSubscribe + { + private readonly ILogger _logger; + private readonly ITcpService _tcpService; + private readonly IServiceProvider _serviceProvider; + private readonly IoTDBSessionPoolProvider _dbProvider; + private readonly IProtocolService _protocolService; + + + public ServiceCommunicationChannelSubscriberService(ILogger logger, + ITcpService tcpService, + IServiceProvider serviceProvider, + IoTDBSessionPoolProvider dbProvider, + IProtocolService protocolService) + { + _logger = logger; + _tcpService = tcpService; + _serviceProvider = serviceProvider; + _dbProvider = dbProvider; + _protocolService = protocolService; + } + + + /// + /// 数据通讯通道消息消费订阅 + /// + /// + /// + [KafkaSubscribe(KafkaTopicConsts.ServiceCommunicationChannelTopic)] + public async Task ServiceCommunicationChannelIssuedEvent(Dictionary issuedMessage) + { + Logger.LogWarning($"数据通讯通道消息消费订阅解析:{issuedMessage.Serialize()}"); + var tempFirstKeyInfo = issuedMessage.FirstOrDefault(); + if (tempFirstKeyInfo.Value == null) + { + return SubscribeAck.Fail(); + } + + ServiceCommunicationTypeEnum serviceCommunication = tempFirstKeyInfo.Key; + bool tempResult = false; + switch (serviceCommunication) + { + case ServiceCommunicationTypeEnum.ArchivalDataIssued: + if(!string.IsNullOrWhiteSpace(tempFirstKeyInfo.Value)) + { + FocusCacheInfos focusCacheInfo = tempFirstKeyInfo.Value.Deserialize(); + tempResult = await SendArchivalDataIssued(focusCacheInfo); + } + break; + default: + throw new Exception("暂不支持该数据通讯通道消息消费订阅解析"); + } + + return tempResult == true ? SubscribeAck.Success() : SubscribeAck.Fail(); + } + + protected async Task SendArchivalDataIssued(FocusCacheInfos focusCacheInfo) + { + try + { + var checkResult = _tcpService.ClientExists(focusCacheInfo.FocusAddress); + if (checkResult) + { + string issuedMessageHexString = ""; + await _tcpService.SendAsync(focusCacheInfo.FocusAddress, Convert.FromHexString(issuedMessageHexString)); + + return true; + } + else + { + return false; + } + } + catch (Exception) + { + throw; + } + } + } +} diff --git a/services/JiShe.CollectBus.Application/Subscribers/SubscriberAnalysisAppService.cs b/services/JiShe.CollectBus.Application/Subscribers/SubscriberAnalysisAppService.cs index 7b3517b..8e99a56 100644 --- a/services/JiShe.CollectBus.Application/Subscribers/SubscriberAnalysisAppService.cs +++ b/services/JiShe.CollectBus.Application/Subscribers/SubscriberAnalysisAppService.cs @@ -1,21 +1,13 @@ -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.Helpers; -using JiShe.CollectBus.IoTDB.Interface; +using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.IotSystems.MessageReceiveds; -using JiShe.CollectBus.Kafka.Attributes; -using JiShe.CollectBus.Kafka.Internal; -using JiShe.CollectBus.Protocol.Contracts; +using JiShe.CollectBus.Protocol; +using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto; +using JiShe.CollectBus.Protocol.Dto; using JiShe.CollectBus.Protocol.Interfaces; using JiShe.CollectBus.Protocol3761; -using JiShe.CollectBus.Repository.MeterReadingRecord; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -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 { @@ -24,20 +16,19 @@ namespace JiShe.CollectBus.Subscribers private readonly ILogger _logger; private readonly ITcpService _tcpService; private readonly IServiceProvider _serviceProvider; - private readonly IMeterReadingRecordRepository _meterReadingRecordsRepository; - private readonly IIoTDbProvider _dbProvider; + private readonly IoTDBSessionPoolProvider _dbProvider; private readonly IProtocolService _protocolService; + public SubscriberAnalysisAppService(ILogger logger, ITcpService tcpService, IServiceProvider serviceProvider, - IIoTDbProvider dbProvider, - IMeterReadingRecordRepository meterReadingRecordsRepository, IProtocolService protocolService) + IoTDBSessionPoolProvider dbProvider, + IProtocolService protocolService) { _logger = logger; _tcpService = tcpService; _serviceProvider = serviceProvider; - _meterReadingRecordsRepository = meterReadingRecordsRepository; _dbProvider = dbProvider; _protocolService = protocolService; } @@ -47,7 +38,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN00HReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN00HReceivedEventName)] public async Task ReceivedAFN00Event(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -83,7 +74,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN01HReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN01HReceivedEventName)] public async Task ReceivedAFN01Event(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -120,7 +111,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN02HReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN02HReceivedEventName)] public async Task ReceivedAFN02Event(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -162,7 +153,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN03HReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN03HReceivedEventName)] public async Task ReceivedAFN03Event(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -200,7 +191,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN04HReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN04HReceivedEventName)] public async Task ReceivedAFN04Event(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -238,7 +229,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN05HReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN05HReceivedEventName)] public async Task ReceivedAFN05Event(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -276,7 +267,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN09HReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN09HReceivedEventName)] public async Task ReceivedAFN09Event(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -313,7 +304,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN0AHReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN0AHReceivedEventName)] public async Task ReceivedAFN0AEvent(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -350,7 +341,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN0BHReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN0BHReceivedEventName)] public async Task ReceivedAFN0BEvent(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -387,7 +378,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN0CHReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN0CHReceivedEventName)] public async Task ReceivedAFN0CEvent(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -425,7 +416,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN0DHReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN0DHReceivedEventName)] public async Task ReceivedAFN0DEvent(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -463,7 +454,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN0EHReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN0EHReceivedEventName)] public async Task ReceivedAFN0EEvent(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); @@ -501,7 +492,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.SubscriberAFN10HReceivedEventNameTemp)] + [KafkaSubscribe(KafkaTopicConsts.SubscriberAFN10HReceivedEventName)] public async Task ReceivedAFN0HEvent(MessageProtocolAnalysis receivedMessage) { var protocolPlugin = await _protocolService.GetProtocolServiceAsync(receivedMessage.DeviceNo); diff --git a/services/JiShe.CollectBus.Application/Subscribers/SubscriberAppService.cs b/services/JiShe.CollectBus.Application/Subscribers/SubscriberAppService.cs deleted file mode 100644 index 670fd7c..0000000 --- a/services/JiShe.CollectBus.Application/Subscribers/SubscriberAppService.cs +++ /dev/null @@ -1,172 +0,0 @@ -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Models; -using JiShe.CollectBus.Interceptors; -using JiShe.CollectBus.IoTDB.Interface; -using JiShe.CollectBus.IotSystems.MessageReceiveds; -using JiShe.CollectBus.IotSystems.MeterReadingRecords; -using JiShe.CollectBus.Kafka.Attributes; -using JiShe.CollectBus.Kafka.Internal; -using JiShe.CollectBus.Protocol.Interfaces; -using JiShe.CollectBus.Protocol3761; -using JiShe.CollectBus.Repository.MeterReadingRecord; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using TouchSocket.Sockets; -using Volo.Abp.Domain.Repositories; - -namespace JiShe.CollectBus.Subscribers -{ - public class SubscriberAppService : CollectBusAppService, ISubscriberAppService, IKafkaSubscribe - { - private readonly ILogger _logger; - private readonly ITcpService _tcpService; - private readonly IServiceProvider _serviceProvider; - private readonly IRepository _messageReceivedLoginEventRepository; - private readonly IRepository _messageReceivedHeartbeatEventRepository; - private readonly IMeterReadingRecordRepository _meterReadingRecordsRepository; - private readonly IIoTDbProvider _dbProvider; - private readonly IProtocolService _protocolService; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The TCP service. - /// The service provider. - /// The message received login event repository. - /// The message received heartbeat event repository. - /// The device repository. - public SubscriberAppService(ILogger logger, - ITcpService tcpService, - IServiceProvider serviceProvider, - IRepository messageReceivedLoginEventRepository, - IRepository messageReceivedHeartbeatEventRepository, - IIoTDbProvider dbProvider, - IMeterReadingRecordRepository meterReadingRecordsRepository, IProtocolService protocolService) - { - _logger = logger; - _tcpService = tcpService; - _serviceProvider = serviceProvider; - _messageReceivedLoginEventRepository = messageReceivedLoginEventRepository; - _messageReceivedHeartbeatEventRepository = messageReceivedHeartbeatEventRepository; - _meterReadingRecordsRepository = meterReadingRecordsRepository; - _dbProvider = dbProvider; - _protocolService = protocolService; - } - - [LogIntercept] - [KafkaSubscribe(ProtocolConst.SubscriberLoginIssuedEventName, EnableBatch = true)] - public async Task LoginIssuedEvent(List issuedEventMessages) - { - bool isAck = true; - foreach (var issuedEventMessage in issuedEventMessages) - { - //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); - } - // TODO:暂时ACK,等后续处理是否放到私信队列中 - return isAck? SubscribeAck.Success(): SubscribeAck.Fail(); - } - - [KafkaSubscribe(ProtocolConst.SubscriberHeartbeatIssuedEventName, EnableBatch = true)] - public async Task HeartbeatIssuedEvent(List issuedEventMessages) - { - 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(); - } - - [KafkaSubscribe(ProtocolConst.SubscriberReceivedEventName)] - public async Task ReceivedEvent(MessageProtocolAnalysis receivedMessage) - { - var currentTime = Clock.Now; - - var protocolPlugin = _serviceProvider.GetKeyedService("StandardProtocolPlugin"); - if (protocolPlugin == null) - { - _logger.LogError("协议不存在!"); - } - else - { - //todo 会根据不同的协议进行解析,然后做业务处理 - //TB3761? tB3761 = protocolPlugin.Analysis3761(receivedMessage.MessageHexString); - //if (tB3761 == null) - //{ - // Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); - // return SubscribeAck.Success(); - //} - //if (tB3761.DT == null || tB3761.AFN_FC == null) - //{ - // Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); - // return SubscribeAck.Success(); - //} - - //报文入库 - var entity = new MeterReadingRecords() - { - ReceivedMessageHexString = receivedMessage.MessageHexString, - AFN = (AFN)receivedMessage.Data?.AFN_FC.AFN!, - Fn = receivedMessage.Data.DT.Fn, - Pn = 0, - FocusAddress = "", - MeterAddress = "", - }; - - //如果没数据,则插入,有数据则更新 - var updateEntity = await _meterReadingRecordsRepository.FirOrDefaultAsync(entity, currentTime); - if (updateEntity == null) - { - await _meterReadingRecordsRepository.InsertAsync(entity, currentTime); - } - - - //_dbProvider.InsertAsync(); - //todo 查找是否有下发任务 - - //await _messageReceivedEventRepository.InsertAsync(receivedMessage); - - - } - return SubscribeAck.Success(); - } - - [KafkaSubscribe(ProtocolConst.SubscriberHeartbeatReceivedEventName, EnableBatch = true)] - public async Task ReceivedHeartbeatEvent(List receivedHeartbeatMessages) - { - await _messageReceivedHeartbeatEventRepository.InsertManyAsync(receivedHeartbeatMessages); - return SubscribeAck.Success(); - } - - [KafkaSubscribe(ProtocolConst.SubscriberLoginReceivedEventName,EnableBatch =true)] - public async Task ReceivedLoginEvent(List receivedLoginMessages) - { - await _messageReceivedLoginEventRepository.InsertManyAsync(receivedLoginMessages); - return SubscribeAck.Success(); - } - - } -} diff --git a/services/JiShe.CollectBus.Application/Subscribers/WorkerSubscriberAppService.cs b/services/JiShe.CollectBus.Application/Subscribers/WorkerSubscriberAppService.cs index ee5f646..11d7a5c 100644 --- a/services/JiShe.CollectBus.Application/Subscribers/WorkerSubscriberAppService.cs +++ b/services/JiShe.CollectBus.Application/Subscribers/WorkerSubscriberAppService.cs @@ -1,15 +1,6 @@ -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 JiShe.CollectBus.Common.Helpers; 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 { @@ -20,7 +11,7 @@ namespace JiShe.CollectBus.Subscribers { private readonly ILogger _logger; private readonly ITcpService _tcpService; - private readonly IIoTDbProvider _dbProvider; + private readonly IoTDBSessionPoolProvider _dbProvider; /// /// Initializes a new instance of the class. @@ -30,7 +21,7 @@ namespace JiShe.CollectBus.Subscribers /// IoTDB数据驱动 public WorkerSubscriberAppService(ILogger logger, ITcpService tcpService, - IIoTDbProvider dbProvider) + IoTDBSessionPoolProvider dbProvider) { _logger = logger; _tcpService = tcpService; @@ -45,7 +36,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerOneMinuteIssuedEventName)] + [KafkaSubscribe(KafkaTopicConsts.AmmeterSubscriberWorkerOneMinuteIssuedEventName)] public async Task AmmeterScheduledMeterOneMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogError($"1分钟采集电表数据下行消息消费队列开始处理:{receivedMessage.Serialize()}"); @@ -58,7 +49,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerFiveMinuteIssuedEventName, EnableBatch = true, BatchSize = 500)] + [KafkaSubscribe(KafkaTopicConsts.AmmeterSubscriberWorkerFiveMinuteIssuedEventName, EnableBatch = true, BatchSize = 500)] public async Task AmmeterScheduledMeterFiveMinuteReadingIssuedEvent(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogError($"5分钟采集电表数据下行消息消费队列开始处理:{receivedMessage.Serialize()}"); @@ -70,7 +61,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, EnableBatch = true, TaskCount = 30, BatchSize = 500)] + [KafkaSubscribe(KafkaTopicConsts.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, EnableBatch = true, TaskCount = 30, BatchSize = 500)] public async Task AmmeterScheduledMeterFifteenMinuteReadingIssuedEvent(List receivedMessage) { @@ -87,7 +78,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, EnableBatch = true, BatchSize = 500)] + [KafkaSubscribe(KafkaTopicConsts.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, EnableBatch = true, BatchSize = 500)] public async Task AmmeterScheduledAutoValveControl(List receivedMessage) { //todo 如果是时段自动阀控,需要检查当前的时间,如果时间在自动阀控时间段内,则发送自动阀控报文,否则不发送,尤其是消息队列阻塞或者延时过长的时候。以免造成生产事故。 @@ -104,7 +95,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, EnableBatch = true, BatchSize = 500)] + [KafkaSubscribe(KafkaTopicConsts.AmmeterSubscriberWorkerOtherIssuedEventName, EnableBatch = true, BatchSize = 500)] public async Task AmmeterScheduledOther(List receivedMessage) { foreach (var item in receivedMessage) @@ -120,7 +111,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerManualValveControlIssuedEventName)] + [KafkaSubscribe(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveControlIssuedEventName)] public async Task AmmeterScheduledManualValveControl(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogError($"电表手动阀控下行消息消费队列开始处理:{receivedMessage.Serialize()}"); @@ -134,7 +125,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerManualValveReadingIssuedEventName)] + [KafkaSubscribe(KafkaTopicConsts.AmmeterSubscriberWorkerManualValveReadingIssuedEventName)] public async Task AmmeterScheduledManualValveReading(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogError($"电表手动抄读下行消息消费队列开始处理:{receivedMessage.Serialize()}"); @@ -148,7 +139,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.AmmeterSubscriberWorkerRetryEventName)] + [KafkaSubscribe(KafkaTopicConsts.AmmeterSubscriberWorkerRetryEventName)] public async Task AmmeterScheduledMeterRetryReadingEvent(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogInformation("重试电表数据下行消息消费队列开始处理"); @@ -184,7 +175,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.WatermeterSubscriberWorkerAutoReadingIssuedEventName)] + [KafkaSubscribe(KafkaTopicConsts.WatermeterSubscriberWorkerAutoReadingIssuedEventName)] public async Task WatermeterScheduledAutoReading(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogError($"水表数据下行消息消费队列开始处理:{receivedMessage.Serialize()}"); @@ -198,7 +189,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.WatermeterSubscriberWorkerAutoValveControlIssuedEventName)] + [KafkaSubscribe(KafkaTopicConsts.WatermeterSubscriberWorkerAutoValveControlIssuedEventName)] public async Task WatermeterScheduleAutoValveControl(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogError($"水表自动阀控下行消息消费队列开始处理:{receivedMessage.Serialize()}"); @@ -212,7 +203,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.WatermeterSubscriberWorkerManualValveControlIssuedEventName)] + [KafkaSubscribe(KafkaTopicConsts.WatermeterSubscriberWorkerManualValveControlIssuedEventName)] public async Task WatermeterScheduleManualValveControl(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogError($"水表手动阀控下行消息消费队列开始处理:{receivedMessage.Serialize()}"); @@ -226,7 +217,7 @@ namespace JiShe.CollectBus.Subscribers /// /// /// - [KafkaSubscribe(ProtocolConst.WatermeterSubscriberWorkerManualValveReadingIssuedEventName)] + [KafkaSubscribe(KafkaTopicConsts.WatermeterSubscriberWorkerManualValveReadingIssuedEventName)] public async Task WatermeterScheduleManualValveReading(MeterReadingTelemetryPacketInfo receivedMessage) { _logger.LogError($"水表手动抄读下行消息消费队列开始处理:{receivedMessage.Serialize()}"); diff --git a/services/JiShe.CollectBus.Application/Workers/CreateToBeIssueTaskWorker.cs b/services/JiShe.CollectBus.Application/Workers/CreateToBeIssueTaskWorker.cs deleted file mode 100644 index d1de00a..0000000 --- a/services/JiShe.CollectBus.Application/Workers/CreateToBeIssueTaskWorker.cs +++ /dev/null @@ -1,43 +0,0 @@ -//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; - -// /// -// /// 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(); -// } -// } -//} diff --git a/services/JiShe.CollectBus.Application/Workers/DataDetectionFifteenMinuteWorker.cs b/services/JiShe.CollectBus.Application/Workers/DataDetectionFifteenMinuteWorker.cs deleted file mode 100644 index 392c801..0000000 --- a/services/JiShe.CollectBus.Application/Workers/DataDetectionFifteenMinuteWorker.cs +++ /dev/null @@ -1,39 +0,0 @@ -//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 deleted file mode 100644 index 037e2e2..0000000 --- a/services/JiShe.CollectBus.Application/Workers/EpiCollectWorker.cs +++ /dev/null @@ -1,39 +0,0 @@ -//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; - -// /// -// /// 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; -// } -// } -// } -//} diff --git a/services/JiShe.CollectBus.Application/Workers/ScheduledMeterReadingBackGroundWorkService.cs b/services/JiShe.CollectBus.Application/Workers/ScheduledMeterReadingBackGroundWorkService.cs new file mode 100644 index 0000000..b9d0a25 --- /dev/null +++ b/services/JiShe.CollectBus.Application/Workers/ScheduledMeterReadingBackGroundWorkService.cs @@ -0,0 +1,34 @@ +using JiShe.CollectBus.ScheduledMeterReading; +using JiShe.ServicePro.Core; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Workers +{ + /// + /// 定时抄表 + /// + /// 抄读服务 + /// + public class ScheduledMeterReadingBackGroundWorkService(IScheduledMeterReadingService scheduledMeterReadingService, ILogger logger) : SystemBackGroundWorkService(logger) + { + protected override TimeSpan GetInterval() + { + // 返回执行间隔时间 + return TimeSpan.FromSeconds(10); + } + + protected override async Task DoWorkAsync(CancellationToken cancellationToken) + { + // 这里编写具体的后台任务逻辑,例如从数据库中读取数据、发送网络请求等 + // 这里的逻辑会每隔一段时间执行一次,时间间隔由 GetInterval 方法返回的值决定 + Logger.LogWarning($"定时抄读后台任务执行中...{DateTime.Now.ToString()}"); + //await scheduledMeterReadingService.CreateToBeIssueTasks(); + } + } +} diff --git a/services/JiShe.CollectBus.Application/Workers/SubscriberFifteenMinuteWorker.cs b/services/JiShe.CollectBus.Application/Workers/SubscriberFifteenMinuteWorker.cs deleted file mode 100644 index a7ca7c9..0000000 --- a/services/JiShe.CollectBus.Application/Workers/SubscriberFifteenMinuteWorker.cs +++ /dev/null @@ -1,48 +0,0 @@ -//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; - -// /// -// /// 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(); - -// //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 deleted file mode 100644 index 119421e..0000000 --- a/services/JiShe.CollectBus.Application/Workers/SubscriberFiveMinuteWorker.cs +++ /dev/null @@ -1,42 +0,0 @@ -//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; - -// /// -// /// 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(); -// } -// } -//} diff --git a/services/JiShe.CollectBus.Application/Workers/SubscriberOneMinuteWorker.cs b/services/JiShe.CollectBus.Application/Workers/SubscriberOneMinuteWorker.cs deleted file mode 100644 index 419a681..0000000 --- a/services/JiShe.CollectBus.Application/Workers/SubscriberOneMinuteWorker.cs +++ /dev/null @@ -1,44 +0,0 @@ -//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; - -// /// -// /// 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(); - -// //await _scheduledMeterReadingService.WatermeterScheduledMeterOneMinuteReading(); - -// } -// } -//} diff --git a/services/JiShe.CollectBus.DbMigrator/CollectBusDbMigratorModule.cs b/services/JiShe.CollectBus.DbMigrator/CollectBusDbMigratorModule.cs index 3767b52..22b1ff0 100644 --- a/services/JiShe.CollectBus.DbMigrator/CollectBusDbMigratorModule.cs +++ b/services/JiShe.CollectBus.DbMigrator/CollectBusDbMigratorModule.cs @@ -1,4 +1,4 @@ -using JiShe.CollectBus.MongoDB; +using JiShe.ServicePro.IoTDBManagement; using Volo.Abp.Autofac; using Volo.Abp.Modularity; @@ -6,7 +6,7 @@ namespace JiShe.CollectBus.DbMigrator; [DependsOn( typeof(AbpAutofacModule), - typeof(CollectBusMongoDbModule), + typeof(IoTDBManagementDomainModule), typeof(CollectBusApplicationContractsModule) )] public class CollectBusDbMigratorModule : AbpModule diff --git a/services/JiShe.CollectBus.DbMigrator/DbMigratorHostedService.cs b/services/JiShe.CollectBus.DbMigrator/DbMigratorHostedService.cs index 46f1edb..b41831c 100644 --- a/services/JiShe.CollectBus.DbMigrator/DbMigratorHostedService.cs +++ b/services/JiShe.CollectBus.DbMigrator/DbMigratorHostedService.cs @@ -7,6 +7,7 @@ using JiShe.CollectBus.Data; using Serilog; using Volo.Abp; using Volo.Abp.Data; +using JiShe.ServicePro.IoTDBManagement.SessionPools; namespace JiShe.CollectBus.DbMigrator; @@ -33,10 +34,16 @@ public class DbMigratorHostedService : IHostedService { await application.InitializeAsync(); + //await application + // .ServiceProvider + // .GetRequiredService() + // .MigrateAsync(); + + //初始化IoTDB表模型 await application .ServiceProvider - .GetRequiredService() - .MigrateAsync(); + .GetRequiredService().GetSessionPool(true) + .InitTableSessionModelAsync(); await application.ShutdownAsync(); diff --git a/services/JiShe.CollectBus.DbMigrator/JiShe.CollectBus.DbMigrator.csproj b/services/JiShe.CollectBus.DbMigrator/JiShe.CollectBus.DbMigrator.csproj index f875a56..71eb5a2 100644 --- a/services/JiShe.CollectBus.DbMigrator/JiShe.CollectBus.DbMigrator.csproj +++ b/services/JiShe.CollectBus.DbMigrator/JiShe.CollectBus.DbMigrator.csproj @@ -4,22 +4,23 @@ Exe - net8.0 + net9.0 enable - - - - - + + + + + + - - + + diff --git a/services/JiShe.CollectBus.DbMigrator/appsettings.json b/services/JiShe.CollectBus.DbMigrator/appsettings.json index 90ea5ae..bc9289e 100644 --- a/services/JiShe.CollectBus.DbMigrator/appsettings.json +++ b/services/JiShe.CollectBus.DbMigrator/appsettings.json @@ -1,5 +1,15 @@ { "ConnectionStrings": { "Default": "mongodb://admin:collectbus_mongodb_jishe@118.190.144.92:37017/JiSheCollectBus?authSource=admin" + }, + "IoTDBOptions": { + "UserName": "root", + "Password": "Lixiao@1980", + "TreeModelClusterList": [ "47.110.53.196:6667", "47.110.60.222:6667", "47.110.62.104:6667" ], + "TableModelClusterList": [ "47.110.53.196:6667", "47.110.60.222:6667", "47.110.62.104:6667" ], + "PoolSize": 32, + "TableModelDataBaseName": "energy", + "OpenDebugMode": true, + "UseTableSessionPoolByDefault": false } } diff --git a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs deleted file mode 100644 index 796f328..0000000 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs +++ /dev/null @@ -1,41 +0,0 @@ -using JiShe.CollectBus.Analyzers.Shared; -using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Model; -using System; - -namespace JiShe.CollectBus.Ammeters -{ - [SourceAnalyzers(EntityTypeEnum.TableModel)] - public class ElectricityMeter : IoTEntity - { - [ATTRIBUTEColumn] - public string MeterModel { get; set; } - - /// - /// 下发消息内容 - /// - [FIELDColumn] - public string IssuedMessageHexString { get; set; } - - ///// - ///// 下发消息Id - ///// - //[FIELDColumn] - //public string IssuedMessageId { get; set; } - - [FIELDColumn] - public double Voltage { get; set; } - - [FIELDColumn] - public double Current { get; set; } - - [FIELDColumn] - 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 deleted file mode 100644 index 6eb5ef4..0000000 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs +++ /dev/null @@ -1,38 +0,0 @@ -using JiShe.CollectBus.Analyzers.Shared; -using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Model; -using System; - -namespace JiShe.CollectBus.Ammeters -{ - [SourceAnalyzers(EntityTypeEnum.TreeModel)] - public class ElectricityMeterTreeModel : IoTEntity - { - [ATTRIBUTEColumn] - public string MeterModel { get; set; } - - /// - /// 下发消息内容 - /// - [FIELDColumn] - public string IssuedMessageHexString { get; set; } - - ///// - ///// 下发消息Id - ///// - //[FIELDColumn] - //public string IssuedMessageId { get; set; } - - [FIELDColumn] - public double Voltage { get; set; } - - [FIELDColumn] - public double Current { get; set; } - - [FIELDColumn] - public double Power { get; set; } - - [FIELDColumn] - public double? Currentd { get; set; } - } -} diff --git a/services/JiShe.CollectBus.Domain/CollectBusDomainModule.cs b/services/JiShe.CollectBus.Domain/CollectBusDomainModule.cs index b09cbf8..f461cbc 100644 --- a/services/JiShe.CollectBus.Domain/CollectBusDomainModule.cs +++ b/services/JiShe.CollectBus.Domain/CollectBusDomainModule.cs @@ -6,10 +6,12 @@ using Volo.Abp.Caching; using Volo.Abp.AuditLogging; using Volo.Abp.BackgroundJobs; using Volo.Abp.Emailing; +using JiShe.ServicePro.IoTDBManagement; namespace JiShe.CollectBus; [DependsOn( + typeof(IoTDBManagementDomainModule), typeof(AbpCachingModule) )] public class CollectBusDomainModule : AbpModule diff --git a/services/JiShe.CollectBus.Domain/GlobalUsings.cs b/services/JiShe.CollectBus.Domain/GlobalUsings.cs new file mode 100644 index 0000000..61e52b6 --- /dev/null +++ b/services/JiShe.CollectBus.Domain/GlobalUsings.cs @@ -0,0 +1,8 @@ +// Global using directives + +global using System.Text; +global using Volo.Abp.Modularity; +global using JiShe.ServicePro.Enums; +global using JiShe.ServicePro.FreeRedisProvider; +global using JiShe.ServicePro.Consts; +global using JiShe.ServicePro.Core; \ No newline at end of file diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterAutoValveControlSetting.cs b/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterAutoValveControlSetting.cs index 0116def..5a3179f 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterAutoValveControlSetting.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterAutoValveControlSetting.cs @@ -1,4 +1,5 @@ using JiShe.CollectBus.Common.Models; +using JiShe.ServicePro.FreeRedisProvider; using System; using System.Collections.Generic; using System.Linq; diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterInfo.cs index a7792c3..8a9d854 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterInfo.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/Ammeters/AmmeterInfo.cs @@ -1,5 +1,7 @@ using FreeSql.DataAnnotations; using JiShe.CollectBus.Common.Models; +using JiShe.ServicePro.Core; +using JiShe.ServicePro.FreeRedisProvider; using System; using System.Collections.Generic; using System.Linq; @@ -20,7 +22,7 @@ namespace JiShe.CollectBus.IotSystems.Ammeters /// ZSet排序索引分数值,具体值可以根据不同业务场景进行定义,例如时间戳 /// [Column(IsIgnore = true)] - public override long ScoreValue => Common.Helpers.CommonHelper.GetFocusScores(FocusAddress,MeteringCode); + public override long ScoreValue => CommonHelper.GetFocusScores(FocusAddress,MeteringCode); /// /// 电表名称 diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceInfo.cs deleted file mode 100644 index d21a90f..0000000 --- a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceInfo.cs +++ /dev/null @@ -1,174 +0,0 @@ -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; } - - /// - /// 倍率 - /// - public decimal TimesRate { get; set; } - - /// - /// 电表名称 - /// - public string Name { get; set; } - - /// - /// 集中器地址 - /// - public string Address { get; set; } - - /// - /// 集中器区域代码 - /// - public string AreaCode { get; set; } - - /// - /// 仅当MeterType为电表时,电表类别 (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"] - /// - [Column(IsIgnore = true)] - public List 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 deleted file mode 100644 index c909930..0000000 --- a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTableModelDataInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -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)] - [IgnoreInitTable] - public class DeviceTableModelDataInfo : 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 deleted file mode 100644 index 9fcb850..0000000 --- a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTreeModelDataInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -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.TreeModel)] - public class DeviceTreeModelDataInfo : IoTEntity - { - - [FIELDColumn] - public bool xfdsa { get; set; } - } -} diff --git a/services/JiShe.CollectBus.Domain/IotSystems/MessageIssueds/ScheduledMeterReadingIssuedEventMessage.cs b/services/JiShe.CollectBus.Domain/IotSystems/MessageIssueds/ScheduledMeterReadingIssuedEventMessage.cs deleted file mode 100644 index 41ba7ea..0000000 --- a/services/JiShe.CollectBus.Domain/IotSystems/MessageIssueds/ScheduledMeterReadingIssuedEventMessage.cs +++ /dev/null @@ -1,38 +0,0 @@ -using JiShe.CollectBus.Common.Enums; -using System; -using Volo.Abp.Domain.Entities; - -namespace JiShe.CollectBus.IotSystems.MessageIssueds -{ - /// - /// 定时抄读Kafka消息实体,1分钟、5分钟、15分钟 - /// - public class ScheduledMeterReadingIssuedEventMessage - { - /// - /// 下发消息内容 - /// - public string MessageHexString { get; set; } - - /// - /// 集中器编号 - /// - public string FocusAddress { get; set; } - - /// - /// 采集时间间隔,通过Kafka主题区分(分钟,如15) - /// - public string TimeDensity { get; set; } - - /// - /// 消息Id - /// - public string MessageId { get; set; } - - /// - /// 最后一次消息Id,用于在消费消息时检查上一个任务是否处理完。 - /// - public string LastMessageId { get; set; } - - } -} diff --git a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingRecords.cs b/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingRecords.cs index b1f1112..f0fb069 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingRecords.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingRecords.cs @@ -1,4 +1,5 @@ using JiShe.CollectBus.Common.Enums; +using JiShe.ServicePro.Enums; using System; using System.Collections.Generic; using System.Linq; diff --git a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs deleted file mode 100644 index b779022..0000000 --- a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs +++ /dev/null @@ -1,191 +0,0 @@ -using JiShe.CollectBus.Analyzers.Shared; -using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Model; -using System; - -namespace JiShe.CollectBus.IotSystems.MeterReadingRecords -{ - /// - /// 抄读任务数据 - /// - [SourceAnalyzers(EntityTypeEnum.TableModel)] - public class MeterReadingTelemetryPacketInfo : IoTEntity - { - /// - /// 排序索引分数值,具体值可以根据不同业务场景进行定义,例如时间戳、或者某一个固定的标识1 - /// - [FIELDColumn] - public string ScoreValue { get; set; } - - /// - /// 数据包类型 - /// - [FIELDColumn] - public int PacketType { get; set; } - - /// - /// 是否手动操作 - /// - [FIELDColumn] - public bool ManualOrNot { get; set; } - - /// - /// 任务数据唯一标记 - /// - [FIELDColumn] - public string TaskMark { get; set; } - - /// - /// 是否超时 - /// - [FIELDColumn] - public bool IsTimeout { get; set; } = false; - - /// - /// 待抄读时间 - /// - [FIELDColumn] - public DateTime PendingCopyReadTime { get; set; } - - /// - /// 集中器Id - /// - [FIELDColumn] - public int FocusId { get; set; } - - - /// - /// 集中器地址 - /// - [FIELDColumn] - public string FocusAddress { get; set; } - - /// - /// 表地址 - /// - [FIELDColumn] - public string MeterAddress { get; set; } - - /// - /// 数据库业务ID - /// - [FIELDColumn] - public int DatabaseBusiID { get; set; } - - /// - /// AFN功能码 - /// - [FIELDColumn] - public int AFN { get; set; } - - /// - /// 抄读功能码 - /// - [FIELDColumn] - public int Fn { get; set; } - - /// - /// 抄读计量点 - /// - [FIELDColumn] - public int Pn { get; set; } - - /// - /// 采集项编码 - /// - [FIELDColumn] - public string ItemCode { get; set; } - - - /// - /// 子项编码,一般用于透明转发的编码 - /// - [FIELDColumn] - public string SubItemCode { get; set; } - - /// - /// 帧序列域 SEQ - /// - [FIELDColumn] - public int Seq { get; set; } - - /// - /// 地址域A3的主站地址MSA - /// - [FIELDColumn] - public int MSA { get; set; } - - /// - /// 是否发送 - /// - [FIELDColumn] - public bool IsSend { get; set; } - - /// - /// 发送次数 - /// - [FIELDColumn] - public int? SendNum { get; set; } - - /// - /// 下次发送时间 - /// - [FIELDColumn] - public DateTime? NextSendTime { get; set; } - - /// - /// 创建时间 - /// - [FIELDColumn] - public DateTime CreationTime { get; set; } - - /// - /// 下发消息内容 - /// - [FIELDColumn] - public string IssuedMessageHexString { get; set; } - - /// - /// 下发消息Id - /// - [FIELDColumn] - public string IssuedMessageId { get; set; } - - /// - /// 集中器采集密度 - /// - [FIELDColumn] - public int FocusDensity { get; set; } - - /// - /// 消息上报内容 - /// - [FIELDColumn] - public string? ReceivedMessageHexString { get; set; } - - /// - /// 消息上报时间 - /// - [FIELDColumn] - public DateTime? ReceivedTime { get; set; } - - /// - /// 上报消息Id - /// - [FIELDColumn] - public string ReceivedMessageId { get; set; } - - /// - /// 上报报文解析备注,异常情况下才有 - /// - [FIELDColumn] - public string ReceivedRemark { get; set; } - - /// - /// 是否已上报 - /// - [FIELDColumn] - public bool IsReceived { get; set; } - - } -} diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Watermeter/WatermeterInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Watermeter/WatermeterInfo.cs index eac70a1..3749089 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/Watermeter/WatermeterInfo.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/Watermeter/WatermeterInfo.cs @@ -1,6 +1,8 @@ using FreeSql.DataAnnotations; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Models; +using JiShe.ServicePro.Enums; +using JiShe.ServicePro.FreeRedisProvider; using System; using System.Collections.Generic; using System.Linq; diff --git a/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj b/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj index e69f3b6..859f325 100644 --- a/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj +++ b/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj @@ -3,7 +3,7 @@ - net8.0 + net9.0 enable JiShe.CollectBus @@ -20,21 +20,20 @@ - - - - + - - - - - - + + + + + + + + diff --git a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AnalysisBaseDto.cs b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AnalysisBaseDto.cs index c02ee76..6a6e8a2 100644 --- a/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AnalysisBaseDto.cs +++ b/services/JiShe.CollectBus.Domain/Protocol3761/Dto/AnalysisBaseDto.cs @@ -1,4 +1,5 @@ using JiShe.CollectBus.Common.Enums; +using JiShe.ServicePro.Enums; using System; using System.Collections.Generic; using System.Data; @@ -44,7 +45,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto /// /// 项目Id /// - public int ProjectId { get; set; } + public string ProjectId { get; set; } /// /// 设备ID(电表ID,水表ID,气表ID,集中器ID等) diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusDbContext.cs b/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusDbContext.cs deleted file mode 100644 index bf57b27..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusDbContext.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Volo.Abp.Data; -using Volo.Abp.EntityFrameworkCore; - -namespace JiShe.CollectBus.EntityFrameworkCore; - -[ConnectionStringName("Default")] -public class CollectBusDbContext : - AbpDbContext -{ - /* Add DbSet properties for your Aggregate Roots / Entities here. */ - - - #region Entities from the modules - - /* Notice: We only implemented IIdentityProDbContext and ISaasDbContext - * and replaced them for this DbContext. This allows you to perform JOIN - * queries for the entities of these modules over the repositories easily. You - * typically don't need that for other modules. But, if you need, you can - * implement the DbContext interface of the needed module and use ReplaceDbContext - * attribute just like IIdentityProDbContext and ISaasDbContext. - * - * More info: Replacing a DbContext of a module ensures that the related module - * uses this DbContext on runtime. Otherwise, it will use its own DbContext class. - */ - - #endregion - - public CollectBusDbContext(DbContextOptions options) - : base(options) - { - - } - - protected override void OnModelCreating(ModelBuilder builder) - { - base.OnModelCreating(builder); - } -} diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusDbContextFactory.cs b/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusDbContextFactory.cs deleted file mode 100644 index 07cc790..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusDbContextFactory.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.IO; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.Configuration; - -namespace JiShe.CollectBus.EntityFrameworkCore; - -/* This class is needed for EF Core console commands - * (like Add-Migration and Update-Database commands) */ -public class CollectBusDbContextFactory : IDesignTimeDbContextFactory -{ - public CollectBusDbContext CreateDbContext(string[] args) - { - var configuration = BuildConfiguration(); - - CollectBusEfCoreEntityExtensionMappings.Configure(); - - var builder = new DbContextOptionsBuilder() - .UseMySql(configuration.GetConnectionString("Default"), MySqlServerVersion.LatestSupportedServerVersion); - - return new CollectBusDbContext(builder.Options); - } - - private static IConfigurationRoot BuildConfiguration() - { - var builder = new ConfigurationBuilder() - .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../JiShe.CollectBus.DbMigrator/")) - .AddJsonFile("appsettings.json", optional: false); - - return builder.Build(); - } -} diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusEfCoreEntityExtensionMappings.cs b/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusEfCoreEntityExtensionMappings.cs deleted file mode 100644 index 8f002f3..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusEfCoreEntityExtensionMappings.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Volo.Abp.Identity; -using Volo.Abp.ObjectExtending; -using Volo.Abp.Threading; - -namespace JiShe.CollectBus.EntityFrameworkCore; - -public static class CollectBusEfCoreEntityExtensionMappings -{ - private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); - - public static void Configure() - { - CollectBusGlobalFeatureConfigurator.Configure(); - CollectBusModuleExtensionConfigurator.Configure(); - - OneTimeRunner.Run(() => - { - /* You can configure extra properties for the - * entities defined in the modules used by your application. - * - * This class can be used to map these extra properties to table fields in the database. - * - * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. - * USE CollectBusModuleExtensionConfigurator CLASS (in the Domain.Shared project) - * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES - * - * Example: Map a property to a table field: - - ObjectExtensionManager.Instance - .MapEfCoreProperty( - "MyProperty", - (entityBuilder, propertyBuilder) => - { - propertyBuilder.HasMaxLength(128); - } - ); - - * See the documentation for more: - * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities - */ - }); - } -} diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusEntityFrameworkCoreModule.cs b/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusEntityFrameworkCoreModule.cs deleted file mode 100644 index bb34e67..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/CollectBusEntityFrameworkCoreModule.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.AuditLogging.EntityFrameworkCore; -using Volo.Abp.BackgroundJobs.EntityFrameworkCore; -using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.EntityFrameworkCore.MySQL; -using Volo.Abp.FeatureManagement.EntityFrameworkCore; -using Volo.Abp.Identity.EntityFrameworkCore; -using Volo.Abp.Modularity; -using Volo.Abp.PermissionManagement.EntityFrameworkCore; -using Volo.Abp.SettingManagement.EntityFrameworkCore; -using Volo.Abp.BlobStoring.Database.EntityFrameworkCore; - -namespace JiShe.CollectBus.EntityFrameworkCore; - -[DependsOn( - typeof(CollectBusDomainModule), - typeof(AbpPermissionManagementEntityFrameworkCoreModule), - typeof(AbpSettingManagementEntityFrameworkCoreModule), - typeof(AbpEntityFrameworkCoreMySQLModule), - typeof(AbpBackgroundJobsEntityFrameworkCoreModule), - typeof(AbpAuditLoggingEntityFrameworkCoreModule), - typeof(AbpFeatureManagementEntityFrameworkCoreModule), - typeof(AbpIdentityEntityFrameworkCoreModule), - typeof(BlobStoringDatabaseEntityFrameworkCoreModule) - )] -public class CollectBusEntityFrameworkCoreModule : AbpModule -{ - public override void PreConfigureServices(ServiceConfigurationContext context) - { - - CollectBusEfCoreEntityExtensionMappings.Configure(); - } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAbpDbContext(options => - { - /* Remove "includeAllEntities: true" to create - * default repositories only for aggregate roots */ - options.AddDefaultRepositories(includeAllEntities: true); - }); - - Configure(options => - { - /* The main point to change your DBMS. - * See also CollectBusDbContextFactory for EF Core tooling. */ - options.UseMySQL(); - }); - } -} diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreCollectBusDbSchemaMigrator.cs b/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreCollectBusDbSchemaMigrator.cs deleted file mode 100644 index 2b3509a..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreCollectBusDbSchemaMigrator.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using JiShe.CollectBus.Data; -using Volo.Abp.DependencyInjection; - -namespace JiShe.CollectBus.EntityFrameworkCore; - -public class EntityFrameworkCoreCollectBusDbSchemaMigrator - : ICollectBusDbSchemaMigrator, ITransientDependency -{ - private readonly IServiceProvider _serviceProvider; - - public EntityFrameworkCoreCollectBusDbSchemaMigrator(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public async Task MigrateAsync() - { - /* We intentionally resolving the CollectBusDbContext - * from IServiceProvider (instead of directly injecting it) - * to properly get the connection string of the current tenant in the - * current scope. - */ - - await _serviceProvider - .GetRequiredService() - .Database - .MigrateAsync(); - } -} diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/FodyWeavers.xml b/services/JiShe.CollectBus.EntityFrameworkCore/FodyWeavers.xml deleted file mode 100644 index 00e1d9a..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/JiShe.CollectBus.EntityFrameworkCore.abppkg b/services/JiShe.CollectBus.EntityFrameworkCore/JiShe.CollectBus.EntityFrameworkCore.abppkg deleted file mode 100644 index e1c64f0..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/JiShe.CollectBus.EntityFrameworkCore.abppkg +++ /dev/null @@ -1,3 +0,0 @@ -{ - "role": "lib.ef" -} \ No newline at end of file diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/JiShe.CollectBus.EntityFrameworkCore.csproj b/services/JiShe.CollectBus.EntityFrameworkCore/JiShe.CollectBus.EntityFrameworkCore.csproj deleted file mode 100644 index e6a6338..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/JiShe.CollectBus.EntityFrameworkCore.csproj +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - net8.0 - enable - JiShe.CollectBus - - - - - - - - - - - - - - - - - - - - - - - - - - - runtime; build; native; contentfiles; analyzers - compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native - - - - diff --git a/services/JiShe.CollectBus.EntityFrameworkCore/Properties/AssemblyInfo.cs b/services/JiShe.CollectBus.EntityFrameworkCore/Properties/AssemblyInfo.cs deleted file mode 100644 index 23df7c8..0000000 --- a/services/JiShe.CollectBus.EntityFrameworkCore/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,2 +0,0 @@ -using System.Runtime.CompilerServices; -[assembly:InternalsVisibleToAttribute("JiShe.CollectBus.EntityFrameworkCore.Tests")] diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationApplicationContractsModule.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationApplicationContractsModule.cs deleted file mode 100644 index 756ba99..0000000 --- a/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationApplicationContractsModule.cs +++ /dev/null @@ -1,15 +0,0 @@ -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 deleted file mode 100644 index cc0c233..0000000 --- a/services/JiShe.CollectBus.Migration.Application.Contracts/CollectBusMigrationRemoteServiceConsts.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace JiShe.CollectBus.Migration; - -public class CollectBusMigrationRemoteServiceConsts -{ - public const string RemoteServiceName = "CollectBus"; - - public const string ModuleName = "collectBus"; -} diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/IDataMigrationService.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/IDataMigrationService.cs deleted file mode 100644 index c6fbb96..0000000 --- a/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/IDataMigrationService.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Migration -{ - /// - /// 数据迁移服务 - /// - public interface IDataMigrationService - { - /// - /// 开始迁移 - /// - /// - Task StartMigrationAsync(); - } -} diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs deleted file mode 100644 index 6e70531..0000000 --- a/services/JiShe.CollectBus.Migration.Application.Contracts/DataMigration/Options/DataMigrationOptions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Migration -{ - /// - /// 数据迁移配置 - /// - public class DataMigrationOptions - { - /// - /// MongoDb每批处理量 - /// - public int MongoDbDataBatchSize { get; set; } = 1000; - - /// - /// 批量处理通道容量 - /// - public int ChannelCapacity { get; set; } = 100_00; - - /// - /// 数据库 每批处理量 - /// - public int SqlBulkBatchSize { get; set; } = 1000; - - /// - /// 数据库 每批处理超时时间 - /// - public int SqlBulkTimeout { get; set; } = 60; - - /// - /// 处理器数量 - /// - public int ProcessorsCount { get; set; } = 4; - } -} diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/FodyWeavers.xml b/services/JiShe.CollectBus.Migration.Application.Contracts/FodyWeavers.xml deleted file mode 100644 index 1715698..0000000 --- a/services/JiShe.CollectBus.Migration.Application.Contracts/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/services/JiShe.CollectBus.Migration.Application.Contracts/ICollectWorker.cs b/services/JiShe.CollectBus.Migration.Application.Contracts/ICollectWorker.cs deleted file mode 100644 index e2c4fa8..0000000 --- a/services/JiShe.CollectBus.Migration.Application.Contracts/ICollectWorker.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Migration -{ - 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 deleted file mode 100644 index f3ef574..0000000 --- a/services/JiShe.CollectBus.Migration.Application.Contracts/JiShe.CollectBus.Migration.Application.Contracts.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - 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 deleted file mode 100644 index 5ec9a4c..0000000 --- a/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationAppService.cs +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 8a82b7e..0000000 --- a/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationApplicationModule.cs +++ /dev/null @@ -1,70 +0,0 @@ -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 deleted file mode 100644 index 4e1a5c6..0000000 --- a/services/JiShe.CollectBus.Migration.Application/CollectBusMigrationlicationAutoMapperProfile.cs +++ /dev/null @@ -1,13 +0,0 @@ -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.Migration.Application/DataMigration/DataMigrationService.cs b/services/JiShe.CollectBus.Migration.Application/DataMigration/DataMigrationService.cs deleted file mode 100644 index b85d5b0..0000000 --- a/services/JiShe.CollectBus.Migration.Application/DataMigration/DataMigrationService.cs +++ /dev/null @@ -1,152 +0,0 @@ -using JiShe.CollectBus.IotSystems.MeterReadingRecords; -using LiteDB; -using Microsoft.Extensions.Options; -using System; -using System.Data; -using System.Linq; -using System.Threading.Channels; -using System.Threading.Tasks; -using Volo.Abp.Domain.Repositories; - -namespace JiShe.CollectBus.Migration.DataMigration -{ - /// - /// 数据迁移服务 - /// - public class DataMigrationService: CollectBusMigrationAppService, IDataMigrationService - { - private readonly IRepository _meterReadingRecordsRepository; - private readonly DataMigrationOptions _options; - - - public DataMigrationService(IOptions options, - IRepository meterReadingRecordsRepository) - { - _options = options.Value; - _meterReadingRecordsRepository = meterReadingRecordsRepository; - } - - /// - /// 开始迁移 - /// - /// - public async Task StartMigrationAsync() - { - var rawDataChannel = Channel.CreateBounded(new BoundedChannelOptions(_options.ChannelCapacity) - { - SingleWriter = false, - SingleReader = false, - FullMode = BoundedChannelFullMode.Wait - }); - - var cleanDataChannel = Channel.CreateBounded(new BoundedChannelOptions(_options.ChannelCapacity) - { - SingleWriter = false, - SingleReader = false, - FullMode = BoundedChannelFullMode.Wait - }); - - // 启动生产者和消费者 - var producer = Task.Run(() => ProduceDataAsync(rawDataChannel.Writer)); - - var processors = Enumerable.Range(0, _options.ProcessorsCount) - .Select(_ => Task.Run(() => ProcessDataAsync(rawDataChannel.Reader, cleanDataChannel.Writer))) - .ToArray(); - - var consumer = Task.Run(() => ConsumeDataAsync(cleanDataChannel.Reader)); - - await Task.WhenAll(new[] { producer }.Union(processors).Union(new[] { consumer })); - } - - /// - /// 生产者,生产数据,主要是从MongoDB中读取数据 - /// - /// - /// - private async Task ProduceDataAsync(ChannelWriter writer) - { - //while (true) - //{ - // var queryable = await _meterReadingRecordsRepository.GetQueryableAsync(); - // var batchRecords = queryable.Where(d => d.MigrationStatus == Common.Enums.RecordsDataMigrationStatusEnum.NotStarted) - // .Take(_options.MongoDbDataBatchSize) - // .ToArray(); - - // if (batchRecords == null || batchRecords.Length == 0) - // { - // writer.Complete(); - // break; - // } - - // await writer.WriteAsync(batchRecords); - //} - } - - /// - /// 清洗数据 - /// - /// - /// - /// - private async Task ProcessDataAsync(ChannelReader reader, ChannelWriter writer) - { - await foreach (var batch in reader.ReadAllAsync()) - { - //var dataTable = new DataTable(); - //dataTable.Columns.Add("Id", typeof(string)); - //dataTable.Columns.Add("CleanName", typeof(string)); - //dataTable.Columns.Add("ProcessedTime", typeof(DateTime)); - - //foreach (var doc in batch) - //{ - // // 业务清洗逻辑 - // var cleanName = doc["name"].AsString.Trim().ToUpper(); - // dataTable.Rows.Add( - // doc["_id"].ToString(), - // cleanName, - // DateTime.UtcNow); - //} - - //await writer.WriteAsync(dataTable); - - // 批量更新标记 - //var ids = batch.Select(d => d.Id).ToArray(); - //foreach (var item in batch) - //{ - // item.MigrationStatus = Common.Enums.RecordsDataMigrationStatusEnum.InProgress; - // item.MigrationTime = DateTime.Now; - //} - - //await _meterReadingRecordsRepository.UpdateManyAsync(batch); - } - writer.Complete(); - } - - /// - /// 消费清洗后的数据入库 - /// - /// - /// - private async Task ConsumeDataAsync(ChannelReader reader) - { - //await using var connection = new SqlConnection(_sqlConnectionString); - //await connection.OpenAsync(); - - //await foreach (var dataTable in reader.ReadAllAsync()) - //{ - // using var bulkCopy = new SqlBulkCopy(connection) - // { - // DestinationTableName = "CleanData", - // BatchSize = 5000, - // BulkCopyTimeout = 300 - // }; - - // bulkCopy.ColumnMappings.Add("Id", "Id"); - // bulkCopy.ColumnMappings.Add("CleanName", "CleanName"); - // bulkCopy.ColumnMappings.Add("ProcessedTime", "ProcessedTime"); - - // await bulkCopy.WriteToServerAsync(dataTable); - //} - } - } -} diff --git a/services/JiShe.CollectBus.Migration.Application/FodyWeavers.xml b/services/JiShe.CollectBus.Migration.Application/FodyWeavers.xml deleted file mode 100644 index 1715698..0000000 --- a/services/JiShe.CollectBus.Migration.Application/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ 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 deleted file mode 100644 index bce2a34..0000000 --- a/services/JiShe.CollectBus.Migration.Application/JiShe.CollectBus.Migration.Application.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - net8.0 - enable - JiShe.CollectBus.Migration - True - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/services/JiShe.CollectBusEPO.Application.Contracts/CollectBusEPOApplicationContractsModule.cs b/services/JiShe.CollectBusEPO.Application.Contracts/CollectBusEPOApplicationContractsModule.cs deleted file mode 100644 index 1f538b1..0000000 --- a/services/JiShe.CollectBusEPO.Application.Contracts/CollectBusEPOApplicationContractsModule.cs +++ /dev/null @@ -1,16 +0,0 @@ -using JiShe.CollectBus; - -namespace JiShe.CollectBusEPO -{ - [DependsOn( - typeof(CollectBusDomainSharedModule), - typeof(AbpObjectExtendingModule) - )] - public class CollectBusEPOApplicationContractsModule : AbpModule - { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - CollectBusEPODtoExtensions.Configure(); - } - } -} diff --git a/services/JiShe.CollectBusEPO.Application.Contracts/CollectBusEPODtoExtensions.cs b/services/JiShe.CollectBusEPO.Application.Contracts/CollectBusEPODtoExtensions.cs deleted file mode 100644 index 02e750a..0000000 --- a/services/JiShe.CollectBusEPO.Application.Contracts/CollectBusEPODtoExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace JiShe.CollectBusEPO -{ - public static class CollectBusEPODtoExtensions - { - private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); - - public static void Configure() - { - OneTimeRunner.Run(() => - { - /* You can add extension properties to DTOs - * defined in the depended modules. - * - * Example: - * - * ObjectExtensionManager.Instance - * .AddOrUpdateProperty("Title"); - * - * See the documentation for more: - * https://docs.abp.io/en/abp/latest/Object-Extensions - */ - }); - } - } -} \ No newline at end of file diff --git a/services/JiShe.CollectBusEPO.Application.Contracts/Files/FileUploadOutputDto.cs b/services/JiShe.CollectBusEPO.Application.Contracts/Files/FileUploadOutputDto.cs deleted file mode 100644 index 4ddfa20..0000000 --- a/services/JiShe.CollectBusEPO.Application.Contracts/Files/FileUploadOutputDto.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace JiShe.CollectBusEPO.Files; - -public class FileUploadOutputDto -{ - public string Name { get; set; } - public string Path { get; set; } -} diff --git a/services/JiShe.CollectBusEPO.Application.Contracts/GlobalUsings.cs b/services/JiShe.CollectBusEPO.Application.Contracts/GlobalUsings.cs deleted file mode 100644 index 7e82668..0000000 --- a/services/JiShe.CollectBusEPO.Application.Contracts/GlobalUsings.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Global using directives - -global using System; -global using System.Threading.Tasks; -global using Volo.Abp.Application.Services; -global using Volo.Abp.Authorization.Permissions; -global using Volo.Abp.DependencyInjection; -global using Volo.Abp.Localization; -global using Volo.Abp.Modularity; -global using Volo.Abp.ObjectExtending; -global using Volo.Abp.Threading; \ No newline at end of file diff --git a/services/JiShe.CollectBusEPO.Application.Contracts/JiShe.CollectBusEPO.Application.Contracts.csproj b/services/JiShe.CollectBusEPO.Application.Contracts/JiShe.CollectBusEPO.Application.Contracts.csproj deleted file mode 100644 index 23e52c4..0000000 --- a/services/JiShe.CollectBusEPO.Application.Contracts/JiShe.CollectBusEPO.Application.Contracts.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - net8.0 - JiShe.CollectBusEPO - - - - - - - - - - - - - diff --git a/services/JiShe.CollectBusEPO.Application.Contracts/Jobs/IRecurringJob.cs b/services/JiShe.CollectBusEPO.Application.Contracts/Jobs/IRecurringJob.cs deleted file mode 100644 index 6f4df53..0000000 --- a/services/JiShe.CollectBusEPO.Application.Contracts/Jobs/IRecurringJob.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace JiShe.CollectBusEPO.Jobs -{ - public interface IRecurringJob : ITransientDependency - { - /// - /// 执行任务 - /// - /// - Task ExecuteAsync(); - } -} \ No newline at end of file diff --git a/services/JiShe.CollectBusEPO.Application.Contracts/Permissions/CollectBusEPOPermissionDefinitionProvider.cs b/services/JiShe.CollectBusEPO.Application.Contracts/Permissions/CollectBusEPOPermissionDefinitionProvider.cs deleted file mode 100644 index 1b673bd..0000000 --- a/services/JiShe.CollectBusEPO.Application.Contracts/Permissions/CollectBusEPOPermissionDefinitionProvider.cs +++ /dev/null @@ -1,17 +0,0 @@ -using JiShe.CollectBus.Localization; - -namespace JiShe.CollectBusEPO.Permissions -{ - public class CollectBusEPOPermissionDefinitionProvider : PermissionDefinitionProvider - { - public override void Define(IPermissionDefinitionContext context) - { - var myGroup = context.AddGroup(CollectBusEPOPermissions.GroupName, L("Permission:CollectBus")); - } - - private static LocalizableString L(string name) - { - return LocalizableString.Create(name); - } - } -} \ No newline at end of file diff --git a/services/JiShe.CollectBusEPO.Application.Contracts/Permissions/CollectBusEPOPermissions.cs b/services/JiShe.CollectBusEPO.Application.Contracts/Permissions/CollectBusEPOPermissions.cs deleted file mode 100644 index 7acba86..0000000 --- a/services/JiShe.CollectBusEPO.Application.Contracts/Permissions/CollectBusEPOPermissions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Volo.Abp.Reflection; - -namespace JiShe.CollectBusEPO.Permissions -{ - public static class CollectBusEPOPermissions - { - public const string GroupName = "CollectBusEPO"; - - public static string[] GetAll() - { - return ReflectionHelper.GetPublicConstantsRecursively(typeof(CollectBusEPOPermissions)); - } - - } -} \ No newline at end of file diff --git a/services/JiShe.CollectBusEPO.Application/CollectBusEPOAppService.cs b/services/JiShe.CollectBusEPO.Application/CollectBusEPOAppService.cs deleted file mode 100644 index 79d0366..0000000 --- a/services/JiShe.CollectBusEPO.Application/CollectBusEPOAppService.cs +++ /dev/null @@ -1,30 +0,0 @@ -using JiShe.CollectBus; -using JiShe.CollectBus.FreeRedis; -using JiShe.CollectBus.FreeSql; -using JiShe.CollectBus.Localization; -using Microsoft.AspNetCore.Mvc; -using Volo.Abp.Threading; - -namespace JiShe.CollectBusEPO -{ - /* Inherit your application services from this class. - */ - [Authorize] - [ApiExplorerSettings(GroupName = CollectBusDomainSharedConsts.Business)] - public abstract class CollectBusEPOAppService : ApplicationService - { - public IFreeSqlProvider SqlProvider => LazyServiceProvider.LazyGetRequiredService(); - protected IFreeRedisProvider FreeRedisProvider => LazyServiceProvider.LazyGetService()!; - private ICancellationTokenProvider CancellationTokenProvider => - LazyServiceProvider.LazyGetService(NullCancellationTokenProvider.Instance); - - protected CollectBusEPOAppService() - { - LocalizationResource = typeof(CollectBusResource); - ObjectMapperContext = typeof(CollectBusEPOApplicationModule); - } - - - - } -} diff --git a/services/JiShe.CollectBusEPO.Application/CollectBusEPOApplicationModule.cs b/services/JiShe.CollectBusEPO.Application/CollectBusEPOApplicationModule.cs deleted file mode 100644 index 47e8079..0000000 --- a/services/JiShe.CollectBusEPO.Application/CollectBusEPOApplicationModule.cs +++ /dev/null @@ -1,32 +0,0 @@ -using JiShe.CollectBus; -using JiShe.CollectBus.FreeRedis; -using JiShe.CollectBus.FreeSql; -using JiShe.CollectBus.IoTDB; -using JiShe.CollectBus.Kafka; -using Volo.Abp.AspNetCore.Mvc; -using Volo.Abp.AuditLogging; -using Volo.Abp.BackgroundJobs; - -namespace JiShe.CollectBusEPO -{ - [DependsOn( - typeof(CollectBusDomainModule), - typeof(CollectBusFreeRedisModule), - typeof(CollectBusFreeSqlModule), - typeof(CollectBusKafkaModule), - typeof(CollectBusIoTDbModule) - )] - public class CollectBusEPOApplicationModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => { options.AddMaps(); }); - - Configure(options => - { - options.ConventionalControllers.Create(typeof(CollectBusEPOApplicationModule).Assembly); - }); - } - - } -} \ No newline at end of file diff --git a/services/JiShe.CollectBusEPO.Application/EntityHandler.cs b/services/JiShe.CollectBusEPO.Application/EntityHandler.cs deleted file mode 100644 index 7ca2822..0000000 --- a/services/JiShe.CollectBusEPO.Application/EntityHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Volo.Abp.Domain.Entities.Auditing; -using Volo.Abp.Domain.Entities.Events; -using Volo.Abp.EventBus; -using Volo.Abp.MultiTenancy; - -namespace JiShe.CollectBusEPO; - -public class EntityHandler : ILocalEventHandler>>, - ITransientDependency -{ - public IAbpLazyServiceProvider LazyServiceProvider { get; set; } - - protected ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService(); - - - public Task HandleEventAsync(EntityCreatedEventData> eventData) - { - // TO DO SOMETHING - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/services/JiShe.CollectBusEPO.Application/GlobalUsings.cs b/services/JiShe.CollectBusEPO.Application/GlobalUsings.cs deleted file mode 100644 index eacabe1..0000000 --- a/services/JiShe.CollectBusEPO.Application/GlobalUsings.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Global using directives - -global using Microsoft.AspNetCore.Authorization; -global using System; -global using System.Threading.Tasks; -global using Volo.Abp.Application.Services; -global using Volo.Abp.AutoMapper; -global using Volo.Abp.DependencyInjection; -global using Volo.Abp.Modularity; diff --git a/services/JiShe.CollectBusEPO.Application/JiShe.CollectBusEPO.Application.csproj b/services/JiShe.CollectBusEPO.Application/JiShe.CollectBusEPO.Application.csproj deleted file mode 100644 index 0bb7da1..0000000 --- a/services/JiShe.CollectBusEPO.Application/JiShe.CollectBusEPO.Application.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - - net8.0 - JiShe.CollectBusEPO - - - - - - - - - - - diff --git a/services/JiShe.CollectBusEPO.Application/Properties/AssemblyInfo.cs b/services/JiShe.CollectBusEPO.Application/Properties/AssemblyInfo.cs deleted file mode 100644 index f46e19e..0000000 --- a/services/JiShe.CollectBusEPO.Application/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,2 +0,0 @@ -using System.Runtime.CompilerServices; -[assembly:InternalsVisibleToAttribute("JiShe.MicroService.Application.Tests")] diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs b/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs deleted file mode 100644 index 523a5df..0000000 --- a/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs +++ /dev/null @@ -1,60 +0,0 @@ -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/shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs b/shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs deleted file mode 100644 index bddaa86..0000000 --- a/shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace JiShe.CollectBus.Analyzers.Shared -{ - /// - /// 实体类型枚举 - /// - 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 deleted file mode 100644 index 2c3a5b0..0000000 --- a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs +++ /dev/null @@ -1,46 +0,0 @@ -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 deleted file mode 100644 index 3ae7562..0000000 --- a/shared/JiShe.CollectBus.Analyzers.Shared/JiShe.CollectBus.Analyzers.Shared.csproj +++ /dev/null @@ -1,7 +0,0 @@ - - - - netstandard2.0 - - - diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs b/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs deleted file mode 100644 index ad02607..0000000 --- a/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs +++ /dev/null @@ -1,19 +0,0 @@ -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.Analyzers.Shared/SourceEntityAccessorFactory2.cs b/shared/JiShe.CollectBus.Analyzers.Shared/SourceEntityAccessorFactory2.cs deleted file mode 100644 index 5f28270..0000000 --- a/shared/JiShe.CollectBus.Analyzers.Shared/SourceEntityAccessorFactory2.cs +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/shared/JiShe.CollectBus.Common/Consts/CommonConst.cs b/shared/JiShe.CollectBus.Common/Consts/CommonConst.cs deleted file mode 100644 index c3f1e9a..0000000 --- a/shared/JiShe.CollectBus.Common/Consts/CommonConst.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Consts -{ - /// - /// 常用常量管理 - /// - public class CommonConst - { - - /// - /// Kafka - /// - public const string Kafka = "Kafka"; - - /// - /// 服务器标识 - /// - public const string ServerTagName = $"{Kafka}:ServerTagName"; - - /// - /// Kafka副本数量 - /// - public const string KafkaReplicationFactor = $"{Kafka}:KafkaReplicationFactor"; - - /// - /// Kafka主题分区数量 - /// - public const string NumPartitions = $"{Kafka}:NumPartitions"; - - /// - /// 首次采集时间 - /// - public const string FirstCollectionTime = "FirstCollectionTime"; - - } -} diff --git a/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs b/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs deleted file mode 100644 index 872c099..0000000 --- a/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs +++ /dev/null @@ -1,39 +0,0 @@ -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 deleted file mode 100644 index c65b027..0000000 --- a/shared/JiShe.CollectBus.Common/Consts/MeteringPortConst.cs +++ /dev/null @@ -1,24 +0,0 @@ -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 deleted file mode 100644 index 0758899..0000000 --- a/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Consts -{ - public class ProtocolConst - { - public const string SubscriberGroup = "jishe.collectbus"; - /// - /// 心跳下行消息主题 - /// - public const string SubscriberHeartbeatIssuedEventName = "issued.heartbeat.event"; - /// - /// 登录下行消息主题 - /// - public const string SubscriberLoginIssuedEventName = "issued.login.event"; - - /// - /// 上行消息主题,测试使用 - /// - public const string SubscriberReceivedEventName = "received.event"; - - /// - /// 心跳上行消息主题 - /// - public const string SubscriberHeartbeatReceivedEventName = "received.heartbeat.event"; - /// - /// 登录上行消息主题 - /// - public const string SubscriberLoginReceivedEventName = "received.login.event"; - - #region 电表消息主题 - /// - /// 1分钟采集电表数据下行消息主题 - /// - public const string AmmeterSubscriberWorkerOneMinuteIssuedEventName = "issued.auto.one.ammeter.event"; - /// - /// 5分钟采集电表数据下行消息主题 - /// - public const string AmmeterSubscriberWorkerFiveMinuteIssuedEventName = "issued.auto.five.ammeter.event"; - /// - /// 15分钟采集电表数据下行消息主题 - /// - public const string AmmeterSubscriberWorkerFifteenMinuteIssuedEventName = "issued.auto.fifteen.ammeter.event"; - - /// - /// 其他采集数据下行消息主题,日冻结,月冻结、集中器版本号、SIM卡号、定时校时等 - /// - public const string AmmeterSubscriberWorkerOtherIssuedEventName = "issued.auto.other.ammeter.event"; - - /// - /// 电表自动阀控 - /// - public const string AmmeterSubscriberWorkerAutoValveControlIssuedEventName = "issued.auto.control.ammeter.event"; - - /// - /// 电表手动阀控 - /// - public const string AmmeterSubscriberWorkerManualValveControlIssuedEventName = "issued.manual.control.ammeter.event"; - - /// - /// 电表手动抄读 - /// - public const string AmmeterSubscriberWorkerManualValveReadingIssuedEventName = "issued.manual.reading.ammeter.event"; - - /// - /// 采集电表数据重试下行消息主题 - /// - public const string AmmeterSubscriberWorkerRetryEventName = "issued.retry.ammeter.event"; - - #endregion - - #region 水表消息主题 - /// - /// 水表数据下行消息主题,由于水表采集频率不高,所以一个主题就够 - /// - public const string WatermeterSubscriberWorkerAutoReadingIssuedEventName = "issued.auto.reading.watermeter.event"; - - /// - /// 水表自动阀控 - /// - public const string WatermeterSubscriberWorkerAutoValveControlIssuedEventName = "issued.auto.control.watermeter.event"; - - /// - /// 水表手动阀控 - /// - public const string WatermeterSubscriberWorkerManualValveControlIssuedEventName = "issued.manual.control.watermeter.event"; - - /// - /// 水表手动抄读 - /// - public const string WatermeterSubscriberWorkerManualValveReadingIssuedEventName = "issued.manual.reading.watermeter.event"; - #endregion - - /// - /// AFN上行主题格式 - /// - public const string AFNTopicNameFormat = "received.afn{0}h.event"; - - /// - /// AFN00H上行主题格式 - /// - public const string SubscriberAFN00HReceivedEventNameTemp = "received.afn00h.event"; - - /// - /// AFN01H上行主题格式 - /// - public const string SubscriberAFN01HReceivedEventNameTemp = "received.afn01h.event"; - - /// - /// AFN02H上行主题格式 - /// - public const string SubscriberAFN02HReceivedEventNameTemp = "received.afn02h.event"; - - /// - /// AFN03H上行主题格式 - /// - public const string SubscriberAFN03HReceivedEventNameTemp = "received.afn03h.event"; - - /// - /// AFN04H上行主题格式 - /// - public const string SubscriberAFN04HReceivedEventNameTemp = "received.afn04h.event"; - - /// - /// AFN05H上行主题格式 - /// - public const string SubscriberAFN05HReceivedEventNameTemp = "received.afn05h.event"; - - /// - /// AFN09H上行主题格式 - /// - public const string SubscriberAFN09HReceivedEventNameTemp = "received.afn09h.event"; - - /// - /// AFN0AH上行主题格式 - /// - public const string SubscriberAFN0AHReceivedEventNameTemp = "received.afn10h.event"; - - /// - /// AFN0BH上行主题格式 - /// - public const string SubscriberAFN0BHReceivedEventNameTemp = "received.afn11h.event"; - - /// - /// AFN0CH上行主题格式 - /// - public const string SubscriberAFN0CHReceivedEventNameTemp = "received.afn12h.event"; - - /// - /// AFN0DH上行主题格式 - /// - public const string SubscriberAFN0DHReceivedEventNameTemp = "received.afn13h.event"; - - /// - /// AFN0EH上行主题格式 - /// - public const string SubscriberAFN0EHReceivedEventNameTemp = "received.afn14h.event"; - - /// - /// AFN10H上行主题格式 - /// - public const string SubscriberAFN10HReceivedEventNameTemp = "received.afn16h.event"; - - - /// - /// 测试主题格式 - /// - 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 deleted file mode 100644 index bb143ef..0000000 --- a/shared/JiShe.CollectBus.Common/Consts/RedisConst.cs +++ /dev/null @@ -1,76 +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 RedisConst - { - /// - /// 缓存基础目录 - /// - public const string CacheBasicDirectoryKey = "CollectBus:"; - - /// - /// 1分钟采集间隔 - /// - public const string OneMinuteAcquisitionTimeInterval = "One"; - - /// - /// 5分钟采集间隔 - /// - public const string FiveMinuteAcquisitionTimeInterval = "Five"; - - /// - /// 15分钟采集间隔 - /// - public const string FifteenMinuteAcquisitionTimeInterval = "Fifteen"; - - /// - /// 设备信息缓存数据,{0}=>系统类型,{1}=>应用服务部署标记 - /// - public const string CacheDeviceInfoHashKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:DeviceInfo"; - - /// - /// 设备信息缓存Set缓存Key,{0}=>系统类型,{1}=>应用服务部署标记 - /// - public const string CacheDeviceGroupSetIndexKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:DeviceGroupIndex"; - - public const string TaskInfo = "TaskInfo"; - /// - /// 缓存待下发的指令生产任务数据,{0}=>系统类型,{1}=>应用服务部署标记,{2}=>表计类别,{3}=>采集频率 - /// - public const string CacheTasksToBeIssuedKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:{TaskInfo}:{"{2}"}:{"{3}"}"; - - public const string TelemetryPacket = "TelemetryPacket"; - /// - /// 缓存表计下发指令数据集,{0}=>系统类型,{1}=>应用服务部署标记,{2}=>表计类别,{3}=>采集频率,{4}=>集中器所在分组,{5}=>时间格式的任务批次 - /// - public const string CacheTelemetryPacketInfoHashKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:{TelemetryPacket}:{"{2}"}:{"{3}"}:{"{4}"}:{"{5}"}"; - - /// - /// 缓存表计下发指令数据集索引Set缓存Key,{0}=>系统类型,{1}=>应用服务部署标记,{2}=>表计类别,{3}=>采集频率,{4}=>集中器所在分组,{5}=>时间格式的任务批次 - /// - public const string CacheTelemetryPacketInfoSetIndexKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:{TelemetryPacket}:{"{2}"}:SetIndex:{"{3}"}:{"{4}"}:{"{5}"}"; - - /// - /// 缓存表计下发指令数据集排序索引ZSET缓存Key,{0}=>系统类型,{1}=>应用服务部署标记,{2}=>表计类别,{3}=>采集频率,{4}=>集中器所在分组,{5}=>时间格式的任务批次 - /// - public const string CacheTelemetryPacketInfoZSetScoresIndexKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:{TelemetryPacket}:{"{2}"}:ZSetScoresIndex:{"{3}"}:{"{4}"}:{"{5}"}"; - - ///// - ///// 缓存设备平衡关系映射结果,{0}=>系统类型,{1}=>应用服务部署标记 - ///// - //public const string CacheDeviceBalanceRelationMapResultKey = $"{CacheBasicDirectoryKey}{"{0}:{1}"}:RelationMap"; - - public const string CacheAmmeterFocusKey = $"{CacheBasicDirectoryKey}CacheAmmeterFocusKey"; - - /// - /// 协议池缓存标识 - /// - public const string ProtocolKey = $"{CacheBasicDirectoryKey}Protocols"; - } -} diff --git a/shared/JiShe.CollectBus.Common/DeviceBalanceControl/DeviceGroupBalanceControl.cs b/shared/JiShe.CollectBus.Common/DeviceBalanceControl/DeviceGroupBalanceControl.cs deleted file mode 100644 index 470efe7..0000000 --- a/shared/JiShe.CollectBus.Common/DeviceBalanceControl/DeviceGroupBalanceControl.cs +++ /dev/null @@ -1,431 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; - -namespace JiShe.CollectBus.Common.DeviceBalanceControl -{ - /// - /// 设备组负载控制 - /// - public class DeviceGroupBalanceControl - { - private static readonly object _syncRoot = new object(); - - private static volatile CacheState _currentCache; - - /// - /// 使用ConcurrentDictionary保证线程安全的设备分组映射 - /// - private sealed class CacheState - { - public readonly ConcurrentDictionary BalancedMapping; - public readonly List[] CachedGroups; - - public CacheState(int groupCount) - { - BalancedMapping = new ConcurrentDictionary(); - CachedGroups = new List[groupCount]; - for (int i = 0; i < groupCount; i++) - { - CachedGroups[i] = new List(); - } - } - } - - /// - /// 初始化或增量更新缓存 - /// - public static void InitializeCache(List deviceList, int groupCount = 30) - { - if (deviceList == null || deviceList.Count <= 0) - { - throw new ArgumentException($"{nameof(InitializeCache)} 设备分组初始化失败,设备数据为空"); - } - - if (groupCount > 60 || groupCount <= 0) - { - groupCount = 60; - } - - lock (_syncRoot) - { - // 首次初始化 - if (_currentCache == null) - { - var newCache = new CacheState(groupCount); - UpdateCacheWithDevices(newCache, deviceList, groupCount); - _currentCache = newCache; - } - // 后续增量更新 - else - { - if (_currentCache.CachedGroups.Length != groupCount) - { - throw new ArgumentException($"{nameof(InitializeCache)} 设备分组初始化完成以后,分组数量不能更改"); - } - - var clonedCache = CloneExistingCache(); - UpdateCacheWithDevices(clonedCache, deviceList, groupCount); - _currentCache = clonedCache; - } - } - } - - /// - /// 带锁的缓存克隆(写入时复制) - /// - private static CacheState CloneExistingCache() - { - var oldCache = _currentCache; - var newCache = new CacheState(oldCache.CachedGroups.Length); - - // 复制已有映射 - foreach (var kvp in oldCache.BalancedMapping) - { - newCache.BalancedMapping.TryAdd(kvp.Key, kvp.Value); - } - - // 复制分组数据 - for (int i = 0; i < oldCache.CachedGroups.Length; i++) - { - newCache.CachedGroups[i].AddRange(oldCache.CachedGroups[i]); - } - - return newCache; - } - - /// - /// 更新设备到缓存 - /// - private static void UpdateCacheWithDevices(CacheState cache, List deviceList, int groupCount) - { - foreach (var deviceId in deviceList) - { - // 原子操作:如果设备不存在则计算分组 - cache.BalancedMapping.GetOrAdd(deviceId, id => - { - int groupId = GetGroupId(id, groupCount); - lock (cache.CachedGroups[groupId]) - { - cache.CachedGroups[groupId].Add(id); - } - return groupId; - }); - } - } - - /// - /// 并行处理泛型数据集(支持动态线程分配) - /// - /// 已经分组的设备信息 - /// 部分或者全部的已经分组的设备集合 - /// 从泛型对象提取deviceId - /// 处理委托(参数:当前对象,线程ID) - /// 可选线程限制 - /// - /// - public static async Task ProcessGenericListAsync( - List items, Func deviceIdSelector, Action processor, int? maxThreads = null) - { - var cache = _currentCache ?? throw new InvalidOperationException("缓存未初始化"); - - // 创建分组任务队列 - var groupQueues = new ConcurrentQueue[cache.CachedGroups.Length]; - for (int i = 0; i < groupQueues.Length; i++) - { - groupQueues[i] = new ConcurrentQueue(); - } - - // 阶段1:分发数据到分组队列 - Parallel.ForEach(items, item => - { - var deviceId = deviceIdSelector(item); - if (cache.BalancedMapping.TryGetValue(deviceId, out int groupId)) - { - groupQueues[groupId].Enqueue(item); - } - }); - - if ((maxThreads.HasValue && maxThreads.Value > cache.CachedGroups.Length) || maxThreads.HasValue == false) - { - maxThreads = cache.CachedGroups.Length; - } - - // 阶段2:并行处理队列 - var options = new ParallelOptions - { - MaxDegreeOfParallelism = maxThreads.Value, - }; - - await Task.Run(() => - { - Parallel.For(0, cache.CachedGroups.Length, options, async groupId => - { - var queue = groupQueues[groupId]; - while (queue.TryDequeue(out T item)) - { - processor(item, groupId); - } - }); - }); - } - - - /// - /// 智能节流处理(CPU友好型) - /// - /// 已经分组的设备信息 - /// 部分或者全部的已经分组的设备集合 - /// 从泛型对象提取deviceId - /// 处理委托(参数:当前对象,分组ID) - /// 可选最佳并发度 - /// - /// - public static async Task ProcessWithThrottleAsync( - List items, - Func deviceIdSelector, - Action processor, - int? maxConcurrency = null) - { - var cache = _currentCache ?? throw new InvalidOperationException("缓存未初始化"); - //var timer = Stopwatch.StartNew(); - - // 自动计算最佳并发度 - int recommendedThreads = CalculateOptimalThreadCount(); - if ((maxConcurrency.HasValue && maxConcurrency.Value > cache.CachedGroups.Length) || maxConcurrency.HasValue == false) - { - maxConcurrency = cache.CachedGroups.Length; - } - - int actualThreads = maxConcurrency ?? recommendedThreads; - - - // 创建节流器 - using var throttler = new SemaphoreSlim(initialCount: actualThreads); - - // 使用LongRunning避免线程池饥饿 - var tasks = items.Select(async item => - { - await throttler.WaitAsync(); - try - { - var deviceId = deviceIdSelector(item); - if (cache.BalancedMapping.TryGetValue(deviceId, out int groupId)) - { - // 分组级处理(保持顺序性) - await ProcessItemAsync(item, processor, groupId); - } - } - finally - { - throttler.Release(); - } - }); - - await Task.WhenAll(tasks); - //timer.Stop(); - //Console.WriteLine($"任务处理完成,耗时:{timer.ElapsedMilliseconds}ms"); - } - - /// - /// 自动计算最优线程数 - /// - public static int CalculateOptimalThreadCount() - { - int coreCount = Environment.ProcessorCount; - return Math.Min( - coreCount * 8, // 超线程优化 - _currentCache?.CachedGroups.Length ?? 60 - ); - } - - /// - /// 分组异步处理(带节流) - /// - private static async Task ProcessItemAsync(T item, Action processor, int groupId) - { - // 使用内存缓存降低CPU负载 - await Task.Yield(); // 立即释放当前线程 - - // 分组处理上下文 - var context = ExecutionContext.Capture(); - ThreadPool.QueueUserWorkItem(_ => - { - ExecutionContext.Run(context!, state => - { - processor(item,groupId); - }, null); - }); - } - - - /// - /// 通过 deviceId 获取所在的分组集合 - /// - public static List GetGroup(string deviceId) - { - var cache = _currentCache; - if (cache == null) - throw new InvalidOperationException("缓存未初始化"); - - return cache.CachedGroups[cache.BalancedMapping[deviceId]]; - } - - /// - /// 通过 deviceId 获取分组Id - /// - public static int GetDeviceGroupId(string deviceId) - { - var cache = _currentCache; - if (cache == null) - throw new InvalidOperationException("缓存未初始化"); - - return cache.BalancedMapping[deviceId]; - } - - - /// - /// 创建均衡映射表 - /// - /// 数据集合 - /// 分组数量 - /// 允许的最大偏差百分比 - /// - public static Dictionary CreateBalancedMapping(List deviceList, int groupCount, int maxDeviation = 5) - { - var mapping = new Dictionary(); - int targetPerGroup = deviceList.Count / groupCount; - int maxAllowed = (int)(targetPerGroup * (1 + maxDeviation / 100.0)); - - // 初始化分组计数器 - int[] groupCounters = new int[groupCount]; - - foreach (var deviceId in deviceList) - { - int preferredGroup = GetGroupId(deviceId, groupCount); - - // 如果首选分组未满,直接分配 - if (groupCounters[preferredGroup] < maxAllowed) - { - mapping[deviceId] = preferredGroup; - groupCounters[preferredGroup]++; - } - else - { - // 寻找当前最空闲的分组 - int fallbackGroup = Array.IndexOf(groupCounters, groupCounters.Min()); - mapping[deviceId] = fallbackGroup; - groupCounters[fallbackGroup]++; - } - } - - return mapping; - } - - /// - /// 分析分组分布 - /// - /// - /// - /// - public static Dictionary AnalyzeDistribution(List deviceList, int groupCount) - { - Dictionary distribution = new Dictionary(); - foreach (var deviceId in deviceList) - { - int groupId = GetGroupId(deviceId, groupCount); - distribution[groupId] = distribution.TryGetValue(groupId, out var count) ? count + 1 : 1; - } - return distribution; - } - - /// - /// 获取设备ID对应的分组ID - /// - /// - /// - /// - public static int GetGroupId(string deviceId, int groupCount) - { - int hash = Fnv1aHash(deviceId); - // 双重取模确保分布均匀 - return (hash % groupCount + groupCount) % groupCount; - } - - /// - /// FNV-1a哈希算法 - /// - /// - /// - public static int Fnv1aHash(string input) - { - const uint fnvPrime = 16777619; - const uint fnvOffsetBasis = 2166136261; - - uint hash = fnvOffsetBasis; - foreach (char c in input) - { - hash ^= (byte)c; - hash *= fnvPrime; - } - return (int)hash; - } - - /// - /// CRC16算法实现 - /// - /// - /// - public static ushort CRC16Hash(byte[] bytes) - { - ushort crc = 0xFFFF; - for (int i = 0; i < bytes.Length; i++) - { - crc ^= bytes[i]; - for (int j = 0; j < 8; j++) - { - if ((crc & 0x0001) == 1) - { - crc = (ushort)((crc >> 1) ^ 0xA001); - } - else - { - crc >>= 1; - } - } - } - return crc; - } - - /// - /// 打印分组统计数据 - /// - public static void PrintDistributionStats() - { - var cache = _currentCache; - if (cache == null) - { - Console.WriteLine("缓存未初始化"); - return; - } - - var stats = cache.CachedGroups - .Select((group, idx) => new { GroupId = idx, Count = group.Count }) - .OrderBy(x => x.GroupId); - - Console.WriteLine("分组数据量统计:"); - foreach (var stat in stats) - { - Console.WriteLine($"Group {stat.GroupId}: {stat.Count} 条数据"); - } - - Console.WriteLine($"总共: {stats.Sum(d=>d.Count)} 条数据"); - } - - } -} diff --git a/shared/JiShe.CollectBus.Common/Encrypt/EncryptUtil.cs b/shared/JiShe.CollectBus.Common/Encrypt/EncryptUtil.cs deleted file mode 100644 index 72cdf41..0000000 --- a/shared/JiShe.CollectBus.Common/Encrypt/EncryptUtil.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Encrypt -{ - /// - /// 各种加密辅助类 - /// - public static class EncryptUtil - { - #region MD5加密 - - /// - /// MD5加密 - /// - public static string Md5Fun(this string value) - { - if (value == null) - { - throw new ArgumentNullException("未将对象引用设置到对象的实例。"); - } - - var encoding = Encoding.UTF8; - MD5 md5 = MD5.Create(); - return HashAlgorithmBase(md5, value, encoding); - } - - /// - /// 加权MD5加密 - /// - public static string Md5Fun(this string value, string salt) - { - return salt == null ? value.Md5Fun() : (value + "『" + salt + "』").Md5Fun(); - } - - #endregion - - /// - /// HashAlgorithm 加密统一方法 - /// - private static string HashAlgorithmBase(HashAlgorithm hashAlgorithmObj, string source, Encoding encoding) - { - byte[] btStr = encoding.GetBytes(source); - byte[] hashStr = hashAlgorithmObj.ComputeHash(btStr); - return hashStr.Bytes2Str(); - } - - /// - /// 转换成字符串 - /// - private static string Bytes2Str(this IEnumerable source, string formatStr = "{0:X2}") - { - StringBuilder pwd = new StringBuilder(); - foreach (byte btStr in source) - { - pwd.AppendFormat(formatStr, btStr); - } - return pwd.ToString(); - } - } -} diff --git a/shared/JiShe.CollectBus.Common/Enums/MeterTypeEnum.cs b/shared/JiShe.CollectBus.Common/Enums/MeterTypeEnum.cs deleted file mode 100644 index dc78e45..0000000 --- a/shared/JiShe.CollectBus.Common/Enums/MeterTypeEnum.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Enums -{ - /// - /// 表计类型 - /// 电表= 1,水表= 2,燃气表= 3,热能表= 4,水表流量计=5,燃气表流量计=6 - /// - public enum MeterTypeEnum - { - /// - /// 电表 - /// - Ammeter = 1, - /// - /// 水表 - /// - WaterMeter = 2, - /// - /// 燃气表 - /// - Gasmeter = 3, - /// - /// 热能表 - /// - HeatMeter = 4, - /// - /// 水表流量计 - /// - WaterMeterFlowmeter = 5, - /// - /// 燃气表流量计 - /// - GasmeterFlowmeter = 6, - /// - /// 特殊电表 - /// - SpecialAmmeter = 7, - /// - /// 传感器 - /// - Sensor = 8, - - /// - /// 采集器 - /// - Collector = 9, - - /// - /// 集中器 - /// - Focus = 10, - } -} diff --git a/shared/JiShe.CollectBus.Common/Extensions/DateTimeOffsetExtensions.cs b/shared/JiShe.CollectBus.Common/Extensions/DateTimeOffsetExtensions.cs deleted file mode 100644 index 0f07e9c..0000000 --- a/shared/JiShe.CollectBus.Common/Extensions/DateTimeOffsetExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; - -namespace JiShe.CollectBus.Common.Extensions -{ - public static class DateTimeOffsetExtensions - { - - /// - /// 获取当前时间毫秒级时间戳 - /// - /// - public static long GetCurrentTimeMillis() - { - return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); - } - - /// - /// 将Unix时间戳转换为日期时间 - /// - /// - /// - public static DateTime FromUnixMillis(long millis) - { - return DateTimeOffset.FromUnixTimeMilliseconds(millis).DateTime; - } - - /// - /// 将 DateTime 时间转换为 DateTimeOffset 时间 - /// - /// - /// - public static DateTimeOffset GetDateTimeOffset(this DateTime rawDateTime) - { - //确保 Kind 为 Local(如果是 Unspecified) - DateTime localDateTime = rawDateTime.Kind == DateTimeKind.Unspecified - ? DateTime.SpecifyKind(rawDateTime, DateTimeKind.Local) - : rawDateTime; - - // 转换为 DateTimeOffset(自动应用本地时区偏移) - return new DateTimeOffset(localDateTime); - } - } -} diff --git a/shared/JiShe.CollectBus.Common/Extensions/EnumExtensions.cs b/shared/JiShe.CollectBus.Common/Extensions/EnumExtensions.cs deleted file mode 100644 index f54a3a4..0000000 --- a/shared/JiShe.CollectBus.Common/Extensions/EnumExtensions.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; - -namespace JiShe.CollectBus.Common.Extensions -{ - public static class EnumExtensions - { - /// - /// 将枚举转换为字典 - /// - /// - /// - public static Dictionary ToDictionary() where TEnum : Enum - { - return Enum.GetValues(typeof(TEnum)) - .Cast() - .ToDictionary( - e => e.ToString(), - e => Convert.ToInt32(e) - ); - } - - /// - /// 将枚举转换为字典 - /// - /// - /// - public static Dictionary ToEnumDictionary() where TEnum : Enum - { - return Enum.GetValues(typeof(TEnum)) - .Cast() - .ToDictionary( - e => e.ToString(), - e => e - ); - } - - /// - /// 将枚举转换为字典 - /// - /// - /// - public static Dictionary ToValueNameDictionary() where TEnum : Enum - { - return Enum.GetValues(typeof(TEnum)) - .Cast() - .ToDictionary( - e => Convert.ToInt32(e), - e => e.ToString() - ); - } - - /// - /// 将枚举转换为字典 - /// - /// - /// - public static Dictionary ToNameValueDictionary() where TEnum : Enum - { - return Enum.GetValues(typeof(TEnum)) - .Cast() - .ToDictionary( - e => e.ToString(), - e => Convert.ToInt32(e) - ); - } - - /// - /// 将枚举转换为字典 - /// - /// - /// - public static Dictionary ToEnumNameDictionary() where TEnum : Enum - { - return Enum.GetValues(typeof(TEnum)) - .Cast() - .ToDictionary( - e => e, - e => e.ToString() - ); - } - - } -} diff --git a/shared/JiShe.CollectBus.Common/Extensions/EnumerableExtensions.cs b/shared/JiShe.CollectBus.Common/Extensions/EnumerableExtensions.cs deleted file mode 100644 index b17e9c2..0000000 --- a/shared/JiShe.CollectBus.Common/Extensions/EnumerableExtensions.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; - -namespace JiShe.CollectBus.Common.Extensions -{ - /// - /// Extension methods for . - /// - public static class EnumerableExtensions - { - /// - /// Concatenates the members of a constructed collection of type System.String, using the specified separator between each member. - /// This is a shortcut for string.Join(...) - /// - /// A collection that contains the strings to concatenate. - /// The string to use as a separator. separator is included in the returned string only if values has more than one element. - /// A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty. - [Description("Enumerable转换String")] - public static string JoinAsString(this IEnumerable source, string separator) - { - return string.Join(separator, source); - } - - /// - /// Concatenates the members of a collection, using the specified separator between each member. - /// This is a shortcut for string.Join(...) - /// - /// A collection that contains the objects to concatenate. - /// The string to use as a separator. separator is included in the returned string only if values has more than one element. - /// The type of the members of values. - /// A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty. - public static string JoinAsString(this IEnumerable source, string separator) - { - return string.Join(separator, source); - } - - /// - /// Filters a by given predicate if given condition is true. - /// - /// Enumerable to apply filtering - /// A boolean value - /// Predicate to filter the enumerable - /// Filtered or not filtered enumerable based on - [Description("Enumerable筛选")] - public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate) - { - return condition - ? source.Where(predicate) - : source; - } - - /// - /// Filters a by given predicate if given condition is true. - /// - /// Enumerable to apply filtering - /// A boolean value - /// Predicate to filter the enumerable - /// Filtered or not filtered enumerable based on - public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate) - { - return condition - ? source.Where(predicate) - : source; - } - - /// - /// 分批 - /// - /// - /// - /// - /// - public static IEnumerable> Batch( - this IEnumerable source, - int batchSize) - { - var buffer = new List(batchSize); - foreach (var item in source) - { - buffer.Add(item); - if (buffer.Count == batchSize) - { - yield return buffer; - buffer = new List(batchSize); - } - } - if (buffer.Count > 0) - yield return buffer; - } - - //public static IEnumerable> Batch(this IEnumerable source, int batchSize) - //{ - // if (batchSize <= 0) - // throw new ArgumentOutOfRangeException(nameof(batchSize)); - - // using var enumerator = source.GetEnumerator(); - // while (enumerator.MoveNext()) - // { - // yield return GetBatch(enumerator, batchSize); - // } - //} - - //private static IEnumerable GetBatch(IEnumerator enumerator, int batchSize) - //{ - // do - // { - // yield return enumerator.Current; - // batchSize--; - // } while (batchSize > 0 && enumerator.MoveNext()); - //} - } -} diff --git a/shared/JiShe.CollectBus.Common/Extensions/LockExtensions.cs b/shared/JiShe.CollectBus.Common/Extensions/LockExtensions.cs deleted file mode 100644 index cff7df7..0000000 --- a/shared/JiShe.CollectBus.Common/Extensions/LockExtensions.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; - -namespace JiShe.CollectBus.Common.Extensions -{ - /// - /// Extension methods to make locking easier. - /// - public static class LockExtensions - { - /// - /// Executes given by locking given object. - /// - /// Source object (to be locked) - /// Action (to be executed) - public static void Locking(this object source, Action action) - { - lock (source) - { - action(); - } - } - - /// - /// Executes given by locking given object. - /// - /// Type of the object (to be locked) - /// Source object (to be locked) - /// Action (to be executed) - public static void Locking(this T source, Action action) where T : class - { - lock (source) - { - action(source); - } - } - - /// - /// Executes given and returns it's value by locking given object. - /// - /// Return type - /// Source object (to be locked) - /// Function (to be executed) - /// Return value of the - public static TResult Locking(this object source, Func func) - { - lock (source) - { - return func(); - } - } - - /// - /// Executes given and returns it's value by locking given object. - /// - /// Type of the object (to be locked) - /// Return type - /// Source object (to be locked) - /// Function (to be executed) - /// Return value of the - public static TResult Locking(this T source, Func func) where T : class - { - lock (source) - { - return func(source); - } - } - } -} diff --git a/shared/JiShe.CollectBus.Common/Extensions/ProtocolConstExtensions.cs b/shared/JiShe.CollectBus.Common/Extensions/ProtocolConstExtensions.cs deleted file mode 100644 index 1dbb301..0000000 --- a/shared/JiShe.CollectBus.Common/Extensions/ProtocolConstExtensions.cs +++ /dev/null @@ -1,69 +0,0 @@ -using JiShe.CollectBus.Common.Consts; -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Extensions; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Extensions -{ - public class ProtocolConstExtensions - { - /// - /// 自动获取 ProtocolConst 类中所有下行 Kafka 主题名称 - /// (通过反射筛选 public const string 且字段名以 "EventName" 结尾的常量) - /// - public static List GetAllTopicNamesByIssued() - { - List topics = typeof(ProtocolConst) - .GetFields(BindingFlags.Public | BindingFlags.Static) - .Where(f => - f.IsLiteral && - !f.IsInitOnly && - f.FieldType == typeof(string) && - f.Name.EndsWith("IssuedEventName")) // 通过命名规则过滤主题字段 - .Select(f => (string)f.GetRawConstantValue()!) - .ToList(); - - return topics; - } - - /// - /// 自动获取 ProtocolConst 类中所有下行 Kafka 主题名称 - /// (通过反射筛选 public const string 且字段名以 "EventName" 结尾的常量) - /// - public static List GetAllTopicNamesByReceived() - { - //固定的上报主题 - var topicList = typeof(ProtocolConst) - .GetFields(BindingFlags.Public | BindingFlags.Static) - .Where(f => - f.IsLiteral && - !f.IsInitOnly && - f.FieldType == typeof(string) && - f.Name.EndsWith("ReceivedEventName")) // 通过命名规则过滤主题字段 - .Select(f => (string)f.GetRawConstantValue()!) - .ToList(); - - //动态上报主题,需根据协议的AFN功能码动态获取 - var afnList = EnumExtensions.ToNameValueDictionary(); - //需要排除的AFN功能码 - var excludeItems = new List() { 6, 7, 8,15 }; - - foreach (var item in afnList) - { - if (excludeItems.Contains(item.Value)) - { - continue; - } - - topicList.Add(string.Format(ProtocolConst.AFNTopicNameFormat, item.Value.ToString().PadLeft(2, '0'))); - } - - return topicList; - } - } -} diff --git a/shared/JiShe.CollectBus.Common/Helpers/BusJsonSerializer.cs b/shared/JiShe.CollectBus.Common/Helpers/BusJsonSerializer.cs deleted file mode 100644 index 713501e..0000000 --- a/shared/JiShe.CollectBus.Common/Helpers/BusJsonSerializer.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Encodings.Web; -using System.Text.Json.Serialization; -using System.Text.Json; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Helpers -{ - /// - /// json帮助类 - /// - public static class BusJsonSerializer - { - /// - /// json对象转换成字符串 - /// - /// 需要序列化的对象 - /// 是否忽略实体中实体,不再序列化里面包含的实体 - /// 配置 - /// - public static string Serialize(this object obj, bool IsIgnore = false, JsonSerializerOptions jsonSerializerOptions = null) - { - if (jsonSerializerOptions == null) - { - jsonSerializerOptions = new JsonSerializerOptions - { - 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() }, // 注册你的自定义转换器, - DefaultBufferSize = 4096, - }; - } - - if (IsIgnore == true) - { - jsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; // 忽略循环引用 - - return JsonSerializer.Serialize(obj, jsonSerializerOptions); - } - else - { - return JsonSerializer.Serialize(obj, jsonSerializerOptions); - } - } - - /// - /// json字符串转换成json对象 - /// - /// - /// - /// 是否忽略实体中实体,不再序列化里面包含的实体 - /// 配置 - /// - public static T? Deserialize(this string json, bool IsIgnore = false, JsonSerializerOptions jsonSerializerOptions = null) - { - if (jsonSerializerOptions == null) - { - jsonSerializerOptions = new JsonSerializerOptions - { - 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() }, // 注册你的自定义转换器, - DefaultBufferSize = 4096, - }; - } - - if (IsIgnore == true) - { - jsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; // 忽略循环引用 - - return json == null ? default(T) : JsonSerializer.Deserialize(json, jsonSerializerOptions); - } - else - { - return json == null ? default(T) : JsonSerializer.Deserialize(json, jsonSerializerOptions); - } - } - - /// - /// json字符串转换成json对象 - /// - /// - /// - /// 是否忽略实体中实体,不再序列化里面包含的实体 - /// 配置 - /// - public static object? Deserialize(this string json, Type type, bool IsIgnore = false, JsonSerializerOptions jsonSerializerOptions = null) - { - if (jsonSerializerOptions == null) - { - jsonSerializerOptions = new JsonSerializerOptions - { - 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() } // 注册你的自定义转换器, - }; - } - - - - if (IsIgnore == true) - { - jsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; // 忽略循环引用 - - return json == null ? null : JsonSerializer.Deserialize(json, type, jsonSerializerOptions); - } - else - { - return json == null ? null : JsonSerializer.Deserialize(json, type, jsonSerializerOptions); - } - } - - /// - /// list json字符串转换成list - /// - /// - /// - /// - public static List? DeserializeToList(this string json) - { - return json == null ? default(List) : Deserialize>(json); - } - } - - - public class DateTimeJsonConverter : JsonConverter - { - private readonly string _dateFormatString; - public DateTimeJsonConverter() - { - _dateFormatString = "yyyy-MM-dd HH:mm:ss"; - } - - public DateTimeJsonConverter(string dateFormatString) - { - _dateFormatString = dateFormatString; - } - - public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return DateTime.Parse(reader.GetString()); - } - - public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) - { - writer.WriteStringValue(value.ToString(_dateFormatString)); - } - } - - /// - /// Unix格式时间格式化 - /// - public class UnixTimeConverter : JsonConverter - { - public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - if (long.TryParse(reader.GetString(), out long timestamp)) - return DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime; - } - - if (reader.TokenType == JsonTokenType.Number) - { - long timestamp = reader.GetInt64(); - return DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime; - } - return reader.GetDateTime(); - } - - public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) - { - long timestamp = new DateTimeOffset(value).ToUnixTimeSeconds(); - writer.WriteStringValue(timestamp.ToString()); - } - } -} diff --git a/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs b/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs deleted file mode 100644 index 7c7ef1f..0000000 --- a/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs +++ /dev/null @@ -1,936 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -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 -{ - public static class CommonHelper - { - /// - /// 获得无符号GUID - /// - /// - public static string GetGUID() - { - return Guid.NewGuid().ToString("N"); - } - - /// - /// 获取时间戳 - /// - /// 是否返回秒,false返回毫秒 - /// - public static long GetTimeStampTen(bool isSeconds) - { - if (isSeconds) - { - return DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - } - else - { - return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); - } - } - - /// - /// 获取指定长度的随机数 - /// - /// - /// - public static string GetRandomNumber(int length = 8) - { - if (length <= 8) - { - length = 8; - } - - if (length > 31) - { - length = 32; - } - - var randomArray = RandomNumberGenerator.GetBytes(length); - StringBuilder stringBuilder = new StringBuilder(); - foreach (var item in randomArray) - { - stringBuilder.Append(item); - } - - return stringBuilder.ToString().Substring(0, length); - } - - /// - /// C#反射遍历对象属性获取键值对 - /// - /// 对象类型 - /// 对象 - public static Dictionary GetClassProperties(T model) - { - Type t = model.GetType(); - List propertyList = new List(); - - PropertyInfo[] tempPropertyList = t.GetProperties(); - if (tempPropertyList != null && tempPropertyList.Length > 0) - { - propertyList.AddRange(tempPropertyList); - } - - var parentPropertyInfo = t.BaseType?.GetProperties(); - if (parentPropertyInfo != null && parentPropertyInfo.Length > 0) - { - foreach (var item in parentPropertyInfo) - { - if (!propertyList.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理 - { - propertyList.Add(item); - } - } - } - - Dictionary resultData = new Dictionary(); - - foreach (PropertyInfo item in propertyList) - { - resultData.Add(item.Name, item.GetValue(model, null)); - } - - return resultData; - } - - /// - /// C#反射遍历对象属性,将键值对赋值给属性 - /// - public static object SetClassProperties(string typeModel, Dictionary keyValues) - { - if (keyValues.Count <= 0) - { - return null; - } - - Type tType = Type.GetType(typeModel); - - - PropertyInfo[] PropertyList = tType.GetProperties(); - - object objModel = tType.Assembly.CreateInstance(tType.FullName); - foreach (PropertyInfo item in PropertyList) - { - if (keyValues.ContainsKey(item.Name)) - { - object objectValue = keyValues[item.Name]; - item.SetValue(objModel, objectValue); - } - } - - return objModel; - } - - - - /// - /// 获取指定枚举的所有 Attribute 说明以及value组成的键值对 - /// - /// 对象类 - /// false获取字段、true获取属性 - /// - public static List GetEnumAttributeList(Type type, bool getPropertie = false) - { - if (type == null) - { - return null; - } - - List selectResults = new List(); - List memberInfos = new List(); - - if (getPropertie == false) - { - FieldInfo[] fieldArray = type.GetFields(); - if (null == fieldArray || fieldArray.Length <= 0) - { - return null; - } - - memberInfos.AddRange(fieldArray); - //获取父类的字段 - var parentFieldInfo = type.BaseType?.GetFields(); - if (parentFieldInfo != null && parentFieldInfo.Length > 0) - { - foreach (var item in parentFieldInfo) - { - if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理 - { - memberInfos.Add(item); - } - } - } - } - else - { - PropertyInfo[] properties = type.GetProperties(); - if (null == properties || properties.Length <= 0) - { - return null; - } - - memberInfos.AddRange(properties); - //获取父类的属性 - var parentPropertyInfo = type.BaseType?.GetProperties(); - if (parentPropertyInfo != null && parentPropertyInfo.Length > 0) - { - foreach (var item in parentPropertyInfo) - { - if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理 - { - memberInfos.Add(item); - } - } - } - } - - foreach (var item in memberInfos) - { - DescriptionAttribute[] EnumAttributes = - (DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false); - - dynamic infoObject = null; - if (getPropertie == false) - { - infoObject = (FieldInfo)item; - } - else - { - infoObject = (PropertyInfo)item; - } - - if (EnumAttributes.Length > 0) - { - SelectResult selectResult = new SelectResult() - { - Key = Convert.ToInt32(infoObject.GetValue(null)).ToString(), - Value = EnumAttributes[0].Description, - }; - - selectResults.Add(selectResult); - } - - DisplayAttribute[] DisplayAttributes = - (DisplayAttribute[])item.GetCustomAttributes(typeof(DisplayAttribute), false); - if (DisplayAttributes.Length > 0) - { - SelectResult selectResult = - selectResults.FirstOrDefault(e => e.Key == Convert.ToInt32(infoObject.GetValue(null)).ToString()); - if (selectResult != null) - { - selectResult.SecondValue = DisplayAttributes[0].Name; - } - } - } - - return selectResults; - } - - /// - /// 获取指定枚举的所有 Attribute 说明以及value组成的键值对 - /// - /// 对象类 - /// 第三个标签类型 - /// 第三个标签类型取值名称 - /// false获取字段、true获取属性 - /// - public static List GetEnumAttributeListWithThirdValue(Type type, Type thirdAttributeType, string thirdAttributePropertieName, bool getPropertie = false) - { - if (type == null) - { - return null; - } - - List selectResults = new List(); - List memberInfos = new List(); - - if (getPropertie == false) - { - FieldInfo[] EnumInfo = type.GetFields(); - if (null == EnumInfo || EnumInfo.Length <= 0) - { - return null; - } - memberInfos.AddRange(EnumInfo); - var parentFieldInfo = type.BaseType?.GetFields(); - if (parentFieldInfo != null && parentFieldInfo.Length > 0) - { - memberInfos.AddRange(parentFieldInfo); - } - } - else - { - PropertyInfo[] EnumInfo = type.GetProperties(); - if (null == EnumInfo || EnumInfo.Length <= 0) - { - return null; - } - memberInfos.AddRange(EnumInfo); - var parentPropertyInfo = type.BaseType?.GetProperties(); - if (parentPropertyInfo != null && parentPropertyInfo.Length > 0) - { - memberInfos.AddRange(parentPropertyInfo); - } - } - - foreach (var item in memberInfos) - { - var thirdAttributes = item. - GetCustomAttributes(thirdAttributeType, false); - if (thirdAttributes == null || thirdAttributes.Length <= 0) - { - continue; - } - - DescriptionAttribute[] descriptionAttributes = (DescriptionAttribute[])item. - GetCustomAttributes(typeof(DescriptionAttribute), false); - - dynamic infoObject = null; - if (getPropertie == false) - { - infoObject = (FieldInfo)item; - } - else - { - infoObject = (PropertyInfo)item; - } - - if (descriptionAttributes.Length > 0) - { - SelectResult selectResult = new SelectResult() - { - Key = infoObject.Name, - Value = descriptionAttributes[0].Description, - }; - - selectResults.Add(selectResult); - } - - DisplayAttribute[] displayAttributes = (DisplayAttribute[])item. - GetCustomAttributes(typeof(DisplayAttribute), false); - if (displayAttributes.Length > 0) - { - SelectResult selectResult = selectResults.FirstOrDefault(e => e.Key == infoObject.Name); - if (selectResult != null) - { - selectResult.SecondValue = displayAttributes[0].Name; - } - } - - if (thirdAttributes.Length > 0 && !string.IsNullOrWhiteSpace(thirdAttributePropertieName)) - { - foreach (var attr in thirdAttributes) - { - // 使用反射获取特性的属性值 - var properties = thirdAttributeType.GetProperties(); - foreach (var prop in properties) - { - // 假设你要获取特性的某个属性值,例如 TypeName - if (prop.Name == thirdAttributePropertieName) - { - object value = prop.GetValue(attr); - SelectResult selectResult = selectResults.FirstOrDefault(e => e.Key == infoObject.Name); - if (selectResult != null) - { - selectResult.ThirdValue = value?.ToString(); // 将属性值赋给 ThirdValue - } - break; // 如果找到了需要的属性,可以跳出循环 - } - } - } - } - } - - return selectResults; - } - - /// - /// 获取指定类、指定常量值的Description说明 - /// 包含直接继承的父级字段 - /// - /// 对象类 - /// - /// - public static List> GetTypeDescriptionListToTuple(Type t, bool getPropertie = false) - { - if (t == null) - { - return null; - } - - List memberInfos = new List(); - - if (getPropertie == false) - { - FieldInfo[] fieldInfo = t.GetFields(); - if (null == fieldInfo || fieldInfo.Length <= 0) - { - return null; - } - - memberInfos.AddRange(fieldInfo); - var parentFieldInfo = t.BaseType?.GetFields(); - if (parentFieldInfo != null && parentFieldInfo.Length > 0) - { - foreach (var item in parentFieldInfo) - { - if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理 - { - memberInfos.Add(item); - } - } - } - } - else - { - PropertyInfo[] fieldInfo = t.GetProperties(); - if (null == fieldInfo || fieldInfo.Length <= 0) - { - return null; - } - - memberInfos.AddRange(fieldInfo); - var parentPropertyInfo = t.BaseType?.GetProperties(); - if (parentPropertyInfo != null && parentPropertyInfo.Length > 0) - { - foreach (var item in parentPropertyInfo) - { - if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理 - { - memberInfos.Add(item); - } - } - } - } - - List> tuples = new List>(); - - foreach (var item in memberInfos) - { - DescriptionAttribute[] descriptionAttribute = - (DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false); - - NumericalOrderAttribute[] indexAttributes = - (NumericalOrderAttribute[])item.GetCustomAttributes(typeof(NumericalOrderAttribute), false); - - - if (descriptionAttribute.Length > 0 && indexAttributes.Length > 0) - { - Tuple tuple = new Tuple(item.Name, - descriptionAttribute[0].Description, indexAttributes[0].Index); - tuples.Add(tuple); - } - } - - return tuples; - } - - /// - /// 获取指定类、指定常量值的常量说明 - /// - /// 常量字段名称 - ///属性还是字段 - /// - public static string GetTypeDescriptionName(string fieldName, bool getPropertie = false) - { - if (string.IsNullOrEmpty(fieldName)) - { - return ""; - } - - MemberInfo memberInfo = null; - if (getPropertie == false) - { - memberInfo = typeof(T).GetField(fieldName); - } - else - { - memberInfo = typeof(T).GetProperty(fieldName); - } - - if (null == memberInfo) - { - return ""; - } - - DescriptionAttribute[] EnumAttributes = - (DescriptionAttribute[])memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); - if (EnumAttributes.Length <= 0) - { - return ""; - } - - return EnumAttributes[0].Description; - } - - /// - /// 获取指定命名空间下指定常量值的常量说明 - /// - /// 常量字段名称 - /// 命名空间,主要用来找到对应程序集 - ///属性还是字段 - /// - public static string GetTypeDescriptionName(string fieldName, string assemblyName, bool getPropertie = false) - { - if (string.IsNullOrWhiteSpace(fieldName) || string.IsNullOrWhiteSpace(assemblyName)) - { - return null; - } - - string desc = ""; - foreach (var item in GetEnumList(assemblyName)) - { - desc = GetTypeDescriptionName(item, fieldName, getPropertie); - if (!string.IsNullOrEmpty(desc)) - { - break; - } - } - - return desc; - } - - /// - /// 获取指定类、指定常量值的常量说明 - /// - /// 对象类 - /// 常量字段名称 - ///属性还是字段 - /// - public static string GetTypeDescriptionName(this Type t, string fieldName, bool getPropertie = false) - { - if (string.IsNullOrWhiteSpace(fieldName)) - { - return ""; - } - - MemberInfo memberInfo = null; - if (getPropertie == false) - { - memberInfo = t.GetField(fieldName); - } - else - { - memberInfo = t.GetProperty(fieldName); - } - - if (null != memberInfo) - { - DescriptionAttribute[] EnumAttributes = - (DescriptionAttribute[])memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); - if (EnumAttributes.Length > 0) - { - return EnumAttributes[0].Description; - } - } - - return ""; - } - - /// - /// 扩展方法,获得枚举值集合 - /// - ///枚举的DisplayName - public static List GetEnumList() where T : Enum - { - List enumList = new List(); - foreach (T value in Enum.GetValues(typeof(T))) - { - enumList.Add(value); - } - - return enumList; - } - - private static List GetEnumList(string assemblyName) - { - if (!String.IsNullOrEmpty(assemblyName)) - { - Assembly assembly = Assembly.Load(assemblyName); - List ts = assembly.GetTypes().Where(x => x.GetTypeInfo().IsClass).ToList(); - return ts; - } - - return new List(); - } - - /// - /// 扩展方法,获得枚举的Display值 - /// - ///枚举值 - ///当枚举值没有定义DisplayNameAttribute,是否使用枚举名代替,默认是使用 - ///属性还是字段 - ///枚举的DisplayName - public static string GetDisplayName(this Enum value, Boolean nameInstead = true, bool getPropertie = false) - { - Type type = value.GetType(); - string name = Enum.GetName(type, value); - if (name == null) - { - return null; - } - - DisplayAttribute attribute = null; - - if (getPropertie == false) - { - attribute = Attribute.GetCustomAttribute(type.GetField(name), typeof(DisplayAttribute)) as DisplayAttribute; - } - else - { - attribute = - Attribute.GetCustomAttribute(type.GetProperty(name), typeof(DisplayAttribute)) as DisplayAttribute; - } - - - if (attribute == null && nameInstead == true) - { - return name; - } - - return attribute == null ? null : attribute.Name; - } - - /// - /// 获取枚举的描述信息 - /// - /// - /// - public static string GetEnumDescription(this Enum value) - { - var name = value.ToString(); - var field = value.GetType().GetField(name); - if (field == null) return name; - - var att = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute), false); - - return att == null ? field.Name : ((DescriptionAttribute)att).Description; - } - - - /// - /// 根据枚举类型值返回枚举定义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()]; - } - - - /// - /// 将传入的字符串中间部分字符替换成特殊字符 - /// - /// 需要替换的字符串 - /// 前保留长度 - /// 尾保留长度 - /// 特殊字符 - /// 被特殊字符替换的字符串 - public static string ReplaceWithSpecialChar(this string value, int startLen = 1, int endLen = 1, - char specialChar = '*') - { - if (string.IsNullOrEmpty(value)) - { - return value; - } - - try - { - - if (value.Length <= startLen + endLen) - { - var temStartVal = value.Substring(0, startLen); - return $"{temStartVal}{"".PadLeft(endLen, specialChar)}"; - } - - if (value.Length == 10 && endLen == 1) - { - endLen = 3; - } - - var startVal = value.Substring(0, startLen); - var endVal = value.Substring(value.Length - endLen); - if (value.Length == 2) - { - endVal = ""; - } - - value = $"{startVal}{endVal.PadLeft(value.Length - startLen, specialChar)}"; - } - catch (Exception) - { - throw; - } - - return value; - } - - /// - /// Linux下字体名称转换 - /// - /// - /// - public static string GetLinuxFontFamily(this string fontValue) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - if (fontValue == "楷体") - { - fontValue = "KaiTi"; - } - else if (fontValue == "隶书") - { - fontValue = "LiSu"; - } - else if (fontValue == "宋体") - { - fontValue = "SimSun"; - } - else if (fontValue == "微软雅黑") - { - fontValue = "Microsoft YaHei"; - } - else if (fontValue == "新宋体") - { - fontValue = "NSimSun"; - } - else if (fontValue == "仿宋") - { - fontValue = "FangSong"; - } - else if (fontValue == "黑体") - { - fontValue = "SimHei"; - } - - } - - return fontValue; - } - - /// - /// 获取任务标识 - /// - /// - /// - /// - /// - /// - /// - 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')}"; - - return makstr;// Convert.ToInt32(makstr) << 32 | msa; - } - - /// - /// 判断是生成月 - /// - /// - /// - /// - public static bool JudgeIsGenerate_Month(string eachMonthWith, DateTime curTime) - { - var arr = eachMonthWith.Split(','); - if (arr.Contains(curTime.Day.ToString())) - return true; - return false; - } - - /// - /// 判断是生成一次 - /// - /// - /// - /// - public static bool JudgeIsGenerate_Once(DateTime onceWithDate, DateTime curTime) => curTime.Date.Equals(onceWithDate);//为当天时发送 - - /// - /// 判断是生成日 - /// - /// - /// - /// - 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); - } - - public static readonly List strWeeks = new List() { "周日", "周一", "周二", "周三", "周四", "周五", "周六" }; - - /// - /// 判断是生成周 - /// - /// - /// - /// - public static bool JudgeIsGenerate_Week(string eachWeekWith, DateTime curTime) - { - if (string.IsNullOrWhiteSpace(eachWeekWith)) - { - return false; - } - - var weekName = strWeeks[(int)curTime.DayOfWeek]; - var arr = eachWeekWith.Split(','); - return arr.Contains(weekName); - - } - - /// - /// 系统采集频率转换为集中器采集密度 - /// - /// - /// - 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); - } - - /// - /// 加载指定名称的程序集 - /// - /// - /// - public static List LoadAssemblies(string[] assemblyNames) - { - var assemblies = new List(); - - // 获取已加载的程序集 - foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) - { - if (assemblyNames.Contains(asm.GetName().Name)) - assemblies.Add(asm); - } - - // 尝试加载未加载的程序集 - foreach (var name in assemblyNames) - { - if (!assemblies.Any(a => a.GetName().Name == name)) - { - try - { - var assembly = Assembly.Load(name); - assemblies.Add(assembly); - } - catch (FileNotFoundException) - { - // 若Load失败,尝试从基目录加载 - var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{name}.dll"); - if (File.Exists(path)) - { - try - { - assemblies.Add(Assembly.LoadFrom(path)); - } - catch { /* 记录错误 */ } - } - } - } - } - - return assemblies; - } - - /// - /// 创建类型实例 - /// - /// - /// - public static List CreateInstances(List types) - { - var instances = new List(); - foreach (var type in types) - { - try - { - instances.Add(Activator.CreateInstance(type)); - } - catch (Exception) - { - throw; - } - } - return instances; - } - } -} diff --git a/shared/JiShe.CollectBus.Common/Helpers/SelectResult.cs b/shared/JiShe.CollectBus.Common/Helpers/SelectResult.cs deleted file mode 100644 index 4ccaf99..0000000 --- a/shared/JiShe.CollectBus.Common/Helpers/SelectResult.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Helpers -{ - /// - /// 下拉框选项元素 - /// - public class SelectResult - { - /// - /// 下拉框 键 - /// - public string Key { get; set; } - - /// - /// 下拉框 值 - /// - public string Value { get; set; } - - /// - /// 下拉框 值2 - /// - public string SecondValue { get; set; } - - /// - /// 下拉框 值3 - /// - public object ThirdValue { get; set; } - - } -} diff --git a/shared/JiShe.CollectBus.Common/Helpers/TimestampHelper.cs b/shared/JiShe.CollectBus.Common/Helpers/TimestampHelper.cs deleted file mode 100644 index 9edc3cd..0000000 --- a/shared/JiShe.CollectBus.Common/Helpers/TimestampHelper.cs +++ /dev/null @@ -1,68 +0,0 @@ -using JiShe.CollectBus.Common.Enums; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Helpers -{ - /// - /// 时间戳帮助类 - /// - public static class TimestampHelper - { - private static readonly long UnixEpochTicks = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).Ticks; - - /// - /// 获取当前 DateTimeOffset 距离 Unix 纪元(1970-01-01)的微秒数 - /// - public static long ToUnixTimeMicroseconds(this DateTimeOffset dateTimeOffset) - { - // Ticks 单位是 100 纳秒,转换为微秒需除以 10 - long elapsedTicks = dateTimeOffset.Ticks - UnixEpochTicks; - return elapsedTicks / 10; // 1 微秒 = 1000 纳秒 = 10 Ticks - } - - /// - /// 获取当前 DateTimeOffset 距离 Unix 纪元(1970-01-01)的纳秒数 - /// - public static long ToUnixTimeNanoseconds(this DateTimeOffset dateTimeOffset) - { - long nanoseconds = (dateTimeOffset.Ticks - UnixEpochTicks) * 100; - return nanoseconds; - } - - /// - /// 将 long 类型时间戳转换为 DateTime(UTC) - /// - /// 时间戳数值 - /// 时间戳单位 - public static DateTime ConvertToDateTime(long timestamp, TimestampUnit unit = TimestampUnit.Milliseconds) - { - long ticks = unit switch - { - TimestampUnit.Seconds => checked(timestamp * TimeSpan.TicksPerSecond), - TimestampUnit.Milliseconds => checked(timestamp * TimeSpan.TicksPerMillisecond), - TimestampUnit.Microseconds => checked(timestamp * 10), // 1微秒 = 10 Ticks(100纳秒) - TimestampUnit.Nanoseconds => checked(timestamp / 100),// 1 Tick = 100纳秒 - _ => throw new ArgumentException("无效的时间单位", nameof(unit)) - }; - - try - { - DateTime result = new DateTime(UnixEpochTicks + ticks, DateTimeKind.Utc); - // 校验结果是否在 DateTime 合法范围内(0001-01-01 至 9999-12-31) - if (result < DateTime.MinValue || result > DateTime.MaxValue) - { - throw new ArgumentOutOfRangeException(nameof(timestamp), "时间戳超出 DateTime 范围"); - } - return result; - } - catch (ArgumentOutOfRangeException ex) - { - throw new ArgumentOutOfRangeException("时间戳无效", ex); - } - } - } -} diff --git a/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj b/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj index 6cf0246..5a6134b 100644 --- a/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj +++ b/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable @@ -16,16 +16,21 @@ - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/shared/JiShe.CollectBus.Common/Models/DeviceCacheBasicModel.cs b/shared/JiShe.CollectBus.Common/Models/DeviceCacheBasicModel.cs deleted file mode 100644 index 178b625..0000000 --- a/shared/JiShe.CollectBus.Common/Models/DeviceCacheBasicModel.cs +++ /dev/null @@ -1,56 +0,0 @@ -using JiShe.CollectBus.Common.Enums; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.Common.Models -{ - /// - /// 设备缓存基础模型 - /// - public abstract class DeviceCacheBasicModel - { - /// - /// 集中器Id - /// - public int FocusId { get; set; } - - /// - /// 表Id - /// - public int MeterId { get; set; } - - /// - /// 关系映射标识,用于ZSet的Member字段和Set的Value字段,具体值可以根据不同业务场景进行定义 - /// - public virtual string MemberId => $"{FocusId}:{MeterId}"; - - /// - /// ZSet排序索引分数值,具体值可以根据不同业务场景进行定义,例如时间戳 - /// - public virtual long ScoreValue=> ((long)FocusId << 32) | (uint)MeterId; - - /// - /// 是否已处理 - /// - public virtual bool IsHandle { get; set; } = false; - - /// - /// 集中器地址 - /// - 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 deleted file mode 100644 index 525b5a2..0000000 --- a/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace JiShe.CollectBus.Common -{ - /// - /// 服务器应用配置 - /// - public class ServerApplicationOptions - { - /// - /// 服务器标识 - /// - public string ServerTagName { get; set; } - - /// - /// 系统类型 - /// - public string SystemType { get; set; } - - /// - /// 首次采集时间 - /// - public DateTime? FirstCollectionTime { get; set; } - - /// - /// 自动验证时间 - /// - public string AutomaticVerificationTime { get; set; } - - /// - /// 自动获取终端版时间 - /// - public string AutomaticTerminalVersionTime { get; set; } - - /// - /// 自动获取远程通信模块(SIM)版本时间 - /// - 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.Domain.Shared/CollectBusDomainSharedModule.cs b/shared/JiShe.CollectBus.Domain.Shared/CollectBusDomainSharedModule.cs index ad19eb4..4530d96 100644 --- a/shared/JiShe.CollectBus.Domain.Shared/CollectBusDomainSharedModule.cs +++ b/shared/JiShe.CollectBus.Domain.Shared/CollectBusDomainSharedModule.cs @@ -8,11 +8,13 @@ using Volo.Abp.Validation.Localization; using Volo.Abp.VirtualFileSystem; using JiShe.CollectBus.Interceptors; using Microsoft.Extensions.DependencyInjection; +using JiShe.ServicePro.IoTDBManagement; namespace JiShe.CollectBus; [DependsOn( typeof(AbpValidationModule), + typeof(IoTDBManagementDomainSharedModule), typeof(AbpDddDomainSharedModule) )] public class CollectBusDomainSharedModule : AbpModule diff --git a/shared/JiShe.CollectBus.Domain.Shared/DynamicModule/DynamicModuleManager.cs b/shared/JiShe.CollectBus.Domain.Shared/DynamicModule/DynamicModuleManager.cs index 8f8e0eb..73d5a85 100644 --- a/shared/JiShe.CollectBus.Domain.Shared/DynamicModule/DynamicModuleManager.cs +++ b/shared/JiShe.CollectBus.Domain.Shared/DynamicModule/DynamicModuleManager.cs @@ -6,7 +6,9 @@ using System.Reflection; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.DependencyInjection; +using Volo.Abp.Logging; using Volo.Abp.Modularity; +using Volo.Abp.Modularity.PlugIns; namespace JiShe.CollectBus.DynamicModule { @@ -17,13 +19,22 @@ namespace JiShe.CollectBus.DynamicModule { private readonly IModuleContainer _moduleContainer; private readonly IServiceProvider _serviceProvider; + //private readonly IModuleLoader _moduleLoader; + //private readonly IAbpApplicationWithInternalServiceProvider _abpApplicationWithInternalServiceProvider; + //private readonly IServiceCollection _services; public DynamicModuleManager( IModuleContainer moduleContainer, - IServiceProvider serviceProvider) + IServiceProvider serviceProvider + //IModuleLoader moduleLoader, + //IServiceCollection services, IAbpApplicationWithInternalServiceProvider abpApplicationWithInternalServiceProvider + ) { _moduleContainer = moduleContainer; _serviceProvider = serviceProvider; + //_moduleLoader = moduleLoader; + //_services = services; + //_abpApplicationWithInternalServiceProvider= abpApplicationWithInternalServiceProvider; } public Type[] GetRegisteredModuleTypes() @@ -31,6 +42,21 @@ namespace JiShe.CollectBus.DynamicModule return _moduleContainer.Modules.Select(m => m.Type).ToArray(); } + public async Task LoadModuleAsync(Type moduleType) + { + if (!typeof(IAbpModule).IsAssignableFrom(moduleType)) + { + throw new ArgumentException($"指定的类型 {moduleType.FullName} 不是有效的ABP模块类型", nameof(moduleType)); + } + //var modules = _moduleLoader.LoadModules(_services, moduleType, new PlugInSourceList()); + using (var application = AbpApplicationFactory.Create(moduleType)) + { + await application.InitializeAsync(); + } + + //await _abpApplicationWithInternalServiceProvider.InitializeAsync(); + } + public async Task ReinitializeModuleAsync(Type moduleType) { if (!typeof(IAbpModule).IsAssignableFrom(moduleType)) diff --git a/shared/JiShe.CollectBus.Domain.Shared/DynamicModule/IDynamicModuleManager.cs b/shared/JiShe.CollectBus.Domain.Shared/DynamicModule/IDynamicModuleManager.cs index 3f87820..079f754 100644 --- a/shared/JiShe.CollectBus.Domain.Shared/DynamicModule/IDynamicModuleManager.cs +++ b/shared/JiShe.CollectBus.Domain.Shared/DynamicModule/IDynamicModuleManager.cs @@ -41,5 +41,7 @@ namespace JiShe.CollectBus.DynamicModule /// 模块名称 /// 模块类型,如果找不到则为null Type GetModuleTypeByName(string moduleName); + + Task LoadModuleAsync(Type moduleType); } } \ No newline at end of file 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 5453712..978122c 100644 --- a/shared/JiShe.CollectBus.Domain.Shared/JiShe.CollectBus.Domain.Shared.csproj +++ b/shared/JiShe.CollectBus.Domain.Shared/JiShe.CollectBus.Domain.Shared.csproj @@ -1,21 +1,21 @@ - + - net8.0 + net9.0 enable JiShe.CollectBus true - - + + - + @@ -31,6 +31,12 @@ + + + + + + diff --git a/web/JiShe.CollectBus.Host/CollectBusHostModule.Configure.cs b/web/JiShe.CollectBus.Host/CollectBusHostModule.Configure.cs index b00b7b6..824a892 100644 --- a/web/JiShe.CollectBus.Host/CollectBusHostModule.Configure.cs +++ b/web/JiShe.CollectBus.Host/CollectBusHostModule.Configure.cs @@ -19,39 +19,13 @@ using TouchSocket.Sockets; using JiShe.CollectBus.Plugins; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; -using JiShe.CollectBus.Cassandra; namespace JiShe.CollectBus.Host { public partial class CollectBusHostModule { - /// - /// Configures the hangfire. - /// - /// The context. - private void ConfigureHangfire(ServiceConfigurationContext context) - { - var redisStorageOptions = new RedisStorageOptions() - { - Db = context.Services.GetConfiguration().GetValue("Redis:HangfireDB") - }; - - Configure(options => { options.IsJobExecutionEnabled = false; }); - - context.Services.AddHangfire(config => - { - config.UseRedisStorage( - context.Services.GetConfiguration().GetValue("Redis:Configuration"), redisStorageOptions) - .WithJobExpirationTimeout(TimeSpan.FromDays(7)); - var delaysInSeconds = new[] { 10, 60, 60 * 3 }; // 重试时间间隔 - const int Attempts = 3; // 重试次数 - config.UseFilter(new AutomaticRetryAttribute() { Attempts = Attempts, DelaysInSeconds = delaysInSeconds }); - //config.UseFilter(new AutoDeleteAfterSuccessAttribute(TimeSpan.FromDays(7))); - config.UseFilter(new JobRetryLastFilter(Attempts)); - }); - context.Services.AddHangfireServer(); - } + /// /// Configures the JWT authentication. @@ -122,22 +96,7 @@ namespace JiShe.CollectBus.Host }; }); } - - /// - /// Configures the cache. - /// - /// The context. - private void ConfigureCache(ServiceConfigurationContext context) - { - Configure( - options => { options.KeyPrefix = "CollectBus:"; }); - var configuration = context.Services.GetConfiguration(); - var redis = ConnectionMultiplexer.Connect($"{configuration.GetValue("Redis:Configuration")},defaultdatabase={configuration.GetValue("Redis:DefaultDB")}"); - context.Services - .AddDataProtection() - .PersistKeysToStackExchangeRedis(redis, "CollectBus-Protection-Keys"); - } - + /// /// Configures the swagger services. /// @@ -194,9 +153,9 @@ namespace JiShe.CollectBus.Host options => { options.IgnoredUrls.Add("/AuditLogs/page"); - options.IgnoredUrls.Add("/hangfire/stats"); + //options.IgnoredUrls.Add("/hangfire/stats"); options.IgnoredUrls.Add("/hangfire/recurring/trigger"); - options.IgnoredUrls.Add("/cap"); + //options.IgnoredUrls.Add("/cap"); options.IgnoredUrls.Add("/"); }); } @@ -252,11 +211,9 @@ namespace JiShe.CollectBus.Host /// private void ConfigureHealthChecks(ServiceConfigurationContext context, IConfiguration configuration) { - if (!configuration.GetValue("HealthChecks:IsEnable")) return; - var cassandraConfig = new CassandraConfig(); - configuration.GetSection("Cassandra").Bind(cassandraConfig); + if (!configuration.GetValue("HealthChecks:IsEnable")) return; context.Services.AddHealthChecks() - .AddMongoDb(configuration.GetConnectionString("Default"), "MongoDB", HealthStatus.Unhealthy) + //.AddMongoDb(configuration.GetConnectionString("Default"), "MongoDB", HealthStatus.Unhealthy) .AddRedis(configuration.GetValue("Redis:Configuration") ?? string.Empty, "Redis", HealthStatus.Unhealthy) //.AddKafka(new Confluent.Kafka.ProducerConfig diff --git a/web/JiShe.CollectBus.Host/CollectBusHostModule.cs b/web/JiShe.CollectBus.Host/CollectBusHostModule.cs index 1666341..a43aabe 100644 --- a/web/JiShe.CollectBus.Host/CollectBusHostModule.cs +++ b/web/JiShe.CollectBus.Host/CollectBusHostModule.cs @@ -1,18 +1,13 @@ -using Hangfire; -using HealthChecks.UI.Client; -using JiShe.CollectBus.Common; -using JiShe.CollectBus.Host.Extensions; +using JiShe.CollectBus.Common; using JiShe.CollectBus.Host.HealthChecks; using JiShe.CollectBus.Host.Swaggers; -using JiShe.CollectBus.IoTDB.Options; -using JiShe.CollectBus.MongoDB; +using JiShe.ServicePro.ServerOptions; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Swashbuckle.AspNetCore.SwaggerUI; using Volo.Abp; using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.Autofac; -using Volo.Abp.BackgroundWorkers.Hangfire; using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.Modularity; using Volo.Abp.Swashbuckle; @@ -30,9 +25,7 @@ namespace JiShe.CollectBus.Host typeof(AbpSwashbuckleModule), typeof(AbpTimingModule), typeof(CollectBusApplicationModule), - typeof(CollectBusMongoDbModule), - typeof(AbpCachingStackExchangeRedisModule), - typeof(AbpBackgroundWorkersHangfireModule) + typeof(AbpCachingStackExchangeRedisModule) )] public partial class CollectBusHostModule : AbpModule { @@ -43,12 +36,11 @@ namespace JiShe.CollectBus.Host public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); - ConfigureCache(context); ConfigureSwaggerServices(context, configuration); ConfigureNetwork(context, configuration); ConfigureJwtAuthentication(context, configuration); - ConfigureHangfire(context); - ConfigureAuditLog(context); + //ConfigureHangfire(context); + //ConfigureAuditLog(context); ConfigureCustom(context, configuration); ConfigureHealthChecks(context, configuration); Configure(options => { options.Kind = DateTimeKind.Local; }); @@ -92,10 +84,10 @@ namespace JiShe.CollectBus.Host app.UseAuditing(); app.UseAbpSerilogEnrichers(); app.UseUnitOfWork(); - app.UseHangfireDashboard("/hangfire", new DashboardOptions - { - IgnoreAntiforgeryToken = true - }); + //app.UseHangfireDashboard("/hangfire", new DashboardOptions + //{ + // IgnoreAntiforgeryToken = true + //}); app.UseConfiguredEndpoints(endpoints => { if (!configuration.GetValue("HealthChecks:IsEnable")) return; diff --git a/web/JiShe.CollectBus.Host/HealthChecks/CassandraHealthCheck.cs b/web/JiShe.CollectBus.Host/HealthChecks/CassandraHealthCheck.cs index 1157239..edc5c37 100644 --- a/web/JiShe.CollectBus.Host/HealthChecks/CassandraHealthCheck.cs +++ b/web/JiShe.CollectBus.Host/HealthChecks/CassandraHealthCheck.cs @@ -1,5 +1,5 @@ -using Cassandra; -using JiShe.CollectBus.Cassandra; +//using Cassandra; +//using JiShe.CollectBus.Cassandra; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace JiShe.CollectBus.Host.HealthChecks @@ -31,27 +31,28 @@ namespace JiShe.CollectBus.Host.HealthChecks /// public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) { - var cassandraConfig = new CassandraConfig(); - _configuration.GetSection("Cassandra").Bind(cassandraConfig); - try - { - var clusterBuilder = Cluster.Builder(); - foreach (var node in cassandraConfig.Nodes) - { - clusterBuilder.AddContactPoint(node.Host) - .WithPort(node.Port); - } - clusterBuilder.WithCredentials(cassandraConfig.Username, cassandraConfig.Password); - var cluster = clusterBuilder.Build(); - using var session = await cluster.ConnectAsync(); - var result = await Task.FromResult(session.Execute("SELECT release_version FROM system.local")); - var version = result.First().GetValue("release_version"); - return HealthCheckResult.Healthy($"Cassandra is healthy. Version: {version}"); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, $"Cassandra is unhealthy: {ex.Message}", ex); - } + return HealthCheckResult.Healthy("Cassandra is unhealthy."); + //var cassandraConfig = new CassandraConfig(); + //_configuration.GetSection("Cassandra").Bind(cassandraConfig); + //try + //{ + // var clusterBuilder = Cluster.Builder(); + // foreach (var node in cassandraConfig.Nodes) + // { + // clusterBuilder.AddContactPoint(node.Host) + // .WithPort(node.Port); + // } + // clusterBuilder.WithCredentials(cassandraConfig.Username, cassandraConfig.Password); + // var cluster = clusterBuilder.Build(); + // using var session = await cluster.ConnectAsync(); + // var result = await Task.FromResult(session.Execute("SELECT release_version FROM system.local")); + // var version = result.First().GetValue("release_version"); + // return HealthCheckResult.Healthy($"Cassandra is healthy. Version: {version}"); + //} + //catch (Exception ex) + //{ + // return new HealthCheckResult(context.Registration.FailureStatus, $"Cassandra is unhealthy: {ex.Message}", ex); + //} } } } \ No newline at end of file diff --git a/web/JiShe.CollectBus.Host/HealthChecks/IoTDBHealthCheck.cs b/web/JiShe.CollectBus.Host/HealthChecks/IoTDBHealthCheck.cs index a1cebf2..7063e91 100644 --- a/web/JiShe.CollectBus.Host/HealthChecks/IoTDBHealthCheck.cs +++ b/web/JiShe.CollectBus.Host/HealthChecks/IoTDBHealthCheck.cs @@ -1,8 +1,3 @@ -using System.Net.Sockets; -using JiShe.CollectBus.Cassandra; -using JiShe.CollectBus.IoTDB.Interface; -using JiShe.CollectBus.IoTDB.Options; -using JiShe.CollectBus.IoTDB.Provider; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace JiShe.CollectBus.Host.HealthChecks diff --git a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj b/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj index 96786fe..9337526 100644 --- a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj +++ b/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable True @@ -24,44 +24,38 @@ - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + @@ -85,4 +79,4 @@ - + \ No newline at end of file diff --git a/web/JiShe.CollectBus.Host/appsettings.Production.json b/web/JiShe.CollectBus.Host/appsettings.Production.json index 3fa91ed..93b480c 100644 --- a/web/JiShe.CollectBus.Host/appsettings.Production.json +++ b/web/JiShe.CollectBus.Host/appsettings.Production.json @@ -4,83 +4,45 @@ "PrepayDB": "server=rm-m5el3d1u1k0wzk70n2o.sqlserver.rds.aliyuncs.com,3433;database=jishe.sysdb;uid=v3sa;pwd=JiShe123;Encrypt=False;Trust Server Certificate=False", "EnergyDB": "server=rm-wz9hw529i3j1e3b5fbo.sqlserver.rds.aliyuncs.com,3433;database=db_energy;uid=yjdb;pwd=Kdjdhf+9*7ad222LL;Encrypt=False;Trust Server Certificate=False" }, - "Redis": { - "Configuration": "47.110.60.222:6379,password=3JBGfyhTaD46nS,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true", - "MaxPoolSize": "50", - "DefaultDB": "14", - "HangfireDB": "13" + "FreeRedisOptions": { + "ConnectionString": "47.110.53.196:6379,password=1q3J@BGf!yhTaD46nS#,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true,maxPoolSize=50,defaultdatabase=14", + "UseDistributedCache": true + }, + "FreeSqlProviderOptions": { + "UsePrepayDB": true, + "UseEnergyDB": true, + "PrintLog": true }, "Kafka": { - "BootstrapServers": "47.110.62.104:9092,47.110.53.196:9092,47.110.60.222:9092", + "BootstrapServers": "47.110.62.104:9094,47.110.53.196:9094,47.110.60.222:9094", "EnableFilter": true, - "EnableAuthorization": true, + "EnableAuthorization": false, "SaslUserName": "lixiao", - "SaslPassword": "lixiao@1980", + "SaslPassword": "lixiao1980", "KafkaReplicationFactor": 3, "NumPartitions": 30, - "TaskThreadCount": -1, - "ServerTagName": "JiSheCollectBus100", - "FirstCollectionTime": "2025-04-22 16:07:00" + "TaskThreadCount": -1 }, "IoTDBOptions": { "UserName": "root", - "Password": "root", - //"ClusterList": [ "47.110.53.196:6667", "47.110.60.222:6667", "47.110.62.104:6667" ], - //"Password": "root", - "ClusterList": [ "121.42.175.177:16667" ], - "PoolSize": 2, - "DataBaseName": "energy", + "Password": "Lixiao@1980", + "TreeModelClusterList": [ "47.110.53.196:6667", "47.110.60.222:6667", "47.110.62.104:6667" ], + "TableModelClusterList": [ "47.110.53.196:6667", "47.110.60.222:6667", "47.110.62.104:6667" ], + "PoolSize": 32, + "TableModelDataBaseName": "energy", "OpenDebugMode": true, "UseTableSessionPoolByDefault": false }, - "Cassandra": { - "ReplicationStrategy": { - "Class": "NetworkTopologyStrategy", //策略为NetworkTopologyStrategy时才会有多个数据中心,SimpleStrategy用在只有一个数据中心的情况下 - "DataCenters": [ - { - "Name": "dc1", - "ReplicationFactor": 3 - } - ] - }, - "Nodes": [ - { - "Host": "121.42.175.177", - "Port": 19042, - "DataCenter": "dc1", - "Rack": "RAC1" - }, - { - "Host": "121.42.175.177", - "Port": 19043, - "DataCenter": "dc1", - "Rack": "RAC2" - }, - { - "Host": "121.42.175.177", - "Port": 19044, - "DataCenter": "dc1", - "Rack": "RAC2" - } - ], - "Username": "admin", - "Password": "lixiao1980", - "Keyspace": "jishecollectbus", - "ConsistencyLevel": "Quorum", - "PoolingOptions": { - "CoreConnectionsPerHost": 4, - "MaxConnectionsPerHost": 8, - "MaxRequestsPerConnection": 2000 - }, - "SocketOptions": { - "ConnectTimeoutMillis": 10000, - "ReadTimeoutMillis": 20000 - }, - "QueryOptions": { - "ConsistencyLevel": "Quorum", - "SerialConsistencyLevel": "Serial", - "DefaultIdempotence": true - } + "ServerApplicationOptions": { + "ServerTagName": "JiSheCollectBus77", + "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" }, "HealthChecks": { "IsEnable": false diff --git a/web/JiShe.CollectBus.Host/appsettings.json b/web/JiShe.CollectBus.Host/appsettings.json index 6bfcc45..efc776d 100644 --- a/web/JiShe.CollectBus.Host/appsettings.json +++ b/web/JiShe.CollectBus.Host/appsettings.json @@ -5,81 +5,35 @@ "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" }, - "Redis": { - "Configuration": "192.168.5.9:6380,password=1q2w3e!@#,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true", - "MaxPoolSize": "50", - "DefaultDB": "14", - "HangfireDB": "13" + "FreeRedisOptions": { + "ConnectionString": "47.110.53.196:6379,password=1q3J@BGf!yhTaD46nS#,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true,maxPoolSize=50,defaultdatabase=14", + "UseDistributedCache": true + }, + "FreeSqlProviderOptions": { + "UsePrepayDB": true, + "UseEnergyDB": true, + "PrintLog": true }, "Kafka": { - "BootstrapServers": "192.168.5.9:29092,192.168.5.9:39092,192.168.5.9:49092", + "BootstrapServers": "47.110.62.104:9094,47.110.53.196:9094,47.110.60.222:9094", "EnableFilter": true, "EnableAuthorization": false, "SaslUserName": "lixiao", "SaslPassword": "lixiao1980", "KafkaReplicationFactor": 3, "NumPartitions": 30, - "TaskThreadCount": -1, - "FirstCollectionTime": "2025-04-22 16:07:00" + "TaskThreadCount": -1 }, "IoTDBOptions": { "UserName": "root", - "Password": "root", - "ClusterList": [ "121.42.175.177:16667" ], + "Password": "Lixiao@1980", + "TreeModelClusterList": [ "47.110.53.196:6667", "47.110.60.222:6667", "47.110.62.104:6667" ], + "TableModelClusterList": [ "47.110.53.196:6667", "47.110.60.222:6667", "47.110.62.104:6667" ], "PoolSize": 32, - "DataBaseName": "energy", + "TableModelDataBaseName": "energy", "OpenDebugMode": true, "UseTableSessionPoolByDefault": false }, - "Cassandra": { - "ReplicationStrategy": { - "Class": "NetworkTopologyStrategy", //策略为NetworkTopologyStrategy时才会有多个数据中心,SimpleStrategy用在只有一个数据中心的情况下 - "DataCenters": [ - { - "Name": "dc1", - "ReplicationFactor": 3 - } - ] - }, - "Nodes": [ - { - "Host": "192.168.5.9", - "Port": 9042, - "DataCenter": "dc1", - "Rack": "RAC1" - }, - { - "Host": "192.168.5.9", - "Port": 9043, - "DataCenter": "dc1", - "Rack": "RAC2" - }, - { - "Host": "192.168.5.9", - "Port": 9044, - "DataCenter": "dc1", - "Rack": "RAC2" - } - ], - "Username": "admin", - "Password": "lixiao1980", - "Keyspace": "jishecollectbus", - "ConsistencyLevel": "Quorum", - "PoolingOptions": { - "CoreConnectionsPerHost": 4, - "MaxConnectionsPerHost": 8, - "MaxRequestsPerConnection": 2000 - }, - "SocketOptions": { - "ConnectTimeoutMillis": 10000, - "ReadTimeoutMillis": 20000 - }, - "QueryOptions": { - "ConsistencyLevel": "Quorum", - "SerialConsistencyLevel": "Serial", - "DefaultIdempotence": true - } - }, "Serilog": { "Using": [ "Serilog.Sinks.Console", @@ -140,7 +94,7 @@ } ], "ServerApplicationOptions": { - "ServerTagName": "JiSheCollectBus99", + "ServerTagName": "JiSheCollectBus77", "SystemType": "Energy", "FirstCollectionTime": "2025-04-28 15:07:00", "AutomaticVerificationTime": "16:07:00", @@ -153,5 +107,8 @@ "PlugInFolder": "", "TCP": { "ClientPort": 10500 + }, + "BackgroundJobs": { + "IsJobExecutionEnabled": false // 关闭任务执行 } } \ No newline at end of file diff --git a/web/JiShe.CollectBus.HttpApi/JiShe.CollectBus.HttpApi.csproj b/web/JiShe.CollectBus.HttpApi/JiShe.CollectBus.HttpApi.csproj index 3ea1d32..d81e1e8 100644 --- a/web/JiShe.CollectBus.HttpApi/JiShe.CollectBus.HttpApi.csproj +++ b/web/JiShe.CollectBus.HttpApi/JiShe.CollectBus.HttpApi.csproj @@ -1,9 +1,9 @@ - + - net8.0 + net9.0 enable JiShe.CollectBus True @@ -15,7 +15,7 @@ - + diff --git a/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostConst.cs b/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostConst.cs deleted file mode 100644 index d710275..0000000 --- a/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostConst.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace JiShe.CollectBus.Migration.Host -{ - /// - /// CollectBusMigrationHostConst - /// - public static class CollectBusMigrationHostConst - { - /// - /// 跨域策略名 - /// - public const string DefaultCorsPolicyName = "Default"; - - /// - /// Cookies名称 - /// - public const string DefaultCookieName = "JiShe.CollectBus.Migration.Host"; - - /// - /// SwaggerUi 端点 - /// - public const string SwaggerUiEndPoint = "/swagger"; - - /// - /// Hangfire 端点 - /// - public const string HangfireDashboardEndPoint = "/hangfire"; - - /// - /// 健康检查 端点 - /// - public const string HealthEndPoint = "/health"; - - /// - /// 健康检查 端点 - /// - public const string HealthDashboardEndPoint = "/health-ui"; - - - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostModule.Configure.cs b/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostModule.Configure.cs deleted file mode 100644 index ebe0541..0000000 --- a/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostModule.Configure.cs +++ /dev/null @@ -1,235 +0,0 @@ -using JiShe.CollectBus.Migration.Host.HealthChecks; -using JiShe.CollectBus.Migration.Host.Swaggers; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.IdentityModel.Tokens; -using Microsoft.OpenApi.Models; -using StackExchange.Redis; -using System.Text; -using Volo.Abp.AspNetCore.Auditing; -using Volo.Abp.Auditing; -using Volo.Abp.Caching; -using Volo.Abp.Modularity; - - -namespace JiShe.CollectBus.Migration.Host -{ - public partial class CollectBusMigrationHostModule - { - /// - /// Configures the JWT authentication. - /// - /// The context. - /// The configuration. - private void ConfigureJwtAuthentication(ServiceConfigurationContext context, IConfiguration configuration) - { - context.Services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(options => - { - options.TokenValidationParameters = - new TokenValidationParameters() - { - // 是否开启签名认证 - ValidateIssuerSigningKey = true, - ValidateIssuer = true, - ValidateAudience = true, - ValidateLifetime = true, - ClockSkew = TimeSpan.Zero, - ValidIssuer = configuration["Jwt:Issuer"], - ValidAudience = configuration["Jwt:Audience"], - IssuerSigningKey = - new SymmetricSecurityKey( - Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"])) - }; - - options.Events = new JwtBearerEvents - { - OnMessageReceived = currentContext => - { - var path = currentContext.HttpContext.Request.Path; - if (path.StartsWithSegments("/login")) - { - return Task.CompletedTask; - } - - var accessToken = string.Empty; - if (currentContext.HttpContext.Request.Headers.ContainsKey("Authorization")) - { - accessToken = currentContext.HttpContext.Request.Headers["Authorization"]; - if (!string.IsNullOrWhiteSpace(accessToken)) - { - accessToken = accessToken.Split(" ").LastOrDefault(); - } - } - - if (string.IsNullOrWhiteSpace(accessToken)) - { - accessToken = currentContext.Request.Query["access_token"].FirstOrDefault(); - } - - if (string.IsNullOrWhiteSpace(accessToken)) - { - accessToken = currentContext.Request.Cookies[@CollectBusMigrationHostConst.DefaultCookieName]; - } - - currentContext.Token = accessToken; - currentContext.Request.Headers.Remove("Authorization"); - currentContext.Request.Headers.Add("Authorization", $"Bearer {accessToken}"); - - return Task.CompletedTask; - } - }; - }); - } - - /// - /// Configures the cache. - /// - /// The context. - private void ConfigureCache(ServiceConfigurationContext context) - { - Configure( - options => { options.KeyPrefix = "CollectBus:"; }); - var configuration = context.Services.GetConfiguration(); - var redis = ConnectionMultiplexer.Connect($"{configuration.GetValue("Redis:Configuration")},defaultdatabase={configuration.GetValue("Redis:DefaultDB")}"); - context.Services - .AddDataProtection() - .PersistKeysToStackExchangeRedis(redis, "CollectBus-Protection-Keys"); - } - - /// - /// Configures the swagger services. - /// - /// The context. - /// The configuration. - private void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) - { - context.Services.AddSwaggerGen( - options => - { - configuration.GetSection("SwaggerConfig").Get>()?.ForEach(group => - { - options.SwaggerDoc(group.GroupName, - new OpenApiInfo { Title = group.Title, Version = group.Version }); - }); - - options.DocInclusionPredicate((docName, apiDes) => - { - if (docName == "Basic" && string.IsNullOrWhiteSpace(apiDes.GroupName)) return true; - return docName == apiDes.GroupName; - }); - - options.EnableAnnotations(); - options.DocumentFilter(); - options.SchemaFilter(); - var xmlPaths = Directory.GetFiles(AppContext.BaseDirectory, "*.xml") - .Where(a => a.EndsWith("Application.xml") || - a.EndsWith("Application.Contracts.xml") || - a.EndsWith("httpApi.xml") || - a.EndsWith("Host.xml")) - .Distinct() - .ToList(); - foreach (var xml in xmlPaths) options.IncludeXmlComments(xml, true); - }); - } - - /// - /// Configures the audit log. - /// - /// The context. - private void ConfigureAuditLog(ServiceConfigurationContext context) - { - Configure - ( - options => - { - options.IsEnabled = true; - options.EntityHistorySelectors.AddAllEntities(); - options.ApplicationName = "JiShe.CollectBus.Migration"; - } - ); - - Configure( - options => - { - options.IgnoredUrls.Add("/AuditLogs/page"); - options.IgnoredUrls.Add("/hangfire/stats"); - options.IgnoredUrls.Add("/hangfire/recurring/trigger"); - options.IgnoredUrls.Add("/cap"); - options.IgnoredUrls.Add("/"); - }); - } - - - /// - /// Configures the custom. - /// - /// The context. - /// The configuration. - private void ConfigureCustom(ServiceConfigurationContext context, IConfiguration configuration) - { - context.Services.AddSingleton(); - } - - /// - /// Configures the network. - /// - /// The context. - /// The configuration. - public void ConfigureNetwork(ServiceConfigurationContext context, IConfiguration configuration) - { - //context.Services.AddTcpService(config => - //{ - // config.SetListenIPHosts(int.Parse(configuration["TCP:ClientPort"] ?? "10500")) - // //.SetTcpDataHandlingAdapter(()=>new StandardFixedHeaderDataHandlingAdapter()) - // //.SetGetDefaultNewId(() => Guid.NewGuid().ToString())//定义ClientId的生成策略 - // .ConfigurePlugins(a => - // { - // a.Add(); - // a.Add(); - // a.Add(); - // }); - //}); - - //context.Services.AddUdpSession(config => - //{ - // config.SetBindIPHost(int.Parse(configuration["UDP:ClientPort"] ?? "10500")) - // .ConfigurePlugins(a => - // { - // a.Add(); - // a.Add(); - // }) - // .UseBroadcast() - // .SetUdpDataHandlingAdapter(() => new NormalUdpDataHandlingAdapter()); - //}); - } - - /// - /// 健康检查 - /// - /// - /// - private void ConfigureHealthChecks(ServiceConfigurationContext context, IConfiguration configuration) - { - if (!configuration.GetValue("HealthChecks:IsEnable")) return; - context.Services.AddHealthChecks() - .AddRedis(configuration.GetValue("Redis:Configuration") ?? string.Empty, "Redis", - HealthStatus.Unhealthy) - .AddCheck("IoTDB"); - - context.Services - .AddHealthChecksUI(options => - { - options.AddHealthCheckEndpoint("JiSheCollectBusMigration", "/health"); // 映射本地端点 - }) - .AddInMemoryStorage(); - - - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostModule.cs b/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostModule.cs deleted file mode 100644 index b9a5f05..0000000 --- a/web/JiShe.CollectBus.Migration.Host/CollectBusMigrationHostModule.cs +++ /dev/null @@ -1,110 +0,0 @@ -using Hangfire; -using JiShe.CollectBus.Common; -using JiShe.CollectBus.Migration.Host.HealthChecks; -using JiShe.CollectBus.Migration.Host.Swaggers; -using JiShe.CollectBus.MongoDB; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Swashbuckle.AspNetCore.SwaggerUI; -using Volo.Abp; -using Volo.Abp.AspNetCore; -using Volo.Abp.AspNetCore.Authentication.JwtBearer; -using Volo.Abp.AspNetCore.Serilog; -using Volo.Abp.Autofac; -using Volo.Abp.BackgroundWorkers.Hangfire; -using Volo.Abp.Caching.StackExchangeRedis; -using Volo.Abp.Modularity; -using Volo.Abp.Swashbuckle; -using Volo.Abp.Timing; - -namespace JiShe.CollectBus.Migration.Host -{ - /// - /// - /// - [DependsOn(typeof(CollectBusMigrationHttpApiModule), - typeof(AbpAutofacModule), - typeof(AbpAspNetCoreAuthenticationJwtBearerModule), - typeof(AbpAspNetCoreSerilogModule), - typeof(AbpSwashbuckleModule), - typeof(AbpTimingModule), - typeof(CollectBusMongoDbModule), - typeof(CollectBusMigrationApplicationModule), - typeof(AbpCachingStackExchangeRedisModule) - )] - public partial class CollectBusMigrationHostModule : AbpModule - { - /// - /// ConfigureServices - /// - /// - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - ConfigureCache(context); - ConfigureSwaggerServices(context, configuration); - //ConfigureNetwork(context, configuration); - ConfigureJwtAuthentication(context, configuration); - ConfigureAuditLog(context); - ConfigureCustom(context, configuration); - ConfigureHealthChecks(context, configuration); - Configure(options => { options.Kind = DateTimeKind.Local; }); - - Configure(options => - { - configuration.GetSection(nameof(ServerApplicationOptions)).Bind(options); - }); - - } - - - /// - /// OnApplicationInitialization - /// - /// - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var app = context.GetApplicationBuilder(); - var configuration = context.GetConfiguration(); - var env = context.GetEnvironment(); - app.UseCorrelationId(); - app.UseStaticFiles(); - app.UseRouting(); - app.UseCors(CollectBusMigrationHostConst.DefaultCorsPolicyName); - app.UseAuthentication(); - app.UseAuthorization(); - if (env.IsDevelopment()) - { - app.UseSwagger(); - app.UseAbpSwaggerUI(options => - { - configuration.GetSection("SwaggerConfig").Get>()?.ForEach(group => - { - options.SwaggerEndpoint($"/swagger/{group.GroupName}/swagger.json", group.Title); //分组显示 - }); - options.DocExpansion(DocExpansion.None); - options.DefaultModelsExpandDepth(-1); - }); - } - app.UseAuditing(); - app.UseAbpSerilogEnrichers(); - app.UseUnitOfWork(); - //app.UseHangfireDashboard("/hangfire", new DashboardOptions - //{ - // IgnoreAntiforgeryToken = true - //}); - app.UseConfiguredEndpoints(endpoints => - { - if (!configuration.GetValue("HealthChecks:IsEnable")) return; - endpoints.MapHealthChecks("/health", new HealthCheckOptions - { - Predicate = _ => true, - ResponseWriter = HealthCheckResponse.Writer - }); - endpoints.MapHealthChecksUI(options => - { - options.UIPath = "/health-ui"; - }); - }); - } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/Controllers/HomeController.cs b/web/JiShe.CollectBus.Migration.Host/Controllers/HomeController.cs deleted file mode 100644 index be4c1c6..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Controllers/HomeController.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Volo.Abp.AspNetCore.Mvc; - -namespace JiShe.CollectBus.Migration.Host.Controllers -{ - public class HomeController : AbpController - { - public ActionResult Index() - { - return Redirect("/Monitor"); - } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/Extensions/CustomApplicationBuilderExtensions.cs b/web/JiShe.CollectBus.Migration.Host/Extensions/CustomApplicationBuilderExtensions.cs deleted file mode 100644 index 6dab344..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Extensions/CustomApplicationBuilderExtensions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace JiShe.CollectBus.Migration.Host.Extensions -{ - public static class CustomApplicationBuilderExtensions - { - public static IApplicationBuilder UseProtocolPlugin(this IApplicationBuilder app) - { - return app; - } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/Extensions/ServiceCollections/ServiceCollectionExtensions.cs b/web/JiShe.CollectBus.Migration.Host/Extensions/ServiceCollections/ServiceCollectionExtensions.cs deleted file mode 100644 index 9351c45..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Extensions/ServiceCollections/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Reflection; -using Volo.Abp.Modularity; - -// ReSharper disable once CheckNamespace -namespace Microsoft.Extensions.DependencyInjection -{ - public static class ServiceCollectionExtensions - { - public static void AddPluginApplications(this IServiceCollection services, string pluginPath = "") - { - if (string.IsNullOrWhiteSpace(pluginPath)) - { - pluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins"); - } - var assemblies = GetAssembliesFromFolder(pluginPath); - - foreach (var assembly in assemblies) - { - var applicationServiceType = assembly.GetTypes() - .FirstOrDefault(a => a.IsClass && !a.IsAbstract && typeof(AbpModule).IsAssignableFrom(a)); - services.AddApplication(applicationServiceType); - } - } - - private static IEnumerable GetAssembliesFromFolder(string folderPath) - { - var directory = new DirectoryInfo(folderPath); - if (!directory.Exists) return []; - - var files = directory.GetFiles("*.dll"); - - var assemblies = new List(); - foreach (var file in files) - { - try - { - var assembly = Assembly.LoadFrom(file.FullName); - assemblies.Add(assembly); - } - catch (Exception ex) - { - Console.WriteLine($"Error loading assembly from {file.FullName}: {ex.Message}"); - } - } - - return assemblies; - } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/HealthChecks/HealthCheckResponse.cs b/web/JiShe.CollectBus.Migration.Host/HealthChecks/HealthCheckResponse.cs deleted file mode 100644 index d15a5da..0000000 --- a/web/JiShe.CollectBus.Migration.Host/HealthChecks/HealthCheckResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Newtonsoft.Json; - -namespace JiShe.CollectBus.Migration.Host.HealthChecks -{ - public class HealthCheckResponse - { - public static Task Writer(HttpContext context, HealthReport healthReport) - { - context.Response.ContentType = "application/json"; - - var result = JsonConvert.SerializeObject(new - { - status = healthReport.Status.ToString(), - errors = healthReport.Entries.Select(e => new - { - key = e.Key, - value = e.Value.Status.ToString() - }) - }); - return context.Response.WriteAsync(result); - - } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/HealthChecks/IoTDBHealthCheck.cs b/web/JiShe.CollectBus.Migration.Host/HealthChecks/IoTDBHealthCheck.cs deleted file mode 100644 index 31956d9..0000000 --- a/web/JiShe.CollectBus.Migration.Host/HealthChecks/IoTDBHealthCheck.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace JiShe.CollectBus.Migration.Host.HealthChecks -{ - /// - /// IoTDBHealthCheck - /// - /// - public class IoTdbHealthCheck : IHealthCheck - { - private readonly IConfiguration _configuration; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration. - public IoTdbHealthCheck(IConfiguration configuration) - { - _configuration = configuration; - } - - /// - /// Runs the health check, returning the status of the component being checked. - /// - /// A context object associated with the current execution. - /// A that can be used to cancel the health check. - /// - /// A that completes when the health check has finished, yielding the status of the component being checked. - /// - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) - { - try - { - // 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) - { - return new HealthCheckResult(context.Registration.FailureStatus, $"IoTDB不健康: {ex.Message}", ex); - } - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.Host/JiShe.CollectBus.Migration.Host.csproj b/web/JiShe.CollectBus.Migration.Host/JiShe.CollectBus.Migration.Host.csproj deleted file mode 100644 index 5a66ca8..0000000 --- a/web/JiShe.CollectBus.Migration.Host/JiShe.CollectBus.Migration.Host.csproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - net8.0 - enable - enable - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - - diff --git a/web/JiShe.CollectBus.Migration.Host/Pages/Monitor.cshtml b/web/JiShe.CollectBus.Migration.Host/Pages/Monitor.cshtml deleted file mode 100644 index 9bd1e80..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Pages/Monitor.cshtml +++ /dev/null @@ -1,188 +0,0 @@ -@page -@using JiShe.CollectBus.Migration.Host -@model JiShe.CollectBus.Migration.Host.Pages.Monitor - - -@{ - Layout = null; -} - - - - - - - - - - 后端服务 - - - - -
- -
-
-
- - - -
-

- SwaggerUI -

-
-
-
- -
-
- - - -
-

- Hangfire面板 -

-
-
-
-
-
- - - -
-

- 健康检查API | - UI -

-
-
-
- @*
-
- - - -
-

- 了解更多... -

-
-
-
*@ -
-
- - - \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.Host/Pages/Monitor.cshtml.cs b/web/JiShe.CollectBus.Migration.Host/Pages/Monitor.cshtml.cs deleted file mode 100644 index feab3b1..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Pages/Monitor.cshtml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace JiShe.CollectBus.Migration.Host.Pages -{ - public class Monitor : PageModel - { - - public void OnGet() - { - - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.Host/Program.cs b/web/JiShe.CollectBus.Migration.Host/Program.cs deleted file mode 100644 index a9bd5b9..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Program.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Serilog; -using Volo.Abp.Modularity.PlugIns; - -namespace JiShe.CollectBus.Migration.Host; - -/// -/// Program -/// -public class Program -{ - /// - /// Main - /// - /// - /// - public static async Task Main(string[] args) - { - //var builder = WebApplication.CreateBuilder(args); - //builder.Host - // .UseContentRoot(Directory.GetCurrentDirectory()) - // .UseSerilog((context, loggerConfiguration) => - // { - // loggerConfiguration.ReadFrom.Configuration(context.Configuration); - // }) - // .UseAutofac(); - //var app = builder.Build(); - //await app.InitializeApplicationAsync(); - //await app.RunAsync(); - - var builder = WebApplication.CreateBuilder(args); - builder.Host.UseContentRoot(Directory.GetCurrentDirectory()) - .UseSerilog((context, loggerConfiguration) => - { - loggerConfiguration.ReadFrom.Configuration(context.Configuration); - }) - .UseAutofac(); - var configuration = builder.Configuration; - await builder.AddApplicationAsync(options => - { - //options.PlugInSources.AddFolder((configuration["PlugInFolder"].IsNullOrWhiteSpace() ? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins") : configuration["PlugInFolder"]) ?? string.Empty); - }); - var app = builder.Build(); - await app.InitializeApplicationAsync(); - await app.RunAsync(); - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.Host/Properties/launchSettings.json b/web/JiShe.CollectBus.Migration.Host/Properties/launchSettings.json deleted file mode 100644 index 642958f..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Properties/launchSettings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "profiles": { - "JiShe.CollectBus.Migration.Host": { - "commandName": "Project", - "launchBrowser": true, - "applicationUrl": "http://localhost:44316", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.Host/Swaggers/EnumSchemaFilter.cs b/web/JiShe.CollectBus.Migration.Host/Swaggers/EnumSchemaFilter.cs deleted file mode 100644 index f06c6ab..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Swaggers/EnumSchemaFilter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; - -namespace JiShe.CollectBus.Migration.Host.Swaggers -{ - /// - /// swagger 枚举映射, - /// 原因:前端代理生成枚举是数字 - /// - public class EnumSchemaFilter : ISchemaFilter - { - public void Apply(OpenApiSchema schema, SchemaFilterContext context) - { - if (!context.Type.IsEnum) - return; - OpenApiArray openApiArray = new OpenApiArray(); - openApiArray.AddRange((IEnumerable)Enum.GetNames(context.Type).Select(n => new OpenApiString(n))); - schema.Extensions.Add("x-enumNames", openApiArray); - schema.Extensions.Add("x-enum-varnames", openApiArray); - } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/Swaggers/HiddenAbpDefaultApiFilter.cs b/web/JiShe.CollectBus.Migration.Host/Swaggers/HiddenAbpDefaultApiFilter.cs deleted file mode 100644 index a5ae689..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Swaggers/HiddenAbpDefaultApiFilter.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Reflection; -using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; - -namespace JiShe.CollectBus.Migration.Host.Swaggers -{ - /// - /// 在使用nswag的时候,原生默认的api导致生产的代理类存在问题 - /// 所有隐藏原生的api,重写路由 - /// - public class HiddenAbpDefaultApiFilter : IDocumentFilter - { - public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) - { - foreach (ApiDescription apiDescription in context.ApiDescriptions) - { - if (apiDescription.TryGetMethodInfo(out MethodInfo _)) - { - string key = "/" + apiDescription.RelativePath; - if (IsHidden(key)) - swaggerDoc.Paths.Remove(key); - } - } - } - - private bool IsHidden(string key) - { - foreach (string hiddenAbpDefaultApi in GetHiddenAbpDefaultApiList()) - { - if (key.Contains(hiddenAbpDefaultApi)) - return true; - } - return false; - } - - private List GetHiddenAbpDefaultApiList() - { - return new List() - { - "/api/abp/multi-tenancy/tenants", - "/api/account", - "/api/feature-management/features", - "/api/permission-management/permissions", - "/api/identity/my-profile", - "/api/identity", - "/api/multi-tenancy/tenants", - "/api/setting-management/emailing", - "/configuration", - "/outputcache" - }; - } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/Swaggers/SwaggerConfig.cs b/web/JiShe.CollectBus.Migration.Host/Swaggers/SwaggerConfig.cs deleted file mode 100644 index a363ebb..0000000 --- a/web/JiShe.CollectBus.Migration.Host/Swaggers/SwaggerConfig.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace JiShe.CollectBus.Migration.Host.Swaggers -{ - public class SwaggerConfig - { - public string GroupName { get; set; } - - public string Title { get; set; } - - public string Version { get; set; } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/appsettings.Development.json b/web/JiShe.CollectBus.Migration.Host/appsettings.Development.json deleted file mode 100644 index bcdd3fc..0000000 --- a/web/JiShe.CollectBus.Migration.Host/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Warning", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/web/JiShe.CollectBus.Migration.Host/appsettings.Production.json b/web/JiShe.CollectBus.Migration.Host/appsettings.Production.json deleted file mode 100644 index 9c7d2e0..0000000 --- a/web/JiShe.CollectBus.Migration.Host/appsettings.Production.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "ConnectionStrings": { - "Default": "mongodb://admin:4mFmPTTB8tn6aI@47.110.62.104:27017,47.110.53.196:27017,47.110.60.222:27017/JiSheCollectBus?authSource=admin&maxPoolSize=400&minPoolSize=10&waitQueueTimeoutMS=5000", - "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" - }, - "Redis": { - "Configuration": "47.110.60.222:6379,password=3JBGfyhTaD46nS,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true", - "MaxPoolSize": "50", - "DefaultDB": "14", - "HangfireDB": "13" - }, - "Kafka": { - "BootstrapServers": "47.110.62.104:9092,47.110.53.196:9092,47.110.60.222:9092", - "EnableFilter": true, - "EnableAuthorization": false, - "SecurityProtocol": "SaslPlaintext", - "SaslMechanism": "Plain", - "SaslUserName": "lixiao", - "SaslPassword": "lixiao1980", - "KafkaReplicationFactor": 3, - "NumPartitions": 30, - "ServerTagName": "JiSheCollectBus100", - "FirstCollectionTime": "2025-04-22 16:07:00" - }, - "IoTDBOptions": { - "UserName": "root", - "Password": "Yp2eU6MVdIjXCL", - "ClusterList": [ "47.110.53.196:6667", "47.110.60.222:6667", "47.110.62.104:6667" ], - "PoolSize": 2, - "DataBaseName": "energy", - "OpenDebugMode": true, - "UseTableSessionPoolByDefault": false - }, - "Cassandra": { - "ReplicationStrategy": { - "Class": "NetworkTopologyStrategy", //策略为NetworkTopologyStrategy时才会有多个数据中心,SimpleStrategy用在只有一个数据中心的情况下 - "DataCenters": [ - { - "Name": "dc1", - "ReplicationFactor": 3 - } - ] - }, - "Nodes": [ - { - "Host": "121.42.175.177", - "Port": 19042, - "DataCenter": "dc1", - "Rack": "RAC1" - }, - { - "Host": "121.42.175.177", - "Port": 19043, - "DataCenter": "dc1", - "Rack": "RAC2" - }, - { - "Host": "121.42.175.177", - "Port": 19044, - "DataCenter": "dc1", - "Rack": "RAC2" - } - ], - "Username": "admin", - "Password": "lixiao1980", - "Keyspace": "jishecollectbus", - "ConsistencyLevel": "Quorum", - "PoolingOptions": { - "CoreConnectionsPerHost": 4, - "MaxConnectionsPerHost": 8, - "MaxRequestsPerConnection": 2000 - }, - "SocketOptions": { - "ConnectTimeoutMillis": 10000, - "ReadTimeoutMillis": 20000 - }, - "QueryOptions": { - "ConsistencyLevel": "Quorum", - "SerialConsistencyLevel": "Serial", - "DefaultIdempotence": true - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.Host/appsettings.json b/web/JiShe.CollectBus.Migration.Host/appsettings.json deleted file mode 100644 index d7ebf50..0000000 --- a/web/JiShe.CollectBus.Migration.Host/appsettings.json +++ /dev/null @@ -1,158 +0,0 @@ -{ - "Serilog": { - "Using": [ - "Serilog.Sinks.Console", - "Serilog.Sinks.File" - ], - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Microsoft": "Warning", - "Volo.Abp": "Warning", - "Hangfire": "Warning", - "DotNetCore.CAP": "Warning", - "Serilog.AspNetCore": "Information", - "Microsoft.EntityFrameworkCore": "Warning", - "Microsoft.AspNetCore": "Warning", - "Microsoft.AspNetCore.Diagnostics.HealthChecks": "Warning" - } - }, - "WriteTo": [ - { - "Name": "Console" - }, - { - "Name": "File", - "Args": { - "path": "logs/logs-.txt", - "rollingInterval": "Day" - } - } - ] - }, - "App": { - "SelfUrl": "http://localhost:44315", - "CorsOrigins": "http://localhost:4200,http://localhost:3100" - }, - "ConnectionStrings": { - "Default": "mongodb://mongo_PmEeF3:lixiao1980@192.168.5.9:27017/JiSheCollectBus?authSource=admin&maxPoolSize=400&minPoolSize=10&waitQueueTimeoutMS=5000", - "Kafka": "192.168.5.9:29092,192.168.5.9:39092,192.168.5.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" - }, - "Redis": { - "Configuration": "192.168.5.9:6380,password=1q2w3e!@#,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true", - "MaxPoolSize": "50", - "DefaultDB": "14", - "HangfireDB": "13" - }, - "Jwt": { - "Audience": "JiShe.CollectBus", - "SecurityKey": "dzehzRz9a8asdfasfdadfasdfasdfafsdadfasbasdf=", - "Issuer": "JiShe.CollectBus", - "ExpirationTime": 2 - }, - "HealthChecks": { - "IsEnable": true, - "HealthCheckDatabaseName": "HealthChecks", - "EvaluationTimeInSeconds": 10, - "MinimumSecondsBetweenFailureNotifications": 60 - }, - "SwaggerConfig": [ - { - "GroupName": "Basic", - "Title": "【后台管理】基础模块", - "Version": "V1" - }, - { - "GroupName": "Business", - "Title": "【后台管理】业务模块", - "Version": "V1" - } - ], - "Kafka": { - "BootstrapServers": "192.168.5.9:29092,192.168.5.9:39092,192.168.5.9:49092", - "EnableFilter": true, - "EnableAuthorization": false, - "SecurityProtocol": "SaslPlaintext", - "SaslMechanism": "Plain", - "SaslUserName": "lixiao", - "SaslPassword": "lixiao1980", - "KafkaReplicationFactor": 3, - "NumPartitions": 30, - "FirstCollectionTime": "2025-04-22 16:07:00" - }, - "IoTDBOptions": { - "UserName": "root", - "Password": "root", - "ClusterList": [ "192.168.5.9:6667" ], - "PoolSize": 32, - "DataBaseName": "energy", - "OpenDebugMode": false, - "UseTableSessionPoolByDefault": false - }, - "Cassandra": { - "ReplicationStrategy": { - "Class": "NetworkTopologyStrategy", //策略为NetworkTopologyStrategy时才会有多个数据中心,SimpleStrategy用在只有一个数据中心的情况下 - "DataCenters": [ - { - "Name": "dc1", - "ReplicationFactor": 3 - } - ] - }, - "Nodes": [ - { - "Host": "192.168.5.9", - "Port": 9042, - "DataCenter": "dc1", - "Rack": "RAC1" - }, - { - "Host": "192.168.5.9", - "Port": 9043, - "DataCenter": "dc1", - "Rack": "RAC2" - }, - { - "Host": "192.168.5.9", - "Port": 9044, - "DataCenter": "dc1", - "Rack": "RAC2" - } - ], - "Username": "admin", - "Password": "lixiao1980", - "Keyspace": "jishecollectbus", - "ConsistencyLevel": "Quorum", - "PoolingOptions": { - "CoreConnectionsPerHost": 4, - "MaxConnectionsPerHost": 8, - "MaxRequestsPerConnection": 2000 - }, - "SocketOptions": { - "ConnectTimeoutMillis": 10000, - "ReadTimeoutMillis": 20000 - }, - "QueryOptions": { - "ConsistencyLevel": "Quorum", - "SerialConsistencyLevel": "Serial", - "DefaultIdempotence": true - } - }, - "ServerApplicationOptions": { - "ServerTagName": "JiSheCollectBus8", - "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": "", - "TCP": { - "ClientPort": 10500 - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/cap.png b/web/JiShe.CollectBus.Migration.Host/wwwroot/images/cap.png deleted file mode 100644 index 76c667e..0000000 Binary files a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/cap.png and /dev/null differ diff --git a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/hangfire.png b/web/JiShe.CollectBus.Migration.Host/wwwroot/images/hangfire.png deleted file mode 100644 index 5cdeb40..0000000 Binary files a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/hangfire.png and /dev/null differ diff --git a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/miniprofiler.png b/web/JiShe.CollectBus.Migration.Host/wwwroot/images/miniprofiler.png deleted file mode 100644 index 244c702..0000000 Binary files a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/miniprofiler.png and /dev/null differ diff --git a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/more.png b/web/JiShe.CollectBus.Migration.Host/wwwroot/images/more.png deleted file mode 100644 index 55c056f..0000000 Binary files a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/more.png and /dev/null differ diff --git a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/swagger.png b/web/JiShe.CollectBus.Migration.Host/wwwroot/images/swagger.png deleted file mode 100644 index 7bcbd43..0000000 Binary files a/web/JiShe.CollectBus.Migration.Host/wwwroot/images/swagger.png and /dev/null differ diff --git a/web/JiShe.CollectBus.Migration.Host/wwwroot/libs/bootstrap/css/bootstrap.min.css b/web/JiShe.CollectBus.Migration.Host/wwwroot/libs/bootstrap/css/bootstrap.min.css deleted file mode 100644 index ed3905e..0000000 --- a/web/JiShe.CollectBus.Migration.Host/wwwroot/libs/bootstrap/css/bootstrap.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} -/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.HttpApi/CollectBusController.cs b/web/JiShe.CollectBus.Migration.HttpApi/CollectBusController.cs deleted file mode 100644 index fb10997..0000000 --- a/web/JiShe.CollectBus.Migration.HttpApi/CollectBusController.cs +++ /dev/null @@ -1,12 +0,0 @@ -using JiShe.CollectBus.Localization; -using Volo.Abp.AspNetCore.Mvc; - -namespace JiShe.CollectBus.Migration; - -public abstract class CollectBusController : AbpControllerBase -{ - protected CollectBusController() - { - LocalizationResource = typeof(CollectBusResource); - } -} diff --git a/web/JiShe.CollectBus.Migration.HttpApi/CollectBusMigrationHttpApiModule.cs b/web/JiShe.CollectBus.Migration.HttpApi/CollectBusMigrationHttpApiModule.cs deleted file mode 100644 index c02a3a9..0000000 --- a/web/JiShe.CollectBus.Migration.HttpApi/CollectBusMigrationHttpApiModule.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Localization.Resources.AbpUi; -using JiShe.CollectBus.Localization; -using Volo.Abp.AspNetCore.Mvc; -using Volo.Abp.Localization; -using Volo.Abp.Modularity; -using Microsoft.Extensions.DependencyInjection; - -namespace JiShe.CollectBus.Migration; - -[DependsOn( - typeof(CollectBusMigrationApplicationModule), - typeof(CollectBusMigrationApplicationContractsModule), - typeof(AbpAspNetCoreMvcModule) - )] -public class CollectBusMigrationHttpApiModule : AbpModule -{ - public override void PreConfigureServices(ServiceConfigurationContext context) - { - PreConfigure(mvcBuilder => - { - mvcBuilder.AddApplicationPartIfNotExists(typeof(CollectBusMigrationHttpApiModule).Assembly); - }); - - Configure(options => - { - options.ConventionalControllers - .Create(typeof(CollectBusMigrationApplicationModule).Assembly); - }); - } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.Resources - .Get() - .AddBaseTypes(typeof(AbpUiResource)); - }); - } -} diff --git a/web/JiShe.CollectBus.Migration.HttpApi/FodyWeavers.xml b/web/JiShe.CollectBus.Migration.HttpApi/FodyWeavers.xml deleted file mode 100644 index 1715698..0000000 --- a/web/JiShe.CollectBus.Migration.HttpApi/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/web/JiShe.CollectBus.Migration.HttpApi/JiShe.CollectBus.Migration.HttpApi.csproj b/web/JiShe.CollectBus.Migration.HttpApi/JiShe.CollectBus.Migration.HttpApi.csproj deleted file mode 100644 index 5047d92..0000000 --- a/web/JiShe.CollectBus.Migration.HttpApi/JiShe.CollectBus.Migration.HttpApi.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - net8.0 - enable - JiShe.CollectBus - True - - - - - - - - - - - - - - - - - - - - - diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/.config/dotnet-tools.json b/web/JiShe.CollectBusEPO.HttpApi.Host/.config/dotnet-tools.json deleted file mode 100644 index 76ca931..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/.config/dotnet-tools.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": 1, - "isRoot": true, - "tools": { - "dotnet-ef": { - "version": "8.0.10", - "commands": [ - "dotnet-ef" - ], - "rollForward": false - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostConst.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostConst.cs deleted file mode 100644 index e4783b7..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostConst.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace JiShe.CollectBusEPO -{ - public static class CollectBusEPOHttpApiHostConst - { - /// - /// 跨域策略名 - /// - public const string DefaultCorsPolicyName = "Default"; - - /// - /// Cookies名称 - /// - public const string DefaultCookieName = "JiShe.MicroService.Http.Api"; - - /// - /// SwaggerUi 端点 - /// - public const string SwaggerUiEndPoint = "/swagger"; - - /// - /// Hangfire 端点 - /// - public const string HangfireDashboardEndPoint = "/hangfire"; - - /// - /// CAP 端点 - /// - public const string CapDashboardEndPoint = "/cap"; - - - public const string MoreEndPoint = "https://doc.cncore.club/"; - - - /// - /// HMiniprofiler端点 - /// - public const string MiniprofilerEndPoint = "/profiler/results-index"; - - /// - /// HealthCheck端点 - /// - public const string HealthCheckEndPoint = "/health"; - - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostModule.Configure.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostModule.Configure.cs deleted file mode 100644 index 8f5f93a..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostModule.Configure.cs +++ /dev/null @@ -1,179 +0,0 @@ -using JiShe.CollectBusEPO.HttpApi.Host.Swaggers; - -namespace JiShe.CollectBusEPO; - -public partial class CollectBusEPOHttpApiHostModule -{ - - /// - /// 配置JWT - /// - private void ConfigureJwtAuthentication(ServiceConfigurationContext context, IConfiguration configuration) - { - context.Services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(options => - { - options.TokenValidationParameters = - new TokenValidationParameters() - { - // 是否开启签名认证 - ValidateIssuerSigningKey = true, - ValidateIssuer = true, - ValidateAudience = true, - ValidateLifetime = true, - ClockSkew = TimeSpan.Zero, - ValidIssuer = configuration["Jwt:Issuer"], - ValidAudience = configuration["Jwt:Audience"], - IssuerSigningKey = - new SymmetricSecurityKey( - Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"])) - }; - - options.Events = new JwtBearerEvents - { - OnMessageReceived = currentContext => - { - var path = currentContext.HttpContext.Request.Path; - if (path.StartsWithSegments("/login")) - { - return Task.CompletedTask; - } - - var accessToken = string.Empty; - if (currentContext.HttpContext.Request.Headers.ContainsKey("Authorization")) - { - accessToken = currentContext.HttpContext.Request.Headers["Authorization"]; - if (!string.IsNullOrWhiteSpace(accessToken)) - { - accessToken = accessToken.Split(" ").LastOrDefault(); - } - } - - if (accessToken.IsNullOrWhiteSpace()) - { - accessToken = currentContext.Request.Query["access_token"].FirstOrDefault(); - } - - if (accessToken.IsNullOrWhiteSpace()) - { - accessToken = currentContext.Request.Cookies[@CollectBusEPOHttpApiHostConst.DefaultCookieName]; - } - - currentContext.Token = accessToken; - currentContext.Request.Headers.Remove("Authorization"); - currentContext.Request.Headers.Add("Authorization", $"Bearer {accessToken}"); - - return Task.CompletedTask; - } - }; - }); - } - - - /// - /// Redis缓存 - /// - private void ConfigureCache(ServiceConfigurationContext context) - { - Configure( - options => { options.KeyPrefix = "MicroService:"; }); - var configuration = context.Services.GetConfiguration(); - var redis = ConnectionMultiplexer.Connect(configuration.GetValue("Redis:Configuration")); - context.Services - .AddDataProtection() - .PersistKeysToStackExchangeRedis(redis, "MicroService-Protection-Keys"); - } - - /// - /// 配置Identity - /// - private void ConfigureIdentity(ServiceConfigurationContext context) - { - context.Services.Configure(options => { options.Lockout = new LockoutOptions() { AllowedForNewUsers = false }; }); - } - - - private void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) - { - context.Services.AddSwaggerGen( - options => - { - configuration.GetSection("SwaggerConfig").Get>().ForEach(group => - { - options.SwaggerDoc(group.GroupName, - new OpenApiInfo { Title = group.Title, Version = group.Version }); - }); - - options.DocInclusionPredicate((docName, apiDes) => - { - if (docName == "Basic" && apiDes.GroupName.IsNullOrWhiteSpace()) return true; - return docName == apiDes.GroupName; - }); - - options.EnableAnnotations(); - options.DocumentFilter(); - options.SchemaFilter(); - var xmlPaths = Directory.GetFiles(AppContext.BaseDirectory, "*.xml") - .Where(a => a.EndsWith("Application.App.xml") || - a.EndsWith("Application.Contracts.App.xml") || - a.EndsWith("Application.xml") || - a.EndsWith("Application.Contracts.xml") || - a.EndsWith("HttpApi.xml") || - a.EndsWith("HttpApi.Host.xml")) - .Distinct() - .ToList(); - foreach (var xml in xmlPaths) options.IncludeXmlComments(xml, true); - }); - } - - - - /// - /// 审计日志 - /// - private void ConfigureAuditLog(ServiceConfigurationContext context) - { - Configure - ( - options => - { - options.IsEnabled = true; - options.EntityHistorySelectors.AddAllEntities(); - options.ApplicationName = "JiShe.MicroService"; - } - ); - - Configure( - options => - { - options.IgnoredUrls.Add("/AuditLogs/page"); - options.IgnoredUrls.Add("/hangfire/stats"); - options.IgnoredUrls.Add("/hangfire/recurring/trigger"); - options.IgnoredUrls.Add("/cap"); - options.IgnoredUrls.Add("/"); - }); - } - - //private void ConfigurationMultiTenancy() - //{ - // Configure(options => { options.IsEnabled = MultiTenancyConsts.IsEnabled; }); - //} - - private void ConfigureCustom(ServiceConfigurationContext context, IConfiguration configuration) - { - context.Services.AddSingleton(); - //context.Services.AddStorage(configuration); - } - - /// - /// 配置Serilog - /// - private void ConfigureSerilog(ServiceConfigurationContext context) - { - context.Services.AddSerilog(); - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostModule.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostModule.cs deleted file mode 100644 index e97e840..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/CollectBusEPOHttpApiHostModule.cs +++ /dev/null @@ -1,73 +0,0 @@ -using JiShe.CollectBusEPO.Extensions.HealthCheck; -using JiShe.CollectBusEPO.HttpApi.Host.Swaggers; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Volo.Abp.Swashbuckle; - -namespace JiShe.CollectBusEPO; - -[DependsOn( - typeof(CollectBusEPOHttpApiModule), - typeof(AbpAspNetCoreAuthenticationJwtBearerModule), - typeof(AbpAspNetCoreSerilogModule), - typeof(AbpSwashbuckleModule), - typeof(CollectBusEPOApplicationModule) -)] -public partial class CollectBusEPOHttpApiHostModule : AbpModule -{ - public override void OnPostApplicationInitialization(ApplicationInitializationContext context) - { - base.OnPostApplicationInitialization(context); - } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - ConfigureSerilog(context); - - ConfigureCache(context); - ConfigureSwaggerServices(context, configuration); - ConfigureJwtAuthentication(context, configuration); - ConfigureIdentity(context); - ConfigureAuditLog(context); - ConfigureCustom(context, configuration); - - } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var app = context.GetApplicationBuilder(); - var configuration = context.GetConfiguration(); - app.UseCorrelationId(); - app.UseStaticFiles(); - - - app.UseRouting(); - app.UseCors(CollectBusEPOHttpApiHostConst.DefaultCorsPolicyName); - - - app.UseAuthorization(); - app.UseSwagger(); - app.UseAbpSwaggerUI(options => - { - configuration.GetSection("SwaggerConfig").Get>().ForEach(group => - { - options.SwaggerEndpoint($"/swagger/{group.GroupName}/swagger.json", group.Title); //分组显示 - }); - options.DocExpansion(DocExpansion.None); - options.DefaultModelsExpandDepth(-1); - }); - - app.UseAuditing(); - app.UseAbpSerilogEnrichers(); - app.UseUnitOfWork(); - app.UseConfiguredEndpoints(endpoints => - { - //endpoints.MapHealthChecks("/health", new HealthCheckOptions - //{ - // Predicate = _ => true, - // ResponseWriter = HealthCheckResponse.Writer - //}); - }); - - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Controllers/HomeController.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Controllers/HomeController.cs deleted file mode 100644 index 4e5ab2f..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Controllers/HomeController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -namespace JiShe.CollectBusEPO.Controllers -{ - public class HomeController : AbpController - { - private readonly ILogger _logger; - private readonly IConfiguration configuration; - - public HomeController(ILogger logger, IConfiguration configuration) - { - _logger = logger; - this.configuration = configuration; - } - - public ActionResult Index() - { - return Redirect("/Monitor"); - } - - /// - /// ������� - /// - /// - [HttpGet] - public IActionResult Health() - { - return Ok(); - } - } -} diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/Dockerfile b/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/Dockerfile deleted file mode 100644 index 75a20a7..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/Dockerfile +++ /dev/null @@ -1,47 +0,0 @@ -FROM docker.jisheyun.com/jisheyun/aspnetcore:8.0.10_basic_ub24 AS base - -# 这里确定使用的端口 -EXPOSE 8080 -EXPOSE 443 - - -COPY publish /app - -WORKDIR /app -ARG BUD_ENV=Development - -# 这里确定生产环境还是DEV环境等 -ENV RUN_ENV=$BUD_ENV - -# 根据 RUN_ENV 的值删除特定的配置文件 -# 只在构建过程中执行的指令 -RUN if [ "$RUN_ENV" = "Development" ]; then \ - rm -f ./appsettings.Production.json; \ - fi - -RUN if [ "$RUN_ENV" = "Production" ]; then \ - rm -f ./appsettings.Development.json; \ - fi - -ENTRYPOINT ["dotnet", "JiShe.MicroService.HttpApi.Host.dll"] - -##See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -# -#FROM mcr.microsoft.com/dotnet/aspnet:8.0.10-noble AS base - # -#WORKDIR /app -# -##USER root -# -## apt-get源 使用aliyun的源 -#COPY ["sources.list", "/etc/apt/"] -# -## 转换时区 -#RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ - #&& echo 'Asia/Shanghai' >/etc/timezone \ -## 更新系统并安装网络调试工具 - #&& apt-get update \ - #&& apt-get install -y \ - #vim \ - #net-tools \ - #iputils-ping \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/dockerbuild_dev.ps1 b/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/dockerbuild_dev.ps1 deleted file mode 100644 index 09dc2cd..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/dockerbuild_dev.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -# 汾 -$version = "1.0.2" - -$csprojFile = '..\.\*.csproj' -$files = Get-ChildItem -Path $csprojFile -$fullPath = $files[0] -$name = $fullPath.BaseName - -Write-Host "׼¼ֿ" -docker login 192.168.111.248:10001 --username=jenkins --password GTCz3pV8kdme4rh5 - -$lowerName = $name.toLower() - -$tagName = "$($lowerName):$($version)" - -Write-Host "ʼ" -Write-Host $tagName - -docker build --build-arg BUD_ENV=Development --progress=plain -t $tagName . - -Write-Host "ɹ"; - -docker tag $tagName "192.168.111.248:10001/jisheyun/jishe.testservice:$($version)" - -Write-Host "ʼ;"; -#docker push "192.168.111.248:10001/jisheyun/jishe.testservice:$($version)" diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/dockerbuild_pro.ps1 b/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/dockerbuild_pro.ps1 deleted file mode 100644 index 5145ec3..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/dockerbuild_pro.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -# 汾 -$version = "1.0.2" - -$csprojFile = '..\.\*.csproj' -$files = Get-ChildItem -Path $csprojFile -$fullPath = $files[0] -$name = $fullPath.BaseName - -Write-Host "׼¼ֿ" -docker login 192.168.111.248:10001 --username=jenkins --password GTCz3pV8kdme4rh5 - -$lowerName = $name.toLower() - -$tagName = "$($lowerName):$($version)" - -Write-Host "ʼ" -Write-Host $tagName - -docker build --build-arg BUD_ENV=Production --progress=plain -t $tagName . - -Write-Host "ɹ"; - -docker tag $tagName "192.168.111.248:10001/jisheyun/jishe.testservice:$($version)" - -Write-Host "ʼ;"; -#docker push "192.168.111.248:10001/jisheyun/jishe.testservice:$($version)" diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/sources.list b/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/sources.list deleted file mode 100644 index d2814c4..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Docker/sources.list +++ /dev/null @@ -1,10 +0,0 @@ -deb http://mirrors.aliyun.com/ubuntu/ noble main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ noble main restricted universe multiverse -deb http://mirrors.aliyun.com/ubuntu/ noble-security main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ noble-security main restricted universe multiverse -deb http://mirrors.aliyun.com/ubuntu/ noble-updates main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ noble-updates main restricted universe multiverse -deb http://mirrors.aliyun.com/ubuntu/ noble-proposed main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ noble-proposed main restricted universe multiverse -deb http://mirrors.aliyun.com/ubuntu/ noble-backports main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ noble-backports main restricted universe multiverse \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Extensions/HealthCheck/Extensions.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Extensions/HealthCheck/Extensions.cs deleted file mode 100644 index 9a65556..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Extensions/HealthCheck/Extensions.cs +++ /dev/null @@ -1,88 +0,0 @@ -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace JiShe.CollectBusEPO.Extensions.HealthCheck -{ - public static class Extensions - { - /// - /// 添加监控检查,支持配置文件配置 - /// - /// - /// - /// - public static IServiceCollection AddHealthChecks( - this IServiceCollection services, IConfiguration configuration) - { - if (Convert.ToBoolean(configuration["HealthCheck:IsEnable"])) - { - var healthChecksService = services - .AddHealthChecks(); - - //添加对mysql的监控检查 - //if (Convert.ToBoolean(configuration["HealthCheck:MySql:IsEnable"])) - //{ - // var connectionString = configuration["HealthCheck:MySql:Connection"]; - // if (connectionString.IsNullOrWhiteSpace()) - // connectionString = configuration.GetConnectionString("Default"); - // healthChecksService.AddMySql( - // connectionString, - // "Mysql", - // HealthStatus.Degraded, - // new string[] { "db", "sql", "mysql" } - // ); - //} - //添加对Pings的监控检查 - //if (Convert.ToBoolean(configuration["HealthCheck:Pings:IsEnable"])) - // healthChecksService.AddPingHealthCheck(setup => - // { - // setup.AddHost(configuration["HealthCheck:Pings:Host"], Convert.ToInt32(configuration["HealthCheck:Pings:TimeOut"])); - // }, tags: new string[] { "ping" }); - - ////添加对postgresql的监控检查 - //if (Convert.ToBoolean(configuration["HealthCheck:PostgreSql:IsEnable"])) - // healthChecksService.AddNpgSql( - // configuration["ConnectionStrings:Default"], - // name: configuration["HealthCheck:PostgreSql:Name"], - // failureStatus: HealthStatus.Degraded, - // tags: new string[] { "db", "sql", "postgresql" } - // ); - - ////添加对Redis的监控检查 - //if (Convert.ToBoolean(configuration["HealthCheck:Redis:IsEnable"])) - // healthChecksService.AddRedis( - // configuration["HealthCheck:Redis:ConnectionString"], - // tags: new string[] { "redis" } - // ); - - ////添加对RabbitMq的监控检查 - //if (Convert.ToBoolean(configuration["HealthCheck:RabbitMq:IsEnable"])) - // healthChecksService.AddRabbitMQ( - // rabbitConnectionString: configuration["HealthCheck:RabbitMq:ConnectionString"], - // tags: new string[] { "redis" } - // ); - - ////添加对sql server的监控检查 - //if (Convert.ToBoolean(configuration["HealthCheck:SqlServer:IsEnable"])) - // healthChecksService.AddSqlServer( - // configuration["ConnectionStrings:Default"], - // "SELECT 1;", - // configuration["HealthCheck:SqlServer:Name"], - // HealthStatus.Degraded, - // new string[] { "db", "sql", "sqlserver" } - - ////添加对Hangfire的监控检查 - //if (Convert.ToBoolean(configuration["HealthCheck:Hangfire:IsEnable"])) - // healthChecksService.AddHangfire(options => - // { - // options.MaximumJobsFailed = Convert.ToInt32(configuration["HealthCheck:Hangfire:MaximumJobsFailed"]); - // options.MinimumAvailableServers = Convert.ToInt32(configuration["HealthCheck:Hangfire:MinimumAvailableServers"]); - // }, tags: new string[] { "hangfire" }); - - ////添加对SignalR的监控检查 - //if (Convert.ToBoolean(configuration["HealthCheck:SignalR:IsEnable"])) - // healthChecksService.AddSignalRHub(configuration["HealthCheck:SignalR:Url"], tags: new string[] { "signalr" }); - } - return services; - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Extensions/HealthCheck/HealthCheckResponse.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Extensions/HealthCheck/HealthCheckResponse.cs deleted file mode 100644 index 9fe52ef..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Extensions/HealthCheck/HealthCheckResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Newtonsoft.Json; - -namespace JiShe.CollectBusEPO.Extensions.HealthCheck -{ - public class HealthCheckResponse - { - public static Task Writer(HttpContext context, HealthReport healthReport) - { - context.Response.ContentType = "application/json"; - - var result = JsonConvert.SerializeObject(new - { - status = healthReport.Status.ToString(), - errors = healthReport.Entries.Select(e => new - { - key = e.Key, - value = e.Value.Status.ToString() - }) - }); - return context.Response.WriteAsync(result); - - } - } -} diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/GlobalUsings.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/GlobalUsings.cs deleted file mode 100644 index c588db2..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/GlobalUsings.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Global using directives - -global using Microsoft.AspNetCore.Authentication.JwtBearer; -global using Microsoft.AspNetCore.Builder; -global using Microsoft.AspNetCore.DataProtection; -global using Microsoft.AspNetCore.Hosting; -global using Microsoft.AspNetCore.Http; -global using Microsoft.AspNetCore.Identity; -global using Microsoft.AspNetCore.Mvc; -global using Microsoft.Extensions.Configuration; -global using Microsoft.Extensions.DependencyInjection; -global using Microsoft.Extensions.Hosting; -global using Microsoft.Extensions.Logging; -global using Microsoft.IdentityModel.Tokens; -global using Microsoft.OpenApi.Models; -global using Serilog; -global using StackExchange.Redis; -global using Swashbuckle.AspNetCore.SwaggerUI; -global using System; -global using System.Collections.Generic; -global using System.IO; -global using System.Linq; -global using System.Text; -global using System.Threading.Tasks; -global using Volo.Abp; -global using Volo.Abp.AspNetCore.Auditing; -global using Volo.Abp.AspNetCore.Authentication.JwtBearer; -global using Volo.Abp.AspNetCore.Mvc; -global using Volo.Abp.AspNetCore.Serilog; -global using Volo.Abp.Auditing; -global using Volo.Abp.Caching; -global using Volo.Abp.Modularity; diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/JiShe.CollectBusEPO.HttpApi.Host.csproj b/web/JiShe.CollectBusEPO.HttpApi.Host/JiShe.CollectBusEPO.HttpApi.Host.csproj deleted file mode 100644 index 1c0e309..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/JiShe.CollectBusEPO.HttpApi.Host.csproj +++ /dev/null @@ -1,62 +0,0 @@ - - - net8.0 - JiShe.CollectBusEPO - true - JiShe.MicroService-4681b4fd-151f-4221-84a4-929d86723e4c - Linux - ..\.. - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ContentIncludedByDefault Remove="wwwroot\files\a.txt" /> - - - - - - diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Pages/Monitor.cshtml b/web/JiShe.CollectBusEPO.HttpApi.Host/Pages/Monitor.cshtml deleted file mode 100644 index 1825dbb..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Pages/Monitor.cshtml +++ /dev/null @@ -1,193 +0,0 @@ -@page "/Monitor" -@using JiShe.CollectBusEPO -@model JiShe.CollectBusEPO.Pages.Monitor - - -@{ - Layout = null; -} - - - - - - - - - - 后端服务 - - - -
- -
-
-
- - - -
-

- SwaggerUI -

-
-
-
- -
-
- - - -
-

- CAP面板 -

-
-
-
- -
-
- - - -
-

- Hangfire面板 -

-
-
-
-
-
- - - -
-

- Miniprofiler -

-
-
-
-
-
- - - -
-

- HealthCheck -

-
-
-
-
-
- - - \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Pages/Monitor.cshtml.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Pages/Monitor.cshtml.cs deleted file mode 100644 index d57d898..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Pages/Monitor.cshtml.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace JiShe.CollectBusEPO.Pages -{ - public class Monitor : PageModel - { - public void OnGet() - { - - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Program.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Program.cs deleted file mode 100644 index 20b7d21..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Program.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace JiShe.CollectBusEPO -{ - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - - } - - private static IHostBuilder CreateHostBuilder(string[] args) - { - var env = Environment.GetEnvironmentVariable("RUN_ENV") ?? "Development"; - - return Host.CreateDefaultBuilder(args) - .UseEnvironment(env) - .ConfigureAppConfiguration((context, builder) => - { - var c = builder.Build(); - - builder.AddJsonFile($"appsettings.json", false, true); - builder.AddJsonFile($"appsettings.{env}.json", false, true); - - //builder.AddNacosV2Configuration(c.GetSection("NacosConfig")); - }) - .ConfigureWebHostDefaults(webBuilder => - { - var runPort = Environment.GetEnvironmentVariable("RUN_PORT") ?? "8088"; - webBuilder.ConfigureKestrel((context, options) => { options.Limits.MaxRequestBodySize = 1024 * 50; }); - webBuilder.UseStartup(); - webBuilder.UseUrls($"http://*:{runPort}"); - }) - .UseSerilog((context, loggerConfiguration) => - { - loggerConfiguration.ReadFrom.Configuration(context.Configuration); - }).UseAutofac(); - } - } -} diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Properties/launchSettings.json b/web/JiShe.CollectBusEPO.HttpApi.Host/Properties/launchSettings.json deleted file mode 100644 index 8481021..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Properties/launchSettings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "profiles": { - "JiShe.MicroService.HttpApi.Host": { - "commandName": "Project", - "commandLineArgs": "serviceip=192.168.111.174 serviceport=8088", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "http://localhost:8088" - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Startup.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Startup.cs deleted file mode 100644 index f655483..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Startup.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace JiShe.CollectBusEPO -{ - public class Startup - { - private readonly IConfiguration _configuration; - - public Startup(IConfiguration configuration) - { - _configuration = configuration; - } - - - public void ConfigureServices(IServiceCollection services) - { - services.AddApplication(); - } - - public void Configure(IApplicationBuilder app,IHostApplicationLifetime lifetime) - { - app.InitializeApplication(); - } - } -} diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/EnumSchemaFilter.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/EnumSchemaFilter.cs deleted file mode 100644 index c31c8c2..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/EnumSchemaFilter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; - -namespace JiShe.CollectBusEPO.HttpApi.Host.Swaggers -{ - /// - /// swagger 枚举映射, - /// 原因:前端代理生成枚举是数字 - /// - public class EnumSchemaFilter : ISchemaFilter - { - public void Apply(OpenApiSchema schema, SchemaFilterContext context) - { - if (!context.Type.IsEnum) - return; - OpenApiArray openApiArray = new OpenApiArray(); - openApiArray.AddRange((IEnumerable)Enum.GetNames(context.Type).Select(n => new OpenApiString(n))); - schema.Extensions.Add("x-enumNames", openApiArray); - schema.Extensions.Add("x-enum-varnames", openApiArray); - } - } -} diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/HiddenAbpDefaultApiFilter.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/HiddenAbpDefaultApiFilter.cs deleted file mode 100644 index 31dbca5..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/HiddenAbpDefaultApiFilter.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Reflection; -using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; - -namespace JiShe.CollectBusEPO.HttpApi.Host.Swaggers -{ - /// - /// 在使用nswag的时候,原生默认的api导致生产的代理类存在问题 - /// 所有隐藏原生的api,重写路由 - /// - public class HiddenAbpDefaultApiFilter : IDocumentFilter - { - public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) - { - foreach (ApiDescription apiDescription in context.ApiDescriptions) - { - if (apiDescription.TryGetMethodInfo(out MethodInfo _)) - { - string key = "/" + apiDescription.RelativePath; - if (IsHidden(key)) - swaggerDoc.Paths.Remove(key); - } - } - } - - private bool IsHidden(string key) - { - foreach (string hiddenAbpDefaultApi in GetHiddenAbpDefaultApiList()) - { - if (key.Contains(hiddenAbpDefaultApi)) - return true; - } - return false; - } - - private List GetHiddenAbpDefaultApiList() - { - return new List() - { - "/api/abp/multi-tenancy/tenants", - "/api/account", - "/api/feature-management/features", - "/api/permission-management/permissions", - "/api/identity/my-profile", - "/api/identity", - "/api/multi-tenancy/tenants", - "/api/setting-management/emailing", - "/configuration", - "/outputcache" - }; - } - } -} diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/SwaggerConfig.cs b/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/SwaggerConfig.cs deleted file mode 100644 index 9b6de43..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/Swaggers/SwaggerConfig.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace JiShe.CollectBusEPO.HttpApi.Host.Swaggers -{ - public class SwaggerConfig - { - public string GroupName { get; set; } - - public string Title { get; set; } - - public string Version { get; set; } - } -} diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.Development.json b/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.Development.json deleted file mode 100644 index c1860fa..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.Development.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.Production.json b/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.Production.json deleted file mode 100644 index c1860fa..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.Production.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.json b/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.json deleted file mode 100644 index 92d8dc2..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/appsettings.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "Serilog": { - "Using": [ - "Serilog.Sinks.Console", - "Serilog.Sinks.File" - ], - "MinimumLevel": { - "Default": "Debug", - "Override": { - "Microsoft": "Information", - "Volo.Abp": "Information", - "Hangfire": "Information", - "DotNetCore.CAP": "Information", - "Serilog.AspNetCore": "Information", - "Microsoft.EntityFrameworkCore": "Warning", - "Microsoft.AspNetCore": "Information" - } - }, - "WriteTo": [ - { - "Name": "Console" - }, - { - "Name": "File", - "Args": { - "path": "logs/logs-.txt", - "rollingInterval": "Day" - } - } - ] - }, - "ConnectionStrings": { - "Default": "mongodb://mongo_PmEeF3:lixiao1980@192.168.5.9:27017/JiSheCollectBus?authSource=admin&maxPoolSize=400&minPoolSize=10&waitQueueTimeoutMS=5000", - "Kafka": "192.168.5.9:29092,192.168.5.9:39092,192.168.5.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" - }, - "Redis": { - "Configuration": "192.168.5.9:6380,password=1q2w3e!@#,syncTimeout=30000,abortConnect=false,connectTimeout=30000,allowAdmin=true", - "MaxPoolSize": "50", - "DefaultDB": "14", - "HangfireDB": "13" - }, - "Kafka": { - "BootstrapServers": "192.168.5.9:29092,192.168.5.9:39092,192.168.5.9:49092", - "EnableFilter": true, - "EnableAuthorization": false, - "SecurityProtocol": "SaslPlaintext", - "SaslMechanism": "Plain", - "SaslUserName": "lixiao", - "SaslPassword": "lixiao1980", - "KafkaReplicationFactor": 3, - "NumPartitions": 30, - "FirstCollectionTime": "2025-04-22 16:07:00" - }, - "IoTDBOptions": { - "UserName": "root", - "Password": "root", - "ClusterList": [ "121.42.175.177:16667" ], - "PoolSize": 32, - "DataBaseName": "energy", - "OpenDebugMode": true, - "UseTableSessionPoolByDefault": false - }, - "App": { - "SelfUrl": "http://localhost:44315", - "CorsOrigins": "http://localhost:4200,http://localhost:3100" - }, - "Jwt": { - "Audience": "JiShe.CollectBus", - "SecurityKey": "dzehzRz9a8asdfasfdadfasdfasdfafsdadfasbasdf=", - "Issuer": "JiShe.CollectBus", - "ExpirationTime": 2 - }, - "HealthChecks": { - "IsEnable": false, - "HealthCheckDatabaseName": "HealthChecks", - "EvaluationTimeInSeconds": 10, - "MinimumSecondsBetweenFailureNotifications": 60 - }, - "SwaggerConfig": [ - { - "GroupName": "Basic", - "Title": "【后台管理】基础模块", - "Version": "V1" - }, - { - "GroupName": "Business", - "Title": "【后台管理】业务模块", - "Version": "V1" - } - ], - "ServerApplicationOptions": { - "ServerTagName": "JiSheCollectBus99", - "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" - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/tempkey.jwk b/web/JiShe.CollectBusEPO.HttpApi.Host/tempkey.jwk deleted file mode 100644 index b4f8b7d..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/tempkey.jwk +++ /dev/null @@ -1 +0,0 @@ -{"AdditionalData":{},"Alg":"RS256","Crv":null,"D":"eH-Ld45J684VguyI2jACQEEVGtTx79Nt7ElT20JeUi-pbVnhJxxAJwnAe68d9Q8skpv6BxZs5QuyIORwfGpJK-lKVuo8EtyUQTuUuPmP4o1YK4cv2FIi5xN18tddTltg2JmJi1sN2AD5z-zwm45YNvoFxdQYlnUlA9lJL8QfG0HQLMQX1sv2_lgND8RfRGQBCpVXC2kcap4GvkFVQpKaQ5xaUqvNdH6ftwkGMdFfMRlHGhyYyabIjs4T16HslofvXiHbOCAzk37HtBNNsBpeoQuZul1-G7tAndHe1XtuGvuE-k1fyqdm3YiCU8wK7FpvQU3x6JqvfqmWgMAPnWKOtQ","DP":"hd3I9Nc3LlaZDoPg20JZu48kpv9rMMQ0rLtcZ0UPB_HpZWBC_No-3t3t1HFRbD4iz0MCpCR6gb5q4UsL2N2xh3Q8OhQ1Zrl76UKDZrVKs3oE0VVr9K2VUU3s1sytE4OWSv7PAHYURygcx_MrunMn8Ryd4ZJBQ_g5M2GvpBj1o5M","DQ":"T3ibciK4KxGGHqau9dnWxE6l3fGtcNw1GcjV93Lxe0NKTbfrwPEIFVVAyPsFS8QdmRXEgyunkDFKLHyq2hXBi2fZCwXGoWkUqVUKAKMaNYZaDDd_XeJKOu7mwNY8rgxNETHCyMSnnNNPNabBf2iiXmrBnMwesle2L1kwky42yns","E":"AQAB","K":null,"KeyId":"0D94529E740F5FD50EC6B8A19FF460D6","Kid":"0D94529E740F5FD50EC6B8A19FF460D6","Kty":"RSA","N":"w2jhtWb6a3kH4VqAPfuuvdF5hBh7U6gwMRnddHAH7zaVL6aYwjpCzNW56RQy4W4Zabv1My4Yw9GZpjrOcyr3Bm669eZjn_JC0O00eRTNStNgmg2kB_6AB6ROkEW7br1JC0jKr_dXhOYPBMmR-KHvpwaZXA9R1xOqY02S3JD0KB-TGMSC9q1RlVydt81aMOHFzWVyruLsYGdmcKhRPKDtL6GXpU_DG1gzzOYbk795x_D_UUTOJYuhIDEj7aYi3o32yXLEBvh4Q7HPLjLcWzV-EzCn6Ossl-EVJ2TrR53Eln03R93Vmo63DzQbLIOi3yTcZD2a3O6mpGLiqyZjUducIQ","Oth":null,"P":"y84cEtE6IRBeU2sDJxjDYb50HB4nAF7-bfvbEq0haQL2sFBz-Q-uOUAeXhaS74Gh_IagmW1TzOKblVilijMHCsfOFTWlCljaDoNfdl31enh50HMFvUu8IFjcWiQ9fjR5no8n5-jDeRO5zVfgcWoRHfVTOq4Di7WlVHJRr8FB-R8","Q":"9XRZvvMIvoumlDAVxWZHkb7_an0_dFwBLqc8v74XBZhiK5SLuBqmsJICB5kwNTKzORH7yedx-RXOJWkchJLlEtmH_cQO_6WKQQAyc1PMnLPa0tYkhjotWo8VRE9bAdVmrR0cnJeudfSJ-6gDpUBQYy9g1m8cAfWbTAk3at2_gr8","QI":"xRLXLwhTdNbevlEzANlDDnU9lDeKZWV9-YrvUxHMJBBygBNVqkNFWiee7LNUi82YgTHRn46rpHY9TZf6oQbgk6xa86MyDYXGU2uGO8DHm5oh20Spp7A-RlzZ4JRXAJ3eAYMZHQIP45JApVvKbgHh_pUGjNaiqZKZ9IN6H_L9k1s","Use":null,"X":null,"X5t":null,"X5tS256":null,"X5u":null,"Y":null,"KeySize":2048,"HasPrivateKey":true,"CryptoProviderFactory":{"CryptoProviderCache":{},"CustomCryptoProvider":null,"CacheSignatureProviders":true}} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/tempkey.rsa b/web/JiShe.CollectBusEPO.HttpApi.Host/tempkey.rsa deleted file mode 100644 index ed0defa..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi.Host/tempkey.rsa +++ /dev/null @@ -1 +0,0 @@ -{"KeyId":"600caa200caf5d805eba9f06ace9e236","Parameters":{"D":"KCNDHA96eimN+UqchSKocgYITGflaAIwxzCS5KqSTkYAFliPthQx7LySuLor4F1+uLvwnh3ZocyI3y43GZu+eVHD256sxdV8/UsQz1HC23RRFqcUiAZjze8K5VMVStrBOxaa/Ds1U9/bpuNE7jZdcgFIEHsdZtCACqwtlE4nlIs1/GLiokqjBOESgxJMy9WUeDbWcvoo+YdwgKf5jt6AZHOYSS+TokLL+Y7TEfGMXe3jZD9VtSMkBSM8wGB89zNGR0FZB9maCG/BCoRJqxdYRyeb4FFXJclQtK3DexyDVqlNZQaNKVHu0tVAnVNKKcd7Iex8gA+5DNqqucUA7C/F6Q==","DP":"fr9iaNb1W4YZ/NJ56+N3SCeDQYuKobq1qeaQWmHlQsOHKoHhNZJQZ5x0M9PQilou16AwVlNGCJncMwxsSUxXn6itG0LcBnvfMeo2v3xKcij1BtFR9qfXecwEn2nnhI3mpXtZxyCdP3NIYUp9qViLJUjGJqrbQk+OIAGRQd2rRe0=","DQ":"o1umLkDodtwvpCsDguQYSjd3iob+WHNmfe/9HyjADmUehP8b9SpUgcrb+QF301J8YmQMnYZKWW5rEwKOtwsWNswgXfMnXeWerlZmz0tj9y38YczS70liU0vETsRefhrRCaXHraMvneqYNNedhsrCNalWK+DNwcixi4L59vA8ofs=","Exponent":"AQAB","InverseQ":"btd1nwwxl/E3ryfDi2bN12TuVDvv7yoPvryIlLgu+FiLpe4vaA1omDLliQBcl7oeyA563HBUop4D5oE7si+jD64N8XgFz37dD3KqUokeQ4lrTSSOePT1K+nWIl30sqDd7YE4auz4CvSjm2wXmN31+CXW1hp3YWN2972yrUt+R5U=","Modulus":"uwMB6reAVtm/Cq0BRPZ0ozBq6g3wDh2kzqFKBf8I7u8d9p7i5ExLSrOWPupHwPr/IW1VUn2TKHrJ8OnyYhznKIRxqlxj0U3D2GXijz5kfFOoHK+mlfKaDMqweRoS0UzEz58kMlgwUoDraUj6dTHTPCVPo3TqA2ImRw50j6D+jobFrY5321EFvlirZViMPDAgB8Ca7wGCqNBcCxvIPYw1O6WZmcVmjG7umelD3XjcUIQlEbIyAmi/3gXAo7NdPmgOamla6bnSWsy429HfsNpXyCfPBzV3QS3ubpTekWPoPcOVZbWwVPYtFQbhRh8PmWATRx0cV6oePZNZGxGeJl8WYQ==","P":"wplelBfVmiOPmr6iUxtOgIzuvwSqvP6Rqmh8dhaGDiJjU8OqZ0tZhuh0G+xnMLPIHb2fMeg0dqZMJZ5iXaIi1QycYn/JKz1i4cUonJ6IIQeKKf67tvzn/BY0V0N8rJw8hVfzou+/5sRBCbiHtJ2KIN1YJQuWGFFfrZJOJzc95ss=","Q":"9gTGKoDiOdrY8kqIXJ2nMhoeNryAH4q3EUrROJ7simqc28oYlGx24Sco/wOoeB2xxrdcF5JYOlyJ7H2YY/huLvJISaw/wHLPskiKiYQ78tuNwW0ip+5ceB1dSToHcEe3sR30+OeTh0Z4ZKoqthKziFGIt3EhEgiGq1gjZuWB5gM="}} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/TemporaryFiles/.gitkeep b/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/TemporaryFiles/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/cap.png b/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/cap.png deleted file mode 100644 index 76c667e..0000000 Binary files a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/cap.png and /dev/null differ diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/hangfire.png b/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/hangfire.png deleted file mode 100644 index 5cdeb40..0000000 Binary files a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/hangfire.png and /dev/null differ diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/healthchecks.png b/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/healthchecks.png deleted file mode 100644 index 63950e4..0000000 Binary files a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/healthchecks.png and /dev/null differ diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/miniprofiler.png b/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/miniprofiler.png deleted file mode 100644 index 244c702..0000000 Binary files a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/miniprofiler.png and /dev/null differ diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/more.png b/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/more.png deleted file mode 100644 index 55c056f..0000000 Binary files a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/more.png and /dev/null differ diff --git a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/swagger.png b/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/swagger.png deleted file mode 100644 index 7bcbd43..0000000 Binary files a/web/JiShe.CollectBusEPO.HttpApi.Host/wwwroot/images/swagger.png and /dev/null differ diff --git a/web/JiShe.CollectBusEPO.HttpApi/CollectBusEPOHttpApiModule.cs b/web/JiShe.CollectBusEPO.HttpApi/CollectBusEPOHttpApiModule.cs deleted file mode 100644 index 100383b..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi/CollectBusEPOHttpApiModule.cs +++ /dev/null @@ -1,39 +0,0 @@ - -using JiShe.CollectBus; -using JiShe.CollectBus.Localization; -using Microsoft.Extensions.DependencyInjection; - -namespace JiShe.CollectBusEPO -{ - [DependsOn( - typeof(CollectBusEPOApplicationContractsModule), - typeof(CollectBusEPOApplicationModule), - typeof(AbpAspNetCoreMvcModule) - )] - public class CollectBusEPOHttpApiModule : AbpModule - { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - PreConfigure(mvcBuilder => - { - mvcBuilder.AddApplicationPartIfNotExists(typeof(CollectBusEPOHttpApiModule).Assembly); - }); - - Configure(options => - { - options.ConventionalControllers - .Create(typeof(CollectBusEPOHttpApiModule).Assembly); - }); - } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.Resources - .Get() - .AddBaseTypes(typeof(AbpUiResource)); - }); - } - } -} diff --git a/web/JiShe.CollectBusEPO.HttpApi/Controllers/CollectBusEPOController.cs b/web/JiShe.CollectBusEPO.HttpApi/Controllers/CollectBusEPOController.cs deleted file mode 100644 index cd8ffa8..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi/Controllers/CollectBusEPOController.cs +++ /dev/null @@ -1,14 +0,0 @@ -using JiShe.CollectBus.Localization; - -namespace JiShe.CollectBusEPO.Controllers -{ - /* Inherit your controllers from this class. - */ - public abstract class CollectBusEPOController : AbpController - { - protected CollectBusEPOController() - { - LocalizationResource = typeof(CollectBusResource); - } - } -} \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi/GlobalUsings.cs b/web/JiShe.CollectBusEPO.HttpApi/GlobalUsings.cs deleted file mode 100644 index 99bd72c..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi/GlobalUsings.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Global using directives - -global using Localization.Resources.AbpUi; -global using Volo.Abp.AspNetCore.Mvc; -global using Volo.Abp.Localization; -global using Volo.Abp.Modularity; \ No newline at end of file diff --git a/web/JiShe.CollectBusEPO.HttpApi/JiShe.CollectBusEPO.HttpApi.csproj b/web/JiShe.CollectBusEPO.HttpApi/JiShe.CollectBusEPO.HttpApi.csproj deleted file mode 100644 index 52da299..0000000 --- a/web/JiShe.CollectBusEPO.HttpApi/JiShe.CollectBusEPO.HttpApi.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - net8.0 - JiShe.CollectBusEPO - - - - - - - - - - - -