OPC UAクライアントでサーバーのデータを読み書き

# 目的
- 認証ありのOPC UAサーバーを設置
- そのサーバーに接続し、値を書き換える


# 環境

Windows10 Pro
バージョン	10.0.18362 ビルド 18362

# cygwin setup

[setup-x86_64.exeをダウンロード](https://www.cygwin.com/)・実行し以下をインストールする。

openssl
gcc-core
python37
python37-pip
python37-devel
python37-cryptography
dateutil
python37-lxml
python37-pytz


# install python-opcua

cygwinを起動し、ターミナル上で以下のコマンドを実行する。

```Console
pip3.7 install --upgrade pip
pip3.7 install opcua
```

# 動作確認（その1）
最小限のサーバーとクライアントの動作確認。

https://github.com/FreeOpcUa/python-opcua/archive/master.zip をダウンロード・解凍する。
解凍後、python-opcua-master\examples内に含まれているserver-minimal.pyとclient-minimal.pyを実行する。


サーバー側を実行する。

```Console
$ python3.7 server-minimal.py
Endpoints other than open requested but private key and certificate are not set.
Listening on 0.0.0.0:4840
```

別のcygwinターミナルを開き、クライアント側を実行する。
以下のように表示されたら成功。

```Console
$ python3.7 client-minimal.py
Objects node is:  Node(TwoByteNodeId(i=84))
Children of root are:  [Node(NumericNodeId(i=85)), Node(NumericNodeId(i=86)), Node(NumericNodeId(i=87))]
myvar is:  Node(NumericNodeId(ns=2;i=2))
myobj is:  Node(NumericNodeId(ns=2;i=1))
```

# 動作確認（その2）
サーバーの値を読み書き。

サーバー側ソースコード（server-minimal.pyを一部改変しserver-minimal2.pyとする）

```py:server-minimal2.py
import sys
sys.path.insert(0, "..")
import time


from opcua import ua, Server


if __name__ == "__main__":

    # setup our server
    server = Server()
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")

    # setup our own namespace, not really necessary but should as spec
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # get Objects node, this is where we should put our nodes
    objects = server.get_objects_node()

    # populating our address space
    myobj = objects.add_object(idx, "MyObject")
    myvar = myobj.add_variable(idx, "MyVariable", 3535, ua.VariantType.UInt16)
    myvar.set_writable()    # Set MyVariable to be writable by clients

    # starting!
    server.start()

    try:
        while True:
            time.sleep(1)
    finally:
        #close connection, remove subcsriptions, etc
        server.stop()
```

サーバー側を実行する。

```Console:server-minimal.py
$ python3.7 server-minimal.py
Endpoints other than open requested but private key and certificate are not set.
Listening on 0.0.0.0:4840
```

クライアント側ソースコード（client-minimal.pyを一部改変しclient-minimal2.pyとする）

```py:client-minimal2.py
import sys
sys.path.insert(0, "..")


from opcua import Client


if __name__ == "__main__":

    client = Client("opc.tcp://localhost:4840/freeopcua/server/")
    # client = Client("opc.tcp://admin@localhost:4840/freeopcua/server/") #connect using a user
    try:
        client.connect()

        # get a specific node knowing its node id
        var = client.get_node("ns=2;i=2")
        var.set_value(1234)
        print(var.get_value())
        var.set_value(5678)
        print(var.get_value())
        var.set_value(9999)
        print(var.get_value())
        #var.set_value(ua.Variant([23], ua.VariantType.Int64)) #set node value using explicit data type

    finally:
        client.disconnect()
```

別のcygwinターミナルを開き、クライアント側を実行する。
以下のように表示されたら成功。

```Console
$ python3.7 client-minimal2.py
1234
5678
9999
```

# 動作確認（その3）
証明書を使用したサーバーの値を読み書き。
サーバー側とクライアント側でセキュリティポリシーを合わせた場合、接続が成功し、値の読み書きが実行される。

サーバー側ソースコード(セキュリティポリシー設定部分のみ記載)
証明書はexampleフォルダ内に最初から格納されていたcertificate-example.der, private-key-example.pemを使用する。

```py
    # load server certificate and private key. This enables endpoints
    # with signing and encryption.
    server.load_certificate("certificate-example.der")
    server.load_private_key("private-key-example.pem")

    #セキュリティポリシー
#    server.set_security_policy([
#        ua.SecurityPolicyType.NoSecurity])

    server.set_security_policy([
        ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt])

#    server.set_security_policy([
#        ua.SecurityPolicyType.Basic256Sha256_Sign])

#    server.set_security_policy([
#        ua.SecurityPolicyType.NoSecurity,
#        ua.SecurityPolicyType.Basic256Sha256_Sign,
#        ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt])
```

クライアント側ソースコード（client-minimal.pyを一部改変しclient-minimal3.pyとする）
証明書はexampleフォルダ内に最初から格納されていたcertificate-example.der, private-key-example.pemを使用する。

```py:client-minimal3.py
import sys
sys.path.insert(0, "..")


from opcua import Client


if __name__ == "__main__":

    client = Client("opc.tcp://localhost:4840/freeopcua/server/")
    # client = Client("opc.tcp://admin@localhost:4840/freeopcua/server/") #connect using a user
#    client.set_security_string("Basic256Sha256,Sign,certificate-example.der,private-key-example.pem")
    client.set_security_string("Basic256Sha256,SignAndEncrypt,certificate-example.der,private-key-example.pem")
    try:
        client.connect()

        # get a specific node knowing its node id
        var = client.get_node("ns=2;i=2")
        var.set_value(1234)
        print(var.get_value())
        var.set_value(5678)
        print(var.get_value())
        var.set_value(9999)
        print(var.get_value())
        #var.set_value(ua.Variant([23], ua.VariantType.Int64)) #set node value using explicit data type

    finally:
        client.disconnect()
```

別のcygwinターミナルを開き、クライアント側を実行する。
以下のように表示されたら成功。

```Console
$ python3.7 client-minimal2.py
1234
5678
9999
```