Просмотр исходного кода

OPCUA 移除默认XML文件,使用动态创建

Shun 2 лет назад
Родитель
Сommit
8a464d7e9e

+ 0 - 1
src/YSAI.Opc.Pack/YSAI.Opc.Pack.csproj

@@ -6,7 +6,6 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
   </PropertyGroup>
-
   <ItemGroup>
     <ProjectReference Include="..\YSAI.Opc\YSAI.Opc.csproj" />
   </ItemGroup>

+ 0 - 97
src/YSAI.Opc/Opc.Ua.Client.Config.xml

@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ApplicationConfiguration
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xmlns:ua="http://opcfoundation.org/UA/2008/02/Types.xsd"
-  xmlns="http://opcfoundation.org/UA/SDK/Configuration.xsd"
->
-  <ApplicationName>Opc.Ua.Client</ApplicationName>
-  <ApplicationUri>urn:localhost:UA:Opc.Ua.Client</ApplicationUri>
-  <ProductUri>uri:opcfoundation.org:Opc.Ua.Client</ProductUri>
-  <ApplicationType>Client_1</ApplicationType>
-
-  <SecurityConfiguration>
-
-    <!-- Where the application instance certificate is stored (MachineDefault) -->
-    <ApplicationCertificate>
-      <StoreType>Directory</StoreType>
-      <StorePath>%LocalApplicationData%/OPC Foundation/pki/own</StorePath>
-      <SubjectName>CN=Console Reference Client, C=US, S=Arizona, O=OPC Foundation, DC=localhost</SubjectName>
-    </ApplicationCertificate>
-
-   <!-- Where the issuer certificate are stored (certificate authorities) -->
-    <TrustedIssuerCertificates>
-      <StoreType>Directory</StoreType>
-      <StorePath>%LocalApplicationData%/OPC Foundation/pki/issuer</StorePath>
-    </TrustedIssuerCertificates>
-
-    <!-- Where the trust list is stored -->
-    <TrustedPeerCertificates>
-      <StoreType>Directory</StoreType>
-      <StorePath>%LocalApplicationData%/OPC Foundation/pki/trusted</StorePath>
-    </TrustedPeerCertificates>
-
-    <!-- The directory used to store invalid certficates for later review by the administrator. -->
-    <RejectedCertificateStore>
-      <StoreType>Directory</StoreType>
-      <StorePath>%LocalApplicationData%/OPC Foundation/pki/rejected</StorePath>
-    </RejectedCertificateStore>
-
-    <!-- WARNING: The following setting (to automatically accept untrusted certificates) should be used
-    for easy debugging purposes ONLY and turned off for production deployments! -->
-    <AutoAcceptUntrustedCertificates>true</AutoAcceptUntrustedCertificates>
-	<RejectSHA1SignedCertificates>false</RejectSHA1SignedCertificates>
-	<MinimumCertificateKeySize>1024</MinimumCertificateKeySize>
-  </SecurityConfiguration>
-
-  <TransportConfigurations></TransportConfigurations>
-
-  <TransportQuotas>
-	  <OperationTimeout>600000</OperationTimeout>
-	  <MaxStringLength>1048576</MaxStringLength>
-	  <MaxByteStringLength>4194304</MaxByteStringLength>
-	  <MaxArrayLength>65535</MaxArrayLength>
-	  <MaxMessageSize>4194304</MaxMessageSize>
-	  <MaxBufferSize>65535</MaxBufferSize>
-	  <ChannelLifetime>300000</ChannelLifetime>
-	  <SecurityTokenLifetime>3600000</SecurityTokenLifetime>
-  </TransportQuotas>
-
-	<!-- This element is only required for Client and ClientServer applications -->
-	<ClientConfiguration>
-
-		<!-- The default timeout for new sessions -->
-		<DefaultSessionTimeout>60000</DefaultSessionTimeout>
-
-		<!-- The well-known URLs for the local discovery servers
-             URLs are tested in the order they appear in this list. -->
-		<WellKnownDiscoveryUrls></WellKnownDiscoveryUrls>
-
-		<!-- EndpointDescriptions for system wide discovery servers -->
-		<DiscoveryServers></DiscoveryServers>
-
-		<!-- The minimum subscription lifetime.
-          This ensures subscriptions are not set to expire too quickly. The requesed lifetime count
-          and keep alive count are calculated using this value and the request publishing interval -->
-		<MinSubscriptionLifetime>10000</MinSubscriptionLifetime>
-	</ClientConfiguration>
-
-  <TraceConfiguration>
-    <OutputFilePath>%LocalApplicationData%/log/Opc.Ua.Client.log.txt</OutputFilePath>
-	  <DeleteOnLoad>true</DeleteOnLoad>
-	  <!-- Show Only Errors -->
-	  <!-- <TraceMasks>1</TraceMasks> -->
-	  <!-- Show Only Security and Errors -->
-	  <!-- <TraceMasks>513</TraceMasks> -->
-	  <!-- Show Only Security, Errors and Trace -->
-	  <!-- <TraceMasks>515</TraceMasks> -->
-	  <!-- Show Only Security, COM Calls, Errors and Trace -->
-	  <!-- <TraceMasks>771</TraceMasks> -->
-	  <!-- Show Only Security, Service Calls, Errors and Trace -->
-	  <!-- <TraceMasks>523</TraceMasks> -->
-	  <!-- Show Only Security, ServiceResultExceptions, Errors and Trace -->
-	  <TraceMasks>519</TraceMasks>
-  </TraceConfiguration>
-
-  <!-- Disables the hi-res clock if the QueryPerformanceCounter does work on a particular machine. -->
-  <DisableHiResClock>true</DisableHiResClock>
-</ApplicationConfiguration>

+ 0 - 276
src/YSAI.Opc/Opc.Ua.Service.Config.xml

@@ -1,276 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ApplicationConfiguration
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xmlns:ua="http://opcfoundation.org/UA/2008/02/Types.xsd"
-  xmlns="http://opcfoundation.org/UA/SDK/Configuration.xsd"
->
-	<ApplicationName>Opc.Ua.Service</ApplicationName>
-	<ApplicationUri>urn:localhost:Opc.Ua.Service</ApplicationUri>
-	<ProductUri>https://Shunnet.top</ProductUri>
-	<ApplicationType>Server_0</ApplicationType>
-
-  <SecurityConfiguration>
-
-    <!-- Where the application instance certificate is stored-->
-    <ApplicationCertificate>
-      <StoreType>Directory</StoreType>
-      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\own</StorePath>
-      <SubjectName>CN=Service, C=KR, S=Seoul, O=OpcUaAutomation, DC=localhost</SubjectName>
-    </ApplicationCertificate>
-
-    <!-- Where the issuer certificate are stored (certificate authorities) -->
-    <TrustedIssuerCertificates>
-      <StoreType>Directory</StoreType>
-      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\issuer</StorePath>
-    </TrustedIssuerCertificates>
-
-    <!-- Where the trust list is stored -->
-    <TrustedPeerCertificates>
-      <StoreType>Directory</StoreType>
-      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\trusted</StorePath>
-    </TrustedPeerCertificates>
-
-    <!-- The directory used to store invalid certficates for later review by the administrator. -->
-    <RejectedCertificateStore>
-      <StoreType>Directory</StoreType>
-      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\rejected</StorePath>
-    </RejectedCertificateStore>
-
-    <!-- WARNING: The following setting (to automatically accept untrusted certificates) should be used
-    for easy debugging purposes ONLY and turned off for production deployments! -->
-    <AutoAcceptUntrustedCertificates>false</AutoAcceptUntrustedCertificates>
-
-    <!-- WARNING: SHA1 signed certficates are by default rejected and should be phased out.
-    The setting below to allow them is only required for UACTT (1.02.336.244) which uses SHA-1 signed certs. -->
-    <RejectSHA1SignedCertificates>false</RejectSHA1SignedCertificates>
-    <RejectUnknownRevocationStatus>true</RejectUnknownRevocationStatus>
-    <MinimumCertificateKeySize>2048</MinimumCertificateKeySize>
-    <AddAppCertToTrustedStore>false</AddAppCertToTrustedStore>
-    <SendCertificateChain>true</SendCertificateChain>
-
-    <!-- Where the User issuer certificates are stored -->
-    <UserIssuerCertificates>
-      <StoreType>Directory</StoreType>
-      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\issuerUser</StorePath>
-    </UserIssuerCertificates>
-
-    <!-- Where the User trust list is stored-->
-    <TrustedUserCertificates>
-      <StoreType>Directory</StoreType>
-      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\trustedUser</StorePath>
-    </TrustedUserCertificates>
-  </SecurityConfiguration>
-
-  <TransportConfigurations></TransportConfigurations>
-  <TransportQuotas>
-    <OperationTimeout>600000</OperationTimeout>
-    <MaxStringLength>1048576</MaxStringLength>
-    <MaxByteStringLength>1048576</MaxByteStringLength>
-    <MaxArrayLength>65535</MaxArrayLength>
-    <MaxMessageSize>4194304</MaxMessageSize>
-    <MaxBufferSize>65535</MaxBufferSize>
-    <ChannelLifetime>300000</ChannelLifetime>
-    <SecurityTokenLifetime>3600000</SecurityTokenLifetime>
-  </TransportQuotas>
-  <ServerConfiguration>
-    <BaseAddresses>
-      <ua:String>https://127.0.0.1:6688/Opc.Ua.Service</ua:String>
-      <ua:String>opc.tcp://127.0.0.1:8866/Opc.Ua.Service</ua:String>
-    </BaseAddresses>
-    <!--
-    These list the alternate addresses (via firewalls, multiple NICs etc.) that can be
-    used to communicate with the server. The URL used by the client when calling
-    FindServers/GetEndpoints or CreateSession will be used to filter the list of
-    endpoints returned by checking for alternate base addresses that have a domain
-    that matches the domain in the url provided by the client.
-
-    Note that any additional domains should be listed in the server's certificate. If they
-    are left out the client make refuse to connect because it has no way to know if the
-    alternate domain was authorized by the server administrator.
-    -->
-    <!--
-    <AlternateBaseAddresses>
-      <ua:String>http://AlternateHostName/Service</ua:String>
-      <ua:String>http://10.10.103.150/Service</ua:String>
-      <ua:String>http://[2a01::626d]/Service</ua:String>
-    </AlternateBaseAddresses>
-    -->
-    <SecurityPolicies>
-      <ServerSecurityPolicy>
-        <SecurityMode>Sign_2</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>None_1</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#None</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>SignAndEncrypt_3</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <!-- deprecated security policies for reference only
-      <ServerSecurityPolicy>
-        <SecurityMode>Sign_2</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>SignAndEncrypt_3</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>Sign_2</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>SignAndEncrypt_3</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      -->
-      <ServerSecurityPolicy>
-        <SecurityMode>Sign_2</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>SignAndEncrypt_3</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>Sign_2</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>SignAndEncrypt_3</SecurityMode>
-        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss</SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>Sign_2</SecurityMode>
-        <SecurityPolicyUri></SecurityPolicyUri>
-      </ServerSecurityPolicy>
-      <ServerSecurityPolicy>
-        <SecurityMode>SignAndEncrypt_3</SecurityMode>
-        <SecurityPolicyUri></SecurityPolicyUri>
-      </ServerSecurityPolicy>
-    </SecurityPolicies>
-
-    <MinRequestThreadCount>100</MinRequestThreadCount>
-    <MaxRequestThreadCount>1000</MaxRequestThreadCount>
-    <MaxQueuedRequestCount>2000</MaxQueuedRequestCount>
-
-    <!-- The SDK expects the server to support the same set of user tokens for every endpoint. -->
-    <UserTokenPolicies>
-      <!-- 匿名登录 -->
-      <ua:UserTokenPolicy>
-        <ua:TokenType>Anonymous_0</ua:TokenType>
-        <ua:SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#None</ua:SecurityPolicyUri>
-      </ua:UserTokenPolicy>
-
-      <!-- 账号密码登录 -->
-      <ua:UserTokenPolicy>
-        <ua:TokenType>UserName_1</ua:TokenType>
-        <!-- passwords must be encrypted - this specifies what algorithm to use -->
-        <ua:SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</ua:SecurityPolicyUri>
-      </ua:UserTokenPolicy>
-
-      <!-- 证书登录 -->
-      <ua:UserTokenPolicy>
-        <ua:TokenType>Certificate_2</ua:TokenType>
-        <!-- certificate possession must be proven with a digital signature - this specifies what algorithm to use -->
-        <ua:SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</ua:SecurityPolicyUri>
-      </ua:UserTokenPolicy>
-    </UserTokenPolicies>
-    <DiagnosticsEnabled>true</DiagnosticsEnabled>
-    <MaxSessionCount>10000</MaxSessionCount>
-    <MinSessionTimeout>1000</MinSessionTimeout>
-    <MaxSessionTimeout>3600000</MaxSessionTimeout>
-    <MaxBrowseContinuationPoints>10</MaxBrowseContinuationPoints>
-    <MaxQueryContinuationPoints>10</MaxQueryContinuationPoints>
-    <MaxHistoryContinuationPoints>100</MaxHistoryContinuationPoints>
-    <MaxRequestAge>600000</MaxRequestAge>
-    <MinPublishingInterval>100</MinPublishingInterval>
-    <MaxPublishingInterval>3600000</MaxPublishingInterval>
-    <PublishingResolution>50</PublishingResolution>
-    <MaxSubscriptionLifetime>3600000</MaxSubscriptionLifetime>
-    <MaxMessageQueueSize>10000</MaxMessageQueueSize>
-    <MaxNotificationQueueSize>10000</MaxNotificationQueueSize>
-    <MaxNotificationsPerPublish>10000</MaxNotificationsPerPublish>
-    <MinMetadataSamplingInterval>1000</MinMetadataSamplingInterval>
-    <AvailableSamplingRates>
-      <SamplingRateGroup>
-        <Start>5</Start>
-        <Increment>5</Increment>
-        <Count>20</Count>
-      </SamplingRateGroup>
-      <SamplingRateGroup>
-        <Start>100</Start>
-        <Increment>100</Increment>
-        <Count>4</Count>
-      </SamplingRateGroup>
-      <SamplingRateGroup>
-        <Start>500</Start>
-        <Increment>250</Increment>
-        <Count>2</Count>
-      </SamplingRateGroup>
-      <SamplingRateGroup>
-        <Start>1000</Start>
-        <Increment>500</Increment>
-        <Count>20</Count>
-      </SamplingRateGroup>
-    </AvailableSamplingRates>
-
-    <RegistrationEndpoint>
-      <ua:EndpointUrl>opc.tcp://localhost:4840</ua:EndpointUrl>
-      <ua:Server>
-        <ua:ApplicationUri>opc.tcp://localhost:4840</ua:ApplicationUri>
-        <ua:ApplicationType>DiscoveryServer_3</ua:ApplicationType>
-        <ua:DiscoveryUrls>
-          <ua:String>opc.tcp://localhost:4840</ua:String>
-        </ua:DiscoveryUrls>
-      </ua:Server>
-      <ua:SecurityMode>SignAndEncrypt_3</ua:SecurityMode>
-      <ua:SecurityPolicyUri />
-      <ua:UserIdentityTokens />
-    </RegistrationEndpoint>
-
-    <MaxRegistrationInterval>30000</MaxRegistrationInterval>
-    <NodeManagerSaveFile>Opc.Ua.Service.Nodes.Json</NodeManagerSaveFile>
-    <MinSubscriptionLifetime>10000</MinSubscriptionLifetime>
-    <MaxPublishRequestCount>20</MaxPublishRequestCount>
-    <MaxSubscriptionCount>10000</MaxSubscriptionCount>
-    <MaxEventQueueSize>10000</MaxEventQueueSize>
-
-    <!-- see https://opcfoundation-onlineapplications.org/profilereporting/ for list of available profiles -->
-    <ServerProfileArray>
-      <ua:String>http://opcfoundation.org/UA-Profile/Server/StandardUA2017</ua:String>
-      <ua:String>http://opcfoundation.org/UA-Profile/Server/DataAccess</ua:String>
-      <ua:String>http://opcfoundation.org/UA-Profile/Server/Methods</ua:String>
-    </ServerProfileArray>
-
-    <ShutdownDelay>5</ShutdownDelay>
-    <ServerCapabilities>
-      <ua:String>DA</ua:String>
-    </ServerCapabilities>
-    <SupportedPrivateKeyFormats>
-      <ua:String>PFX</ua:String>
-      <ua:String>PEM</ua:String>
-    </SupportedPrivateKeyFormats>
-    <MaxTrustListSize>0</MaxTrustListSize>
-    <MultiCastDnsEnabled>false</MultiCastDnsEnabled>
-  </ServerConfiguration>
-
-  <TraceConfiguration>
-    <OutputFilePath>%LocalApplicationData%/log/Opc.Ua.Service.log.txt</OutputFilePath>
-    <DeleteOnLoad>true</DeleteOnLoad>
-    <!-- Show Only Errors -->
-    <!-- <TraceMasks>1</TraceMasks> -->
-    <!-- Show Only Security and Errors -->
-    <!-- <TraceMasks>513</TraceMasks> -->
-    <!-- Show Only Security, Errors and Trace -->
-    <!-- <TraceMasks>515</TraceMasks> -->
-    <!-- Show Only Security, COM Calls, Errors and Trace -->
-    <!-- <TraceMasks>771</TraceMasks> -->
-    <!-- Show Only Security, Service Calls, Errors and Trace -->
-    <!-- <TraceMasks>523</TraceMasks> -->
-    <!-- Show Only Security, ServiceResultExceptions, Errors and Trace -->
-    <!-- <TraceMasks>519</TraceMasks> -->
-  </TraceConfiguration>
-</ApplicationConfiguration>

+ 1 - 9
src/YSAI.Opc/YSAI.Opc.csproj

@@ -3,7 +3,7 @@
     <TargetFramework>net6.0</TargetFramework>
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
-    <Version>23.318.29701</Version>
+    <Version>23.318.34902</Version>
     <PackageOutputPath Condition="'$(Configuration)' == 'Release'">../YSAI.Publish/Release</PackageOutputPath>
     <PackageOutputPath Condition="'$(Configuration)' == 'Debug'">../YSAI.Publish/Debug</PackageOutputPath>
     <Authors>Shun</Authors>
@@ -19,14 +19,6 @@
     <None Remove="Opc.Ua.Client.Config.xml" />
     <None Remove="Opc.Ua.Service.Config.xml" />
   </ItemGroup>
-  <ItemGroup>
-    <Content Include="Opc.Ua.Client.Config.xml">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
-    <Content Include="Opc.Ua.Service.Config.xml">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
-  </ItemGroup>
   <ItemGroup>
     <PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.4.372.76" />
     <PackageReference Include="YSAI.Core" Version="23.318.29473" />

+ 143 - 7
src/YSAI.Opc/ua/client/OpcUaClientOperate.cs

@@ -3,6 +3,7 @@ using Opc.Ua.Client;
 using Opc.Ua.Configuration;
 using System.Collections.Concurrent;
 using System.Security.Cryptography.X509Certificates;
+using System.Text;
 using YSAI.Core.data;
 using YSAI.Core.@enum;
 using YSAI.Core.handler;
@@ -1413,6 +1414,125 @@ namespace YSAI.Opc.ua.client
             }, token.Token);
         }
 
+        /// <summary>
+        /// 创建默认配置文件
+        /// </summary>
+        /// <returns>状态,数据</returns>
+        private (bool state, string data) CreationConfig()
+        {
+            try
+            {
+                string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Opc.Ua.Client.Config.xml");
+                if (!File.Exists(path))
+                {
+                    string content = @"<?xml version=""1.0"" encoding=""utf-8""?>
+<ApplicationConfiguration
+  xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
+  xmlns:ua=""http://opcfoundation.org/UA/2008/02/Types.xsd""
+  xmlns=""http://opcfoundation.org/UA/SDK/Configuration.xsd""
+>
+  <ApplicationName>Opc.Ua.Client</ApplicationName>
+  <ApplicationUri>urn:localhost:UA:Opc.Ua.Client</ApplicationUri>
+  <ProductUri>uri:opcfoundation.org:Opc.Ua.Client</ProductUri>
+  <ApplicationType>Client_1</ApplicationType>
+
+  <SecurityConfiguration>
+
+    <!-- Where the application instance certificate is stored (MachineDefault) -->
+    <ApplicationCertificate>
+      <StoreType>Directory</StoreType>
+      <StorePath>%LocalApplicationData%/OPC Foundation/pki/own</StorePath>
+      <SubjectName>CN=Console Reference Client, C=US, S=Arizona, O=OPC Foundation, DC=localhost</SubjectName>
+    </ApplicationCertificate>
+
+   <!-- Where the issuer certificate are stored (certificate authorities) -->
+    <TrustedIssuerCertificates>
+      <StoreType>Directory</StoreType>
+      <StorePath>%LocalApplicationData%/OPC Foundation/pki/issuer</StorePath>
+    </TrustedIssuerCertificates>
+
+    <!-- Where the trust list is stored -->
+    <TrustedPeerCertificates>
+      <StoreType>Directory</StoreType>
+      <StorePath>%LocalApplicationData%/OPC Foundation/pki/trusted</StorePath>
+    </TrustedPeerCertificates>
+
+    <!-- The directory used to store invalid certficates for later review by the administrator. -->
+    <RejectedCertificateStore>
+      <StoreType>Directory</StoreType>
+      <StorePath>%LocalApplicationData%/OPC Foundation/pki/rejected</StorePath>
+    </RejectedCertificateStore>
+
+    <!-- WARNING: The following setting (to automatically accept untrusted certificates) should be used
+    for easy debugging purposes ONLY and turned off for production deployments! -->
+    <AutoAcceptUntrustedCertificates>true</AutoAcceptUntrustedCertificates>
+	<RejectSHA1SignedCertificates>false</RejectSHA1SignedCertificates>
+	<MinimumCertificateKeySize>1024</MinimumCertificateKeySize>
+  </SecurityConfiguration>
+
+  <TransportConfigurations></TransportConfigurations>
+
+  <TransportQuotas>
+	  <OperationTimeout>600000</OperationTimeout>
+	  <MaxStringLength>1048576</MaxStringLength>
+	  <MaxByteStringLength>4194304</MaxByteStringLength>
+	  <MaxArrayLength>65535</MaxArrayLength>
+	  <MaxMessageSize>4194304</MaxMessageSize>
+	  <MaxBufferSize>65535</MaxBufferSize>
+	  <ChannelLifetime>300000</ChannelLifetime>
+	  <SecurityTokenLifetime>3600000</SecurityTokenLifetime>
+  </TransportQuotas>
+
+	<!-- This element is only required for Client and ClientServer applications -->
+	<ClientConfiguration>
+
+		<!-- The default timeout for new sessions -->
+		<DefaultSessionTimeout>60000</DefaultSessionTimeout>
+
+		<!-- The well-known URLs for the local discovery servers
+             URLs are tested in the order they appear in this list. -->
+		<WellKnownDiscoveryUrls></WellKnownDiscoveryUrls>
+
+		<!-- EndpointDescriptions for system wide discovery servers -->
+		<DiscoveryServers></DiscoveryServers>
+
+		<!-- The minimum subscription lifetime.
+          This ensures subscriptions are not set to expire too quickly. The requesed lifetime count
+          and keep alive count are calculated using this value and the request publishing interval -->
+		<MinSubscriptionLifetime>10000</MinSubscriptionLifetime>
+	</ClientConfiguration>
+
+  <TraceConfiguration>
+    <OutputFilePath>%LocalApplicationData%/log/Opc.Ua.Client.log.txt</OutputFilePath>
+	  <DeleteOnLoad>true</DeleteOnLoad>
+	  <!-- Show Only Errors -->
+	  <!-- <TraceMasks>1</TraceMasks> -->
+	  <!-- Show Only Security and Errors -->
+	  <!-- <TraceMasks>513</TraceMasks> -->
+	  <!-- Show Only Security, Errors and Trace -->
+	  <!-- <TraceMasks>515</TraceMasks> -->
+	  <!-- Show Only Security, COM Calls, Errors and Trace -->
+	  <!-- <TraceMasks>771</TraceMasks> -->
+	  <!-- Show Only Security, Service Calls, Errors and Trace -->
+	  <!-- <TraceMasks>523</TraceMasks> -->
+	  <!-- Show Only Security, ServiceResultExceptions, Errors and Trace -->
+	  <TraceMasks>519</TraceMasks>
+  </TraceConfiguration>
+
+  <!-- Disables the hi-res clock if the QueryPerformanceCounter does work on a particular machine. -->
+  <DisableHiResClock>true</DisableHiResClock>
+</ApplicationConfiguration>";
+                    File.WriteAllText(path, content, new UTF8Encoding(true));
+                }
+                return (true, path.Replace(".Config.xml", string.Empty));
+            }
+            catch (Exception ex)
+            {
+                string message = $"OpcUa 客户端配置创建失败:{ex.Message}";
+                return (false, message);
+            }
+        }
+
         public OperateResult On()
         {
             //开始记录运行时间
@@ -1462,16 +1582,32 @@ namespace YSAI.Opc.ua.client
                 //初始化配置
                 AI.ApplicationType = ApplicationType.Client;
 
-                string ConfigName = "Opc.Ua.Client";
+                #region 暂不使用
+                //string ConfigName = "Opc.Ua.Client";
+                //string ConfigPath = string.Empty;
+                //foreach (var item in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.Config.xml", SearchOption.AllDirectories))
+                //{
+                //    if (item.Contains(ConfigName))
+                //    {
+                //        ConfigPath = Path.Combine(FileTool.GetFolderPath(item), ConfigName);
+                //        break;
+                //    }
+                //} 
+                #endregion
+
                 string ConfigPath = string.Empty;
-                foreach (var item in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.Config.xml", SearchOption.AllDirectories))
+
+                //创建配置
+                var res = CreationConfig();
+                if (res.state)
                 {
-                    if (item.Contains(ConfigName))
-                    {
-                        ConfigPath = Path.Combine(FileTool.GetFolderPath(item), ConfigName);
-                        break;
-                    }
+                    ConfigPath = res.data;
                 }
+                else
+                {
+                    return Break("On", false, res.data);
+                }
+
 
                 //配置文件的名称
                 AI.ConfigSectionName = ConfigPath;

+ 322 - 7
src/YSAI.Opc/ua/service/OpcUaServiceOperate.cs

@@ -2,6 +2,7 @@
 using Opc.Ua.Configuration;
 using Opc.Ua.Server;
 using System.Collections;
+using System.Text;
 using YSAI.Core.data;
 using YSAI.Core.@interface;
 using YSAI.Opc.ua.service.core;
@@ -221,6 +222,304 @@ namespace YSAI.Opc.ua.service
             ThisObjList.Remove(this);
         }
 
+        /// <summary>
+        /// 创建默认配置文件
+        /// </summary>
+        /// <returns>状态,数据</returns>
+        private (bool state, string data) CreationConfig()
+        {
+            try
+            {
+                string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Opc.Ua.Service.Config.xml");
+                if (!File.Exists(path))
+                {
+                    string content = @"<?xml version=""1.0"" encoding=""utf-8""?>
+<ApplicationConfiguration
+  xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
+  xmlns:ua=""http://opcfoundation.org/UA/2008/02/Types.xsd""
+  xmlns=""http://opcfoundation.org/UA/SDK/Configuration.xsd""
+>
+	<ApplicationName>Opc.Ua.Service</ApplicationName>
+	<ApplicationUri>urn:localhost:Opc.Ua.Service</ApplicationUri>
+	<ProductUri>https://Shunnet.top</ProductUri>
+	<ApplicationType>Server_0</ApplicationType>
+
+  <SecurityConfiguration>
+
+    <!-- Where the application instance certificate is stored-->
+    <ApplicationCertificate>
+      <StoreType>Directory</StoreType>
+      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\own</StorePath>
+      <SubjectName>CN=Service, C=KR, S=Seoul, O=OpcUaAutomation, DC=localhost</SubjectName>
+    </ApplicationCertificate>
+
+    <!-- Where the issuer certificate are stored (certificate authorities) -->
+    <TrustedIssuerCertificates>
+      <StoreType>Directory</StoreType>
+      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\issuer</StorePath>
+    </TrustedIssuerCertificates>
+
+    <!-- Where the trust list is stored -->
+    <TrustedPeerCertificates>
+      <StoreType>Directory</StoreType>
+      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\trusted</StorePath>
+    </TrustedPeerCertificates>
+
+    <!-- The directory used to store invalid certficates for later review by the administrator. -->
+    <RejectedCertificateStore>
+      <StoreType>Directory</StoreType>
+      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\rejected</StorePath>
+    </RejectedCertificateStore>
+
+    <!-- WARNING: The following setting (to automatically accept untrusted certificates) should be used
+    for easy debugging purposes ONLY and turned off for production deployments! -->
+    <AutoAcceptUntrustedCertificates>false</AutoAcceptUntrustedCertificates>
+
+    <!-- WARNING: SHA1 signed certficates are by default rejected and should be phased out.
+    The setting below to allow them is only required for UACTT (1.02.336.244) which uses SHA-1 signed certs. -->
+    <RejectSHA1SignedCertificates>false</RejectSHA1SignedCertificates>
+    <RejectUnknownRevocationStatus>true</RejectUnknownRevocationStatus>
+    <MinimumCertificateKeySize>2048</MinimumCertificateKeySize>
+    <AddAppCertToTrustedStore>false</AddAppCertToTrustedStore>
+    <SendCertificateChain>true</SendCertificateChain>
+
+    <!-- Where the User issuer certificates are stored -->
+    <UserIssuerCertificates>
+      <StoreType>Directory</StoreType>
+      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\issuerUser</StorePath>
+    </UserIssuerCertificates>
+
+    <!-- Where the User trust list is stored-->
+    <TrustedUserCertificates>
+      <StoreType>Directory</StoreType>
+      <StorePath>%CommonApplicationData%\OpcUaAutomation\pki\trustedUser</StorePath>
+    </TrustedUserCertificates>
+  </SecurityConfiguration>
+
+  <TransportConfigurations></TransportConfigurations>
+  <TransportQuotas>
+    <OperationTimeout>600000</OperationTimeout>
+    <MaxStringLength>1048576</MaxStringLength>
+    <MaxByteStringLength>1048576</MaxByteStringLength>
+    <MaxArrayLength>65535</MaxArrayLength>
+    <MaxMessageSize>4194304</MaxMessageSize>
+    <MaxBufferSize>65535</MaxBufferSize>
+    <ChannelLifetime>300000</ChannelLifetime>
+    <SecurityTokenLifetime>3600000</SecurityTokenLifetime>
+  </TransportQuotas>
+  <ServerConfiguration>
+    <BaseAddresses>
+      <ua:String>https://127.0.0.1:6688/Opc.Ua.Service</ua:String>
+      <ua:String>opc.tcp://127.0.0.1:8866/Opc.Ua.Service</ua:String>
+    </BaseAddresses>
+    <!--
+    These list the alternate addresses (via firewalls, multiple NICs etc.) that can be
+    used to communicate with the server. The URL used by the client when calling
+    FindServers/GetEndpoints or CreateSession will be used to filter the list of
+    endpoints returned by checking for alternate base addresses that have a domain
+    that matches the domain in the url provided by the client.
+
+    Note that any additional domains should be listed in the server's certificate. If they
+    are left out the client make refuse to connect because it has no way to know if the
+    alternate domain was authorized by the server administrator.
+    -->
+    <!--
+    <AlternateBaseAddresses>
+      <ua:String>http://AlternateHostName/Service</ua:String>
+      <ua:String>http://10.10.103.150/Service</ua:String>
+      <ua:String>http://[2a01::626d]/Service</ua:String>
+    </AlternateBaseAddresses>
+    -->
+    <SecurityPolicies>
+      <ServerSecurityPolicy>
+        <SecurityMode>Sign_2</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>None_1</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#None</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>SignAndEncrypt_3</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <!-- deprecated security policies for reference only
+      <ServerSecurityPolicy>
+        <SecurityMode>Sign_2</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>SignAndEncrypt_3</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>Sign_2</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>SignAndEncrypt_3</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      -->
+      <ServerSecurityPolicy>
+        <SecurityMode>Sign_2</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>SignAndEncrypt_3</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>Sign_2</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>SignAndEncrypt_3</SecurityMode>
+        <SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss</SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>Sign_2</SecurityMode>
+        <SecurityPolicyUri></SecurityPolicyUri>
+      </ServerSecurityPolicy>
+      <ServerSecurityPolicy>
+        <SecurityMode>SignAndEncrypt_3</SecurityMode>
+        <SecurityPolicyUri></SecurityPolicyUri>
+      </ServerSecurityPolicy>
+    </SecurityPolicies>
+
+    <MinRequestThreadCount>100</MinRequestThreadCount>
+    <MaxRequestThreadCount>1000</MaxRequestThreadCount>
+    <MaxQueuedRequestCount>2000</MaxQueuedRequestCount>
+
+    <!-- The SDK expects the server to support the same set of user tokens for every endpoint. -->
+    <UserTokenPolicies>
+      <!-- 匿名登录 -->
+      <ua:UserTokenPolicy>
+        <ua:TokenType>Anonymous_0</ua:TokenType>
+        <ua:SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#None</ua:SecurityPolicyUri>
+      </ua:UserTokenPolicy>
+
+      <!-- 账号密码登录 -->
+      <ua:UserTokenPolicy>
+        <ua:TokenType>UserName_1</ua:TokenType>
+        <!-- passwords must be encrypted - this specifies what algorithm to use -->
+        <ua:SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</ua:SecurityPolicyUri>
+      </ua:UserTokenPolicy>
+
+      <!-- 证书登录 -->
+      <ua:UserTokenPolicy>
+        <ua:TokenType>Certificate_2</ua:TokenType>
+        <!-- certificate possession must be proven with a digital signature - this specifies what algorithm to use -->
+        <ua:SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</ua:SecurityPolicyUri>
+      </ua:UserTokenPolicy>
+    </UserTokenPolicies>
+    <DiagnosticsEnabled>true</DiagnosticsEnabled>
+    <MaxSessionCount>10000</MaxSessionCount>
+    <MinSessionTimeout>1000</MinSessionTimeout>
+    <MaxSessionTimeout>3600000</MaxSessionTimeout>
+    <MaxBrowseContinuationPoints>10</MaxBrowseContinuationPoints>
+    <MaxQueryContinuationPoints>10</MaxQueryContinuationPoints>
+    <MaxHistoryContinuationPoints>100</MaxHistoryContinuationPoints>
+    <MaxRequestAge>600000</MaxRequestAge>
+    <MinPublishingInterval>100</MinPublishingInterval>
+    <MaxPublishingInterval>3600000</MaxPublishingInterval>
+    <PublishingResolution>50</PublishingResolution>
+    <MaxSubscriptionLifetime>3600000</MaxSubscriptionLifetime>
+    <MaxMessageQueueSize>10000</MaxMessageQueueSize>
+    <MaxNotificationQueueSize>10000</MaxNotificationQueueSize>
+    <MaxNotificationsPerPublish>10000</MaxNotificationsPerPublish>
+    <MinMetadataSamplingInterval>1000</MinMetadataSamplingInterval>
+    <AvailableSamplingRates>
+      <SamplingRateGroup>
+        <Start>5</Start>
+        <Increment>5</Increment>
+        <Count>20</Count>
+      </SamplingRateGroup>
+      <SamplingRateGroup>
+        <Start>100</Start>
+        <Increment>100</Increment>
+        <Count>4</Count>
+      </SamplingRateGroup>
+      <SamplingRateGroup>
+        <Start>500</Start>
+        <Increment>250</Increment>
+        <Count>2</Count>
+      </SamplingRateGroup>
+      <SamplingRateGroup>
+        <Start>1000</Start>
+        <Increment>500</Increment>
+        <Count>20</Count>
+      </SamplingRateGroup>
+    </AvailableSamplingRates>
+
+    <RegistrationEndpoint>
+      <ua:EndpointUrl>opc.tcp://localhost:4840</ua:EndpointUrl>
+      <ua:Server>
+        <ua:ApplicationUri>opc.tcp://localhost:4840</ua:ApplicationUri>
+        <ua:ApplicationType>DiscoveryServer_3</ua:ApplicationType>
+        <ua:DiscoveryUrls>
+          <ua:String>opc.tcp://localhost:4840</ua:String>
+        </ua:DiscoveryUrls>
+      </ua:Server>
+      <ua:SecurityMode>SignAndEncrypt_3</ua:SecurityMode>
+      <ua:SecurityPolicyUri />
+      <ua:UserIdentityTokens />
+    </RegistrationEndpoint>
+
+    <MaxRegistrationInterval>30000</MaxRegistrationInterval>
+    <NodeManagerSaveFile>Opc.Ua.Service.Nodes.Json</NodeManagerSaveFile>
+    <MinSubscriptionLifetime>10000</MinSubscriptionLifetime>
+    <MaxPublishRequestCount>20</MaxPublishRequestCount>
+    <MaxSubscriptionCount>10000</MaxSubscriptionCount>
+    <MaxEventQueueSize>10000</MaxEventQueueSize>
+
+    <!-- see https://opcfoundation-onlineapplications.org/profilereporting/ for list of available profiles -->
+    <ServerProfileArray>
+      <ua:String>http://opcfoundation.org/UA-Profile/Server/StandardUA2017</ua:String>
+      <ua:String>http://opcfoundation.org/UA-Profile/Server/DataAccess</ua:String>
+      <ua:String>http://opcfoundation.org/UA-Profile/Server/Methods</ua:String>
+    </ServerProfileArray>
+
+    <ShutdownDelay>5</ShutdownDelay>
+    <ServerCapabilities>
+      <ua:String>DA</ua:String>
+    </ServerCapabilities>
+    <SupportedPrivateKeyFormats>
+      <ua:String>PFX</ua:String>
+      <ua:String>PEM</ua:String>
+    </SupportedPrivateKeyFormats>
+    <MaxTrustListSize>0</MaxTrustListSize>
+    <MultiCastDnsEnabled>false</MultiCastDnsEnabled>
+  </ServerConfiguration>
+
+  <TraceConfiguration>
+    <OutputFilePath>%LocalApplicationData%/log/Opc.Ua.Service.log.txt</OutputFilePath>
+    <DeleteOnLoad>true</DeleteOnLoad>
+    <!-- Show Only Errors -->
+    <!-- <TraceMasks>1</TraceMasks> -->
+    <!-- Show Only Security and Errors -->
+    <!-- <TraceMasks>513</TraceMasks> -->
+    <!-- Show Only Security, Errors and Trace -->
+    <!-- <TraceMasks>515</TraceMasks> -->
+    <!-- Show Only Security, COM Calls, Errors and Trace -->
+    <!-- <TraceMasks>771</TraceMasks> -->
+    <!-- Show Only Security, Service Calls, Errors and Trace -->
+    <!-- <TraceMasks>523</TraceMasks> -->
+    <!-- Show Only Security, ServiceResultExceptions, Errors and Trace -->
+    <!-- <TraceMasks>519</TraceMasks> -->
+  </TraceConfiguration>
+</ApplicationConfiguration>";
+                    File.WriteAllText(path, content, new UTF8Encoding(true));
+                }
+                return (true, path.Replace(".Config.xml", string.Empty));
+            }
+            catch (Exception ex)
+            {
+                string message = $"OpcUa 服务端配置创建失败:{ex.Message}";
+                return (false, message);
+            }
+        }
+
         /// <summary>
         /// 打开
         /// </summary>
@@ -237,16 +536,32 @@ namespace YSAI.Opc.ua.service
                 //设置类型
                 AI.ApplicationType = ApplicationType.Server;
 
-                string ConfigName = "Opc.Ua.Service";
+                #region 暂不使用
+                //string ConfigName = "Opc.Ua.Service";
+                //string ConfigPath = string.Empty;
+                //foreach (var item in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.Config.xml", SearchOption.AllDirectories))
+                //{
+                //    if (item.Contains(ConfigName))
+                //    {
+                //        ConfigPath = Path.Combine(FileTool.GetFolderPath(item), ConfigName);
+                //        break;
+                //    }
+                //} 
+                #endregion
+
                 string ConfigPath = string.Empty;
-                foreach (var item in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.Config.xml", SearchOption.AllDirectories))
+
+                //创建配置
+                var res = CreationConfig();
+                if (res.state)
                 {
-                    if (item.Contains(ConfigName))
-                    {
-                        ConfigPath = Path.Combine(FileTool.GetFolderPath(item), ConfigName);
-                        break;
-                    }
+                    ConfigPath = res.data;
                 }
+                else
+                {
+                    return Break("On", false, res.data);
+                }
+
 
                 //获取或设置包含应用程序配置文件路径的配置节的名称(也就是通过配置文件来进行配置)
                 AI.ConfigSectionName = ConfigPath;

+ 93 - 93
src/YSAI.Test.All/Program.cs

@@ -1,4 +1,4 @@
-Console.WriteLine();
+//Console.WriteLine();
 
 //Console.WriteLine(DateTime.Parse($"{0}:{0}:{0}.{123}").ToString("HH:mm:ss.fff"));
 
@@ -717,104 +717,104 @@
 //    public string Description { get; set; }
 //}
 
-//using System.Collections.Concurrent;
-//using YSAI.Core.data;
-//using YSAI.Log;
-//using YSAI.Opc.ua.client;
-//using YSAI.Unility;
-
-///// <summary>
-///// 读取Csv,返回行集合
-///// </summary>
-///// <param name="path"></param>
-///// <param name="hasTitle"></param>
-///// <returns></returns>
-//List<string> ReadCsv(string path, bool hasTitle)
-//{
-//    if (!File.Exists(path))
-//        return new List<string>();
+using System.Collections.Concurrent;
+using YSAI.Core.data;
+using YSAI.Log;
+using YSAI.Opc.ua.client;
+using YSAI.Unility;
+
+/// <summary>
+/// 读取Csv,返回行集合
+/// </summary>
+/// <param name="path"></param>
+/// <param name="hasTitle"></param>
+/// <returns></returns>
+List<string> ReadCsv(string path, bool hasTitle)
+{
+    if (!File.Exists(path))
+        return new List<string>();
+
+    var lines = File.ReadAllLines(path).ToList();
+    if (hasTitle)
+    {
+        lines.RemoveAt(0);
+    }
+    return lines;
+}
+
+//Address address = JsonTool.StringToJsonEntity<Address>(FileTool.FileToString("C:\\Users\\Shun\\Desktop\\[6032]Node_Address 202310120854271486.json"));
+
+Address address = new Address();
+address.SN = Guid.NewGuid().ToString();
+address.CreationTime = DateTime.Now;
+address.AddressArray = new List<AddressDetails>();
+List<string> strings = ReadCsv("C:\\Users\\Shun\\Desktop\\6022.csv", true);
+foreach (var item in strings)
+{
+    string[] str = item.Split(",");
+    string addressD = str[0].Replace("\"", "");
+    address.AddressArray.Add(new AddressDetails()
+    {
+        AddressName = $"ns=2;s=6022.6022.{addressD}",
+        SN = Guid.NewGuid().ToString()
+    });
+}
 
-//    var lines = File.ReadAllLines(path).ToList();
-//    if (hasTitle)
-//    {
-//        lines.RemoveAt(0);
-//    }
-//    return lines;
-//}
-
-////Address address = JsonTool.StringToJsonEntity<Address>(FileTool.FileToString("C:\\Users\\Shun\\Desktop\\[6032]Node_Address 202310120854271486.json"));
-
-//Address address = new Address();
-//address.SN = Guid.NewGuid().ToString();
-//address.CreationTime = DateTime.Now;
-//address.AddressArray = new List<AddressDetails>();
-//List<string> strings = ReadCsv("C:\\Users\\Shun\\Desktop\\6022.csv", true);
-//foreach (var item in strings)
-//{
-//    string[] str = item.Split(",");
-//    string addressD = str[0].Replace("\"", "");
-//    address.AddressArray.Add(new AddressDetails()
-//    {
-//        AddressName = $"ns=2;s=6022.6022.{addressD}",
-//        SN = Guid.NewGuid().ToString()
-//    });
-//}
-
-////address.AddressArray.Add(new AddressDetails()
-////{
-////    AddressName = $"ns=2;s=6022.6022.LAP5_DP2113_AUTO",
-////    SN = Guid.NewGuid().ToString()
-////});
-
-////address.AddressArray.Add(new AddressDetails()
-////{
-////    AddressName = $"ns=2;s=6022.6022.LAP5_DP2112_STATE_RUN",
-////    SN = Guid.NewGuid().ToString()
-////});
-
-//OpcUaClientOperate opcUaClientOperate = OpcUaClientOperate.Instance(new OpcUaClientData.Basics
+//address.AddressArray.Add(new AddressDetails()
 //{
-//    ServerUrl = "opc.tcp://192.168.2.220:49320",
-//    CustomName = "YSAI 性能测试",
-//    TaskNumber = 10,
-//    TaskHandleInterval = 1,
-//    SubscribeSingleGroupMaxCount = 1000,
+//    AddressName = $"ns=2;s=6022.6022.LAP5_DP2113_AUTO",
+//    SN = Guid.NewGuid().ToString()
 //});
-//Console.WriteLine(opcUaClientOperate.On().ToJson().JsonFormatting());
-//opcUaClientOperate.OnEvent += OpcUaClientOperate_OnEvent;
 
-//while (true)
-//{
-//    Console.ReadLine();
-//    OperateResult operateResult = opcUaClientOperate.Subscribe(address);
-//    Console.WriteLine(operateResult.ToJson().JsonFormatting());
-//}
-
-//void OpcUaClientOperate_OnEvent(object? sender, EventResult e)
+//address.AddressArray.Add(new AddressDetails()
 //{
-//    switch (e.RType)
-//    {
-//        case YSAI.Core.@enum.ResultType.KeyValue:
-
-//            ConcurrentDictionary<string, AddressValue> pairs = e.GetRData<ConcurrentDictionary<string, AddressValue>>();
-//            foreach (var item in pairs)
-//            {
-//                if (item.Value.AddressName.Equals("ns=2;s=6022.6022.LAP5_DP2112_STATE_RUN") || item.Value.AddressName.Equals("ns=2;s=6022.6022.LAP5_DP2113_AUTO"))
-//                {
-//                    String str = String.Format("{0,-100}{1,-100}", item.Key, item.Value.Value);
-//                    LogHelper.Verbose(str);
-//                }
-
-//                //String str = String.Format("{0,-100}{1,-100}", item.Key, item.Value.Value);
-//                //LogHelper.Verbose(str);
-//            }
-//            break;
+//    AddressName = $"ns=2;s=6022.6022.LAP5_DP2112_STATE_RUN",
+//    SN = Guid.NewGuid().ToString()
+//});
 
-//        default:
-//            //Console.WriteLine(e.Message);
-//            break;
-//    }
-//}
+OpcUaClientOperate opcUaClientOperate = OpcUaClientOperate.Instance(new OpcUaClientData.Basics
+{
+    ServerUrl = "opc.tcp://192.168.2.220:49320",
+    CustomName = "YSAI 性能测试",
+    TaskNumber = 10,
+    TaskHandleInterval = 1,
+    SubscribeSingleGroupMaxCount = 1000,
+});
+Console.WriteLine(opcUaClientOperate.On().ToJson().JsonFormatting());
+opcUaClientOperate.OnEvent += OpcUaClientOperate_OnEvent;
+
+while (true)
+{
+    Console.ReadLine();
+    OperateResult operateResult = opcUaClientOperate.Subscribe(address);
+    Console.WriteLine(operateResult.ToJson().JsonFormatting());
+}
+
+void OpcUaClientOperate_OnEvent(object? sender, EventResult e)
+{
+    switch (e.RType)
+    {
+        case YSAI.Core.@enum.ResultType.KeyValue:
+
+            ConcurrentDictionary<string, AddressValue> pairs = e.GetRData<ConcurrentDictionary<string, AddressValue>>();
+            foreach (var item in pairs)
+            {
+                if (item.Value.AddressName.Equals("ns=2;s=6022.6022.LAP5_DP2112_STATE_RUN") || item.Value.AddressName.Equals("ns=2;s=6022.6022.LAP5_DP2113_AUTO"))
+                {
+                    String str = String.Format("{0,-100}{1,-100}", item.Key, item.Value.Value);
+                    LogHelper.Verbose(str);
+                }
+
+                //String str = String.Format("{0,-100}{1,-100}", item.Key, item.Value.Value);
+                //LogHelper.Verbose(str);
+            }
+            break;
+
+        default:
+            //Console.WriteLine(e.Message);
+            break;
+    }
+}
 
 //using Opc.Ua;
 //using YSAI.Core.data;