5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

たけびしDxpSERVER向けOPC-UAクライアントを書いてみた

Last updated at Posted at 2021-07-20

たけびしDxpSERVERのOPC-UAクライアントのサンプルを作ることになったので、手順を記録しておく。

1. 使用環境

デモ版が上記サイトからダウンロード可。OPC-UAも利用可。

2. OPC-UAサーバ設定

2-1. 共通プロパティ

**ツール(T)>オプション(O)**で、共通プロパティタブを表示する。

dxp6_property.png

OPC UAサーバー設定を有効にする。アプリケーションを再起動するように促されるので、再起動する。

2-2. UAサーバー設定

共通プロパティタブのOPC UAサーバー設定の右側に...が表示されているところをクリックすると、UAサーバー設定のダイアログが表示される。

dxp6_uaprop.png

  • UAサーバー使用
  • Anonymous接続の許可
  • セキュリティポリシー/セキュリティモード:None

にチェックが入っていること。

2-3. タグの追加

dxp6_tag.png

プロジェクトエクスプローラからSYSTEMポートを選択して、タグを追加する。
タグの追加は プロジェクト(P)>新規作成(N)>タグ(T) で行う。

ここでは、以下の3つのタグを作っておく。

No. タグ名 データ型 サイズ
1 value_string STRING 32
2 value_long Long 1
3 value_float Float 1

注意事項:

  • STRINGのサイズはデフォルトで1なので、そのままでは1文字しか保持できない
  • 一度タグを設定してからサイズだけ変更すると、後続のタグのアドレス位置が移動いないので、領域を上書きされる場合がある(これでハマった)

2-4. プロジェクトの保存

**ファイル(F)>保存(S)**でプロジェクトを保存する。ここでは OPCUA_sampleで保存する。

3. OPC-UAクライアント

3-1. OPC-UAサーバーの設定

DxpSERVER v6のデフォルト設定は以下の通り。

No. 項目名 デフォルト値 内容
1 HOST - DxpSERVERのIPアドレス文字列。localhostも可。
2 PORT 52240 ポート番号
3 PATH (空文字列) end_pointのパス
4 URI urn:Takebishi:DxpOpcUaServer:customprovider 名前空間のURI

上記の設定値から、OPC-UAのアクセス先を示すend_pointは以下の文字列で設定する。

end_point = f'opc.tcp://{HOST}:{PORT}{PATH}'

3-2. パッケージのインストール

asyncuaパッケージをインストールしておく。

$ pip install asyncua

3-3. サンプルプログラム

以下に示す。

dxp6_client.py
import asyncio
from asyncua import Client, ua

# for v5
# URI = 'http://takebishi.co.jp/DeviceXPlorer5/UA'
# PORT = 52210

# for v6
URI = 'urn:Takebishi:DxpOpcUaServer:customprovider'
PORT = 52240

# local machine
HOST = 'localhost'
PATH = ''

OBJ = 'SYSTEM'  # オブジェクト名はプロジェクト直下のポート名と対応


async def main():
    end_point = f'opc.tcp://{HOST}:{PORT}{PATH}'

    try:
        async with Client(url=end_point) as client:
            """
            # URI一覧を表示
            print('[URI List]')
            for uri in await client.get_namespace_array():
                print(uri)
            print()
            """

            # ノードのread/write
            idx = await client.get_namespace_index(URI)
            node1 = client.get_node(f'ns={idx};s={OBJ}.value_string')
            node2 = client.get_node(f'ns={idx};s={OBJ}.value_long')
            node3 = client.get_node(f'ns={idx};s={OBJ}.value_float')

            print('[Read]')
            print(node1.nodeid, ':', await node1.read_value())
            print(node2.nodeid, ':', await node2.read_value())
            print(node3.nodeid, ':', await node3.read_value())
            print()

            # DxpSERVERだとこの形式が未サポート
            # await node1.write_value('HELLO')

            # Write
            # DataValueでset_valueを使用する
            print('[Write]')
            dv1 = ua.DataValue(ua.Variant(u'HELLO', ua.VariantType.String))
            await node1.set_value(dv1)
            dv2 = ua.DataValue(ua.Variant(123, ua.VariantType.Int32))
            await node2.set_value(dv2)
            dv3 = ua.DataValue(ua.Variant(9.8, ua.VariantType.Float))
            await node3.set_value(dv3)
            print()

            print('[Read]')
            print(node1.nodeid, ':', await node1.read_value())
            print(node2.nodeid, ':', await node2.read_value())
            print(node3.nodeid, ':', await node3.read_value())
            print()

    except Exception as e:
        print(e)
        exit()


if __name__ == '__main__':
    asyncio.run(main())

read/writeについては、ここで示した方法で動作することを確認した。

3-4. コードについて補足

コメントにも書いているので、察した方もいらっしゃるかも知れませんが補足しておきます。

  • URIのリストはclient.get_namespace_array()で取得できる
  • node.write_value()で書き込みができたOPC-UAサーバーもあるが、DxpSERVERではDataValueをnode.set_value()で設定する方法しか確認できなかった
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?