From e3288c9353c5969922f0d06d21cca6be52d8585d Mon Sep 17 00:00:00 2001 From: Joseph Abbey Date: Sat, 27 Jan 2024 13:11:24 +0000 Subject: [PATCH] GPS and current activity in background service --- manifest-widget.xml | 212 +++++++++++++-------------- manifest.xml | 217 ++++++++++++++-------------- source/BackgroundServiceDelegate.mc | 40 ++++- source/WebhookManager.mc | 56 ++++--- 4 files changed, 293 insertions(+), 232 deletions(-) diff --git a/manifest-widget.xml b/manifest-widget.xml index 227f805..4683d5f 100644 --- a/manifest-widget.xml +++ b/manifest-widget.xml @@ -25,7 +25,8 @@ Use "Monkey C: Edit Application" from the Visual Studio Code command palette to update the application attributes. --> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - + \ No newline at end of file diff --git a/manifest.xml b/manifest.xml index 1d58e48..90e439a 100644 --- a/manifest.xml +++ b/manifest.xml @@ -28,9 +28,11 @@ Testing in VSCode requires monkey.jungle, so for convenience, swap between watch-app and widget by changing which of the next two lines are commented out --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - + \ No newline at end of file diff --git a/source/BackgroundServiceDelegate.mc b/source/BackgroundServiceDelegate.mc index a1746cb..7876d8b 100644 --- a/source/BackgroundServiceDelegate.mc +++ b/source/BackgroundServiceDelegate.mc @@ -38,12 +38,43 @@ class BackgroundServiceDelegate extends System.ServiceDelegate { } function onTemporalEvent() as Void { - if (! System.getDeviceSettings().phoneConnected) { + if (!System.getDeviceSettings().phoneConnected) { // System.println("BackgroundServiceDelegate onTemporalEvent(): No Phone connection, skipping API call."); - } else if (! System.getDeviceSettings().connectionAvailable) { + } else if (!System.getDeviceSettings().connectionAvailable) { // System.println("BackgroundServiceDelegate onTemporalEvent(): No Internet connection, skipping API call."); } else { + // System.println("BackgroundServiceDelegate onTemporalEvent(): Making API call."); + var position = Position.getInfo(); + // System.println("BackgroundServiceDelegate onTemporalEvent(): gps: " + position.position.toDegrees()); + // System.println("BackgroundServiceDelegate onTemporalEvent(): speed: " + position.speed); + // System.println("BackgroundServiceDelegate onTemporalEvent(): course: " + position.heading + "rad (" + (position.heading * 180 / Math.PI) + "°)"); + // System.println("BackgroundServiceDelegate onTemporalEvent(): altitude: " + position.altitude); + // System.println("BackgroundServiceDelegate onTemporalEvent(): battery: " + System.getSystemStats().battery); + // System.println("BackgroundServiceDelegate onTemporalEvent(): charging: " + System.getSystemStats().charging); + // System.println("BackgroundServiceDelegate onTemporalEvent(): activity: " + Activity.getProfileInfo().name); + // Don't use Settings.* here as the object lasts < 30 secs and is recreated each time the background service is run + Communications.makeWebRequest( + (Properties.getValue("api_url") as Lang.String) + "/webhook/" + (Properties.getValue("webhook_id") as Lang.String), + { + "type" => "update_location", + "data" => { + "gps" => position.position.toDegrees(), + "gps_accuracy" => 10, + "speed" => Math.round(position.speed), + "course" => Math.round(position.heading * 180 / Math.PI), + "altitude" => Math.round(position.altitude), + } + }, + { + :method => Communications.HTTP_REQUEST_METHOD_POST, + :headers => { + "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON + }, + :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON + }, + method(:onReturnBatteryUpdate) + ); Communications.makeWebRequest( (Properties.getValue("api_url") as Lang.String) + "/webhook/" + (Properties.getValue("webhook_id") as Lang.String), { @@ -58,6 +89,11 @@ class BackgroundServiceDelegate extends System.ServiceDelegate { "state" => System.getSystemStats().charging, "type" => "binary_sensor", "unique_id" => "battery_is_charging" + }, + { + "state" => Activity.getProfileInfo().name, + "type" => "sensor", + "unique_id" => "activity" } ] }, diff --git a/source/WebhookManager.mc b/source/WebhookManager.mc index 3e38f72..3307484 100644 --- a/source/WebhookManager.mc +++ b/source/WebhookManager.mc @@ -62,10 +62,12 @@ class WebhookManager { ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound) as Lang.String); break; + case 200: case 201: var id = data.get("webhook_id") as Lang.String or Null; if (id != null) { Settings.setWebhookId(id); + // System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering first sensor: Battery Level"); registerWebhookSensor({ "device_class" => "battery", "name" => "Battery Level", @@ -76,16 +78,7 @@ class WebhookManager { "state_class" => "measurement", "entity_category" => "diagnostic", "disabled" => false - }); - registerWebhookSensor({ - "device_class" => "battery_charging", - "name" => "Battery is Charging", - "state" => System.getSystemStats().charging, - "type" => "binary_sensor", - "unique_id" => "battery_is_charging", - "entity_category" => "diagnostic", - "disabled" => false - }); + }, 0); } else { // System.println("WebhookManager onReturnRequestWebhookId(): No webhook id in response data."); Settings.unsetIsBatteryLevelEnabled(); @@ -129,7 +122,7 @@ class WebhookManager { ); } - function onReturnRegisterWebhookSensor(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void { + function onReturnRegisterWebhookSensor(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String, step as Lang.Number) as Void { switch (responseCode) { case Communications.BLE_HOST_TIMEOUT: case Communications.BLE_CONNECTION_UNAVAILABLE: @@ -155,6 +148,7 @@ class WebhookManager { Settings.unsetWebhookId(); // Ignore and see if we can carry on break; + case Communications.INVALID_HTTP_BODY_IN_NETWORK_RESPONSE: // System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned."); Settings.unsetWebhookId(); @@ -169,12 +163,37 @@ class WebhookManager { ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound) as Lang.String); break; + case 200: case 201: - if ((data.get("success") as Lang.Boolean or Null) != true) { - // When uncommenting, invert the condition above. - // System.println("WebhookManager onReturnRegisterWebhookSensor(): Success"); - // } else { - // System.println("WebhookManager onReturnRegisterWebhookSensor(): Failure"); + if ((data.get("success") as Lang.Boolean or Null) != false) { + // System.println("WebhookManager onReturnRegisterWebhookSensor(): Success"); + switch (step) { + case 0: + // System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering next sensor: Battery is Charging"); + registerWebhookSensor({ + "device_class" => "battery_charging", + "name" => "Battery is Charging", + "state" => System.getSystemStats().charging, + "type" => "binary_sensor", + "unique_id" => "battery_is_charging", + "entity_category" => "diagnostic", + "disabled" => false + }, 1); + break; + case 1: + // System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering next sensor: Activity"); + registerWebhookSensor({ + "name" => "Activity", + "state" => Activity.getProfileInfo().name, + "type" => "sensor", + "unique_id" => "activity", + "disabled" => false + }, 2); + break; + default: + } + } else { + // System.println("WebhookManager onReturnRegisterWebhookSensor(): Failure"); Settings.unsetWebhookId(); Settings.unsetIsBatteryLevelEnabled(); ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String); @@ -189,7 +208,7 @@ class WebhookManager { } } - function registerWebhookSensor(sensor as Lang.Object) { + function registerWebhookSensor(sensor as Lang.Object, step as Lang.Number) { // System.println("WebhookManager registerWebhookSensor(): Registering webhook sensor: " + sensor.toString()); Communications.makeWebRequest( Settings.getApiUrl() + "/webhook/" + Settings.getWebhookId(), @@ -202,7 +221,8 @@ class WebhookManager { :headers => { "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON }, - :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON + :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON, + :context => step }, method(:onReturnRegisterWebhookSensor) );