mirror of
https://github.com/house-of-abbey/GarminHomeAssistant.git
synced 2025-06-16 19:38:34 +00:00
Added update to telemetry on completion of an activity
This commit is contained in:
@ -23,6 +23,7 @@ using Toybox.Lang;
|
|||||||
using Toybox.Application.Properties;
|
using Toybox.Application.Properties;
|
||||||
using Toybox.Background;
|
using Toybox.Background;
|
||||||
using Toybox.System;
|
using Toybox.System;
|
||||||
|
using Toybox.Activity;
|
||||||
|
|
||||||
(:background)
|
(:background)
|
||||||
class BackgroundServiceDelegate extends System.ServiceDelegate {
|
class BackgroundServiceDelegate extends System.ServiceDelegate {
|
||||||
@ -37,99 +38,77 @@ class BackgroundServiceDelegate extends System.ServiceDelegate {
|
|||||||
Background.exit(null);
|
Background.exit(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onActivityCompleted(activity as { :sport as Activity.Sport, :subSport as Activity.SubSport }) as Void {
|
||||||
|
if (!System.getDeviceSettings().phoneConnected) {
|
||||||
|
// System.println("BackgroundServiceDelegate onActivityCompleted(): No Phone connection, skipping API call.");
|
||||||
|
} else if (!System.getDeviceSettings().connectionAvailable) {
|
||||||
|
// System.println("BackgroundServiceDelegate onActivityCompleted(): No Internet connection, skipping API call.");
|
||||||
|
} else {
|
||||||
|
// Ensure we're logging completion, i.e. ignore 'activity' parameter
|
||||||
|
// System.println("BackgroundServiceDelegate onActivityCompleted(): Event triggered");
|
||||||
|
doUpdate(-1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onTemporalEvent() as Void {
|
function onTemporalEvent() as Void {
|
||||||
if (!System.getDeviceSettings().phoneConnected) {
|
if (!System.getDeviceSettings().phoneConnected) {
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): No Phone connection, skipping API call.");
|
// 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.");
|
// System.println("BackgroundServiceDelegate onTemporalEvent(): No Internet connection, skipping API call.");
|
||||||
} else {
|
} else {
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): Making API call.");
|
var activity = Activity.getProfileInfo().sport;
|
||||||
var position = Position.getInfo();
|
var sub_activity = Activity.getProfileInfo().subSport;
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): gps: " + position.position.toDegrees());
|
// We need to check if we are actually tracking any activity as the enumerated type does not include "No Sport".
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): speed: " + position.speed);
|
if ((Activity.getActivityInfo() != null) and
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): course: " + position.heading + "rad (" + (position.heading * 180 / Math.PI) + "°)");
|
((Activity.getActivityInfo().elapsedTime == null) or
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): altitude: " + position.altitude);
|
(Activity.getActivityInfo().elapsedTime == 0))) {
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): battery: " + System.getSystemStats().battery);
|
// Indicate no activity with -1, not part of Garmin's activity codes.
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): charging: " + System.getSystemStats().charging);
|
// https://developer.garmin.com/connect-iq/api-docs/Toybox/Activity.html#Sport-module
|
||||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): activity: " + Activity.getProfileInfo().name);
|
activity = -1;
|
||||||
|
sub_activity = -1;
|
||||||
// Don't use Settings.* here as the object lasts < 30 secs and is recreated each time the background service is run
|
|
||||||
|
|
||||||
if (position.accuracy != Position.QUALITY_NOT_AVAILABLE && position.accuracy != Position.QUALITY_LAST_KNOWN) {
|
|
||||||
var accuracy = 0;
|
|
||||||
switch (position.accuracy) {
|
|
||||||
case Position.QUALITY_POOR:
|
|
||||||
accuracy = 500;
|
|
||||||
break;
|
|
||||||
case Position.QUALITY_USABLE:
|
|
||||||
accuracy = 100;
|
|
||||||
break;
|
|
||||||
case Position.QUALITY_GOOD:
|
|
||||||
accuracy = 10;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
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" => accuracy,
|
|
||||||
"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)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
var data = [
|
// System.println("BackgroundServiceDelegate onTemporalEvent(): Event triggered, activity = " + activity + " sub_activity = " + sub_activity);
|
||||||
{
|
doUpdate(activity, sub_activity);
|
||||||
"state" => System.getSystemStats().battery,
|
}
|
||||||
"type" => "sensor",
|
}
|
||||||
"unique_id" => "battery_level"
|
|
||||||
},
|
private function doUpdate(activity as Lang.Number, sub_activity as Lang.Number) {
|
||||||
{
|
// System.println("BackgroundServiceDelegate onTemporalEvent(): Making API call.");
|
||||||
"state" => System.getSystemStats().charging,
|
var position = Position.getInfo();
|
||||||
"type" => "binary_sensor",
|
// System.println("BackgroundServiceDelegate onTemporalEvent(): gps: " + position.position.toDegrees());
|
||||||
"unique_id" => "battery_is_charging"
|
// 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);
|
||||||
if ((Activity has :getActivityInfo) and (Activity has :getProfileInfo)) {
|
// System.println("BackgroundServiceDelegate onTemporalEvent(): battery: " + System.getSystemStats().battery);
|
||||||
var activity = Activity.getProfileInfo().sport;
|
// System.println("BackgroundServiceDelegate onTemporalEvent(): charging: " + System.getSystemStats().charging);
|
||||||
var sub_activity = Activity.getProfileInfo().subSport;
|
// System.println("BackgroundServiceDelegate onTemporalEvent(): activity: " + Activity.getProfileInfo().name);
|
||||||
// We need to check if we are actually tracking any activity as the enumerated type does not include "No Sport".
|
|
||||||
if ((Activity.getActivityInfo() != null) and
|
// Don't use Settings.* here as the object lasts < 30 secs and is recreated each time the background service is run
|
||||||
((Activity.getActivityInfo().elapsedTime == null) or
|
|
||||||
(Activity.getActivityInfo().elapsedTime == 0))) {
|
if (position.accuracy != Position.QUALITY_NOT_AVAILABLE && position.accuracy != Position.QUALITY_LAST_KNOWN) {
|
||||||
// Indicate no activity with -1, not part of Garmin's activity codes.
|
var accuracy = 0;
|
||||||
// https://developer.garmin.com/connect-iq/api-docs/Toybox/Activity.html#Sport-module
|
switch (position.accuracy) {
|
||||||
activity = -1;
|
case Position.QUALITY_POOR:
|
||||||
sub_activity = -1;
|
accuracy = 500;
|
||||||
}
|
break;
|
||||||
data.add({
|
case Position.QUALITY_USABLE:
|
||||||
"state" => activity,
|
accuracy = 100;
|
||||||
"type" => "sensor",
|
break;
|
||||||
"unique_id" => "activity"
|
case Position.QUALITY_GOOD:
|
||||||
});
|
accuracy = 10;
|
||||||
data.add({
|
break;
|
||||||
"state" => sub_activity,
|
|
||||||
"type" => "sensor",
|
|
||||||
"unique_id" => "sub_activity"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Communications.makeWebRequest(
|
Communications.makeWebRequest(
|
||||||
(Properties.getValue("api_url") as Lang.String) + "/webhook/" + (Properties.getValue("webhook_id") as Lang.String),
|
(Properties.getValue("api_url") as Lang.String) + "/webhook/" + (Properties.getValue("webhook_id") as Lang.String),
|
||||||
{
|
{
|
||||||
"type" => "update_sensor_states",
|
"type" => "update_location",
|
||||||
"data" => data
|
"data" => {
|
||||||
|
"gps" => position.position.toDegrees(),
|
||||||
|
"gps_accuracy" => accuracy,
|
||||||
|
"speed" => Math.round(position.speed),
|
||||||
|
"course" => Math.round(position.heading * 180 / Math.PI),
|
||||||
|
"altitude" => Math.round(position.altitude),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:method => Communications.HTTP_REQUEST_METHOD_POST,
|
:method => Communications.HTTP_REQUEST_METHOD_POST,
|
||||||
@ -141,6 +120,45 @@ class BackgroundServiceDelegate extends System.ServiceDelegate {
|
|||||||
method(:onReturnBatteryUpdate)
|
method(:onReturnBatteryUpdate)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
var data = [
|
||||||
|
{
|
||||||
|
"state" => System.getSystemStats().battery,
|
||||||
|
"type" => "sensor",
|
||||||
|
"unique_id" => "battery_level"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state" => System.getSystemStats().charging,
|
||||||
|
"type" => "binary_sensor",
|
||||||
|
"unique_id" => "battery_is_charging"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
if ((Activity has :getActivityInfo) and (Activity has :getProfileInfo)) {
|
||||||
|
data.add({
|
||||||
|
"state" => activity,
|
||||||
|
"type" => "sensor",
|
||||||
|
"unique_id" => "activity"
|
||||||
|
});
|
||||||
|
data.add({
|
||||||
|
"state" => sub_activity,
|
||||||
|
"type" => "sensor",
|
||||||
|
"unique_id" => "sub_activity"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Communications.makeWebRequest(
|
||||||
|
(Properties.getValue("api_url") as Lang.String) + "/webhook/" + (Properties.getValue("webhook_id") as Lang.String),
|
||||||
|
{
|
||||||
|
"type" => "update_sensor_states",
|
||||||
|
"data" => data
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:method => Communications.HTTP_REQUEST_METHOD_POST,
|
||||||
|
:headers => {
|
||||||
|
"Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON
|
||||||
|
},
|
||||||
|
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
|
||||||
|
},
|
||||||
|
method(:onReturnBatteryUpdate)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -95,9 +95,11 @@ class Settings {
|
|||||||
if ((Background.getTemporalEventRegisteredTime() == null) or
|
if ((Background.getTemporalEventRegisteredTime() == null) or
|
||||||
(Background.getTemporalEventRegisteredTime() != (mBatteryRefreshRate * 60))) {
|
(Background.getTemporalEventRegisteredTime() != (mBatteryRefreshRate * 60))) {
|
||||||
Background.registerForTemporalEvent(new Time.Duration(mBatteryRefreshRate * 60)); // Convert to seconds
|
Background.registerForTemporalEvent(new Time.Duration(mBatteryRefreshRate * 60)); // Convert to seconds
|
||||||
|
Background.registerForActivityCompletedEvent();
|
||||||
}
|
}
|
||||||
} else if (Background.getTemporalEventRegisteredTime() != null) {
|
} else if (Background.getTemporalEventRegisteredTime() != null) {
|
||||||
Background.deleteTemporalEvent();
|
Background.deleteTemporalEvent();
|
||||||
|
Background.deleteActivityCompletedEvent();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Explicitly disable the background event which persists when the application closes.
|
// Explicitly disable the background event which persists when the application closes.
|
||||||
@ -182,6 +184,7 @@ class Settings {
|
|||||||
Properties.setValue("enable_battery_level", mIsSensorsLevelEnabled);
|
Properties.setValue("enable_battery_level", mIsSensorsLevelEnabled);
|
||||||
if (mHasService and (Background.getTemporalEventRegisteredTime() != null)) {
|
if (mHasService and (Background.getTemporalEventRegisteredTime() != null)) {
|
||||||
Background.deleteTemporalEvent();
|
Background.deleteTemporalEvent();
|
||||||
|
Background.deleteActivityCompletedEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user