GUIで操作できるRaspberry PiのGPIO監視モニタープログラムをJavaで作ってみた

2020年12月31日

最近ラズパイ使って遊んでいるのですが、テストでいちいちPythonプログラム流したりコマンド使ったりするのが面倒になってきたので、WindowsからラズパイのGPIOの状態を監視、操作できるGUIプログラム作ってみました。

JavaなのでLinuxやMACでも動くかも。。。

LEDつけたり消したりしたいとき、クリックするだけでON、OFF切り替えできます。

GPIOの番号をクリックするだけなので楽ちん。

使用したライブラリ
https://github.com/nkolban/jpigpio

GUIプログラム

import java.awt.Color;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;

import jpigpio.GPIOListener;
import jpigpio.JPigpio;
import jpigpio.PigpioException;
import jpigpio.PigpioSocket;

public class RaspberryPiMonitor extends JFrame {
	private DrawCanvas canvas = new DrawCanvas();
	private PigpioSocket pi;

	public static void main(String[] args) {
		RaspberryPiMonitor wnd = new RaspberryPiMonitor();
		wnd.setSize(750,280);
		wnd.setLocationRelativeTo(null);
		wnd.setVisible(true);
	}

	RaspberryPiMonitor(){
		super("Raspberry Pi GPIO Monitor");
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				try {
					pi.gpioTerminate();
				} catch (PigpioException e1) {
					e1.printStackTrace();
				}
				System.exit(0);
			}
		});
		remoteInit();
		Container con = getContentPane();
		con.add(canvas);
	}

	public void remoteInit() {
		try {
			pi = new PigpioSocket("192.168.1.123", 8888);

			DrawCanvas.GPIO[][] gpioList = canvas.gpioList;
			for ( int i = 0;i < gpioList.length;i++ ) {

				for ( int j = 0;j < gpioList[i].length;j++ ) {
					DrawCanvas.GPIO gpio = gpioList[i][j];
					if ( gpio.num.equals("") ) continue;
					int n = Integer.parseInt(gpio.num);
					gpio.flg = pi.gpioRead(n);
					pi.addCallback( new GPIOListener(n,JPigpio.PI_EITHER_EDGE) {

						@Override
						public void alert(int gpio, int level, long tick) {
							if ( level == 0 ) canvas.off(gpio);
							else canvas.on(gpio);
						}
					});
				}
			}
		} catch (PigpioException e) {
			e.printStackTrace();
		}
	}

	class DrawCanvas extends JPanel{
		GPIO[][] gpioList = {
				{
					new GPIO("",Color.RED)
					,new GPIO("",Color.RED)
					,new GPIO("",Color.BLACK)
					,new GPIO("14",Color.YELLOW)
					,new GPIO("15",Color.YELLOW)
					,new GPIO("18",Color.YELLOW)
					,new GPIO("",Color.BLACK)
					,new GPIO("23",Color.YELLOW)
					,new GPIO("24",Color.YELLOW)
					,new GPIO("",Color.BLACK)
					,new GPIO("25",Color.YELLOW)
					,new GPIO("8",Color.YELLOW)
					,new GPIO("7",Color.YELLOW)
					,new GPIO("",Color.WHITE)
					,new GPIO("",Color.BLACK)
					,new GPIO("12",Color.YELLOW)
					,new GPIO("",Color.BLACK)
					,new GPIO("16",Color.YELLOW)
					,new GPIO("20",Color.YELLOW)
					,new GPIO("21",Color.YELLOW)
				}
				,{
					new GPIO("",Color.ORANGE)
					,new GPIO("2",Color.YELLOW)
					,new GPIO("3",Color.YELLOW)
					,new GPIO("4",Color.YELLOW)
					,new GPIO("",Color.BLACK)
					,new GPIO("17",Color.YELLOW)
					,new GPIO("27",Color.YELLOW)
					,new GPIO("22",Color.YELLOW)
					,new GPIO("",Color.ORANGE)
					,new GPIO("10",Color.YELLOW)
					,new GPIO("9",Color.YELLOW)
					,new GPIO("11",Color.YELLOW)
					,new GPIO("",Color.BLACK)
					,new GPIO("",Color.WHITE)
					,new GPIO("5",Color.YELLOW)
					,new GPIO("6",Color.YELLOW)
					,new GPIO("13",Color.YELLOW)
					,new GPIO("19",Color.YELLOW)
					,new GPIO("26",Color.YELLOW)
					,new GPIO("",Color.BLACK)
				}
		};
		MouseInputAdapter adapter = new MouseInputAdapter() {
			public void mousePressed(MouseEvent e) {
				for ( int i = 0;i < gpioList.length;i++ ) {

					for ( int j = 0;j < gpioList[i].length;j++ ) {
						GPIO gpio = gpioList[i][j];
						if (containsMousePoint(e,gpio)&& !"".equals(gpio.num)) {
							try {
								pi.gpioWrite(Integer.parseInt(gpio.num), !gpio.flg);
							} catch (NumberFormatException | PigpioException e1) {
								e1.printStackTrace();
							}
							break;
						}
					}
				}
			}

			public void mouseMoved(MouseEvent e) {
				boolean isHand = false;
				for ( int i = 0;i < gpioList.length;i++ ) {

					for ( int j = 0;j < gpioList[i].length;j++ ) {
						GPIO gpio = gpioList[i][j];
						if (containsMousePoint(e,gpio) && !"".equals(gpio.num)) {
							isHand = true;
							break;
						}
					}
				}
				if (isHand) {
					setCursor(new Cursor(Cursor.HAND_CURSOR));
				} else {
					setCursor(Cursor.getDefaultCursor());
				}
			}
		};
		boolean containsMousePoint(MouseEvent e, GPIO gpio){
			double r = gpio.r2/2;
			double cx = gpio.x+r;
			double cy = gpio.y+r;
			if (r*r > Math.pow(e.getX()-cx,2)+Math.pow(e.getY()-cy, 2)) {
				return true;
			}
			return false;
		}
		DrawCanvas(){
			addMouseMotionListener(adapter);
			addMouseListener(adapter);
		}
		final Color GREEN = new Color(20,150,20);
		public void paint(Graphics g) {
			g.setColor(GREEN);
			g.fillRoundRect(45, 50, 650, 100, 5, 5);
			g.setColor(Color.GRAY);
			g.fillRect(75, 75, 590, 50);

			int oy = 75;
			int ox = 75;
			for ( int i = 0;i < gpioList.length;i++ ) {

				for ( int j = 0;j < gpioList[i].length;j++ ) {
					GPIO gpio = gpioList[i][j];
					g.setColor(gpio.flg ? Color.GREEN : gpio.clr);
					int x = j*30+ox;
					int y = i*30+oy;
					g.fillOval(x, y, (int)gpio.r2, (int)gpio.r2);
					gpio.x = x;
					gpio.y = y;
					if ( gpio.clr != Color.BLACK ) {
						g.setColor(Color.BLACK);
					} else {
						g.setColor(Color.WHITE);
					}
					int w = g.getFontMetrics().stringWidth(gpio.num);
					g.drawString(gpio.num, x+9-w/2, y+15);
				}
			}
			g.setColor(Color.YELLOW);
			g.fillOval(100, 170, 20, 20);
			g.setColor(Color.BLACK);
			g.drawString("GPIO (Low)",123,185);

			g.setColor(Color.GREEN);
			g.fillOval(200, 170, 20, 20);
			g.setColor(Color.BLACK);
			g.drawString("GPIO (High)",223,185);

			g.setColor(Color.BLACK);
			g.fillOval(300, 170, 20, 20);
			g.setColor(Color.BLACK);
			g.drawString("Ground",323,185);

			g.setColor(Color.RED);
			g.fillOval(400, 170, 20, 20);
			g.setColor(Color.BLACK);
			g.drawString("5v",423,185);

			g.setColor(Color.ORANGE);
			g.fillOval(500, 170, 20, 20);
			g.setColor(Color.BLACK);
			g.drawString("3.3v",523,185);

			g.setColor(Color.WHITE);
			g.fillOval(600, 170, 20, 20);
			g.setColor(Color.BLACK);
			g.drawString("ID EEPROM",623,185);
		}

		GPIO get(int gpio) {

			for ( int i = 0;i < gpioList.length;i++ ) {

				for ( int j = 0;j < gpioList[i].length;j++ ) {
					GPIO gpioInfo = gpioList[i][j];
					if ((gpio+"").equals(gpioInfo.num)) {
						return gpioInfo;
					}
				}
			}
			return null;
		}

		void on(int gpio) {

			GPIO g = get(gpio);
			g.flg = true;
			RaspberryPiMonitor.this.repaint();
		}

		void off(int gpio) {

			GPIO g = get(gpio);
			g.flg = false;
			RaspberryPiMonitor.this.repaint();
		}

		class GPIO{
			String num;
			Color clr;
			boolean flg;
			double x,y,r2=20;
			GPIO(String num, Color clr){
				this.num = num;
				this.clr = clr;
			}
		}
	}
}
実行結果

かなり適当な作りですが、使えりゃいいでしょ。

プログラム内のラズパイのIPアドレスは変えてください。

後は、ラズパイのリモートGPIOの設定をオンにしておくのと、pigpioデーモンを起動しておいてください。(下記の記事で説明済み)

IoT, Java

Posted by nompor