Skip to content

Commit

Permalink
- Implemented Meross cloud paring vs custom
Browse files Browse the repository at this point in the history
- Fix wifi-handlers being called multiple times
- Improved wifi-location warning banner logic
- Minor labeling and textual refactor
- Minor UI improvements
  • Loading branch information
albertogeniola committed Jan 22, 2022
1 parent 841fb5e commit 0493c8a
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 32 deletions.
4 changes: 2 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">

<!-- android:theme="@style/AppTheme.NoActionBar" -->

<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:label="@string/title_activity_main"
android:theme="@style/Theme.MaterialComponents.Light.NoActionBar"
android:theme="@style/AppTheme"
/>
<activity
android:name=".PairActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ public class Constants {
public static final String HA_ADDON_DEFAULT_EMAIL = "meross_local@local";
public static final String HA_ADDON_DEFAULT_PASSWORD = "Changeme!";

public static final long PAIRING_VERIFY_TIMEOUT_MILLISECONDS = 30000;
public static final long MDNS_DISCOVERY_TIMEOUT_MILLISEOONDS = 5000;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.albertogeniola.merossconf.model.MerossDeviceAp;
import com.albertogeniola.merossconf.model.WifiConfiguration;
import com.albertogeniola.merossconf.model.WifiLocationStatus;
import com.albertogeniola.merosslib.model.http.ApiCredentials;
import com.albertogeniola.merosslib.model.protocol.MessageGetConfigWifiListResponse;
import com.albertogeniola.merosslib.model.protocol.MessageGetSystemAllResponse;

Expand All @@ -20,6 +21,8 @@ public class PairActivityViewModel extends ViewModel {
private MutableLiveData<MqttConfiguration> targetMqttConfig;
private MutableLiveData<MessageGetSystemAllResponse> deviceInfo;
private MutableLiveData<WifiLocationStatus> wifiLocationStatus;
private MutableLiveData<String> overridedKey;
private MutableLiveData<String> overridedUserId;


public PairActivityViewModel() {
Expand All @@ -30,6 +33,8 @@ public PairActivityViewModel() {
deviceInfo = new MutableLiveData<>(null);
deviceAvailableWifis = new MutableLiveData<>(null);
wifiLocationStatus = new MutableLiveData<>(null);
overridedKey = new MutableLiveData<>(null);
overridedUserId = new MutableLiveData<>(null);
}

public LiveData<com.albertogeniola.merosslib.MerossDeviceAp> getDevice() {
Expand Down Expand Up @@ -80,4 +85,18 @@ public LiveData<WifiLocationStatus> getWifiLocationStatus() {
public void setWifiLocationStatus(WifiLocationStatus status) {
this.wifiLocationStatus.setValue(status);
}

public LiveData<String> getOverridedUserId() {
return this.overridedUserId;
}
public void setOverrideUserId(String overrideUserId) {
this.overridedUserId.setValue(overrideUserId);
}

public LiveData<String> getOverridedKey() {
return this.overridedKey;
}
public void setOverrideKey(String overrideKey) {
this.overridedKey.setValue(overrideKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

Expand Down Expand Up @@ -44,10 +45,17 @@ public View onCreateView(@NonNull LayoutInflater inflater,
final Button merossCloudLoginButton = root.findViewById(R.id.merossCloudLoginButton);
final CardView loginCardView = root.findViewById(R.id.loginCard);
final Button manualSetupButton = root.findViewById(R.id.setManualButton);
final ImageView loggedInAccountLogoImageView = root.findViewById(R.id.loggedInAccountLogo);

mainActivityViewModel.getCredentials().observe(getViewLifecycleOwner(), new Observer<ApiCredentials>() {
@Override
public void onChanged(ApiCredentials apiCredentials) {
if (apiCredentials == null || apiCredentials.getApiServer().compareTo(Constants.MEROSS_CLOUD_EP)==0) {
loggedInAccountLogoImageView.setImageResource(R.drawable.meross_logo);
} else {
loggedInAccountLogoImageView.setImageResource(R.drawable.ha_logo);
}

if (apiCredentials == null || Strings.isEmpty(apiCredentials.getApiServer())) {
httpUrlEditText.setText("Not set");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ public void onCreate(Bundle savedInstanceState) {
@Override
public void onDestroy() {
super.onDestroy();
}

@Override
public void onDestroyView() {
super.onDestroyView();

// Unschedule the timeout task, if any
if (mTimeoutTask!=null) {
Expand All @@ -108,7 +113,6 @@ public void onDestroy() {
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
}


@Override
public void onPause() {
super.onPause();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.albertogeniola.merossconf.R;
import com.albertogeniola.merossconf.model.MqttConfiguration;
import com.albertogeniola.merossconf.ui.PairActivityViewModel;
import com.albertogeniola.merosslib.model.http.ApiCredentials;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;

import java.util.List;
Expand All @@ -35,6 +37,9 @@ public class ConfigureMqttFragment extends Fragment {
private TextInputLayout mqttPortEditText;
private Spinner mqttConfigurationSpinner;
private CheckBox saveCheckbox;
private CheckBox overrideMqttParamsCheckbox;
private TextInputLayout customMqttUserId;
private TextInputLayout customMqttKey;
private MqttConfiguration mDiscoveredConfig;
private ArrayAdapter<MqttConfiguration> adapter;
private MqttConfiguration newMqttConfig = new MqttConfiguration("Add new...", null, -1);
Expand Down Expand Up @@ -81,6 +86,12 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
mqttPortEditText = view.findViewById(R.id.mqttPortEditText);
Button pairButton = view.findViewById(R.id.pairButton);
saveCheckbox = view.findViewById(R.id.saveCheckbox);
customMqttUserId = view.findViewById(R.id.customMqttUserId);
customMqttKey = view.findViewById(R.id.customMqttKey);
overrideMqttParamsCheckbox = view.findViewById(R.id.overrideMqttParams);

customMqttKey.setVisibility(View.GONE);
customMqttUserId.setVisibility(View.GONE);

List<MqttConfiguration> configurations = AndroidPreferencesManager.loadAllMqttConfigurations(requireContext());
configurations.add(this.newMqttConfig);
Expand All @@ -94,6 +105,13 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mqttConfigurationNameEditText.setVisibility(isChecked ? View.VISIBLE : View.GONE);
}
});
overrideMqttParamsCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
customMqttUserId.setVisibility(isChecked ? View.VISIBLE:View.GONE);
customMqttKey.setVisibility(isChecked ? View.VISIBLE:View.GONE);
}
});
mqttConfigurationSpinner.setAdapter(adapter);

mqttConfigurationSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
Expand Down Expand Up @@ -187,6 +205,14 @@ public void onClick(View v) {
pairActivityViewModel.setTargetMqttConfig(tmp);
}

if (overrideMqttParamsCheckbox.isChecked()) {
pairActivityViewModel.setOverrideKey(customMqttKey.getEditText().toString());
pairActivityViewModel.setOverrideUserId(customMqttUserId.getEditText().toString());
} else {
pairActivityViewModel.setOverrideKey(null);
pairActivityViewModel.setOverrideUserId(null);
}

NavController ctrl = NavHostFragment.findNavController(ConfigureMqttFragment.this);
ctrl.navigate(R.id.action_configureMqtt_to_executePair, null, new NavOptions.Builder().setEnterAnim(android.R.animator.fade_in).setExitAnim(android.R.animator.fade_out).build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import androidx.navigation.fragment.NavHostFragment;

import com.albertogeniola.merossconf.AndroidPreferencesManager;
import com.albertogeniola.merossconf.Constants;
import com.albertogeniola.merossconf.MerossUtils;
import com.albertogeniola.merossconf.R;
import com.albertogeniola.merossconf.model.WifiConfiguration;
Expand Down Expand Up @@ -198,10 +199,10 @@ private void startApiDiscovery() {
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}

// Start a timer for aborting discovery after 10 seconds if nothing is found.
// Start a timer for aborting discovery after some time if nothing is found.
if (mTimer == null) {
mTimer = new Timer();
mTimer.schedule(new ConfigureWifiFragment.TimeoutTask(), 5000);
mTimer.schedule(new ConfigureWifiFragment.TimeoutTask(), Constants.MDNS_DISCOVERY_TIMEOUT_MILLISEOONDS);
}
}

Expand Down Expand Up @@ -307,8 +308,10 @@ private void notifyResolveCompleted(@Nullable final String hostname,
}

// Cancel the timeout task
if (mTimer!=null)
if (mTimer!=null) {
mTimer.cancel();
mTimer = null;
}

Runnable r = new Runnable() {
@Override
Expand Down Expand Up @@ -457,7 +460,6 @@ public void onServiceResolved(final NsdServiceInfo serviceInfo) {
private class TimeoutTask extends TimerTask {
@Override
public void run() {
mTimer = null;
if (mDiscoveryInProgress)
mNsdManager.stopServiceDiscovery(mDiscoveryListener);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import androidx.navigation.fragment.NavHostFragment;

import com.albertogeniola.merossconf.AndroidPreferencesManager;
import com.albertogeniola.merossconf.Constants;
import com.albertogeniola.merossconf.R;
import com.albertogeniola.merossconf.model.MqttConfiguration;
import com.albertogeniola.merossconf.model.exception.PermissionNotGrantedException;
Expand Down Expand Up @@ -76,7 +77,7 @@ private void stateMachine(Signal signal) {
if (signal == Signal.RESUMED) {connectToDeviceWifiAp();}
break;
case CONNECTING_DEVICE_WIFI_AP:
if (signal == Signal.DEVICE_WIFI_CONNECTED) {configureDevice(mCreds.getUserId(), mCreds.getKey());}
if (signal == Signal.DEVICE_WIFI_CONNECTED) {configureDevice();}
break;
case SENDING_PAIRING_COMMAND:
if (signal == Signal.DEVICE_CONFIGURED) {
Expand All @@ -93,6 +94,7 @@ private void stateMachine(Signal signal) {
break;
case VERIFYING_PAIRING_SUCCEEDED:
if (signal == Signal.DEVICE_PAIRED) {completeActivityFragment(true);}
if (signal == Signal.MISSING_CONFIRMATION) {completeActivityFragment(false);}
break;
}

Expand Down Expand Up @@ -142,7 +144,7 @@ private void connectToLocalWifi() {
private void pollDeviceList() {
state = State.VERIFYING_PAIRING_SUCCEEDED;

final long timeout = GregorianCalendar.getInstance().getTimeInMillis() + 60000; // 30 seconds timeout
final long timeout = GregorianCalendar.getInstance().getTimeInMillis() + Constants.PAIRING_VERIFY_TIMEOUT_MILLISECONDS;
ScheduledFuture<?> future = worker.schedule(new Runnable() {
private @Nullable DeviceInfo findDevice(Collection<DeviceInfo> devices, String deviceUuid) {
for (DeviceInfo d : devices) {
Expand Down Expand Up @@ -184,6 +186,7 @@ public void run() {
Log.e(TAG, "An unexpected exception occurred", e);
} finally {
timedOut = GregorianCalendar.getInstance().getTimeInMillis() >= timeout;
error = "Timeout: waiting for confirmation from remote broker.";
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Expand All @@ -195,13 +198,15 @@ public void run() {
}
}


final boolean finalSucceeed = succeeed;
final boolean finalTimedOut = timedOut;
uiThreadHandler.post(new Runnable() {
@Override
public void run() {
if (finalSucceeed)
stateMachine(Signal.DEVICE_PAIRED);
else if (finalTimedOut)
stateMachine(Signal.MISSING_CONFIRMATION);
else
stateMachine(Signal.ERROR);
}
Expand All @@ -210,8 +215,11 @@ public void run() {
}, 2, TimeUnit.SECONDS);
}

private void configureDevice(final String userId, final String key) {
private void configureDevice() {
state = State.SENDING_PAIRING_COMMAND;
// In custom credentials has been specified, override userId/key
final String userId = pairActivityViewModel.getOverridedUserId().getValue() != null ? pairActivityViewModel.getOverridedUserId().getValue() : mCreds.getUserId();
final String key = pairActivityViewModel.getOverridedKey().getValue() != null ? pairActivityViewModel.getOverridedKey().getValue() : mCreds.getKey();

worker.schedule(new Runnable() {
@Override
Expand Down Expand Up @@ -438,6 +446,7 @@ enum Signal {
DEVICE_CONFIGURED,
LOCAL_WIFI_CONNECTED,
DEVICE_PAIRED,
MISSING_CONFIRMATION,
ERROR
}
}
1 change: 1 addition & 0 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme"
tools:openDrawer="start">

<include
Expand Down
17 changes: 16 additions & 1 deletion app/src/main/res/layout/fragment_account.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@
android:textSize="18sp"
android:textStyle="bold" />

<TextView
android:id="@+id/textView21"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="@string/account_activity_logged_info" />

<ImageView
android:id="@+id/loggedInAccountLogo"
android:layout_width="match_parent"
android:layout_height="121dp"
android:layout_margin="5dp"
android:src="@drawable/question_mark" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textField"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
Expand Down Expand Up @@ -92,7 +106,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:text="N/A" />
android:text="N/A"
android:textIsSelectable="true" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.button.MaterialButton
Expand Down
47 changes: 45 additions & 2 deletions app/src/main/res/layout/fragment_mqtt_config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />


<Spinner
android:id="@+id/mqttConfigurationSpinner"
android:layout_width="0dp"
Expand Down Expand Up @@ -144,9 +143,53 @@
android:checked="true"
android:text="@string/save_checkbox"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="@+id/mqttPortEditText"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/mqttPortEditText" />

<CheckBox
android:id="@+id/overrideMqttParams"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:text="@string/mqtt_key_override_message"
android:visibility="visible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/saveCheckbox" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/customMqttUserId"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/mqtt_custom_user_id"
android:inputType="textPersonName"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overrideMqttParams">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/customMqttKey"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/mqtt_custom_key"
android:inputType="textPersonName"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/customMqttUserId">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
Loading

0 comments on commit 0493c8a

Please sign in to comment.