OMRON FINS UDP communication library
Project description
OMRONの通信プロトコルのFINSコマンドをpythonで送る
FINSコマンドはメッセージサービス用の通信コマンドでPC-PLC間やPLC-デバイス間で使用されています ここではpythonを使ってEthernetでPLCとメッセージ通信するクラスを作りました
環境
Windows10
python3.9
PLC OMRON CJ/NJ/NX series
ファンクション一覧
| メソッド名 | 内容 |
|---|---|
| read | メモリエリアの読み出し |
| write | メモリエリアへ書き込み |
| fill | メモリエリアの一括書き込み |
| run | 動作モード切り替え |
| stop | プログラムモードに切り替え |
| ReadUnitData | CPUユニット情報の読出し |
| ReadUnitStatus | CPUユニットステータスの読出し |
| ReadCycletime | サイクルタイム読出し |
| Clock | 時間情報の読出し |
| SetClock | 時間情報の書込み |
| ErrorClear | 異常解除 |
| ErrorLogRead | 異常履歴の読出し |
| ErrorLogClear | 異常履歴のクリア |
| SendCommand | その他のFINSコマンドを送信 |
使い方
オブジェクトの作成 fins(IPAddress, 相手FinsAddress, 自分FinsAddress, timeout)
finsudp = fins('192.168.250.1', '0.1.0', '0.10.0', 2)
finsクラスは通信相手のIPアドレス, 相手のFINSアドレス, 自分のFINSアドレスを指定してオブジェクトを作ります
FINSアドレスを省略すると相手のIPアドレスの下1桁の数値をノードとして相手先FINSアドレスとします
timeoutは指定しなければデフォルト2秒です
FINSアドレスとは 「FINSネットワークアドレス . ノードアドレス . 号機アドレス」の3つの数字を . (ドット)でつなぎます ネットワークアドレスは直接接続することを想定して 0 (自ネットワーク)にしています ノードアドレスはIPアドレスの一番下の数値と合わせて受信側(PLC)は 1 を、送信側(PC)はIPアドレスは192.168.250.10としているので 10 としています 号機アドレスは 0 (CPU宛て)とします
read(address, num)
# E0_30000から10CH読出し
data = finsudp.read('E0_30000', 10)
上で作ったオブジェクトのreadメソッドでアドレスとCH数を指定して値を読み出します アドレスはCIOは000、DMはD0、EMはE0_0、WRはW0のように指定します 読み出したデータはバイト列(bytes)で受け取ります
write(address, data)
# E0_0からdataを書込み
rcv = finsudp.write('E0_0', data)
writeメソッドでアドレスと書き込みデータを渡して書き込みます 書き込みデータdataはバイト列(bytes)で渡します
fill(address, num, data)
# D110から10CH分(D110-119)に55を書込み
rcv = finsudp.fill('D110', 10, 55)
連続したメモリエリアに同一のデータを書き込みます
multiRead(addresses)
# 複合読出し D1000,D1010,D1020
data = finsudp.multiRead('D1000, D1010, D1020')
メモリエリアの複合読出し
run(mode)
# 動作モード切り替え (0x02=Monitor 0x04=Run)
rcv = finsudp.run(0x02)
stop()
# プログラムモードに切り替え
rcv = finsudp.stop()
ReadUnitData()
# CPUユニット情報の読出し
rcv = finsudp.ReadUnitData()
レスポンス内容
| byte数 | 4 | 20 | 20 | 40 | 12 |
|---|---|---|---|---|---|
| 内容 | 05 01 00 00 | CPUユニットの形式 | システムバージョン | システム情報 | エリア情報 |
ReadUnitStatus()
# CPUユニットステータスの読出し
rcv = finsudp.ReadUnitStatus()
レスポンス内容
| byte数 | 4 | 1 | 1 | 2 | 2 | 2 | 2 | 16 |
|---|---|---|---|---|---|---|---|---|
| 内容 | 06 01 00 00 | 運転状態 | 動作モード | 運転停止異常情報 | 運転継続異常情報 | メッセージ有無 | 故障コード | 異常メッセージ |
ReadCycletime()
# サイクルタイム読出し
rcv = finsudp.ReadCycletime()
レスポンス内容
| byte数 | 4 | 4 | 4 | 4 |
|---|---|---|---|---|
| 内容 | 06 20 00 00 | 平均 | 最大 | 最小 |
Clock()
# 時間情報の読出し
rcv = finsudp.Clock()
レスポンス type:datetime.datetime
SetClock(datetime)
# 時間情報の書込み(PCの時間を書込み)
rcv = finsudp.SetClock(datetime.now())
ErrorClear()
# 異常解除
rcv = finsudp.ErrorClear()
発生中の異常を解除
ErrorLogRead()
# 異常履歴の読出し 最新10件
rcv = finsudp.ErrorLogRead()
レスポンス内容
| byte数 | 4 | 2 | 2 | 2 | 10 | ... | 10 |
|---|---|---|---|---|---|---|---|
| 内容 | 21 02 00 00 | レコード最大数 | 格納数 | 読出しレコード数 | 異常履歴データ | ... | 異常履歴データ |
ErrorLogClear()
# 異常履歴のクリア
rcv = finsudp.ErrorLogClear()
SendCommand()
cmd = bytearray([0x05,0x01])
rcv = finsudp.SendCommand(cmd)
FINSコマンドを直接送信するメソッドです
データ変換
print (finsudp.toInt16(data))
受け取ったデータのバイト列(bytes)を変換するためのメソッド バイト列のデータがどのようなデータかによってメソッドが変わります
| メソッド名 | 変換するデータの長さ |
|---|---|
| toBin | ビット列 |
| WordtoBin | 16ビット単位のビット列 |
| toInt16 | 16bit数値 |
| toUInt16 | 16bit符号なし |
| toInt32 | 32bit数値 |
| toUInt32 | 32bit符号なし |
| toInt64 | 64bit数値 |
| toUInt64 | 64bit符号なし |
| toFloat | 浮動小数点 |
| toDouble | 倍精度 |
| toString | 文字列 |
サンプル
# Sample
# インスタンス作成
# NXではポート2を使用
finsudp = fins('192.168.251.1') #接続先IPアドレス, 接続先FINSアドレス, 自分FINSアドレス, タイムアウト(2s)
# 0CHから1CH分読出し ビット表記
data = finsudp.read('0', 1)
print(finsudp.toBin(data)) # ゼロサプレス表記
print(finsudp.WordToBin(data)) # ゼロ埋め表記
print(list(finsudp.WordToBin(data))) # ゼロ埋めのリスト
# W0から2CH分読出し ビット表記
data = finsudp.read('W0', 2)
print(finsudp.toBin(data))
print(finsudp.WordToBin(data))
print(list(finsudp.WordToBin(data)))
# H0から4CH分読出し ビット表記
data = finsudp.read('H0', 4)
print(finsudp.toBin(data))
print(finsudp.WordToBin(data))
print(list(finsudp.WordToBin(data)))
# D1000を読出し ビット表記
data = finsudp.read('D1000', 1)
print(finsudp.toBin(data))
print(finsudp.WordToBin(data))
print(list(finsudp.WordToBin(data)))
# D1001を読出しINT
data = finsudp.read('D1001', 1)
print(finsudp.toInt16(data))
# D1002-D1003を読出しDINT
data = finsudp.read('D1002', 2)
print(finsudp.toInt32(data))
# D1004-D1007を読出しLINT
data = finsudp.read('D1004', 4)
print(finsudp.toInt64(data))
# D1008を読出しUINT
data = finsudp.read('D1008', 1)
print(finsudp.toUInt16(data))
# D1009-D1010を読出しUDINT
data = finsudp.read('D1009', 2)
print(finsudp.toUInt32(data))
# D1011-D1014を読出しULINT
data = finsudp.read('D1011', 4)
print(finsudp.toUInt64(data))
# D1015-D1016を読出しFLOAT
data = finsudp.read('D1015', 2)
print(finsudp.toFloat(data))
# D1017-D1020を読出しDOUBLE
data = finsudp.read('D1017', 4)
print(finsudp.toDouble(data))
# D1021-D1025を読出しDOUBLE
data = finsudp.read('D1021', 5)
print(finsudp.toString(data))
# D1100から10CH分のデータを読出し
data = finsudp.read('D1100', 10)
print(finsudp.toUInt16(data))
# E0_0から上で読み出したデータを10CH分を書込み
rcv = finsudp.write('E0_0', data)
print(rcv)
# D1000から1000CH分に連番を書込み
l = list(range(1000))
writedata = list()
for num in range(1000):
writedata.extend(list(int(l[num]).to_bytes(2,'big')))
rcv = finsudp.write('D1000', writedata)
print(rcv)
# D110から10CH分に55を書込み
rcv = finsudp.fill('E0_100', 10, 55)
print(rcv)
# 複合読出し D1000,D1010,D1020
data = finsudp.multiRead('D1000, D1010, D1020')
print(finsudp.toUInt16(data))
# CPUユニット情報の読出し
rcv = finsudp.ReadUnitData()
print(rcv)
# CPUユニットステータスの読出し
rcv = finsudp.ReadUnitStatus()
print(rcv)
# 時間情報の読出し
rcv = finsudp.Clock()
print(rcv)
# 時間情報の書込み(PCの時間を書込み)
rcv = finsudp.SetClock(datetime.now())
print(rcv)
# 以下CJのみ
isCJ = False
if isCJ:
# モニタモードに切り替え (0x02=Monitor 0x04=Run) (NJ/NXは非対応)
rcv = finsudp.run(0x04)
print(rcv)
# プログラムモードに切り替え (NJ/NXは非対応)
rcv = finsudp.stop()
print(rcv)
# サイクルタイム読出し (NJ/NXは非対応)
rcv = finsudp.ReadCycletime()
print(rcv)
# 異常解除
rcv = finsudp.ErrorClear()
print(rcv)
# 異常履歴の読出し 最新10件
rcv = finsudp.ErrorLogRead()
print(rcv)
# 異常履歴のクリア
rcv = finsudp.ErrorLogClear()
print(rcv)
# その他のFINSコマンドを送信するときはこちら
# 例)0x05 0x01 0x01 CPUユニット情報の読出し
cmd = bytearray([0x05,0x01])
rcv = finsudp.SendCommand(cmd)
print(rcv)
except Exception as e:
print(e)
説明サイト
https://osdes.com/python/plccomm/finscommand.html
Qiita記事
https://qiita.com/OkitaSystemDesign/items/7a958388d16c162148b2
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file finscommand-0.1.1.tar.gz.
File metadata
- Download URL: finscommand-0.1.1.tar.gz
- Upload date:
- Size: 13.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69f61517bf445575d23732c4606bbeb7a1ef0a7ff8d8f37048268cb89ae5c99a
|
|
| MD5 |
15caa661ceceea936a140a528a6a622c
|
|
| BLAKE2b-256 |
6e19820c3ecf7c65dded900aa403cc8888b3406635cfd006118901513e051936
|
File details
Details for the file finscommand-0.1.1-py3-none-any.whl.
File metadata
- Download URL: finscommand-0.1.1-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70f54cdf0781e636e784c146450c56f9423c932ced21311d441103d7d36c8d03
|
|
| MD5 |
2445a34b43246bad7c18fca953d233ed
|
|
| BLAKE2b-256 |
8faf9d9711f0469d7abb47a1926b4b93efa49a8d04c1771acc4aa5aa04601a36
|