// SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * Location service. Location providers (e.g. GPS) report fixes to the service. * The most recent fix of a regular provider is used while it's less than 2 minutes old. * Otherwise, the most recent fix of a fallback provider (e.g. IP geolocation) is used, if there is one. * Providers only run while there is at least one subscription. */ #define LOCATION_PROVIDER_ID_MAX_LENGTH 15 /** Horizontal accuracy in meters of a fix with LOCATION_PRECISION_APPROXIMATE */ #define LOCATION_APPROXIMATE_ACCURACY_METERS 3000.0f enum LocationPrecision { /** Providers only report fixes with a horizontal accuracy of LOCATION_APPROXIMATE_ACCURACY_METERS or worse */ LOCATION_PRECISION_APPROXIMATE, /** Providers report fixes as accurate as they can */ LOCATION_PRECISION_PRECISE, }; /** * A location fix. Values the provider doesn't know are NAN for floating point fields and 0 for the others. * Accuracies are the radius of 68% confidence, in the unit of the value they belong to. */ struct Location { /** Degrees in WGS84, positive is north */ double latitude; /** Degrees in WGS84, positive is east */ double longitude; /** Meters */ float horizontal_accuracy; /** Meters above mean sea level */ float altitude; /** Meters above the WGS84 ellipsoid */ float ellipsoidal_altitude; /** Meters */ float vertical_accuracy; /** Speed over ground in meters per second */ float speed; /** Meters per second */ float speed_accuracy; /** Direction of travel in degrees clockwise from true north, in range [0, 360) */ float course; /** Degrees */ float course_accuracy; /** Number of satellites used for the fix */ uint8_t satellites; /** Time of the fix according to the provider, in milliseconds since the Unix epoch */ int64_t time_ms; /** Milliseconds since boot when the service received the fix */ uint64_t uptime_ms; /** Id of the provider that reported the fix */ char provider[LOCATION_PROVIDER_ID_MAX_LENGTH + 1]; }; /** * Allow or disallow the use of location services. The service only runs while allowed. The choice is persisted. * Location services are disallowed by default. */ error_t location_set_enabled(bool enabled); bool location_is_enabled(void); /** Set the precision that providers should report. The choice is persisted. */ error_t location_set_precision(enum LocationPrecision precision); enum LocationPrecision location_get_precision(void); /** * Get the current fix. Without subscriptions, this is the last known fix. * @param[out] location the fix * @retval ERROR_NOT_FOUND when no fix was reported since the service started, or location services are disabled */ error_t location_get(struct Location* location); /** * Caller-owned subscription: the service signals @a bit on the event group whenever a new current fix is reported. * Read the fix with location_get(). * @warning Fields other than `bit` are for internal use only. */ struct LocationSubscription { uint32_t bit; struct { struct TaskEventGroup* event_group; struct LocationSubscription* next; } internal; }; /** * Subscribing starts the providers when location services are enabled. They stop when the last subscription is removed. * Providers start and stop in the background: subscribing and unsubscribing don't wait for them. * @param[in,out] sub subscription to register, must stay alive until unsubscribed * @param[in] event_group caller-owned group to wait on, must outlive @a sub * @retval ERROR_RESOURCE @a event_group has no free bits left * @retval ERROR_INVALID_STATE @a sub is already registered */ error_t location_subscribe(struct LocationSubscription* sub, struct TaskEventGroup* event_group); /** @retval ERROR_NOT_FOUND when @a sub is not registered */ error_t location_unsubscribe(struct LocationSubscription* sub); /** @return true when location services are enabled and there is at least one subscription */ bool location_is_in_use(void); #ifdef __cplusplus } #endif