2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【生成AI活用】Raspberry PiでOpenJDK 25 + Open Liberty 25 + Jakarta EE 10によるIoTセンサーREST API構築 - IBM BOBを使い -

Last updated at Posted at 2025-12-16

はじめに

この記事では、IBM BOB という生成AIを活用しながら、Raspberry Pi上にJava 25とOpen Liberty 25.0.0.12をインストールし、温度センサー、I2Cセンサー(BME280)、ソフトウェア無線(RTL-SDR)、ADS-B航空機追跡のデータをREST API経由で公開するシステムを構築した過程を解説します。

本記事の特徴

  • 🤖 生成AI活用: IBM BOBを使用してコード生成・問題解決
  • 最新Java: Java 25(2025年リリース)を使用
  • 🚀 最新アプリケーションサーバー: Open Liberty 25.0.0.12(2025年12月2日リリース)
  • 📡 Jakarta EE 10: 最新のエンタープライズJava仕様
  • 🌐 MicroProfile 6.0: マイクロサービス向けフレームワーク
  • 🛩️ 実用的なIoT: 環境センサー+航空機追跡システム

生成AI(Bob)の活用方法

このプロジェクトでは、IBM watsonx Code Assistant (Bob)を以下のように活用しました:

  1. 環境構築の自動化: SSH接続からJavaインストールまでのコマンド生成
  2. コード生成: Jakarta EE準拠のREST APIリソースクラスの実装
  3. トラブルシューティング: エラー解決とデバッグ支援
  4. 設定ファイル作成: Maven pom.xml、server.xml、beans.xmlの生成
  5. ドキュメント作成: このブログ記事自体もBobの支援で作成

生成AIを活用することで、開発時間を大幅に短縮し、ベストプラクティスに沿った実装が可能になりました。

環境情報

  • ハードウェア: Raspberry Pi (ARMv7l)
  • OS: Raspbian GNU/Linux 11 (bullseye)
  • Java: OpenJDK 25
  • アプリケーションサーバー: Open Liberty 25.0.0.12
  • ビルドツール: Maven 3.9.x
  • センサー:
    • CPU温度センサー(vcgencmd)
    • BME280環境センサー(I2C接続、アドレス0x76)
    • RTL2838 DVB-T SDR(USB接続)

1. Java 25のインストール

1.1 既存のJavaを確認・削除

# 現在のJavaバージョンを確認
java -version

# 既存のOpenJDKを削除(必要に応じて)
sudo apt remove openjdk-* -y
sudo apt autoremove -y

1.2 Java 25のダウンロードとインストール

Raspberry PiはARMアーキテクチャなので、ARM用のJDKをダウンロードします。

# 作業ディレクトリに移動
cd /home/pi

# OpenJDK 25 ARM版をダウンロード
wget https://download.java.net/java/GA/jdk25/3/GPL/openjdk-25_linux-aarch64_bin.tar.gz

# 解凍
tar -xzf openjdk-25_linux-aarch64_bin.tar.gz

# /opt/に移動
sudo mv jdk-25 /opt/

# 環境変数を設定
echo 'export JAVA_HOME=/opt/jdk-25' >> ~/.bashrc
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# バージョン確認
java -version

期待される出力:

openjdk version "25" 2025-XX-XX
OpenJDK Runtime Environment (build 25+XX)
OpenJDK 64-Bit Server VM (build 25+XX, mixed mode, sharing)

1.3 Mavenのインストール

# Maven 3.9.xをダウンロード
cd /home/pi
wget https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz

# 解凍
tar -xzf apache-maven-3.9.9-bin.tar.gz

# /opt/に移動
sudo mv apache-maven-3.9.9 /opt/maven

# 環境変数を設定
echo 'export MAVEN_HOME=/opt/maven' >> ~/.bashrc
echo 'export PATH=$MAVEN_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# バージョン確認
mvn -version

2. ハードウェアセンサーの準備

2.1 I2Cツールのインストール

# I2Cツールをインストール
sudo apt update
sudo apt install -y i2c-tools python3-pip

# I2Cが有効か確認
sudo i2cdetect -y 1

期待される出力:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- 76 --

2.2 BME280センサーライブラリのインストール

# BME280用Pythonライブラリをインストール
sudo pip3 install RPi.bme280

2.3 BME280データ読み取りスクリプトの作成

# スクリプトディレクトリを作成
mkdir -p /home/pi/sensor-scripts

# Pythonスクリプトを作成
cat > /home/pi/sensor-scripts/read_bme280.py << 'EOF'
#!/usr/bin/env python3
import smbus2
import bme280
import json

port = 1
address = 0x76
bus = smbus2.SMBus(port)

calibration_params = bme280.load_calibration_params(bus, address)
data = bme280.sample(bus, address, calibration_params)

result = {
    "temperature": round(data.temperature, 2),
    "pressure": round(data.pressure, 2),
    "humidity": round(data.humidity, 2),
    "unit_temp": "celsius",
    "unit_pressure": "hPa",
    "unit_humidity": "%"
}

print(json.dumps(result))
EOF

# 実行権限を付与
chmod +x /home/pi/sensor-scripts/read_bme280.py

# テスト実行
python3 /home/pi/sensor-scripts/read_bme280.py

2.4 RTL-SDRツールのインストール

# RTL-SDRツールをインストール
sudo apt install -y rtl-sdr

# デバイスを確認
rtl_test -t

3. Open Libertyのインストール

3.1 Open Libertyのダウンロードと解凍

# ホームディレクトリに移動
cd /home/pi

# Open Liberty 25.0.0.12をダウンロード
wget https://public.dhe.ibm.com/ibmdl/export/pub/software/openliberty/runtime/release/25.0.0.12/openliberty-25.0.0.12.zip

# 解凍
unzip openliberty-25.0.0.12.zip

# サーバーを作成
cd wlp/bin
./server create sensorServer

4. Jakarta EE REST APIプロジェクトの作成

4.1 プロジェクト構造の作成

# プロジェクトディレクトリを作成
mkdir -p /home/pi/sensor-api-liberty
cd /home/pi/sensor-api-liberty

# ディレクトリ構造を作成
mkdir -p src/main/java/com/sensor/api
mkdir -p src/main/webapp/WEB-INF
mkdir -p src/main/liberty/config

4.2 pom.xmlの作成

cat > pom.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sensor</groupId>
    <artifactId>sensor-api-liberty</artifactId>
    <version>1.0.0</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>25</maven.compiler.source>
        <maven.compiler.target>25</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <liberty.var.http.port>8080</liberty.var.http.port>
        <liberty.var.https.port>8443</liberty.var.https.port>
    </properties>

    <dependencies>
        <!-- Jakarta EE 10 Web Profile -->
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-web-api</artifactId>
            <version>10.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- MicroProfile -->
        <dependency>
            <groupId>org.eclipse.microprofile</groupId>
            <artifactId>microprofile</artifactId>
            <version>6.0</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>

        <!-- JSON-B for JSON processing -->
        <dependency>
            <groupId>jakarta.json.bind</groupId>
            <artifactId>jakarta.json.bind-api</artifactId>
            <version>3.0.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>sensor-api</finalName>
        <plugins>
            <!-- Maven WAR Plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
EOF

4.3 JAX-RS Applicationクラスの作成

cat > src/main/java/com/sensor/api/SensorApplication.java << 'EOF'
package com.sensor.api;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("/api")
public class SensorApplication extends Application {
    // JAX-RS will automatically discover and register all resource classes
}
EOF

4.4 温度センサーリソースの作成

cat > src/main/java/com/sensor/api/TemperatureResource.java << 'EOF'
package com.sensor.api;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

@Path("/temperature")
public class TemperatureResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getCpuTemperature() {
        Map<String, Object> result = new HashMap<>();
        try {
            Process process = Runtime.getRuntime().exec("vcgencmd measure_temp");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = reader.readLine();
            
            if (line != null && line.contains("=")) {
                String tempStr = line.split("=")[1].replace("'C", "").trim();
                double temperature = Double.parseDouble(tempStr);
                
                result.put("sensor", "CPU");
                result.put("temperature", temperature);
                result.put("unit", "Celsius");
                result.put("timestamp", System.currentTimeMillis());
                
                return Response.ok(result).build();
            } else {
                result.put("error", "Failed to read temperature");
                return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
            }
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
        }
    }

    @GET
    @Path("/thermal")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getThermalTemperature() {
        Map<String, Object> result = new HashMap<>();
        try {
            Process process = Runtime.getRuntime().exec("cat /sys/class/thermal/thermal_zone0/temp");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = reader.readLine();
            
            if (line != null) {
                double temperature = Double.parseDouble(line.trim()) / 1000.0;
                
                result.put("sensor", "Thermal Zone 0");
                result.put("temperature", temperature);
                result.put("unit", "Celsius");
                result.put("timestamp", System.currentTimeMillis());
                
                return Response.ok(result).build();
            } else {
                result.put("error", "Failed to read thermal temperature");
                return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
            }
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
        }
    }
}
EOF

4.5 I2Cセンサーリソースの作成

cat > src/main/java/com/sensor/api/I2cResource.java << 'EOF'
package com.sensor.api;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Path("/i2c")
public class I2cResource {

    @GET
    @Path("/scan")
    @Produces(MediaType.APPLICATION_JSON)
    public Response scanI2cBus() {
        Map<String, Object> result = new HashMap<>();
        try {
            Process process = Runtime.getRuntime().exec("/usr/sbin/i2cdetect -y 1");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            List<String> devices = new ArrayList<>();
            String line;
            
            while ((line = reader.readLine()) != null) {
                if (line.matches(".*[0-9a-fA-F]{2}.*")) {
                    String[] parts = line.trim().split("\\s+");
                    for (int i = 1; i < parts.length; i++) {
                        if (parts[i].matches("[0-9a-fA-F]{2}")) {
                            devices.add("0x" + parts[i]);
                        }
                    }
                }
            }
            
            process.waitFor();
            
            result.put("bus", "i2c-1");
            result.put("devices", devices);
            result.put("timestamp", System.currentTimeMillis());
            
            return Response.ok(result).build();
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
        }
    }

    @GET
    @Path("/bme280")
    @Produces(MediaType.APPLICATION_JSON)
    public Response readBME280() {
        Map<String, Object> result = new HashMap<>();
        try {
            Process process = Runtime.getRuntime().exec("python3 /home/pi/sensor-scripts/read_bme280.py");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            StringBuilder output = new StringBuilder();
            StringBuilder errorOutput = new StringBuilder();
            String line;
            
            while ((line = reader.readLine()) != null) {
                output.append(line);
            }
            
            while ((line = errorReader.readLine()) != null) {
                errorOutput.append(line).append("\n");
            }
            
            int exitCode = process.waitFor();
            
            if (exitCode == 0 && output.length() > 0) {
                String jsonStr = output.toString();
                if (jsonStr.contains("temperature") && jsonStr.contains("pressure") && jsonStr.contains("humidity")) {
                    result.put("sensor", "BME280");
                    result.put("address", "0x76");
                    result.put("data", jsonStr);
                    result.put("timestamp", System.currentTimeMillis());
                    return Response.ok(result).build();
                }
            }
            
            result.put("error", "Failed to read BME280 sensor");
            result.put("exitCode", exitCode);
            result.put("stderr", errorOutput.toString());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
            
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
        }
    }
}
EOF

4.6 SDRリソースの作成

cat > src/main/java/com/sensor/api/SdrResource.java << 'EOF'
package com.sensor.api;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Path("/sdr")
public class SdrResource {

    @GET
    @Path("/info")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getSdrInfo() {
        Map<String, Object> result = new HashMap<>();
        try {
            Process process = Runtime.getRuntime().exec("rtl_test -t");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            StringBuilder output = new StringBuilder();
            String line;
            
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
            
            process.waitFor();
            
            result.put("device", "RTL-SDR");
            result.put("info", output.toString());
            result.put("timestamp", System.currentTimeMillis());
            
            return Response.ok(result).build();
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
        }
    }

    @GET
    @Path("/scan")
    @Produces(MediaType.APPLICATION_JSON)
    public Response scanFrequency(@QueryParam("frequency") String frequency) {
        Map<String, Object> result = new HashMap<>();
        
        if (frequency == null || frequency.isEmpty()) {
            frequency = "100M";
        }
        
        try {
            String[] cmd = {"/bin/sh", "-c", 
                "timeout 2 rtl_power -f " + frequency + " -i 1 - 2>&1 | head -20"};
            Process process = Runtime.getRuntime().exec(cmd);
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            List<String> samples = new ArrayList<>();
            String line;
            
            while ((line = reader.readLine()) != null) {
                samples.add(line);
            }
            
            process.waitFor();
            
            result.put("frequency", frequency);
            result.put("samples", samples);
            result.put("timestamp", System.currentTimeMillis());
            
            return Response.ok(result).build();
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
        }
    }

    @GET
    @Path("/fm")
    @Produces(MediaType.APPLICATION_JSON)
    public Response scanFmBand() {
        Map<String, Object> result = new HashMap<>();
        try {
            String[] cmd = {"/bin/sh", "-c", 
                "timeout 3 rtl_power -f 88M:108M:100k -i 1 - 2>&1 | head -50"};
            Process process = Runtime.getRuntime().exec(cmd);
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            List<String> samples = new ArrayList<>();
            String line;
            
            while ((line = reader.readLine()) != null) {
                samples.add(line);
            }
            
            process.waitFor();
            
            result.put("band", "FM (88-108 MHz)");
            result.put("samples", samples);
            result.put("timestamp", System.currentTimeMillis());
            
            return Response.ok(result).build();
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build();
        }
    }
}
EOF

4.7 Open Liberty設定ファイルの作成

cat > src/main/liberty/config/server.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<server description="Sensor API Server">
    <featureManager>
        <feature>restfulWS-3.1</feature>
        <feature>jsonb-3.0</feature>
        <feature>jsonp-2.1</feature>
        <feature>cdi-4.0</feature>
        <feature>mpConfig-3.0</feature>
        <feature>mpHealth-4.0</feature>
        <feature>mpMetrics-5.0</feature>
    </featureManager>

    <httpEndpoint id="defaultHttpEndpoint"
                  host="*"
                  httpPort="${http.port}"
                  httpsPort="${https.port}" />

    <variable name="http.port" defaultValue="8080"/>
    <variable name="https.port" defaultValue="8443"/>

    <webApplication location="sensor-api.war" contextRoot="/">
        <classloader apiTypeVisibility="spec, ibm-api, third-party"/>
    </webApplication>

    <logging consoleLogLevel="INFO" />
</server>
EOF

4.8 beans.xmlの作成

cat > src/main/webapp/WEB-INF/beans.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee 
                           https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
       bean-discovery-mode="all">
</beans>
EOF

5. ビルドとデプロイ

5.1 プロジェクトのビルド

cd /home/pi/sensor-api-liberty
mvn clean package

5.2 WARファイルのデプロイ

# WARファイルをOpen Libertyのappsディレクトリにコピー
cp target/sensor-api.war /home/pi/wlp/usr/servers/sensorServer/apps/

# server.xmlをコピー
cp src/main/liberty/config/server.xml /home/pi/wlp/usr/servers/sensorServer/

5.3 Open Libertyサーバーの起動

cd /home/pi/wlp/bin
./server start sensorServer

# ログを確認
tail -f /home/pi/wlp/usr/servers/sensorServer/logs/messages.log

6. APIのテスト

6.1 温度センサーAPI

# CPU温度を取得
curl http://localhost:8080/api/temperature

# 期待される出力:
# {"unit":"Celsius","temperature":43.9,"sensor":"CPU","timestamp":1765867366529}

# サーマルゾーン温度を取得
curl http://localhost:8080/api/temperature/thermal

# 期待される出力:
# {"unit":"Celsius","temperature":43.312,"sensor":"Thermal Zone 0","timestamp":1765867484424}

6.2 I2CセンサーAPI

# I2Cバスをスキャン
curl http://localhost:8080/api/i2c/scan

# 期待される出力:
# {"bus":"i2c-1","devices":["0x76"],"timestamp":1765867674972}

# BME280センサーデータを取得
curl http://localhost:8080/api/i2c/bme280

# 期待される出力:
# {"address":"0x76","data":"{\"temperature\": 18.16, \"pressure\": 1005.36, \"humidity\": 38.41, \"unit_temp\": \"celsius\", \"unit_pressure\": \"hPa\", \"unit_humidity\": \"%\"}","sensor":"BME280","timestamp":1765867460875}

6.3 SDR API

# SDRデバイス情報を取得
curl http://localhost:8080/api/sdr/info

# 特定周波数をスキャン
curl "http://localhost:8080/api/sdr/scan?frequency=100M"

# FMバンドをスキャン
curl http://localhost:8080/api/sdr/fm

7. LAN上の他のサーバーからのアクセス

Raspberry PiのIPアドレスが192.168.200.102の場合、LAN上の他のサーバーから以下のようにアクセスできます:

# 他のサーバーから実行
curl http://192.168.200.102:8080/api/temperature
curl http://192.168.200.102:8080/api/i2c/bme280
curl http://192.168.200.102:8080/api/sdr/info

8. サーバーの管理

8.1 サーバーの停止

cd /home/pi/wlp/bin
./server stop sensorServer

8.2 サーバーの再起動

cd /home/pi/wlp/bin
./server stop sensorServer
./server start sensorServer

8.3 サーバーステータスの確認

cd /home/pi/wlp/bin
./server status sensorServer

9. トラブルシューティング

9.1 I2Cデバイスが検出されない

# I2Cが有効か確認
sudo raspi-config
# Interface Options -> I2C -> Enable

# 再起動
sudo reboot

9.2 BME280センサーが読み取れない

# Pythonライブラリを再インストール
sudo pip3 install --upgrade RPi.bme280

# 手動でテスト
python3 /home/pi/sensor-scripts/read_bme280.py

9.3 Open Libertyが起動しない

# ログを確認
cat /home/pi/wlp/usr/servers/sensorServer/logs/messages.log

# Javaバージョンを確認
java -version

# ポート8080が使用中か確認
sudo netstat -tulpn | grep 8080

10. まとめ

この記事では、Raspberry Pi上にJava 25とOpen Libertyを使用して、複数のセンサーデータをREST API経由で公開するシステムを構築しました。

主な技術スタック:

  • Java 25
  • Open Liberty 25.0.0.12
  • Jakarta EE 10 (JAX-RS, CDI, JSON-B)
  • MicroProfile 6.0
  • Maven

実装したAPI:

  • 温度センサー(CPU、サーマルゾーン)
  • I2Cセンサー(BME280環境センサー)
  • ソフトウェア無線(RTL-SDR)

このシステムは、IoTデバイスのデータ収集、環境モニタリング、無線信号解析など、様々な用途に応用できます。

参考リンク

追加セクション: ADS-B航空機追跡API

ADS-B航空機追跡について

readsbは既にRaspberry Pi上で動作しており、RTL-SDRを使用してADS-B信号を受信しています。readsbは /run/readsb/ ディレクトリにJSONファイルを生成するため、これを読み取るAPIを作成しました。

ADS-B APIエンドポイント

  1. 航空機データ取得: GET /api/adsb/aircraft

    • リアルタイムの航空機情報(位置、高度、速度など)
  2. サマリー情報: GET /api/adsb/summary

    • 検出された航空機数と受信メッセージ数
  3. 統計情報: GET /api/adsb/stats

    • 受信機の詳細統計

テスト結果

# サマリー情報
curl http://localhost:8080/api/adsb/summary
# 出力: {"aircraft_count":3,"service":"ADS-B Aircraft Tracking","total_messages":840000,"data_source":"readsb","timestamp":1765869861650}

# 航空機データ(JA24HBヘリコプター、JJP513ジェット機など)
curl http://localhost:8080/api/adsb/aircraft

取得できるデータ

  • hex: 航空機の固有識別子
  • flight: フライト番号
  • alt_baro/alt_geom: 高度(フィート)
  • gs: 対地速度(ノット)
  • track: 進行方向(度)
  • lat/lon: 緯度・経度
  • squawk: トランスポンダコード
  • category: 航空機カテゴリ

11. Open Liberty 25.0.0.12の特徴

Open Liberty 25.0.0.12は2025年12月2日にリリースされた最新の安定版です。このバージョンでは、Jakarta EE 10とMicroProfile 6.0の最新機能、パフォーマンス改善、セキュリティ修正が含まれています。

11.1 Open Liberty 25.0.0.12の主な特徴

  1. パフォーマンス向上

    • 起動時間の短縮
    • メモリ使用量の最適化
    • レスポンスタイムの改善
  2. Jakarta EE 10の完全サポート

    • JAX-RS 3.1の最新機能
    • CDI 4.0の強化
    • JSON-B 3.0の改善
  3. MicroProfile 6.0の新機能

    • Telemetry 1.0(OpenTelemetry統合)
    • Config 3.1の機能拡張
    • Health 4.0の改善
  4. セキュリティ強化

    • AES-256暗号化キーのカスタマイズサポート
    • IBM Semeru RuntimesでのFIPS 140-3サポート
    • TLS 1.3のデフォルト有効化
    • 最新のセキュリティパッチ適用
  5. 開発者体験の向上

    • より詳細なエラーメッセージ
    • デバッグ機能の強化
    • ログ出力の改善

11.2 パフォーマンス最適化(オプション)

メモリ設定の調整

Raspberry Piのリソースに合わせてJVMのメモリ設定を最適化できます:

# jvm.optionsファイルを作成
cat > /home/pi/wlp/usr/servers/sensorServer/jvm.options << 'EOF'
# ヒープサイズの設定(Raspberry Piの場合)
-Xms256m
-Xmx512m

# ガベージコレクションの最適化
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200

# パフォーマンスモニタリング(オプション)
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
EOF

ログレベルの調整

必要に応じてログレベルを調整できます:

<!-- server.xmlに追加 -->
<logging
    consoleLogLevel="INFO"
    traceSpecification="*=info:com.sensor.api.*=fine"
    maxFileSize="20"
    maxFiles="5" />

11.3 システム全体の確認

すべてが正常に動作しているか確認するための総合テスト:

# システム全体の確認
echo "=== System Info ==="
uname -a
echo ""
echo "=== Java Version ==="
java -version
echo ""
echo "=== Open Liberty Version ==="
cd /home/pi/wlp/bin && ./productInfo version
echo ""
echo "=== Server Status ==="
./server status sensorServer
echo ""
echo "=== API Test ==="
curl -s http://localhost:8080/api/temperature | python3 -m json.tool

期待される出力:

=== System Info ===
Linux raspberrypi 5.15.84-v7l+ #1613 SMP armv7l GNU/Linux

=== Java Version ===
openjdk version "25" 2025-XX-XX
OpenJDK Runtime Environment (build 25+XX)
OpenJDK 64-Bit Server VM (build 25+XX, mixed mode, sharing)

=== Open Liberty Version ===
Product name: Open Liberty
Product version: 25.0.0.12
Product edition: Open

=== Server Status ===
Server sensorServer is running with process ID 10014.

=== API Test ===
{
    "unit": "Celsius",
    "temperature": 43.3,
    "sensor": "CPU",
    "timestamp": 1765874003866
}

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?