Skip to content

Commit fed1b2f

Browse files
committed
Merge branch 'feature/device_automation' into 'master'
Feature: Device Automation See merge request app-frameworks/esp-rainmaker-android!51
2 parents 5a70dbe + 04e91a9 commit fed1b2f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+5585
-21
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,22 @@ Sharing can be enabled/disabled by setting true/false value of `isNodeSharingSup
119119
Sharing feature is optional but enabled by default.
120120
Add `isNodeSharingSupported=false` in `local.properties` file to disable this feature.
121121

122+
### Device Automation
123+
124+
Device Automation is a set of actions that will be triggered based on the completion of certain events. For example, the user can set an event as the Temperature sensor equals 35 degrees celsius. Then based on this event user can trigger different actions like Switching on AC or Setting the AC temperature to 20 degrees celsius or a combination of both.
125+
126+
Users will be allowed to perform different automation operations in the app as mentioned below:
127+
128+
1. Adding new automation.
129+
2. Updating existing automation.
130+
3. Enabling/disabling automation triggers.
131+
4. Deleting automation.
132+
5. Receiving notifications related to triggered automation.
133+
134+
Device automation can be enabled/disabled by setting true/false value of `isAutomationSupported` field in `local.properties`.
135+
Device automation is optional but enabled by default.
136+
Add `isAutomationSupported=false` in `local.properties` file to disable this feature.
137+
122138
### Time Series
123139

124140
- Time series allows a user to see historical values of parameters plotted as a bar or line chart.

app/build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ android {
4444
applicationId "com.espressif.rainmaker"
4545
minSdkVersion 23
4646
targetSdkVersion 31
47-
versionCode 64
48-
versionName "2.7.0 - ${getGitHash()}"
47+
versionCode 70
48+
versionName "2.8.0 - ${getGitHash()}"
4949
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
5050

5151
buildConfigField "String", "GitHash", "\"${getGitHash()}\""
@@ -89,6 +89,7 @@ android {
8989
buildConfigField "boolean", "isLocalControlSupported", localProperties.getProperty("isLocalControlSupported", "true")
9090
buildConfigField "boolean", "isNodeGroupingSupported", localProperties.getProperty("isNodeGroupingSupported", "true")
9191
buildConfigField "boolean", "isNodeSharingSupported", localProperties.getProperty("isNodeSharingSupported", "true")
92+
buildConfigField "boolean", "isAutomationSupported", localProperties.getProperty("isAutomationSupported", "true")
9293

9394
def clientId = localProperties.getProperty("clientId", defaultClientId)
9495
def authUrl = localProperties.getProperty("authUrl", defaultAuthUrl)

app/src/main/AndroidManifest.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
132132
android:label="@string/app_name"
133133
android:screenOrientation="portrait"
134+
android:windowSoftInputMode="adjustPan"
134135
android:theme="@style/AppTheme.NoActionBar" />
135136
<activity
136137
android:name="com.espressif.ui.activities.EspDeviceActivity"
@@ -254,6 +255,21 @@
254255
android:screenOrientation="portrait"
255256
android:theme="@style/AppTheme.NoActionBar"
256257
android:windowSoftInputMode="adjustPan" />
258+
<activity
259+
android:name="com.espressif.ui.activities.EventDeviceActivity"
260+
android:label="@string/title_activity_automations"
261+
android:screenOrientation="portrait"
262+
android:theme="@style/AppTheme.NoActionBar" />
263+
<activity
264+
android:name="com.espressif.ui.activities.AutomationActionsActivity"
265+
android:label="@string/title_activity_automations"
266+
android:screenOrientation="portrait"
267+
android:theme="@style/AppTheme.NoActionBar" />
268+
<activity
269+
android:name="com.espressif.ui.activities.AutomationDetailActivity"
270+
android:label="@string/title_activity_automations"
271+
android:screenOrientation="portrait"
272+
android:theme="@style/AppTheme.NoActionBar" />
257273

258274
<receiver android:name="com.espressif.NodeSharingActionReceiver" />
259275

app/src/main/java/com/espressif/AppConstants.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public enum UpdateEventType {
9090
+ AppConstants.CURRENT_VERSION + "/user/nodes/sharing";
9191
public static final String URL_USER_NODES_TS = BuildConfig.BASE_URL + AppConstants.PATH_SEPARATOR
9292
+ AppConstants.CURRENT_VERSION + "/user/nodes/tsdata";
93+
public static final String URL_USER_NODE_AUTOMATION = BuildConfig.BASE_URL + AppConstants.PATH_SEPARATOR
94+
+ AppConstants.CURRENT_VERSION + "/user/node_automation";
9395

9496
// UI Types of Device
9597
public static final String UI_TYPE_TOGGLE = "esp.ui.toggle";
@@ -200,6 +202,8 @@ public enum UpdateEventType {
200202
public static final String KEY_SCENE = "Scene";
201203
public static final String KEY_ACTION = "action";
202204
public static final String KEY_ACTIONS = "actions";
205+
public static final String KEY_EVENTS = "events";
206+
public static final String KEY_CHECK = "check";
203207
public static final String KEY_DAYS = "d";
204208
public static final String KEY_MINUTES = "m";
205209
public static final String KEY_ENABLED = "enabled";
@@ -270,6 +274,11 @@ public enum UpdateEventType {
270274
public static final String KEY_SKILL = "skill";
271275
public static final String KEY_STATUS_LINKED = "LINKED";
272276
public static final String KEY_RESPONSE = "response";
277+
public static final String KEY_AUTOMATION_ID = "automation_id";
278+
public static final String KEY_AUTOMATION_NAME = "automation_name";
279+
public static final String KEY_AUTOMATION_TRIGGER_ACTIONS = "automation_trigger_actions";
280+
public static final String KEY_AUTOMATION = "automation";
281+
public static final String KEY_LOAD_AUTOMATION_PAGE = "load_automation";
273282

274283
public static final String KEY_OPERATION = "operation";
275284
public static final String KEY_OPERATION_ADD = "add";
@@ -303,6 +312,7 @@ public enum UpdateEventType {
303312
public static final String EVENT_NODE_SHARING_ADD = "rmaker.event.user_node_sharing_add";
304313
public static final String EVENT_NODE_PARAM_MODIFIED = "rmaker.event.node_params_changed";
305314
public static final String EVENT_ALERT = "rmaker.event.alert";
315+
public static final String EVENT_NODE_AUTOMATION_TRIGGER = "rmaker.event.node_automation_trigger";
306316

307317
// Notification channel IDs
308318
public static final String CHANNEL_NODE_ONLINE_ID = "notify_node_online_id";
@@ -311,6 +321,7 @@ public enum UpdateEventType {
311321
public static final String CHANNEL_NODE_REMOVED = "notify_node_removed_id";
312322
public static final String CHANNEL_ALERT = "notify_alert_id";
313323
public static final String CHANNEL_NODE_SHARING = "notify_node_sharing_id";
324+
public static final String CHANNEL_NODE_AUTOMATION_TRIGGER = "notify_node_automation_trigger";
314325

315326
public static final String ACTION_ACCEPT = "com.espressif.rainmaker.ACTION_ACCEPT";
316327
public static final String ACTION_DECLINE = "com.espressif.rainmaker.ACTION_DECLINE";

app/src/main/java/com/espressif/EspApplication.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@
3030
import com.espressif.cloudapi.ApiManager;
3131
import com.espressif.cloudapi.ApiResponseListener;
3232
import com.espressif.db.EspDatabase;
33-
import com.espressif.local_control.LocalControlApiManager;
3433
import com.espressif.local_control.EspLocalDevice;
34+
import com.espressif.local_control.LocalControlApiManager;
3535
import com.espressif.local_control.mDNSManager;
3636
import com.espressif.provisioning.ESPProvisionManager;
3737
import com.espressif.rainmaker.BuildConfig;
3838
import com.espressif.rainmaker.R;
3939
import com.espressif.ui.activities.ConsentActivity;
40+
import com.espressif.ui.models.Automation;
41+
import com.espressif.ui.models.Device;
4042
import com.espressif.ui.models.EspNode;
4143
import com.espressif.ui.models.Group;
4244
import com.espressif.ui.models.Param;
@@ -56,6 +58,8 @@
5658

5759
import java.util.ArrayList;
5860
import java.util.HashMap;
61+
import java.util.Iterator;
62+
import java.util.Map;
5963

6064
public class EspApplication extends Application {
6165

@@ -68,6 +72,7 @@ public class EspApplication extends Application {
6872
public HashMap<String, Scene> sceneMap;
6973
public HashMap<String, EspLocalDevice> localDeviceMap;
7074
public HashMap<String, Group> groupMap;
75+
public HashMap<String, Automation> automations;
7176

7277
private SharedPreferences appPreferences;
7378
private ApiManager apiManager;
@@ -92,6 +97,8 @@ public void onCreate() {
9297
sceneMap = new HashMap<>();
9398
localDeviceMap = new HashMap<>();
9499
groupMap = new HashMap<>();
100+
automations = new HashMap<>();
101+
95102
appPreferences = getSharedPreferences(AppConstants.ESP_PREFERENCES, Context.MODE_PRIVATE);
96103
apiManager = ApiManager.getInstance(this);
97104
ESPProvisionManager.getInstance(this);
@@ -327,6 +334,7 @@ private void clearData() {
327334
sceneMap.clear();
328335
localDeviceMap.clear();
329336
groupMap.clear();
337+
automations.clear();
330338
}
331339

332340
private void startLocalDeviceDiscovery() {
@@ -343,6 +351,27 @@ public void stopLocalDeviceDiscovery() {
343351
}
344352
}
345353

354+
/**
355+
* This method is used to get copy of all devices.
356+
*
357+
* @return Copy of all devices array for the user.
358+
*/
359+
public ArrayList<Device> getAllDevices() {
360+
ArrayList<Device> devices = new ArrayList<>();
361+
for (Map.Entry<String, EspNode> entry : nodeMap.entrySet()) {
362+
363+
EspNode node = entry.getValue();
364+
if (node != null) {
365+
ArrayList<Device> espDevices = node.getDevices();
366+
Iterator<Device> iterator = espDevices.iterator();
367+
while (iterator.hasNext()) {
368+
devices.add(new Device(iterator.next()));
369+
}
370+
}
371+
}
372+
return devices;
373+
}
374+
346375
mDNSManager.mDNSEvenListener listener = new mDNSManager.mDNSEvenListener() {
347376

348377
@Override
@@ -506,13 +535,17 @@ private void setupNotificationChannels() {
506535
NotificationChannel alertChannel = new NotificationChannel(AppConstants.CHANNEL_ALERT,
507536
getString(R.string.channel_node_alert), NotificationManager.IMPORTANCE_HIGH);
508537

538+
NotificationChannel automationChannel = new NotificationChannel(AppConstants.CHANNEL_NODE_AUTOMATION_TRIGGER,
539+
getString(R.string.channel_node_automation_trigger), NotificationManager.IMPORTANCE_HIGH);
540+
509541
NotificationManager notificationManager = getSystemService(NotificationManager.class);
510542
notificationManager.createNotificationChannel(nodeConnectedChannel);
511543
notificationManager.createNotificationChannel(nodeDisconnectedChannel);
512544
notificationManager.createNotificationChannel(nodeAddedChannel);
513545
notificationManager.createNotificationChannel(nodeRemovedChannel);
514546
notificationManager.createNotificationChannel(nodeSharingChannel);
515547
notificationManager.createNotificationChannel(alertChannel);
548+
notificationManager.createNotificationChannel(automationChannel);
516549
}
517550
}
518551

app/src/main/java/com/espressif/JsonDataParser.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,17 @@ public static void setDeviceParamValue(JSONObject deviceJson, Device device, Par
7272
labelValue = deviceJson.optString(paramName);
7373
param.setLabelValue(labelValue);
7474
}
75-
} else if (AppConstants.UI_TYPE_TOGGLE.equalsIgnoreCase(param.getUiType())) {
75+
} else if (AppConstants.UI_TYPE_TOGGLE.equalsIgnoreCase(param.getUiType())
76+
|| AppConstants.UI_TYPE_TRIGGER.equalsIgnoreCase(param.getUiType())) {
7677

7778
boolean value = deviceJson.optBoolean(paramName);
7879
param.setSwitchStatus(value);
7980

80-
} else if (AppConstants.UI_TYPE_TRIGGER.equalsIgnoreCase(param.getUiType())) {
81-
82-
boolean value = deviceJson.optBoolean(paramName);
83-
param.setSwitchStatus(value);
81+
if (value) {
82+
param.setLabelValue("true");
83+
} else {
84+
param.setLabelValue("false");
85+
}
8486

8587
} else if (AppConstants.UI_TYPE_DROP_DOWN.equalsIgnoreCase(param.getUiType())) {
8688

@@ -102,6 +104,7 @@ public static void setDeviceParamValue(JSONObject deviceJson, Device device, Par
102104
if (dataType.equalsIgnoreCase("bool") || dataType.equalsIgnoreCase("boolean")) {
103105

104106
boolean value = deviceJson.optBoolean(paramName);
107+
param.setSwitchStatus(value);
105108
if (value) {
106109
param.setLabelValue("true");
107110
} else {

0 commit comments

Comments
 (0)