2
* Copyright © 2012-2013 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Thomas Voß <thomas.voss@canonical.com>
18
#include <location/providers/skyhook/provider.h>
20
#include <location/logging.h>
21
#include <location/provider_factory.h>
23
#pragma GCC diagnostic push
24
#pragma GCC diagnostic warning "-Wignored-qualifiers"
26
#pragma GCC diagnostic pop
30
namespace cul = location;
31
namespace culs = location::providers::skyhook;
35
static const std::map<int, std::string> return_code_lut =
38
{WPS_ERROR_SCANNER_NOT_FOUND, "WPS_ERROR_SCANNER_NOT_FOUND"},
39
{WPS_ERROR_WIFI_NOT_AVAILABLE, "WPS_ERROR_WIFI_NOT_AVAILABLE"},
40
{WPS_ERROR_NO_WIFI_IN_RANGE, "WPS_ERROR_NO_WIFI_IN_RANGE"},
41
{WPS_ERROR_UNAUTHORIZED, "WPS_ERROR_UNAUTHORIZED"},
42
{WPS_ERROR_SERVER_UNAVAILABLE, "WPS_ERROR_SERVER_UNAVAILABLE"},
43
{WPS_ERROR_LOCATION_CANNOT_BE_DETERMINED, "WPS_ERROR_LOCATION_CANNOT_BE_DETERMINED"},
44
{WPS_ERROR_PROXY_UNAUTHORIZED, "WPS_ERROR_PROXY_UNAUTHORIZED"},
45
{WPS_ERROR_FILE_IO, "WPS_ERROR_FILE_IO"},
46
{WPS_ERROR_INVALID_FILE_FORMAT, "WPS_ERROR_INVALID_FILE_FORMAT"},
47
{WPS_ERROR_TIMEOUT, "WPS_ERROR_TIMEOUT"},
48
{WPS_NOT_APPLICABLE, "WPS_NOT_APPLICABLE"},
49
{WPS_GEOFENCE_ERROR, "WPS_GEOFENCE_ERROR"},
50
{WPS_ERROR_NOT_TUNED, "WPS_ERROR_NOT_TUNED"},
51
{WPS_NOMEM, "WPS_NOMEM"},
52
{WPS_ERROR, "WPS_ERROR"}
57
WPS_Continuation culs::Provider::Private::periodic_callback(void* context,
59
const WPS_Location* location,
64
LOG(WARNING) << return_code_lut.at(code);
65
if (code == WPS_ERROR_WIFI_NOT_AVAILABLE)
71
auto thiz = static_cast<culs::Provider::Private*>(context);
73
if (thiz->state == culs::Provider::Private::State::stop_requested)
75
LOG(INFO) << "Stop requested";
76
thiz->state = culs::Provider::Private::State::stopped;
81
pos.latitude(cul::wgs84::Latitude{location->latitude * cul::units::Degrees})
82
.longitude(cul::wgs84::Longitude{location->longitude * cul::units::Degrees});
83
if (location->altitude >= 0.f)
84
pos.altitude(cul::wgs84::Altitude{location->altitude * cul::units::Meters});
88
thiz->parent->deliver_position_updates(cul::Update<cul::Position>{pos, cul::Clock::now()});
90
if (location->speed >= 0.f)
92
cul::Velocity v{location->speed * cul::units::MetersPerSecond};
94
thiz->parent->deliver_velocity_updates(cul::Update<cul::Velocity>{v, cul::Clock::now()});
97
if (location->bearing >= 0.f)
99
cul::Heading h{location->bearing * cul::units::Degrees};
101
thiz->parent->deliver_heading_updates(cul::Update<cul::Heading>{h, cul::Clock::now()});
107
cul::Provider::Ptr culs::Provider::create_instance(const cul::ProviderFactory::Configuration& config)
109
culs::Provider::Configuration configuration
111
config.get(Configuration::key_username(), ""),
112
config.get(Configuration::key_realm(), ""),
113
std::chrono::milliseconds{config.get(Configuration::key_period(), 500)}
116
return cul::Provider::Ptr{new culs::Provider{configuration}};
119
const cul::Provider::FeatureFlags& culs::Provider::default_feature_flags()
121
static const cul::Provider::FeatureFlags flags{"001"};
125
const cul::Provider::RequirementFlags& culs::Provider::default_requirement_flags()
127
static const cul::Provider::RequirementFlags flags{"1010"};
131
culs::Provider::Provider(const culs::Provider::Configuration& config)
132
: location::Provider(culs::Provider::default_feature_flags(), culs::Provider::default_requirement_flags()),
134
state(State::stopped)
138
culs::Provider::~Provider() noexcept
143
void culs::Provider::start()
145
if (state != State::stopped)
148
if (worker.joinable())
151
static const unsigned infinite_iterations = 0;
153
authentication.username = config.user_name.c_str();
154
authentication.realm = config.realm.c_str();
156
worker = std::move(std::thread([&]()
158
int rc = WPS_periodic_location(&authentication, WPS_NO_STREET_ADDRESS_LOOKUP, config.period.count(),
159
infinite_iterations, culs::Provider::Private::periodic_callback, this);
162
LOG(ERROR) << return_code_lut.at(rc);
165
state = State::started;
168
void culs::Provider::request_stop()
170
state = State::stop_requested;
173
bool culs::Provider::matches_criteria(const cul::Criteria&)
178
void culs::Provider::start_position_updates()
183
void culs::Provider::stop_position_updates()
188
void culs::Provider::start_velocity_updates()
193
void culs::Provider::stop_velocity_updates()
198
void culs::Provider::start_heading_updates()
203
void culs::Provider::stop_heading_updates()