はじめに
MH ソフトウェア&サービスのUDP通信を利用した、リモートターミナルの紹介です。
工場の制御機器や画像センサは、UDP出力に対応してる機器があります。
これらの機器から出力される信号を、リモートで監視できます。
UDPとは
User Datagram Protocolの略で、ウィキペディアより
TCPとは異なり、UDPはコネクションレス型であり、通信相手の応答を待つことなくデータを送り続けるプロトコルである。
TCPとは
Transmission Control Protocolの略です。コネクションします。つまり相手がいないと、エラーとなります。
UDPのメリット
あくまでも自分の感覚ですが、
1. TCPより全体の通信時間が短い
2. 相手がいなくても送信できるため、エラー処理が簡素化できる
3. 簡素化できるため、スマホでも送受信が簡単にできる
リモートターミナルRiT
Pythonを使用して作成されています。Pythonですので、WindowsPCやAndroidスマホで動作します。
もちろんMac環境、iPhone環境でも動くと思いますが、機器を持ち合わせておりませんので、未確認です。
GUIはtkinterです。
Windows Python 3.8.6
Android Pydroid 3 4.01_arm64
Pydroid 3では、アイコンが出ません。タイトルに日本語が使えません。設定があるのかもしれませんが、不明です。
アドバイス頂けますと、幸いです。
Raspberry Pi 4 と Kuman K82
サーマルカメラ(サーモ AI デバイス TiD) 紹介編で紹介しました、Physical Computing Lab / Raspberry Pi4 Model B DIYメタルケースにRaspberry Piを入れて、Kuman K82を差し込んだだけの、シンプルな構成です。
Rootクラス
Form初期化
class Root(mhtk.Form):
def __init__(self):
self.__version__ = __version__
self.root = self
self.ini = Ini(fullpath=__file__)
self.LANG = 'ja'
self.id_name = self.ini.udp.id_name
self.udp_port = self.ini.udp.port
self.destination = self.ini.udp.destination
minsize = (400, 180)
super().__init__(
dialog=True,
font=('system'),
icon=self.icon_file,
minsize=minsize,
name='main',
position=self.ini.get_geometry(
self.ini,
self.ini.config,
minsize),
title=(lambda: 'Remote Terminal'
if self.LANG == 'en' else 'Remote Terminal')(),
udp_port=self.udp_port,
)
# NOTE: Output Bit. This value is binary.
self.output = tk.IntVar(value=0)
self.output.trace('w', self.output_changed)
self.create_io()
self.menu = Menu(self)
self.indicator = Indicator(self)
self.indicator.pack(anchor=tk.CENTER)
# NOTE: Logo
self.logo = mhtk.IconFramePack(self)
self.logo.pack(anchor=tk.CENTER)
minsizeを指定して、サーマルカメラ(サーモ AI デバイス TiD) Python Form編で紹介しましたFormクラス(form.py)を使用しています。
I/O
create_ioで、GPIO用のクラス(mhrp.gpio)からI/Oを作成しています。
def create_io(self):
"""
for K82.
CH1 GPIO19 PIN35
CH2 GPIO26 PIN37
CH3 GPIO20 PIN38
CH4 GPIO21 PIN40
================
self.force_* value is
-1: Not forced.
0: Forced off.
1: Forced on.
"""
#self.input_list = [29, 31, 33, 35, 37]
#self.output_list = [16, 18, 32, 36, 38, 40]
self.input_list = [11, 13, 16, 18]
self.force_input = []
for _ in range(len(self.input_list)):
self.force_input.append(-1)
self.output_list = self.ini.config.output_io_list
self.force_output = []
for _ in range(len(self.output_list)):
self.force_output.append(-1)
self.io = mhrp.gpio.IO(
'PIN',
self.input_list,
self.output_list,
mhrp.gpio.BOTH,
)
self.io.input.bin.trace('w', self.io_callback)
mhrp.gpio -> input/outpu.py -> bit.py
mhrpはMH ソフトウェア&サービスのRaspberry Pi用のライブラリです。
この中には、input/output.pyから各クラスがインスタンス化されます。
さらにinput/output.puは、bit.pyのBitクラスをインスタンス化しています。
bit.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tkinter as tk
class Bit(list):
def __init__(self, count, callback):
self._count = count
self._callback = callback
for bit in range(count):
self.append(tk.BooleanVar(value=False))
self[bit].trace('w', self.BitChanged(bit, self._bit_changed))
def _bit_changed(self, *args):
self._callback(*args)
class BitChanged():
def __init__(self, index, callback):
self._index = index
self._callback = callback
def __call__(self, *args):
self._callback(self._index)
Bitクラスはlistを継承しています。
入力・出力の数だけlistにBitChangedをインスタンス化し、追加します。
各BitChangedクラスは、自分が何番目かのindexを持っています。オン/オフが切り替わった場合、callback関数を実行します。
tkinterの trace 最強!
MH ソフトウェア&サービスでのPython GUIは、主にtkinterとなっています。
変数が変わった時に、関数を実行できる.traceがあります。
bit.py内で
self[bit].trace('w', self.BitChanged(bit, self._bit_changed))
があります。
self._bit_changedは、self.BitChanged(bit, self._bit_changed)の部分で、インスタンス化されて、trace属性が付きます。
これはbitが変更された時、self.bit_changedが実行されます。
self._bit_changedはBitChangedクラスで、call_によりインスタンスを関数の様に実行する事が出来ます。
class BitChanged():
def __init__(self, index, callback):
self._index = index
self._callback = callback
def __call__(self, *args): # ここが実行されます
self._callback(self._index)
単純なクラスですが、インスタンス化時に自分のビットとコールバック関数を覚えておいて、ビットが変更になったら、ビットをinput/output.pyへ戻すという感じです。
その他、traceは文字変数でも可能です。
YouTube: リモートターミナル RiT
web: RiT リモートターミナル (URLが変更されました)