最近兜兜轉轉,看了各種各樣的OPC UA的庫,尤其是看了OPC Foundation的庫後,特別困惑,直到耐着性子看完milo庫的Server例子後,對於如何寫一個OPC UA服務器終於有了一定的瞭解。
Milo是Eclipse開源的項目之一,GitHub地址:Milo
我們直接通過Server的例程來了解整個Server是怎麼運行的:
1.主體函數
public static void main(String[] args) throws Exception {
ExampleServer server = new ExampleServer();
server.startup().get();
final CompletableFuture<Void> future = new CompletableFuture<>();
Runtime.getRuntime().addShutdownHook(new Thread(() -> future.complete(null)));
future.get();
}
這是Server主體的main函數,主要包含了以下幾點:
- 生成一個Server對象,並且啓動Server
- 定義異步寫的方式(CompletableFuture庫還沒怎麼看)
2.Server的定義方式
接下來我們主要是看如何去定義一個Server
獲取證書
SelfSignedHttpsCertificateBuilder httpsCertificateBuilder = new SelfSignedHttpsCertificateBuilder(httpsKeyPair);
httpsCertificateBuilder.setCommonName(HostnameUtil.getHostname());
HostnameUtil.getHostnames("0.0.0.0").forEach(httpsCertificateBuilder::addDnsName);
X509Certificate httpsCertificate = httpsCertificateBuilder.build();
這裏是通過X509的方式去生成OPC UA所需要的證書文件,進行加密傳輸,具體可以看生成證書。
之後則是證書的驗證相關。
OPC UA Server配置
String applicationUri = CertificateUtil
.getSanUri(certificate)
.orElseThrow(() -> new UaRuntimeException(
StatusCodes.Bad_ConfigurationError,
"certificate is missing the application URI"));
Set<EndpointConfiguration> endpointConfigurations = createEndpointConfigurations(certificate);
先獲取證書中的uri地址,通過方法實現對端點的配置,配置方法詳見milo ExampleServer
OpcUaServerConfig serverConfig = OpcUaServerConfig.builder()
.setApplicationUri(applicationUri)
.setApplicationName(LocalizedText.english("Eclipse Milo OPC UA Example Server"))
.setEndpoints(endpointConfigurations)
.setBuildInfo(
new BuildInfo(
"urn:eclipse:milo:example-server",
"eclipse",
"eclipse milo example server",
OpcUaServer.SDK_VERSION,
"", DateTime.now()))
//設置對應的證書管理器
.setCertificateManager(certificateManager)
//獲取信任列表 --- 用於信任Application
.setTrustListManager(trustListManager)
.setCertificateValidator(certificateValidator)
// 這個還不太明白
.setHttpsKeyPair(httpsKeyPair)
.setHttpsCertificate(httpsCertificate)
//驗證身份
.setIdentityValidator(new CompositeValidator(identityValidator, x509IdentityValidator))
//s設定生成的服務器URI
.setProductUri("urn:eclipse:milo:example-server")
.build();
server = new OpcUaServer(serverConfig);
配置OPCUA Server,具體信息已在代碼中闡述,最後將其賦值給server,其中serrver在Example類中定義
private final OpcUaServer server;
3.配置Server的命名空間 – 即Server的屬性
具體配置方式定義在ExampleServerfang方法中。
- 最前面的一大坨是後面例子中需要用的東西
super.onStartup()
這個是使用父類中的啓動方法,用於生成服務器自身的節點信息
// Create a "HelloWorld" folder and add it to the node manager
NodeId folderNodeId = newNodeId("HelloWorld");
UaFolderNode folderNode = new UaFolderNode(
getNodeContext(),
folderNodeId,
newQualifiedName("HelloWorld"),
LocalizedText.english("HelloWorld")
);
getNodeManager().addNode(folderNode);
// Make sure our new folder shows up under the server's Objects folder.
folderNode.addReference(new Reference(
//產生引用的結點ID
folderNode.getNodeId(),
//引用的類型
Identifiers.Organizes,
//引用連接的對象
Identifiers.ObjectsFolder.expanded(),
//Reference的指向
false
));
生成根目錄文件,並且天界一個對ObjectsFolder的引用,表示這是生成的一個對象,直屬於Object。
注意這裏的false代表的是reference的指向,true爲正向,false爲反向。
這裏是給folderNode添加的引用,是對Object的,因此結果應該是: