/*
AWSIotLocalManager.java
Copyright (c) 2016 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.deviceplugin.awsiot.local;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import org.deviceconnect.android.deviceplugin.awsiot.cores.core.AWSIotController;
import org.deviceconnect.android.deviceplugin.awsiot.cores.core.AWSIotPrefUtil;
import org.deviceconnect.android.deviceplugin.awsiot.cores.core.RemoteDeviceConnectManager;
import org.deviceconnect.android.deviceplugin.awsiot.cores.util.AWSIotUtil;
import org.deviceconnect.android.deviceplugin.awsiot.remote.BuildConfig;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AWSIotLocalManager {
private static final boolean DEBUG = BuildConfig.DEBUG;
private static final String TAG = "AWS-Local";
private RemoteDeviceConnectManager mRemoteManager;
private AWSIotWebLocalClientManager mAWSIotWebClientManager;
private AWSIotWebLocalServerManager mAWSIotWebServerManager;
private Context mContext;
private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
private String mSessionKey = UUID.randomUUID().toString();
private AWSIotController mIot;
private AWSIotPrefUtil mPrefUtil;
private long mSyncTime = 0;
private Handler mTimerHandler = new Handler();
private String mSendData;
private boolean mIsSendWait = false;
private boolean mIsTimerEnable = false;
public AWSIotLocalManager(final Context context, final AWSIotController controller, final RemoteDeviceConnectManager remote) {
mContext = context;
mIot = controller;
mRemoteManager = remote;
mPrefUtil = new AWSIotPrefUtil(mContext);
mIot.addOnAWSIotEventListener(mOnAWSIotEventListener);
}
public AWSIotController getAWSIotController() {
return mIot;
}
public void connectAWSIoT() {
if (DEBUG) {
Log.i(TAG, "AWSIotLocalManager#connectAWSIoT");
}
mAWSIotWebClientManager = new AWSIotWebLocalClientManager(mContext, this);
mAWSIotWebServerManager = new AWSIotWebLocalServerManager(mContext, this);
DConnectHelper.INSTANCE.openWebSocket(mOnMessageEventListener);
subscribeTopic();
}
public void disconnectAWSIoT() {
if (DEBUG) {
Log.i(TAG, "AWSIotLocalManager#disconnectAWSIoT");
}
mIot.removeOnAWSIotEventListener(mOnAWSIotEventListener);
DConnectHelper.INSTANCE.closeWebSocket();
if (mAWSIotWebClientManager != null) {
mAWSIotWebClientManager.destroy();
mAWSIotWebClientManager = null;
}
if (mAWSIotWebServerManager != null) {
mAWSIotWebServerManager.destroy();
mAWSIotWebServerManager = null;
}
unsubscribeTopic();
}
public void publish(final String message) {
if (mIot != null) {
mIot.publish(mRemoteManager.getResponseTopic(), message);
}
}
public void publishEvent(final String message) {
mSyncTime = (mPrefUtil.getSyncTime()) * 1000;
if (mSyncTime <= 0) {
mIot.publish(mRemoteManager.getEventTopic(), message);
} else {
mSendData = message;
mIsSendWait = true;
if (!mIsTimerEnable) {
mIsTimerEnable = true;
mIot.publish(mRemoteManager.getEventTopic(), mSendData);
mIsSendWait = false;
mTimerHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (mIsSendWait) {
mIot.publish(mRemoteManager.getEventTopic(), mSendData);
mIsSendWait = false;
mTimerHandler.postDelayed(this, mSyncTime);
} else {
mIsTimerEnable = false;
}
}
}, mSyncTime);
}
}
}
private void subscribeTopic() {
if (mIot != null) {
mIot.subscribe(mRemoteManager.getRequestTopic(), mMessageCallback);
}
}
private void unsubscribeTopic() {
if (mIot != null) {
mIot.unsubscribe(mRemoteManager.getRequestTopic());
}
}
private void parseMQTT(final String message) {
try {
JSONObject json = new JSONObject(message);
long requestCode = json.optLong("requestCode");
JSONObject request = json.optJSONObject(AWSIotUtil.KEY_REQUEST);
if (request != null) {
onReceivedDeviceConnectRequest(requestCode, request.toString());
}
JSONObject p2p = json.optJSONObject(AWSIotUtil.KEY_P2P_REMOTE);
if (p2p != null) {
mAWSIotWebClientManager.onReceivedSignaling(p2p.toString());
}
JSONObject p2pa = json.optJSONObject(AWSIotUtil.KEY_P2P_LOCAL);
if (p2pa != null) {
mAWSIotWebServerManager.onReceivedSignaling(p2pa.toString());
}
} catch (JSONException e) {
if (DEBUG) {
Log.w(TAG, "", e);
}
}
}
private void onReceivedDeviceConnectRequest(final long requestCode, final String request) {
if (DEBUG) {
Log.i(TAG, "onReceivedDeviceConnectRequest: request=" + request);
}
DConnectHelper.INSTANCE.sendRequest(request, new DConnectHelper.ConversionCallback() {
@Override
public String convertUri(final String uri) {
Uri u = Uri.parse(uri);
if (u.getHost().equals("localhost") || u.getHost().equals("127.0.0.1")) {
return mAWSIotWebServerManager.createWebServer(u.getAuthority(), u.getEncodedPath() + "?" + u.getEncodedQuery());
} else {
return uri;
}
}
@Override
public String convertSessionKey(final String sessionKey) {
return mSessionKey;
}
}, new DConnectHelper.FinishCallback() {
@Override
public void onFinish(final String response, final Exception error) {
if (DEBUG) {
Log.d(TAG, "onReceivedDeviceConnectRequest: requestCode=" + requestCode + " response=" + response);
}
publish(AWSIotUtil.createResponse(requestCode, response));
}
});
}
private final AWSIotWebSocketClient.OnMessageEventListener mOnMessageEventListener = new AWSIotWebSocketClient.OnMessageEventListener() {
@Override
public void onMessage(final String message) {
publishEvent(message);
}
};
private final AWSIotController.MessageCallback mMessageCallback = new AWSIotController.MessageCallback() {
@Override
public void onReceivedMessage(final String topic, final String message, final Exception err) {
if (DEBUG) {
Log.d(TAG, "AWSIoTLocalManager#onReceivedMessage");
Log.d(TAG, "topic=" + topic);
Log.d(TAG, "message=" + message);
}
if (err != null) {
if (DEBUG) {
Log.w(TAG, "", err);
}
return;
}
if (!topic.equals(mRemoteManager.getRequestTopic())) {
if (DEBUG) {
Log.e(TAG, "Not found the RemoteDeviceConnectManager. topic=" + topic);
}
return;
}
mExecutorService.submit(new Runnable() {
@Override
public void run() {
parseMQTT(message);
}
});
}
};
private final AWSIotController.OnAWSIotEventListener mOnAWSIotEventListener = new AWSIotController.OnAWSIotEventListener() {
@Override
public void onLogin() {
}
@Override
public void onConnected() {
subscribeTopic();
}
};
}