Make the connection establishment non blocking

This commit is contained in:
Michael Zanetti 2020-09-20 00:53:48 +02:00
parent 3bc92633ab
commit e9c345cc8b
12 changed files with 158 additions and 102 deletions

View File

@ -24,18 +24,18 @@ RESOURCES += controlviews/controlviews.qrc \
INCLUDEPATH += ../nymea-app/ INCLUDEPATH += ../nymea-app/
SOURCES += \ SOURCES += \
androidbinder.cpp \
controlviews/devicecontrolapplication.cpp \ controlviews/devicecontrolapplication.cpp \
nymeaappservice/nymeaappservice.cpp \ nymeaappservice/nymeaappservice.cpp \
nymeaappservice/androidbinder.cpp \
../nymea-app/stylecontroller.cpp \ ../nymea-app/stylecontroller.cpp \
../nymea-app/platformhelper.cpp \ ../nymea-app/platformhelper.cpp \
../nymea-app/platformintegration/android/platformhelperandroid.cpp \ ../nymea-app/platformintegration/android/platformhelperandroid.cpp \
service_main.cpp service_main.cpp
HEADERS += \ HEADERS += \
androidbinder.h \
controlviews/devicecontrolapplication.h \ controlviews/devicecontrolapplication.h \
nymeaappservice/nymeaappservice.h \ nymeaappservice/nymeaappservice.h \
nymeaappservice/androidbinder.h \
../nymea-app/stylecontroller.h \ ../nymea-app/stylecontroller.h \
../nymea-app/platformhelper.h \ ../nymea-app/platformhelper.h \
../nymea-app/platformintegration/android/platformhelperandroid.h \ ../nymea-app/platformintegration/android/platformhelperandroid.h \

View File

@ -37,6 +37,8 @@ DeviceControlApplication::DeviceControlApplication(int argc, char *argv[]) : QAp
settings.endGroup(); settings.endGroup();
NymeaDiscovery *discovery = new NymeaDiscovery(this); NymeaDiscovery *discovery = new NymeaDiscovery(this);
AWSClient::instance()->setConfig(settings.value("cloudEnvironment").toString());
discovery->setAwsClient(AWSClient::instance());
NymeaHost *host = discovery->nymeaHosts()->find(lastConnected); NymeaHost *host = discovery->nymeaHosts()->find(lastConnected);
qDebug() << "**** Tab settings" << lastConnected << host; qDebug() << "**** Tab settings" << lastConnected << host;

View File

@ -24,6 +24,7 @@ bool AndroidBinder::onTransact(int code, const QAndroidParcel &data, const QAndr
case 0: { // Status request case 0: { // Status request
qDebug() << "Engine is:" << m_engine->jsonRpcClient()->connected(); qDebug() << "Engine is:" << m_engine->jsonRpcClient()->connected();
bool isReady = m_engine->jsonRpcClient()->connected() && !m_engine->thingManager()->fetchingData(); bool isReady = m_engine->jsonRpcClient()->connected() && !m_engine->thingManager()->fetchingData();
isReady = false;
reply.handle().callMethod<void>("writeBoolean", "(Z)V", isReady); reply.handle().callMethod<void>("writeBoolean", "(Z)V", isReady);
if (isReady) { if (isReady) {
reply.handle().callMethod<void>("writeString", "(Ljava/lang/String;)V", QAndroidJniObject::fromString(m_engine->jsonRpcClient()->currentHost()->name()).object<jstring>()); reply.handle().callMethod<void>("writeString", "(Ljava/lang/String;)V", QAndroidJniObject::fromString(m_engine->jsonRpcClient()->currentHost()->name()).object<jstring>());
@ -34,7 +35,7 @@ bool AndroidBinder::onTransact(int code, const QAndroidParcel &data, const QAndr
for (int i = 0; i < m_engine->thingManager()->things()->rowCount(); i++) { for (int i = 0; i < m_engine->thingManager()->things()->rowCount(); i++) {
Device *thing = m_engine->thingManager()->things()->get(i); Device *thing = m_engine->thingManager()->things()->get(i);
QVariantMap thingMap; QVariantMap thingMap;
thingMap.insert("id", thing->id().toString()); thingMap.insert("id", thing->id());
thingMap.insert("name", thing->name()); thingMap.insert("name", thing->name());
thingMap.insert("className", thing->thingClass()->displayName()); thingMap.insert("className", thing->thingClass()->displayName());
thingMap.insert("interfaces", thing->thingClass()->interfaces()); thingMap.insert("interfaces", thing->thingClass()->interfaces());
@ -42,7 +43,7 @@ bool AndroidBinder::onTransact(int code, const QAndroidParcel &data, const QAndr
for (int j = 0; j < thing->states()->rowCount(); j++) { for (int j = 0; j < thing->states()->rowCount(); j++) {
State *state = thing->states()->get(j); State *state = thing->states()->get(j);
QVariantMap stateMap; QVariantMap stateMap;
stateMap.insert("stateTypeId", state->stateTypeId().toString()); stateMap.insert("stateTypeId", state->stateTypeId());
stateMap.insert("name", thing->thingClass()->stateTypes()->getStateType(state->stateTypeId())->name()); stateMap.insert("name", thing->thingClass()->stateTypes()->getStateType(state->stateTypeId())->name());
stateMap.insert("displayName", thing->thingClass()->stateTypes()->getStateType(state->stateTypeId())->displayName()); stateMap.insert("displayName", thing->thingClass()->stateTypes()->getStateType(state->stateTypeId())->displayName());
stateMap.insert("value", state->value()); stateMap.insert("value", state->value());
@ -53,7 +54,7 @@ bool AndroidBinder::onTransact(int code, const QAndroidParcel &data, const QAndr
for (int j = 0; j < thing->thingClass()->actionTypes()->rowCount(); j++) { for (int j = 0; j < thing->thingClass()->actionTypes()->rowCount(); j++) {
ActionType *actionType = thing->thingClass()->actionTypes()->get(j); ActionType *actionType = thing->thingClass()->actionTypes()->get(j);
QVariantMap actionMap; QVariantMap actionMap;
actionMap.insert("actionTypeId", actionType->id().toString()); actionMap.insert("actionTypeId", actionType->id());
actionMap.insert("name", actionType->name()); actionMap.insert("name", actionType->name());
actionMap.insert("displayName", actionType->displayName()); actionMap.insert("displayName", actionType->displayName());
actions.append(actionMap); actions.append(actionMap);

View File

@ -4,40 +4,61 @@
#include <QtAndroid> #include <QtAndroid>
#include <QDebug> #include <QDebug>
#include <QSettings> #include <QSettings>
#include <QJsonDocument>
#include "connection/discovery/nymeadiscovery.h" #include "connection/discovery/nymeadiscovery.h"
#include "connection/nymeahosts.h" #include "connection/nymeahosts.h"
NymeaAppService::NymeaAppService(int argc, char **argv): NymeaAppService::NymeaAppService(int argc, char **argv):
QAndroidService(argc, argv, [=](const QAndroidIntent &) { QAndroidService(argc, argv, [=](const QAndroidIntent &) {
qDebug() << "Android service onBind()";
return new AndroidBinder{m_engine}; return new AndroidBinder{m_engine};
}), })
m_engine(new Engine(this))
{ {
setApplicationName("nymea-app"); setApplicationName("nymea-app");
setOrganizationName("nymea"); setOrganizationName("nymea");
m_engine = new Engine(this);
QSettings settings; QSettings settings;
settings.beginGroup("tabSettings0"); settings.beginGroup("tabSettings0");
QUuid lastConnected = settings.value("lastConnectedHost").toUuid(); QUuid lastConnected = settings.value("lastConnectedHost").toUuid();
settings.endGroup(); settings.endGroup();
NymeaDiscovery *discovery = new NymeaDiscovery(); NymeaDiscovery *discovery = new NymeaDiscovery(this);
AWSClient::instance()->setConfig(settings.value("cloudEnvironment").toString());
discovery->setAwsClient(AWSClient::instance());
NymeaHost *host = discovery->nymeaHosts()->find(lastConnected); NymeaHost *host = discovery->nymeaHosts()->find(lastConnected);
qDebug() << "**** Tab settings" << lastConnected << host;
if (host) { if (host) {
m_engine->jsonRpcClient()->connectToHost(host); m_engine->jsonRpcClient()->connectToHost(host);
} }
QObject::connect(m_engine->thingManager(), &DeviceManager::thingStateChanged, [=](const QUuid &thingId, const QUuid &stateTypeId, const QVariant &value){ QObject::connect(m_engine->thingManager(), &DeviceManager::thingStateChanged, [=](const QUuid &thingId, const QUuid &stateTypeId, const QVariant &value){
// qDebug() << "**** State changed" << thingId << stateTypeId << value; QVariantMap params;
QtAndroid::androidService().callMethod<void>("sendBroadcast", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", params.insert("thingId", thingId);
QAndroidJniObject::fromString(thingId.toString()).object<jstring>(), params.insert("stateTypeId", stateTypeId);
QAndroidJniObject::fromString(stateTypeId.toString()).object<jstring>(), params.insert("value", value);
QAndroidJniObject::fromString(value.toString()).object<jstring>()); sendNotification("ThingStateChanged", params);
}); });
connect(m_engine->thingManager(), &DeviceManager::fetchingDataChanged, [=]() {
QVariantMap params;
params.insert("isReady", !m_engine->thingManager()->fetchingData());
if (m_engine->jsonRpcClient()->connected()) {
params.insert("systemName", m_engine->jsonRpcClient()->currentHost()->name());
}
sendNotification("ReadyStateChanged", params);
});
}
void NymeaAppService::sendNotification(const QString &notification, const QVariantMap &params)
{
QVariantMap data;
data.insert("notification", notification);
data.insert("params", params);
QString payload = QJsonDocument::fromVariant(data).toJson();
QtAndroid::androidService().callMethod<void>("sendBroadcast",
"(Ljava/lang/String;)V",
QAndroidJniObject::fromString(payload).object<jstring>());
} }

View File

@ -11,7 +11,10 @@ class NymeaAppService : public QAndroidService
public: public:
explicit NymeaAppService(int argc, char** argv); explicit NymeaAppService(int argc, char** argv);
signals: private:
void sendNotification(const QString &notification, const QVariantMap &params);
private: private:
Engine *m_engine = nullptr; Engine *m_engine = nullptr;

View File

@ -1,7 +1,9 @@
package io.guh.nymeaapp; package io.guh.nymeaapp;
import java.util.UUID;
public class Action { public class Action {
public String typeId; public UUID typeId;
public String name; public String name;
public String displayName; public String displayName;
} }

View File

@ -20,6 +20,7 @@ import java.util.concurrent.Flow.Publisher;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.UUID;
import java.util.HashMap; import java.util.HashMap;
import io.reactivex.Flowable; import io.reactivex.Flowable;
import io.reactivex.processors.ReplayProcessor; import io.reactivex.processors.ReplayProcessor;
@ -46,8 +47,9 @@ public class NymeaAppControlService extends ControlsProviderService {
@Override public void onReady() { @Override public void onReady() {
process(); process();
} }
@Override public void onUpdate(String thingId) { @Override public void onUpdate(UUID thingId) {
if (m_updatePublisher != null && m_activeControlIds.contains(thingId)) { Log.d(TAG, "onUpdate()");
if (m_updatePublisher != null && m_activeControlIds.contains(thingId.toString())) {
Thing thing = m_serviceConnection.getThing(thingId); Thing thing = m_serviceConnection.getThing(thingId);
Log.d(TAG, "Updating publisher for thing: " + thing.name + " id: " + thing.id); Log.d(TAG, "Updating publisher for thing: " + thing.name + " id: " + thing.id);
m_updatePublisher.onNext(thingToControl(thing)); m_updatePublisher.onNext(thingToControl(thing));
@ -79,7 +81,7 @@ public class NymeaAppControlService extends ControlsProviderService {
} }
if (m_updatePublisher != null) { if (m_updatePublisher != null) {
if (m_activeControlIds.contains(thing.id)) { if (m_activeControlIds.contains(thing.id.toString())) {
Log.d(TAG, "Adding stateful"); Log.d(TAG, "Adding stateful");
m_updatePublisher.onNext(thingToControl(thing)); m_updatePublisher.onNext(thingToControl(thing));
} }
@ -123,14 +125,14 @@ public class NymeaAppControlService extends ControlsProviderService {
//// pendingAction.consumer = consumer; //// pendingAction.consumer = consumer;
//// m_pendingActions.put( //// m_pendingActions.put(
Thing thing = m_serviceConnection.getThing(controlId); Thing thing = m_serviceConnection.getThing(UUID.fromString(controlId));
if (thing == null) { if (thing == null) {
Log.d(TAG, "Thing not found for id: " + controlId); Log.d(TAG, "Thing not found for id: " + controlId);
consumer.accept(ControlAction.RESPONSE_FAIL); consumer.accept(ControlAction.RESPONSE_FAIL);
return; return;
} }
String actionTypeId; UUID actionTypeId;
String param; String param;
if (thing.interfaces.contains("dimmablelight") && action instanceof FloatAction) { if (thing.interfaces.contains("dimmablelight") && action instanceof FloatAction) {
actionTypeId = thing.stateByName("brightness").typeId; actionTypeId = thing.stateByName("brightness").typeId;
@ -165,7 +167,7 @@ public class NymeaAppControlService extends ControlsProviderService {
} }
private HashMap<String, Integer> m_intents = new HashMap<String, Integer>(); private HashMap<UUID, Integer> m_intents = new HashMap<UUID, Integer>();
private Control thingToControl(Thing thing) { private Control thingToControl(Thing thing) {
// Log.d(TAG, "Creating control for thing: " + thing.name + " id: " + thing.id); // Log.d(TAG, "Creating control for thing: " + thing.name + " id: " + thing.id);
@ -182,23 +184,23 @@ public class NymeaAppControlService extends ControlsProviderService {
Context context = getBaseContext(); Context context = getBaseContext();
Intent intent = new Intent(context, NymeaAppControlsActivity.class); Intent intent = new Intent(context, NymeaAppControlsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.putExtra("thingId", thing.id); intent.putExtra("thingId", thing.id.toString());
pi = PendingIntent.getActivity(context, intentId, intent, PendingIntent.FLAG_UPDATE_CURRENT); pi = PendingIntent.getActivity(context, intentId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Log.d(TAG, "Created pendingintent for " + thing.name + " with id " + intentId + " and extra " + thing.id); Log.d(TAG, "Created pendingintent for " + thing.name + " with id " + intentId + " and extra " + thing.id);
Control.StatefulBuilder builder = new Control.StatefulBuilder(thing.id, pi) Control.StatefulBuilder builder = new Control.StatefulBuilder(thing.id.toString(), pi)
.setTitle(thing.name) .setTitle(thing.name)
.setSubtitle(thing.className) .setSubtitle(thing.className)
.setStructure(m_serviceConnection.nymeaName()); .setStructure(m_serviceConnection.nymeaName());
if (thing.interfaces.contains("impulsebasedgaragedoor")) { if (thing.interfaces.contains("impulsebasedgaragedoor")) {
builder.setDeviceType(DeviceTypes.TYPE_GARAGE); builder.setDeviceType(DeviceTypes.TYPE_GARAGE);
builder.setControlTemplate(new StatelessTemplate(thing.id)); builder.setControlTemplate(new StatelessTemplate(thing.id.toString()));
} else if (thing.interfaces.contains("statefulgaragedoor")) { } else if (thing.interfaces.contains("statefulgaragedoor")) {
builder.setDeviceType(DeviceTypes.TYPE_GARAGE); builder.setDeviceType(DeviceTypes.TYPE_GARAGE);
State stateState = thing.stateByName("state"); State stateState = thing.stateByName("state");
ControlButton controlButton = new ControlButton(stateState.value.equals("open"), stateState.displayName); ControlButton controlButton = new ControlButton(stateState.value.equals("open"), stateState.displayName);
builder.setControlTemplate(new ToggleTemplate(thing.id, controlButton)); builder.setControlTemplate(new ToggleTemplate(thing.id.toString(), controlButton));
// } else if (thing.interfaces.contains("extendedstatefulgaragedoor")) { // } else if (thing.interfaces.contains("extendedstatefulgaragedoor")) {
// builder.setDeviceTyoe(DeviceTypes.TYPE_GARAGE); // builder.setDeviceTyoe(DeviceTypes.TYPE_GARAGE);
@ -210,16 +212,16 @@ public class NymeaAppControlService extends ControlsProviderService {
if (thing.interfaces.contains("dimmablelight")) { if (thing.interfaces.contains("dimmablelight")) {
State brightnessState = thing.stateByName("brightness"); State brightnessState = thing.stateByName("brightness");
RangeTemplate rangeTemplate = new RangeTemplate(thing.id, 0, 100, Float.parseFloat(brightnessState.value), 1, brightnessState.displayName); RangeTemplate rangeTemplate = new RangeTemplate(thing.id.toString(), 0, 100, Float.parseFloat(brightnessState.value), 1, brightnessState.displayName);
builder.setControlTemplate(new ToggleRangeTemplate(thing.id, controlButton, rangeTemplate)); builder.setControlTemplate(new ToggleRangeTemplate(thing.id.toString(), controlButton, rangeTemplate));
} else { } else {
builder.setControlTemplate(new ToggleTemplate(thing.id, controlButton)); builder.setControlTemplate(new ToggleTemplate(thing.id.toString(), controlButton));
} }
} else if (thing.interfaces.contains("powersocket")) { } else if (thing.interfaces.contains("powersocket")) {
builder.setDeviceType(DeviceTypes.TYPE_OUTLET); builder.setDeviceType(DeviceTypes.TYPE_OUTLET);
State powerState = thing.stateByName("power"); State powerState = thing.stateByName("power");
ControlButton controlButton = new ControlButton(powerState.value.equals("true"), powerState.displayName); ControlButton controlButton = new ControlButton(powerState.value.equals("true"), powerState.displayName);
builder.setControlTemplate(new ToggleTemplate(thing.id, controlButton)); builder.setControlTemplate(new ToggleTemplate(thing.id.toString(), controlButton));
} else if (thing.interfaces.contains("mediaplayer")) { } else if (thing.interfaces.contains("mediaplayer")) {
if (thing.stateByName("playerType").value == "video") { if (thing.stateByName("playerType").value == "video") {
builder.setDeviceType(DeviceTypes.TYPE_TV); builder.setDeviceType(DeviceTypes.TYPE_TV);
@ -229,7 +231,7 @@ public class NymeaAppControlService extends ControlsProviderService {
} }
if (thing.interfaces.contains("extendedvolumecontroller")) { if (thing.interfaces.contains("extendedvolumecontroller")) {
State volumeState = thing.stateByName("volume"); State volumeState = thing.stateByName("volume");
RangeTemplate rangeTemplate = new RangeTemplate(thing.id, 0, 100, Float.parseFloat(volumeState.value), 1, volumeState.displayName); RangeTemplate rangeTemplate = new RangeTemplate(thing.id.toString(), 0, 100, Float.parseFloat(volumeState.value), 1, volumeState.displayName);
builder.setControlTemplate(rangeTemplate); builder.setControlTemplate(rangeTemplate);
} }
} else { } else {

View File

@ -13,7 +13,7 @@ import org.qtproject.qt5.android.bindings.QtService;
public class NymeaAppService extends QtService public class NymeaAppService extends QtService
{ {
public static final String BROADCAST_STATE_CHANGE = "io.guh.nymeaapp.NymeaAppService.broadcast.stateChanged"; public static final String NYMEA_APP_BROADCAST = "io.guh.nymeaapp.NymeaAppService.broadcast";
private static final String TAG = "nymea-app: NymeaAppService"; private static final String TAG = "nymea-app: NymeaAppService";
@ -40,13 +40,10 @@ public class NymeaAppService extends QtService
return ret; return ret;
} }
public void sendBroadcast(String thingId, String stateTypeId, String value) { public void sendBroadcast(String payload) {
Intent sendToUiIntent = new Intent(); Intent sendToUiIntent = new Intent();
sendToUiIntent.setAction(BROADCAST_STATE_CHANGE); sendToUiIntent.setAction(NYMEA_APP_BROADCAST);
sendToUiIntent.putExtra("name", "io.guh.nymeaapp.NymeaAppService"); sendToUiIntent.putExtra("data", payload);
sendToUiIntent.putExtra("thingId", thingId);
sendToUiIntent.putExtra("stateTypeId", stateTypeId);
sendToUiIntent.putExtra("value", value);
// Log.d(TAG, "Service sending broadcast"); // Log.d(TAG, "Service sending broadcast");
sendBroadcast(sendToUiIntent); sendBroadcast(sendToUiIntent);
} }

View File

@ -2,6 +2,7 @@ package io.guh.nymeaapp;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.UUID;
import android.util.Log; import android.util.Log;
@ -59,7 +60,7 @@ public class NymeaAppServiceConnection implements ServiceConnection {
final public ArrayList<Thing> getThings() { final public ArrayList<Thing> getThings() {
return m_things; return m_things;
} }
final public Thing getThing(String thingId) { final public Thing getThing(UUID thingId) {
for (int i = 0; i < m_things.size(); i++) { for (int i = 0; i < m_things.size(); i++) {
if (m_things.get(i).id.equals(thingId)) { if (m_things.get(i).id.equals(thingId)) {
return m_things.get(i); return m_things.get(i);
@ -70,13 +71,13 @@ public class NymeaAppServiceConnection implements ServiceConnection {
public void onReady() {} public void onReady() {}
public void onError() {} public void onError() {}
public void onUpdate(String thingId) {} public void onUpdate(UUID thingId) {}
final public void executeAction(String thingId, String actionTypeId, String param) { final public void executeAction(UUID thingId, UUID actionTypeId, String param) {
try { try {
Parcel parcel = Parcel.obtain(); Parcel parcel = Parcel.obtain();
parcel.writeByteArray(thingId.getBytes()); parcel.writeByteArray(thingId.toString().getBytes());
parcel.writeByteArray(actionTypeId.getBytes()); parcel.writeByteArray(actionTypeId.toString().getBytes());
parcel.writeByteArray(param.getBytes()); parcel.writeByteArray(param.getBytes());
Parcel retParcel = Parcel.obtain(); Parcel retParcel = Parcel.obtain();
m_service.transact(2, parcel, retParcel, 0); m_service.transact(2, parcel, retParcel, 0);
@ -90,29 +91,87 @@ public class NymeaAppServiceConnection implements ServiceConnection {
Log.d(TAG, "Connected to NymeaAppService"); Log.d(TAG, "Connected to NymeaAppService");
m_service = service; m_service = service;
registerServiceBroadcastReceiver();
try { try {
boolean ready = false; Parcel parcel = Parcel.obtain();
Log.d(TAG, "Waiting for service to be connected to nymea..."); Parcel retParcel = Parcel.obtain();
do { m_service.transact(0, parcel, retParcel, 0);
Parcel parcel = Parcel.obtain(); m_isReady = retParcel.readBoolean();
Parcel retParcel = Parcel.obtain(); if (!m_isReady) {
m_service.transact(0, parcel, retParcel, 0); m_nymeaName = retParcel.readString();
ready = retParcel.readBoolean(); m_isConnectedToNymea = true;
if (!ready) { Log.d(TAG, "Service is ready!");
Thread.sleep(100); fetchThings();
} else { } else {
m_nymeaName = retParcel.readString(); Log.d(TAG, "Service is not ready yet!");
} }
} while (!ready);
Log.d(TAG, "Service connected to nymea!");
m_isConnectedToNymea = true;
} catch (Exception e) { } catch (Exception e) {
Log.d(TAG, "Error while waiting for service to be connected to nymea"); Log.d(TAG, "Error while waiting for service to be connected to nymea");
m_service = null; m_service = null;
onError(); onError();
return; return;
} }
}
@Override public void onServiceDisconnected(ComponentName arg0) {
m_service = null;
m_isConnectedToNymea = false;
m_isReady = false;
}
public void registerServiceBroadcastReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(NymeaAppService.NYMEA_APP_BROADCAST);
m_context.registerReceiver(serviceMessageReceiver, intentFilter);
Log.d(TAG, "Registered broadcast receiver");
}
private BroadcastReceiver serviceMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Log.d(TAG, "In OnReceive broadcast receiver");
if (NymeaAppService.NYMEA_APP_BROADCAST.equals(intent.getAction())) {
String payload = intent.getStringExtra("data");
try {
processBroadcast(payload);
} catch(JSONException e) {
Log.d(TAG, "Error parsing broadcast JSON: " + e.toString());
}
}
}
};
private void processBroadcast(String payload) throws JSONException
{
JSONObject data = new JSONObject(payload);
JSONObject params = data.getJSONObject("params");
Log.d(TAG, "Broadcast received from NymeaAppService: " + data.getString("notification"));
if (data.getString("notification").equals("ThingStateChanged")) {
UUID thingId = UUID.fromString(params.getString("thingId"));
UUID stateTypeId = UUID.fromString(params.getString("stateTypeId"));
String value = params.getString("value");
Log.d(TAG, "Thing state changed: " + thingId + " stateTypeId: " + stateTypeId + " value: " + value);
for (int i = 0; i < m_things.size(); i++) {
if (m_things.get(i).id.equals(thingId)) {
m_things.get(i).stateById(stateTypeId).value = value;
onUpdate(thingId);
}
}
}
if (data.getString("notification").equals("ReadyStateChanged")) {
m_isReady = params.getBoolean("isReady");
if (m_isReady) {
m_nymeaName = params.getString("systemName");
fetchThings();
}
}
}
private void fetchThings() {
String thingsList; String thingsList;
try { try {
Log.d(TAG, "Fetching things"); Log.d(TAG, "Fetching things");
@ -135,7 +194,7 @@ public class NymeaAppServiceConnection implements ServiceConnection {
for (int i = 0; i < arr.length(); i++) { for (int i = 0; i < arr.length(); i++) {
JSONObject entry = arr.getJSONObject(i); JSONObject entry = arr.getJSONObject(i);
Thing thing = new Thing(); Thing thing = new Thing();
thing.id = entry.getString("id"); thing.id = UUID.fromString(entry.getString("id"));
thing.name = entry.getString("name"); thing.name = entry.getString("name");
thing.className = entry.getString("className"); thing.className = entry.getString("className");
JSONArray ifaces = entry.getJSONArray("interfaces"); JSONArray ifaces = entry.getJSONArray("interfaces");
@ -146,7 +205,7 @@ public class NymeaAppServiceConnection implements ServiceConnection {
for (int j = 0; j < states.length(); j++) { for (int j = 0; j < states.length(); j++) {
JSONObject stateMap = states.getJSONObject(j); JSONObject stateMap = states.getJSONObject(j);
State s = new State(); State s = new State();
s.typeId = stateMap.getString("stateTypeId"); s.typeId = UUID.fromString(stateMap.getString("stateTypeId"));
s.name = stateMap.getString("name"); s.name = stateMap.getString("name");
s.displayName = stateMap.getString("displayName"); s.displayName = stateMap.getString("displayName");
s.value = stateMap.getString("value"); s.value = stateMap.getString("value");
@ -156,7 +215,7 @@ public class NymeaAppServiceConnection implements ServiceConnection {
for (int j = 0; j < actions.length(); j++) { for (int j = 0; j < actions.length(); j++) {
JSONObject actionMap = actions.getJSONObject(j); JSONObject actionMap = actions.getJSONObject(j);
Action a = new Action(); Action a = new Action();
a.typeId = actionMap.getString("actionTypeId"); a.typeId = UUID.fromString(actionMap.getString("actionTypeId"));
a.name = actionMap.getString("name"); a.name = actionMap.getString("name");
a.displayName = actionMap.getString("displayName"); a.displayName = actionMap.getString("displayName");
thing.actions.add(a); thing.actions.add(a);
@ -165,7 +224,7 @@ public class NymeaAppServiceConnection implements ServiceConnection {
} }
} catch (Exception e) { } catch (Exception e) {
Log.d(TAG, "Error parsing JSON from NymeaAppService: " + thingsList); Log.d(TAG, "Error parsing JSON from NymeaAppService: " + e.toString());
m_service = null; m_service = null;
m_isConnectedToNymea = false; m_isConnectedToNymea = false;
onError(); onError();
@ -175,40 +234,5 @@ public class NymeaAppServiceConnection implements ServiceConnection {
Log.d(TAG, "Fetched things"); Log.d(TAG, "Fetched things");
m_isReady = true; m_isReady = true;
onReady(); onReady();
registerServiceBroadcastReceiver();
} }
@Override public void onServiceDisconnected(ComponentName arg0) {
m_service = null;
m_isConnectedToNymea = false;
m_isReady = false;
}
public void registerServiceBroadcastReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(NymeaAppService.BROADCAST_STATE_CHANGE);
m_context.registerReceiver(serviceMessageReceiver, intentFilter);
Log.d(TAG, "Registered broadcast receiver");
}
private BroadcastReceiver serviceMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Log.d(TAG, "In OnReceive broadcast receiver");
if (NymeaAppService.BROADCAST_STATE_CHANGE.equals(intent.getAction())) {
String name = intent.getStringExtra("name");
String thingId = intent.getStringExtra("thingId");
String stateTypeId = intent.getStringExtra("stateTypeId");
String value = intent.getStringExtra("value");
// Log.d(TAG, "Thing state changed: " + thingId + " stateTypeId: " + stateTypeId + " value: " + value);
for (int i = 0; i < m_things.size(); i++) {
if (m_things.get(i).id.equals(thingId)) {
m_things.get(i).stateById(stateTypeId).value = value;
onUpdate(thingId);
}
}
}
}
};
} }

View File

@ -1,7 +1,9 @@
package io.guh.nymeaapp; package io.guh.nymeaapp;
import java.util.UUID;
public class State { public class State {
public String typeId; public UUID typeId;
public String name; public String name;
public String displayName; public String displayName;
public String value; public String value;

View File

@ -4,10 +4,12 @@ import android.util.Log;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.UUID;
public class Thing { public class Thing {
static final public String TAG = "nymea-app: Thing"; static final public String TAG = "nymea-app: Thing";
public String id; public UUID id;
public String name; public String name;
public String className; public String className;
public List interfaces = new ArrayList<State>(); public List interfaces = new ArrayList<State>();
@ -24,7 +26,7 @@ public class Thing {
return null; return null;
} }
public State stateById(String stateTypeId) { public State stateById(UUID stateTypeId) {
for (int i = 0; i < states.size(); i++) { for (int i = 0; i < states.size(); i++) {
if (states.get(i).typeId.equals(stateTypeId)) { if (states.get(i).typeId.equals(stateTypeId)) {
return states.get(i); return states.get(i);
@ -43,7 +45,7 @@ public class Thing {
return null; return null;
} }
public Action actionById(String actionTypeId) { public Action actionById(UUID actionTypeId) {
for (int i = 0; i < actions.size(); i++) { for (int i = 0; i < actions.size(); i++) {
if (actions.get(i).typeId.equals(actionTypeId)) { if (actions.get(i).typeId.equals(actionTypeId)) {
return actions.get(i); return actions.get(i);