今回の記事ではEXOR JMobile RuntimeのDirect Socket機能を使用し、非標準のProtocolとSocket通信する手順を説明します。
さ、FAを楽しもう!

前書き
いつも私の技術ブログとYouTubeチャンネルをご覧いただき、心より感謝申し上げます。また、いまFullさん(full@桜 八重 (@fulhause) / X)と共に毎週水曜日の夜にお届けしている「高橋クリス」ラジオ番組を運営しています。
技術は独り占めせず、届けるもの
私たちは工場の生産技術や制御に関する技術情報を、ブログや動画などで無料公開しています。「知識は誰でもアクセスできるべき」という信念のもと、現場で役立つ具体的なノウハウやトラブル事例などを発信してきました。すべて無料で続けているのは、「知らなかったせいで困る人」を少しでも減らしたいからです。
また、もしあなたの現場で…
- 「このPLCとデバイスの組み合わせ、ちゃんと動くのかな?」
- 「EtherCAT通信でうまくいかない部分を検証してほしい」
- 「新しいリモートI/Oを試したいけど社内に検証環境がない」
など、困っている構成や試してみたいアイデアがあれば、ぜひお知らせください。機器の貸出や構成の共有が可能であれば、検証し、記事や動画で発信します(ご希望に応じて匿名対応も可能です)。
支援のかたち
現在、私達の活動はほぼ無償で続けており、記事や動画の制作には、時間と検証環境の整備が必要です。この活動を継続的にコンテンツを提供するためには、皆様の温かいご支援が大変重要です。
メンバーシップ(ラジオの応援)
Fullさんとのラジオをより充実させるための支援プランです。
https://note.com/fulhause/membership/join
Amazonギフトリスト
コンテンツ制作に必要な機材・書籍をリストにしています。
https://www.amazon.co.jp/hz/wishlist/ls/H7W3RRD7C5QG?ref_=wl_share
Patreon(ブログ・動画活動への応援)
月額での小さなご支援が、記事の執筆・検証環境の充実につながります。
https://www.patreon.com/user?u=84249391
Paypal
小さな支援が大きな力になります。
https://paypal.me/soup01threes?country.x=JP&locale.x=ja_JP
知ってたら助かること、届けたいだけです
あなたの応援が、知識の共有をもっと自由で持続可能なものにしてくれます。これからもどうぞよろしくお願いします。
soup01threes*gmail.com
技術はひとりじゃもったいない。
Reference Link
http://soup01.com/ja/category/exor-ja/
Direct Socket?
Direct Socketプロトコルは、ソケット関数への低レベルアクセスを可能にする汎用プロトコルです。
このプロトコルを使用することで、アプリケーション自体は、専用のプロトコルを開発することなく、IPベースのプロトコルを実装することができます。
Direct Socketプロトコルは標準(タグインターフェース)プロトコルとして使用できますが、JavaScriptからプロトコルを利用できるようにするためのDoCommandインターフェースの適切な実装も用意されています。
このプロトコルは、クライアントソケットタイプでのみ使用可能です。
このプロトコルは、クライアントソケットを1つしかサポートしません。アプリケーションで多数のソケットが必要な場合は、このプロトコルがマルチインスタンスに対応しているため、複数のプロトコルをインストールすることができます。
Implementation1
最初にSuffix・PrefixなしのDirect Socket、つまり一番シンプルな検証をします。
Server Side
最初にRaspberrypi側から構築します。

Raspberrypiに簡単なTCPサーバを作成し、Python3で起動してください。
import socket
|
|---|
EXOR Side
次はEXOR側を構築します。

Protocol追加
JMobile Studioを起動し、Protocol→+で新規Protocolを追加します。

Drop-ListからDirect Socketを選択します。

プロトコルパラメータは、接続の確立方法やトークンの交換方法を定義します。これらのパラメータは通常、プロジェクトによって定義されます。多くのパラメータは変数としてもアクセスできるため、実行時に変更することが可能です。

Socket Type
通信に使用するソケットの種類。選択肢は UDP または TCP です。

Remote IP Address
文字列で、リモートデバイスのIPアドレスを示します。

Remote Port
整数でリモートデバイスが使用するポートを示します。

Local IP Address
文字列でローカルデバイスのIPアドレスを示します。UDPを使用する場合は必須です。

Local Port
整数でローカルデバイスが使用するポートを示します。UDPを使用する場合は必須です。

Broadcast Type
使用する放送の種類で選択肢は「グローバル」または「ローカル」です。

Rx Token Prefix
読み取りトークンのPrefixを、16進数で指定された文字列として示します。

Rx Token Suffix
読み取りトークンのSuffixを、16進数で指定された文字列として示します。

Token Gap
トークン間の間隔をミリ秒単位で示します。

Tx Token Prefix
Socketから送信されるトークンのPrefixを、16進数で指定された文字列として示します。

Tx Token Suffix
送信されたトークンのSuffixを、16進数で指定された文字列として示します。

Hexadecimal Tokens
- チェック済み = トークンが16進数である
- 未チェック = トークンが16進数ではない

Token Queue Size
キュー内のトークンの数を、1 から 10000 までの整数値で示します(デフォルト:100)。

結果
それでDirect Socketを作成しました。

Tag作成
次はTagsをクリックします。

下図のようにDirect Socketに使う変数を全部宣言します。

画面
最後に下図のようなDirect Socket操作画面を作成します。

結果
最初にRemote IP address・Remote PortをServer側に合わせて設定します。

Connect変数に1を入力し、HMI→Serverに接続します。

HMIとServerの間接続OKならConnection Status=1です。

Server側にも接続されたログが表示されました。

次はToken To Sendに文字列を入力しましょう。

Done!Token Received欄からServerの返答が格納されました。

Server側でもデータの送受信を確認できました。

Implementation2
次はPrefixとSuffix機能も試してみましょう。
Socket通信でPrefix(接頭辞)とSuffix(接尾辞)を使う最大の理由は、「データの区切り(デリミタ)を明確にして、データの断片化や結合を防ぐため」です。
TCPによるSocket通信は、データを「ストリーム」として扱います。そのため、送信側が「こんにちは」と「さようなら」という2つのメッセージを送っても、受信側ではこんにちはさようならとくっついて届いたり、こんとにちはさようならに分裂して届いたりします(これをパケットの断片化・結合と言います)。
これを正しく1つのメッセージとして切り出すために、PrefixやSuffixが活躍します。
Suffix(接尾辞)の使い方
データの後ろに特定の終了合図をくっつける方法です。
- 何を使うか: 主に \n(改行コード)、\r\n(CRLF)、または \0(ヌル文字)などの固定のバイトデータ。
- どう機能するか: 受信側は、データを読み込みながら「終了合図(例:\n)が来るまで待つ」という処理をします。
Prefix(接頭辞)の使い方
データの前に、これから送る「データの長さ(バイト数)」などをあらかじめ書いておく方法です。
- 何を使うか: データの長さを表す固定バイト(2バイトや4バイトの整数)。
-
どう機能するか:
- 受信側は、まず先頭の数バイト(Prefix)だけを読み込んで「あ、次に続くデータは100バイトなんだな」と把握する。
- その後、正確に100バイト分だけデータを読み込む。
Server 側
最初にRaspberrypi側から構築します。

こちらは改造したPython TCP Serverのスクリプトです。
import socket
|
|---|
結果
TCP Serverを起動します。

PrefixとSuffixを41と5aに設定します。

次はToken To Sendに文字列を入力します。

次はToken Acknowledgeを1にします。

Done!ServerからA+返事+Zの文字列が返ってきました。

Server側でもデータの送受信を確認できました。

ダウンロード
こちらのLinkから今回の記事のプロジェクトをDownloadできます。
https://github.com/soup01Threes/JMobile/blob/main/JMobile_Tutorial_DirectSocket.zip