概要
KEYENCE社のハンディターミナルで使用するスクリプト言語(SCPファイル)について、簡単にまとめました。
目次
SCPファイルとは
キーエンスのハンディターミナル専用のスクリプト言語で処理が記述されたファイルのことです。画面遷移、入力項目、バーコード読み取り処理、条件分岐などの業務ロジックが含まれています。
元々、初期のBTシリーズ(BT-500/900など)はC言語による開発が中心でした。ただ現場での簡易カスタマイズ需要から「スクリプト言語」が導入されました。
SCPファイル無しでもHTは動くのか
SCPファイルが全くなくても「ハードウェアとしての基本機能」は搭載されていますので、起動はできます。ただ業務処理はほぼできません。
SCPが担う部分としては、サーバー連携やファイル転送などの複雑な部分以外にも、基本的な業務ロジック(どの画面を表示するか、どのキーで次に進むか、画面レイアウトや入力チェックなど)も含まれています。そのため、HTを業務で使用する場合は、ほぼ必ずSCPファイルを使用してスクリプトを組む必要があります。
HTの種類
KEYENCE社のHTは、大きく分けて次の3系統に分かれます。Windows搭載モデルと超小型モデルはSCPスクリプトに対応していますが、AndroidモデルはSCPスクリプトには対応していません。ただAndroidモデルは別の手法で処理を実装できるようになっています。
Windowsモデル
OSにWindows CEを使用しているモデルです。
Windows CEとは組み込み機器向けの軽量版Windowsのようなイメージで、普通のWindows(PC用)より機能を絞っていて、メモリやCPUが小さい機器でも動くようになっています。ハンディターミナルは 省電力・安定性重視なので、軽量OSが必要になってきます。Windows CEはすでにMicrosoftのサポートが終了していて、今後はAndroidなどへの移行が推奨されており、新品販売はほぼ終了しています。
- BT-W300/W200シリーズ:高速オートフォーカス、OCR対応
- BT-W100シリーズ:片手操作+大画面
- BT-W80シリーズ:長時間稼働モデル
- BT-W70シリーズ:超軽量モデル
Androidモデル
OSにAndroidを使用しているモデルです。ほかのモデルよりも少し高額ですが、価格帯は幅広いです。
scpスクリプトは使用できませんが、JavaやKotlinを使用してAndroidアプリとして開発可能です。KEYENCEが提供しているSDKを使用して、バーコード読取、通信、端末制御(ブザー、LEDなど)も実装できます。また、Smart Browser(HTML+JavaScript)を使用して、Web技術で画面・ロジックを構築できるので、サーバ連携やクラウド対応も容易です。さらにノーコードツール(Biz/Browserなど)も使用できます。Androidモデルでも、
- BT-A2000/A1000シリーズ:3眼カメラ+AI搭載、高速読み取り
- BT-A500シリーズ:グリップ型、耐久性重視
- BT-A700シリーズ:フルレンジ読み取り(最短2.5cm~最長10m)
Androidモデルでも、従来SCPでやっていた処理はすべて対応可能です。
専用OSモデル
キーエンス独自の専用OS(BT-OS)を搭載しているモデルです。SCPスクリプトに対応しています。旧世代なので新品ではほぼ手に入らないですが、中古で比較的安価で手に入ります。
- BT-1000シリーズ:コンパクトで軽量
- BT-600シリーズ:カードレス運用などに対応
SCPスクリプトの今後
SCPは専用OSモデルやWindows CEモデル専用の開発手段なので、Androidモデルでは使えません。そのため、SCPは新規の開発手段としては縮小傾向にあります。なので今後は Android SDK(Java/Kotlin)、Webベース(HTML+JS)、ノーコードツールが主流になると思われます。一方、既存で使用されているものは保守や運用でまだまだ現役のものも多く、プロジェクトによっては継続的に使用されています。
HTの容量
機種によって異なりますが、HTの容量について、一般的な目安は以下になります。
Androidモデル
内蔵ストレージ:16GB~64GB(アプリ+データ+OS)、SDカード対応あり
Windowsモデル
内蔵フラッシュ:約 256MB~1GB、RAMは128MB~512MB程度
専用OSモデル
内蔵フラッシュ:約 32MB~128MB(業務データ+アプリ用)
専用OS → Windows → Androidの順に容量が大きくなっています。
フォルダ構成
専用OSやWindowsモデルの場合、以下の構成が多いです。
¥FlashDisk¥ ← 内蔵フラッシュ領域(アプリ・データ保存)
├─ App¥ ← アプリ本体(SCPスクリプトなど)
├─ Data¥ ← 業務データ(CSV、マスタファイル)
├─ Log¥ ← ログファイル
└─ Config¥ ← 設定ファイル(INIなど)
¥System¥ ← OS関連ファイル(触らない)
¥FlashDisk¥はユーザーが自由に使える領域です。なので、SCPスクリプトで指定するパスはこの中が基本になります。
Androidモデルの場合は上記とは異なるフォルダ構成をしています。AndroidモデルはスマートフォンOSをベースにしているため、Linux系のディレクトリ構造を持っています。
Androidモデルでは、業務アプリはLinux上のディレクトリ群の専用ディレクトリ(/Android/data/...) を使うのが基本になってきます。
また、SDKやノーコードツールで開発する場合もディレクトリの中の決まったストレージ領域にデータを保存します。
HTの画面とSCPコードの関係
HTの画面も基本的にSCPのコードで描画します。以下のサンプルコードでも出てきますが、Screen.Clear() や Screen.Print() で画面を構築し、Handy.Input()やHandy.KeyWait() で入力を受け取るのが基本的な流れになります。
そのため、画面遷移もコードで制御し、画面は完全にコードで描画します。
以下サンプルにも出てきますが、画面内で選択できる項目もコードで表示し、キー入力で分岐させるのが基本です。
SCPファイルのサンプルコード
BT‑W/BT‑500のSCPファイルのサンプルコードをいくつか示します。
サンプルコード1:「Hello」表示+キーで終了
- 画面に「HELLO WORLD」と表示
- ユーザーが何かキーを押すまで待つ
- 終了前にブザーを鳴らす
#--------------------------------------------
# 画面にメッセージを表示して、任意キーで終了
#--------------------------------------------
begin
# 画面クリア&メッセージ表示
Screen.Clear()
Screen.Print(1, 1, "HELLO WORLD")
# 何かキーが押されるまで待機(押されたキーコードを返す)
key = Handy.KeyWait() # ←BT-1000/600系ではこの書き方、BT-3000系ではイベント型(Key.onPress)を使う
# 終了前にブザーを鳴らす
Handy.Beep()
end
コメントアウト
コメントアウトは#で記載します
プログラムの開始と終了
begin ~ endでプログラムの開始と終了を示します。begin から end の間に処理を書くのが基本になります。
コントロール
ScreenやHandyなどはコントロール(.NETならクラスのようなイメージ)と呼ばれ、それぞれにメソッドやプロパティがあります。ただクラスではないので、オブジェクトをnewすることはできません。固定のコントロール名を指定して、その中のメソッドを呼ぶイメージです。
コントロールはHT端末にSCPのランタイムとして標準で組み込まれており、このランタイムが、標準API(コントロール+メソッド群)を提供しています。なのでこのように呼び出すことができます。
サンプルコード2:バーコード読取 → CSVへ追記 → 送信待ち
- 1件のバーコード(またはQR)を読み取る
- 読み取った文字列の先頭3文字も作って
- CSVファイルに追記
- 完了音を鳴らしてメッセージ表示
- キーが押されたら終了
#--------------------------------------------
# バーコードを1件読取し、CSVに追記
#--------------------------------------------
begin
# 読取を促すメッセージ
Screen.Clear()
Screen.Print(1, 1, "Scan a code...")
# バーコード/QRを1件読取(読み取った文字列を取得)
code = Handy.Read()
# 文字列の一部抜き出し例(先頭3桁)
head3 = Left(code, 3) # 文字列関数
# 必要なら Mid/Right も使用可
# ローカルCSVへ追記
File.Open("¥FlashDisk¥data¥log.csv", "append")
File.Write(code + "," + head3 + "," + System.Now())
File.Close()
# 成功音とメッセージ
Handy.Beep()
Screen.Print(3, 1, "Saved. Press any key to exit.")
Handy.KeyWait()
end
スキャン待ち
code = Handy.Read()はスキャンを1回実行し、読み取った文字列(バーコード内容)を変数codeに入れています。
ここでアプリはスキャン待ちになります。トリガーキーを引く/自動読取など機種設定に従って読み取りを行い、成功すると文字列が返り、以降の処理が実行されるイメージです。
読み取りに失敗した場合の戻り値の扱い(空文字やエラー)は機種・設定で変わることがあります。実運用では戻り値のチェックを行い、再読取ループなど読み取り失敗時の対応を付けると安全です。
文字取り出し
Left(文字列, 桁数)で、文字列の左側(先頭)から指定桁数を取り出しています。
他にも、以下のように文字抽出ができます。
code = "ABCD1234"の場合
Left(code, 3) → "ABC"
Mid(code, 5, 2) → "12"(5文字目から2文字)
Right(code, 4) → "1234"
ファイルを開く
File.Open(パス, モード)で指定したモードでファイルを開きます。appendは既存の末尾に行を追加する追記モードです。
ファイルに文字を書く
File.Write(文字列)で一行分の文字を書き込みます。ここではCSV形式なので、区切りごとに,を入れています。
複数行に渡って文字を書く場合は、以下のように対応できます。
方法1:改行コードを入れる
File.Write("AAA,BBB,CCC" + Chr(13) + Chr(10) + "DDD,EEE,FFF")
- Chr(13) = キャリッジリターン(CR)
- Chr(10) = ラインフィード(LF)
Windows系の改行は CR+LF なので、この組み合わせで改行できます。
方法2:File.Write()を複数回呼び出す
File.Write("AAA,BBB,CCC")
File.Write("DDD,EEE,FFF")
ファイルを閉じる
File.Open()をした後は、File.Close()で必ず閉じるのが基本です。
サンプルコード3:別スクリプトへの引数付き遷移(最大4つ)
別の画面へ遷移する(別のスクリプトへ遷移する)時に、値を最大4つまで渡しています。
.scpファイル=画面という“完全な1対1”の縛りはありませんが、「1画面=1スクリプト」設計にすると見通しと保守性が高くなるので、実務ではこの単位で切ることが多いです。
※1つの .scp内で複数画面相当の表示を切り替えることも理屈上は可能です。
#--------------------------------------------
# 別スクリプトへの引数付き遷移(最大4つ)
#--------------------------------------------
begin
Screen.Clear()
Screen.Print(1, 1, "Input Item Code:")
# ユーザーからの入力を受け取り、変数 item に入れる
item = Handy.Input() # 入力ウィジェットの例
# 次のスクリプト「detail.scp」を呼出(最大4引数)
System.Load("detail.scp", item, "MODE1", 1, "USERA")
end
Handy.Input()もサンプルコード2のHandy.Read()のように、ユーザーからのアクションがあるまでここで処理待ちになります。
Handy.Input()はユーザーの文字列入力を受け付ける関数で、数字だけでなく、アルファベットや記号なども受付できます。ユーザーが確定キーを押すまで、文字列を受け付けているイメージです。
サンプルコード4:入力値を次の画面(別スクリプト)へ渡す
#--------------------------------------------
# 入力値を次の画面(別スクリプト)へ渡す
#--------------------------------------------
begin
Screen.Clear()
Screen.Print(1,1,"1: 商品登録")
Screen.Print(1,2,"2: 商品検索")
Screen.Print(1,3,"3: 終了")
key = Handy.KeyWait() # ユーザーがキー入力
if key == 1 then
System.Load("register.scp")
elseif key == 2 then
System.Load("search.scp")
else
System.End() # アプリ終了
end
end
数字キーでメニュー番号を選び、押されたキーの番号に応じて System.Load(...) で別スクリプトに画面遷移しています。
こちらのHandy.KeyWait()はサンプルコード3のHandy.Input()と違い、1度のみキー受付を対応している関数です。数字以外にも受け付けていますが、いずれにせよ一度の入力で処理待ちが解放されます。
サンプルコード5:HTの上下キーでの項目選択
Screen.Print()で作った画面は「ただのテキスト表示」なので、HTの上下キーでの選択はできません。そのため、自分で上下キーの入力を検知して、選択位置を更新し、再描画する必要があります。つまり、疑似的な選択カーソル(例:「→」やハイライト記号)を使って、再描画しつつ上下に動いているという形を作成していきます。
上下キーがあるHTでも、標準では選択機能はないので、コードで実装する必要があります。
以下のサンプルでは、画面に「1: 商品登録 / 2: 商品検索 / 3: 終了」を表示し、上下キーで選択位置(カーソル)を移動させています(再描画)。
ENTキーが押されると選択している項目を確定し、
1なら register.scp へ、
2なら search.scp へ、
3ならアプリ終了(System.End()
としています。
#--------------------------------------------
# 入力値を次の画面(別スクリプト)へ渡す
#--------------------------------------------
begin
selected = 1 # 初期選択位置
options = 3 # メニュー項目数
# 無限ループで選択操作を受け付け続ける設計
while true
# 毎回画面をクリア
Screen.Clear()
# 行ごとのプレフィックスを決定(→ / 空白)
prefix1 = " "
prefix2 = " "
prefix3 = " "
if selected == 1 then
prefix1 = "→ "
elseif selected == 2 then
prefix2 = "→ "
elseif selected == 3 then
prefix3 = "→ "
end
# 描画
Screen.Print(1, 1, prefix1 + "1: 商品登録")
Screen.Print(1, 2, prefix2 + "2: 商品検索")
Screen.Print(1, 3, prefix3 + "3: 終了")
key = Handy.KeyWait()
if key == UP then
selected = (selected == 1 ? options : selected - 1)
elseif key == DOWN then
selected = (selected == options ? 1 : selected + 1)
elseif key == ENT then # ENTキーが押されたらループを抜ける
break
end
end
# 選択結果で遷移
if selected == 1 then
System.Load("register.scp")
elseif selected == 2 then
System.Load("search.scp")
else
System.End()
end
end
注意点
記事のサンプルは、BT‑W/BT‑500シリーズでよく使われる記法で、ジョブ単位のシンプルな構成で書けるのが特徴です。
Windows CE搭載モデルの後期世代で採用されたスクリプトはPackage/Method、Include、Catch、//コメント、Screen:Clear()など書き方が少し異なるので、要注意です。
※書き方は異なりますが、言語仕様の根本的な違いではなく、ランタイムの世代差によるものです。