はじめにEclipse Kuraで採用されているOSGiについて少し復習してから、ドキュメントサイトにある簡単なHello Woldアプリを開発してEclipse Kuraへデプロイしてみます。
OSGiの復習
OSGiはEclipseのプラグインの仕組みに採用されているので名前を聞いたことがある方も多いと思います。1999年に設立されたOSGi Allianceが仕様を策定しています。
もともと「Open Service Gateway Initiative」と呼ばれるように、家庭やオフィスに設置したゲートウェイ端末上で家電やセンサーなどを制御するプログラムを動かすためのプラットフォームの仕様でした。その後ゲートウェイ以外に車載や組込機器、工場などエンタープライズの分野に採用が広が���ます。
OSGiバンドルとOSGiフレームワーク
リモートから動的にJavaモジュールを追加、更新できるのが特徴です。このモジュールをOSGiバンドルと呼びます。クラスファイルやリソースファイル、マニフェストなどを含んだ通常のjarファイルです。
OSGiバンドルはJVMで動作するOSGiフレームワークにインストールします。Eclipse KuraではOSGiフレームワークの実装としてEclipse Equinoxが採用されています。アプリケーションのコンポーネント化技術として他のモジュールを停止せずに機能の追加や更新ができます。現在主流になりつつあるコンテナ技術をベースにしたマイクロサービスのアーキテクチャと似ています。前回調査した、Resin.ioやUbuntu CoreもIoT Gatewayのアプリケーション管理に同様のコンテナ化のアプローチを取っています。
Working Setの作成
ここからEclipse使いHello Wolrdアプリを開発していきます。まずEclipseで複数のプロジェクトを管理する仕組みとしてワーキングセットを使います。パッケージエクスプローラの三角マークをクリックし���、表示する単位をワーキングセットにします。適当な名前をつけて新しいワーキングセットを作成します。今回は「Kura Projects」にしました。
Package Exploler -> Top Level Elements -> Working Sets |
サンプルプロジェクトをインポート
Getting StartedにあるKuraのサンプルワークスペースから以下の6つのプロジェクトをEclipseにインポートします。
- org.eclipse.kura.demo.heater
- org.eclipse.kura.emulator
- org.eclipse.kura.example.beacon
- org.eclipse.kura.example.ble.tisensortag
- org.eclipse.kura.example.publisher
- target-definition
Kura User Workspace archiveをダウンロードします。Eclipse Kuraは2.0.2をインストールしているので同じバージョンを使います。
$ wget http://www.eclipse.org/downloads/download.php?file=/kura/releases/2.0.2/user_workspace_archive_2.0.2.zip |
ダウンロードしたzipファイルをEclipseにインポートします。プロジェクトは先ほど作成したKura Projets
に追加します。
File -> Import -> General -> Existing Projects into Workspace |
プロジェクトの再ビルド
target-definitionプロジェクトにあるkura-equinox_3.8.1.targetをTarget Editorで開きます。
target-definition/kura-equinox_3.8.1.target -> 右クリック -> Open With -> Target Editor |
Target Platformをリセットしてプロジェクトを再ビルドします。
Difinitionタブ -> Set as Target Platformをクリック |
Plug-in プロジェクト
OSGiバンドルの開発はPlug-inプロジェクトで行います。 ウィザードを使いプロジェクトを作成します。
File -> New -> Project -> Plug-in Development -> Plug-in Project |
Hello World Exampleの例に沿って新しいプロジェクトを作成します。
- Project name: org.eclipse.kura.example.hello_osgi
- Target Platform: an OSGi framework: チェック
- 選択: standard
ダイアログを次に進みプラグインのプロパティを設定します。
Name: Hello World Example with Logger
Execution Environment : JavaSE-1.8
Generate an activator… : チェックしない
Kura Projects
ワーキングセットにeclipse.kura.example.hello_osgi
が作成されました。
MANIFEST.MFの編集
OSGiバンドルはバンドルのマニフェストファイルを含むjarファイルです。ここにバンドルのメタデータを定義します。プロジェクトに作成されたMETA-INF/MANIFEST.MF
をPlug-in Manifest Editorで開きDependenciesタブをクリックします。
META-INF/MANIFEST.MFを右クリック -> Open With -> Plug-in Manifest Editor -> Dependenciesタブ |
dependenciesにjarファイルを追加してファイルの変更を保存します。
- Automated Management of Dependencies を開く
- Add -> org.eclipse.osgi.services -> OK
- Add -> slf4j.api -> OK
作成されたMANIFEST.MFはEclipseでOpenJDK 8を利用しているためJavaSE-1.8
となっています。Java 1.8のままOSGiバンドルをエクスポートするとExport Plug-ins' has encountered a problem.
のエラーが出るためJavaSE-1.7に変更します。
Manifest-Version: 1.0 |
- Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Javaクラスの作成
プロジェクトにサンプルにあるJavaクラスを作成してactivate()、deactivate()メソッドを定義します。この2つのメソッドはKuraのOSGiフレームワークによってインスタンスがActivate (活性化) 、Deactivate (非活性化)したときに実行され、OSGiバンドルをstart/stopした時に標準出力します。あとでにcomponent.xml
に指定します。
プロジェクトを右クリック -> New -> Class |
- Source folder: org.eclipse.kura.example.hello_osgi/src
- Package field: org.eclipse.kura.example.hello_osgi
- Name field: HelloOsgi
package org.eclipse.kura.example.hello_osgi; |
MANIFEST.MFにパッケージを追加
MANIFEST.MFファイルをPlug-in Manifest Editorで開きDependencisesタブをクリックします。Automated Management of Dependencies
メニューのadd dependencies
リンクをクリックすると、Javaファイルのimport宣言をベースにしてImported Packages
に自動的にjarファイルが追加されます。
- org.osgi.service.component (1.2.0)
- org.slf4j (1.6.4)
忘れずにMANIFEST.MFファイルの変更を保存して反映しておきます。
component.xmlの作成
次にOSGiコンポーネント定義ファイルのcomponent.xml
を作成します。このファイルでHelloOsgi.javaのインスタンスをコンポーネントに定義します。
プロジェクトを右クリック -> New -> Other -> Plug-in Development -> Component Definition |
現在のプロジェクトのフォルダが選択されていることを確認して、Class
の右にあるBrowseボタンをクリッ���します。
Select entriesのフィールドにhello
と入力して先ほど作成したJavaクラスを選択してOKボタンをクリックします。
- Select entries: hello
- Matching items: HelloOsgi
ウィザードに戻ると選択したクラスが入力された状態になります。最後にcomponent.xml
ファイルを保存するOSGI-INF
フォルダを入力します。Finishボタンをクリックしてウィザードは終了です。
- Enter or select the parent folder: org.eclipse.kura.example.hello_osgi/OSGI-INF
component.xmlをComponent Definition Editorで開きます。コンポーネントのライフサイクルは、OSGiフレームワークが管理します。Activate (活性化)、Deactivate (非活性化)のサイクルで実行するコンポーネントのメソッドを指定します。
- Activate: activate
- Deactivate: deactivate
XMLファイルのコンポーネント定義が作成されました。
<?xml version="1.0" encoding="UTF-8"?> |
OSGiバンドルのエクスポート
ここまで開発したOSGiバンドルをエクスポートしてEclipse KuraのOSGiフレームワークにデプロイする準備をします。OSGiバンドルのデプロイ方法は、スタンドアロンのOSGiプラグイン形式と、デプロイ管理サービスを使うDeploymentパッケージの2つあります。
OSGiプラグイン
最初にスタンドアロンのOSGiプラグインとしてOSGiバンドルを作成します。
プロジェクトを右クリック -> Export -> Plug-in Development -> Deployable plug-ins and fragments |
Available Plug-ins and Fragments
で作成したOSGiプラグインを選択します。
- org.eclipse.kura.example.hello_osgi
Directoryをチェックして右のBrowseボタンをクリックします。jarファイルを保存するローカルのファイルシステムの場所を選択します。
MANIFEST.MF
をJavaSE-1.8をJavaSE-1.7に変更していない場合はこのエクスポートの時にエラーになるため確���しておきます。
Bundle-RequiredExecutionEnvironment: JavaSE-1.7 |
Finishボタンでウィザードを終了すると以下のように指定したフォルダにjarファイルがエクスポートされます。
~/myPlugins/plugins/org.eclipse.kura.example.hello_osgi_1.0.0.201702060832.jar |
Deploymentパッケージ
次はもう一つのDeploymentパッケージを作成します。拡張子は*.dp
のファイルです。*.dpp
のパッケージ定義ファイルからビルドして複数のOSGiバンドルをパッケージ化できます。dpファイルはデプロイ管理サービスを使いリモートのEclipse Kuraにデプロイすることができます。
最初にdppとdpファイルをエクスポートするフォルダresources/dp
を作成します。
プロジェクトを右クリック -> New -> Folder -> org.eclipse.kura.example.hello_osgi |
- folder name: resources/dpを作成
Deployment Package Definition
ウィザードを起動してDeploymentパッケージ定義のdppファイルを作成します。
File -> New -> Other -> OSGi -> Deployment Package Definition |
ファイルを出力するフォルダとファイル名を指定します。
- Target folder: /org.eclipse.kura.example.hello_osgi/resources/dp
- File name: hello_osgi
Finishボタンでウィザードを終了するとresources/dp/hello_osgi.dpp
に定義ファイルが作成されます。
次にhello_osgi.dppファイルをDeployment Editorで開きます。BundlesタブにあるNewボタンをクリックして新しい行を作成したあと、Bundle Pathセルにある...
ボタンをクリックします。ここで先ほどmyPluginsフォルダにエクスポートしたOSGiプラグインのjarファイルを選択します。
New -> Bundle Path column -> Browse |
Headersタブは以下のようにキーが入力されます。
- DeploymentPackage-SymbolicName: hello_osgi
- DeploymentPackage-Version: 1.0.0
dppファイルからQuick Build
するとhello_osgi.dpが作成されます。
resources/dp/hello_osgi.dppを右クリック -> Quick Build |
OSGiバンドルのデプロイ - Local Emulation Mode
Deploying Bundlesのページを読みながらOSGiバンドルをデプロイします。
エミュレータの起動
最初に試すLocal Emulation ModeはLinuxとmacOSだけで動作するモードです。KuraのエミュレータをEclipse上で起動してここにOSGiバンドルをデプロイします。
他のプロジェクトが開いているとエミュレータを起動した時に一緒に動いてしまうので、Working SetはインポートしたKuraのサンプルプロジェクトのorg.eclipse.kura.emulator
とhello_osgi
を残し他はcloseしておきます。
macOSの場合src/main/resourcesフォルダにあるKura_Emulator_OSXを起動します。
/org.eclipse.kura.emulator/src/main/resources/Kura_Emulator_OSX.launch ファイル -> 右クリック -> Run as -> Kura_Emulator_OSX |
エミュレータが起動するとhello_osgiのOSGiバンドルにあるactivate()
メソッドが自動的に開始します。EclipseのConsoleにHelloOsgiのログが出力されました。
13:47:07,009 [Component Resolve Thread] INFO HelloOsgi:13 - Bundle org.eclipse.kura.example.hello_osgi has started! |
OSGiコンソール
ConsoleウィンドウをクリックしてEnterキーを押すとOSGiコンソールのosgi>
プロンプトが表示されます。ssコマンドでインストールされたOSGiバンドルのリストを表示することができます。バンドルID: 40が今回作成したhello_osgiのOSGiバンドルです。
osgi> ss |
stopコマンドにバンドルIDを指定して OSGiバンドルを停止させます。deactivate()
メソッドが実行され定義してあるメッセージが出力されました。
osgi> stop 40 |
同様にuninstallコマンドにバンドルIDを指定するとOSGiバンドルを削除することができます。
osgi> uninstall 40 |
OSGiコンソールから直接OSGiバンドルをインストールしてみます。引数にはOSGiプラグインのjarを指定します。今度はバンドルID: 66でデプロイされました。
osgi> install file:/Users/mshimizu/myPlugins/plugins/org.eclipse.kura.example.hello_osgi_1.0.0.201702060832.jar |
startコマンドにバンドルIDを指定してOSGiバンドルを起動します。activate()
メソッドに定義したメッセージが標準出力されました。
osgi> start 66 |
OSGiバンドルのデプロイ - Remote Target Device
最後に前回Raspberry Pi 2にインストールしたEclipse KuraのOSGiフレームワークにリモートからOSGiバンドルをデプロイしてみます。Raspberry Pi 2はmacOSと有線LANで接続してmDNSで名前解決できるように���ておきます。
mToolkitのFrameworksビュー
EclipseにインストールしたmToolkitプラグインからリモートのOSGiフレームワークに接続してみます。最初にmToolkitのFrameworksビューを開きます。
Window -> Show View -> Other -> mToolkit -> Frameworks |
Frameworksビューを右クリックしてOSGiフレームワークを追加します。
右クリック -> Add Framework |
macOSと有線LANで接続したRaspberry Pi 2の名前とアドレスを入力します。mDNSで名前解決する場合はraspberrypi.local
、または直接IPアドレスを入力します。
- Name: RPi2
- Address: raspberrypi.local
Framework名は適当に「RPi2」と名前をつけました。右クリックして接続します。
Framework名を右クリック -> Connect Framework |
OSGiフレームワークのKuraはファイアウォールでポートを許可する必要があります。KuraのWeb UIからファイアウォールの設定を確認します。
OSGiフレームワークへの接続は1450ポートを使います。デフォルトで許可されていました。
Firewall -> Open Portsタブ -> 1450の許可 |
- Port or Port Range: 1450
- Protocol: tcp
- Permitted Network: 0.0.0.0/0
- Permitted Interface Name: eth0
OSGiプラグイン
スタンドアロンのOSGiプラグインのjarを選択してデプロイします。
* mToolkit Frameworksビュー -> Framework名を右クリック -> Install Bundle -> org.eclipse.kura.example.hello_osgi_1.0.0.201702060832.jar |
Framework名のBundlesにデプロイしたorg.eclipse.kura.example.hello_osgiが表示されます。
バンドル名を右クリックしてStart、StopするとOSGiコンソールの時と同じようにactivate()
とdeactivate()
メソッドのメッセージが表示されます。
Deploymentパッケージ
以前にインストールしたOSGiバンドルはuninstallしておきます。Framework名を右クリックして今度はInstall Deployment Package
を選択します。
mToolkit Frameworks view -> Framework名を右クリック -> Install Deployment Package |
dpファイルは先ほどエクスポートしたhello_osgi.dp
ファイルを選択します。
~/Documents/workspace/org.eclipse.kura.example.hello_osgi/resources/dp/hello_osgi.dp |
Deployment Packagesのツリーの中にOSGiバンドルが表示されました。
Eclipse Kuraから確認
Eclipse KuraへmacOSからSSH接続してログを確認します。Hello Worldバンドルのstartとstopのログが表示されています。
$ ssh pi@raspberrypi.local |
teleneでOSGiフレームワークに接続してOSGiバンドルを一覧します。
$ telnet localhost 5002 |
OSGiバンドルを永続化する
mToolkitからリモートのOSGiフレームワークにデプロイする方法は一時的な方法なのでEclipse Kuraを再起動すると消えてしまいます。
SCPする場合
動作確認が終わったらdpファイルをターゲットデバイスの以下のディレクトリにコピーして永続化します。
/opt/eclipse/kura/kura/packages |
macOSから一度Raspberry Pi 2にSCPでdpファイルを転送してから目的のディレクトリにコピーします。
$ scp ~/Documents/workspace/org.eclipse.kura.example.hello_osgi/resources/dp/hello_osgi.dp pi@raspberrypi.local: |
/opt/eclipse/kura/kura/dpa.properties
ファイルに以下の書式でパッケージ名とファイルのパスを追加します。
package_name=file\:/opt/eclipse/kura/kura/packages/package_filename.dp |
org.eclipse.kura.example.hello_osgi=file\:/opt/eclipse/kura/kura/packages/hello_osgi.dp |
Eclipse Kuraをリスタートします。restartコマンドを使うとプロセスの停止に失敗することがあるので、stop -> startします。
$ sudo /etc/init.d/kura stop |
KuraのWeb UIからアップロードする場合
Eclipse KuraのWeb UIにログインしてdpファイルをアップロードしてもOSGiバンドルは永続化されます。Webブラウザからデプロイできるのでこちらの方が簡単です。左のPackageメニューからdpファイルをSubmitします。
Package -> Upload - dpファイル -> Submit |