IOS版はこちらを参考。
SoftLayer Bluemix Community Festa 2016のIoTハンズオンにて、Android版のSensorTagアプリからIoT Foundationに接続できなかったので調べました(調べるといってSensor貸して頂きました。ありがとうございます)。
ハンズオンの資料はこちら。
アプリ設定
まず以下を行います。
- 上記の資料などを参考にIoT Foundation側を設定
- アプリをインストール
- アプリとセンサを起動
- SCAN -> 接続するセンサをconnect
- Advanceボタンを押下 -> Cloud Setup画面を表示
IoT Foundationの場合、MQTTのプロパティを以下のように設定するようです。
プロパティ | 内容 |
---|---|
Username | use-token-auth |
Password | <認証トークン> |
Device id | d:<組織 ID>:<デバイス・タイプ>:<デバイス ID> |
Broker Address | <組織ID>.messaging.internetofthings.ibmcloud.com |
Broker Port | 1883 |
Publish Topic | iot-2/evt/<任意の文字列>/fmt/json |
Device idと書いてありますが、dex2jarとjadをでdecompileしてソースを見たところ、
DeviceIdをClientIdとして使っているみたいでした。
繋がらない
上記の設定でワクワクしながらPush to Cloudしてみると以下の画面が!
ぐぐってみると、同様の事象が結構起こっている模様。
実際ハンズオンでもAndroidの人は繋がっていませんでした。
さらにぐぐってみると、こちらのstackoverflowを見つけました。なるほど。
You can solve it like that:
- get the SensorTag code here : https://git.ti.com/sensortag-20-android
- Open "IBMIoTCloudProfile" class
- line 245, change the connection code from
client.connect(options, new IMqttActionListener() > {....
to
client.connect(options,this.context, new > IMqttActionListener() {...
compile and install the updated app.
ちゃんとリポジトリあったみたいです。
実際にコードを見てみます。
....
public boolean connect() {
try {
memPer = new MemoryPersistence();
String url = config.brokerAddress + ":" + config.brokerPort;
Log.d("IBMIoTCloudProfile","Cloud Broker URL : " + url);
client = new MqttAndroidClient(this.context,url,config.deviceId);
MqttConnectOptions options = null;
if (config.service > CloudProfileConfigurationDialogFragment.DEF_CLOUD_IBMQUICKSTART_CLOUD_SERVICE) {
options = new MqttConnectOptions();
options.setCleanSession(config.cleanSession);
if (config.username.length() > 0)options.setUserName(config.username);
if (config.password.length() > 0)options.setPassword(config.password.toCharArray());
Log.d("IBMIoTCloudProfile","Adding Options : Clean Session : " + options.isCleanSession() + ", Username : " + config.username + ", " + "Password : " + "********");
}
client.connect(options, new IMqttActionListener() {...});
問題の箇所
client.connect(options, new IMqttActionListener(){...});
ここでclientであるMqttAndroidのコードを見てみます。
MqttAndroidの引数2個バージョンのconnect関数を見ると
1個目の引数にcontext、2個目にIMqttActionListenerとなっています。
@Override
public IMqttToken connect(Object userContext, IMqttActionListener callback)
throws MqttException {
return connect(new MqttConnectOptions(), userContext, callback);
}
@Override
public IMqttToken connect(MqttConnectOptions options, Object userContext,
IMqttActionListener callback) throws MqttException {
IMqttToken token = new MqttTokenAndroid(this, userContext,
callback);
...
-> client.connect(<MqttConnectOptions>, <MqttConnectOptions>, <IMqttActionListener>)という風になっていたのでエラーが起きていました。
なのでcom/example/ti/ble/common/IBMIoTCloudProfile.javaのコードをを以下のどちらかに修正します。
java
client.connect(options, this.context, new IMqttActionListener() {...});
client.connect(this.context, new IMqttActionListener() {...});
ビルド
修正してandroid studioでインポートしてビルド。
実行してみると、通信できているようにみえる!
IoT Foundationを確認してみると、正常にPushできていました。
ということで、Androidでも使えました。
署名も何もしていませんが、一応APKを置いておきます。
これupstreamに反映させるにはどうしたらいいんだろう