Raspberry PiでQtを使うUDPソケット通信 ~ QUdpSocket
スマートフォンからデータをRaspberry Piへ送る場合、UDPソケット通信を使う方法があります。これは以前の投稿でやっています。
以前の例では、Raspberry Piの受信プログラムがターミナル用でした。そこで今回はフォーム版で作ります。そしてフォーム版ということで、Qtを使います。
そのQtのプログラムですが、UDPソケットを扱うクラス「QUdpSocket」を使うことにしました。ターミナル版のロジックをそのまま使うと、いろいろ問題がありました。
それでは、プログラムを紹介します。
1.スマートフォン側プログラム
スマートフォン側のデータ送信を行うプログラムは、0から1000の数値をテキストでRaspberry Piに送ります。値はボタンの+ーで調節します。また、Raspberry PiのIPアドレスを入力します。
Androidmanifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
権限を加えてください
プログラム
public class MainActivity extends AppCompatActivity {
private EditText IpAddressInput ;
private final Handler handler = new Handler();
private String wkstr ;
private String clientIPAddress ;
private int power = 0 ;
private Button plusbutton ;
private Button minusbutton ;
private TextView powertext ;
public MainActivity() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
clientIPAddress = "192.XXX.XXX.XXX" ;
plusbutton = (Button) findViewById(R.id.plusbutton);
minusbutton = (Button) findViewById(R.id.minusbutton);
powertext = (TextView) findViewById(R.id.powertext);
IpAddressInput = (EditText) findViewById(R.id.ipaddress) ;
plusbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
power += 10;
if (power > 1000) {
power = 1000;
}
wkstr = String.valueOf(power);
powertext.setText(wkstr);
new Thread(new Runnable() {
@Override
public void run() {
try {
clientIPAddress = IpAddressInput.getText().toString() ;
DatagramSocket sendUdpSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName(clientIPAddress);
byte[] strByte = wkstr.getBytes("UTF-8");
DatagramPacket sendPacket = new DatagramPacket(strByte, strByte.length, IPAddress, 60000);
sendUdpSocket.send(sendPacket);
sendUdpSocket.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}).start();
}
});
// マイナスボタン処理は省略
}
}
UDPソケット通信は別スレッドで行うことに注意してください。
2.Raspberry Pi側プログラム
Raspberry Pi側のプログラムは、Qt Creatorを使って作成します。
フォーム
フォームエディタで画面を作成します。スマートフォンから送られてきたデータを表示するようにします。
プロジェクトファイル
QT += network
今回、QUdpSocketクラスを使うので、プロジェクトファイルに上記の記述を追加します。「QT += core gui」の行の下に追加すると良いでしょう。
ヘッダファイル
以下の記述をしました。説明はコメントにしています。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtNetwork/QUdpSocket>
#include <QDebug>
#define PORT_NUMBER 60000
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void udpupdate() ; // データを受信した時の関数
void on_pushButton_clicked(); // 終了ボタンが押された時
private:
Ui::MainWindow *ui;
QUdpSocket udpSocket; // QUdpSocketインスタンス
};
#endif // MAINWINDOW_H
ソースファイル
以下の記述をしました。QUdpSocketクラスのおかげで、すごく簡単なソースになりました。
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
udpSocket.bind( PORT_NUMBER );
connect( &udpSocket, SIGNAL( readyRead() ),
this, SLOT( udpupdate() ) );
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::udpupdate()
{
QByteArray byteArray;
QString recieveStr;
byteArray.resize( udpSocket.pendingDatagramSize() );
udpSocket.readDatagram( byteArray.data(), byteArray.size() );
ui->le_Power->setText(QString::fromUtf8(byteArray)) ;
}
void MainWindow::on_pushButton_clicked()
{
close() ;
}
3.スマートフォンでRaspberry Piをコントロールしよう!
今回、とても簡単にスマートフォンからRaspberry Piへデータを送ることができました。UDPソケットを使えば、スマートフォンをコントローラにしたRaspberry Piのシステムを簡単に実現できると思います。
ひとつ、Raspberry PiのIPアドレスを取得しなければなりませんが、今回フォームプログラム化したことでデスクトップが表示されているはずなので、IPアドレスの確認は簡単でしょう(Wi-Fiのアイコンにカーソルを置けば表示される)。
それに、スマートフォンのテザリング環境で動作させることを前提としているので、IPアドレスが変わることは少ないと思います。
今回のプログラムは、先に予定している投稿のシステムの一部になります。よろしくお願いします。