~thomas-voss/location-service/add-snapcraft-setup-next

« back to all changes in this revision

Viewing changes to src/location/providers/skyhook/provider.cpp

Merge lp:~thomas-voss/location-service/simplify-provider-interface.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2012-2013 Canonical Ltd.
3
 
 *
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.
7
 
 *
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.
12
 
 *
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/>.
15
 
 *
16
 
 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17
 
 */
18
 
#include <location/providers/skyhook/provider.h>
19
 
 
20
 
#include <location/logging.h>
21
 
#include <location/provider_factory.h>
22
 
 
23
 
#pragma GCC diagnostic push
24
 
#pragma GCC diagnostic warning "-Wignored-qualifiers"
25
 
#include <wpsapi.h>
26
 
#pragma GCC diagnostic pop
27
 
#include <map>
28
 
#include <thread>
29
 
 
30
 
namespace cul = location;
31
 
namespace culs = location::providers::skyhook;
32
 
 
33
 
namespace
34
 
{
35
 
static const std::map<int, std::string> return_code_lut =
36
 
{
37
 
    {WPS_OK, "WPS_OK"},
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"}
53
 
};
54
 
}
55
 
 
56
 
 
57
 
WPS_Continuation culs::Provider::Private::periodic_callback(void* context,
58
 
                                                            WPS_ReturnCode code,
59
 
                                                            const WPS_Location* location,
60
 
                                                            const void*)
61
 
{
62
 
    if (code != WPS_OK)
63
 
    {
64
 
        LOG(WARNING) << return_code_lut.at(code);
65
 
        if (code == WPS_ERROR_WIFI_NOT_AVAILABLE)            
66
 
            return WPS_STOP;
67
 
 
68
 
        return WPS_CONTINUE;
69
 
    }
70
 
 
71
 
    auto thiz = static_cast<culs::Provider::Private*>(context);
72
 
 
73
 
    if (thiz->state == culs::Provider::Private::State::stop_requested)
74
 
    {
75
 
        LOG(INFO) << "Stop requested";
76
 
        thiz->state = culs::Provider::Private::State::stopped;
77
 
        return WPS_STOP;
78
 
    }
79
 
 
80
 
    cul::Position pos;
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});
85
 
 
86
 
    LOG(INFO) << pos;
87
 
 
88
 
    thiz->parent->deliver_position_updates(cul::Update<cul::Position>{pos, cul::Clock::now()});
89
 
        
90
 
    if (location->speed >= 0.f)
91
 
    {
92
 
        cul::Velocity v{location->speed * cul::units::MetersPerSecond};
93
 
        LOG(INFO) << v;
94
 
        thiz->parent->deliver_velocity_updates(cul::Update<cul::Velocity>{v, cul::Clock::now()});
95
 
    }
96
 
 
97
 
    if (location->bearing >= 0.f)
98
 
    {
99
 
        cul::Heading h{location->bearing * cul::units::Degrees};
100
 
        LOG(INFO) << h;
101
 
        thiz->parent->deliver_heading_updates(cul::Update<cul::Heading>{h, cul::Clock::now()});
102
 
    }
103
 
 
104
 
    return WPS_CONTINUE;
105
 
}
106
 
    
107
 
cul::Provider::Ptr culs::Provider::create_instance(const cul::ProviderFactory::Configuration& config)
108
 
{
109
 
    culs::Provider::Configuration configuration
110
 
    {
111
 
        config.get(Configuration::key_username(), ""), 
112
 
        config.get(Configuration::key_realm(), ""),
113
 
        std::chrono::milliseconds{config.get(Configuration::key_period(), 500)}
114
 
    };
115
 
 
116
 
    return cul::Provider::Ptr{new culs::Provider{configuration}};
117
 
}
118
 
 
119
 
const cul::Provider::FeatureFlags& culs::Provider::default_feature_flags()
120
 
{
121
 
    static const cul::Provider::FeatureFlags flags{"001"};
122
 
    return flags;
123
 
}
124
 
 
125
 
const cul::Provider::RequirementFlags& culs::Provider::default_requirement_flags()
126
 
{
127
 
    static const cul::Provider::RequirementFlags flags{"1010"};
128
 
    return flags;
129
 
}
130
 
 
131
 
culs::Provider::Provider(const culs::Provider::Configuration& config) 
132
 
        : location::Provider(culs::Provider::default_feature_flags(), culs::Provider::default_requirement_flags()),
133
 
          config(config),
134
 
          state(State::stopped)
135
 
{
136
 
}
137
 
 
138
 
culs::Provider::~Provider() noexcept
139
 
{
140
 
    request_stop();
141
 
}
142
 
 
143
 
void culs::Provider::start()
144
 
{
145
 
    if (state != State::stopped)
146
 
        return;
147
 
 
148
 
    if (worker.joinable())
149
 
        worker.join();
150
 
 
151
 
    static const unsigned infinite_iterations = 0;
152
 
 
153
 
    authentication.username = config.user_name.c_str();
154
 
    authentication.realm = config.realm.c_str();
155
 
 
156
 
    worker = std::move(std::thread([&]()
157
 
    {
158
 
        int rc = WPS_periodic_location(&authentication, WPS_NO_STREET_ADDRESS_LOOKUP, config.period.count(),
159
 
                                       infinite_iterations, culs::Provider::Private::periodic_callback, this);
160
 
 
161
 
        if (rc != WPS_OK)
162
 
            LOG(ERROR) << return_code_lut.at(rc);
163
 
    }));
164
 
 
165
 
    state = State::started;
166
 
}
167
 
 
168
 
void culs::Provider::request_stop()
169
 
{
170
 
    state = State::stop_requested;
171
 
}
172
 
 
173
 
bool culs::Provider::matches_criteria(const cul::Criteria&)
174
 
{
175
 
    return true;
176
 
}
177
 
 
178
 
void culs::Provider::start_position_updates()
179
 
{
180
 
    start();
181
 
}
182
 
 
183
 
void culs::Provider::stop_position_updates()
184
 
{
185
 
    request_stop();
186
 
}
187
 
 
188
 
void culs::Provider::start_velocity_updates()
189
 
{
190
 
    start();
191
 
}
192
 
 
193
 
void culs::Provider::stop_velocity_updates()
194
 
{
195
 
    request_stop();
196
 
}    
197
 
 
198
 
void culs::Provider::start_heading_updates()
199
 
{
200
 
    start();
201
 
}
202
 
 
203
 
void culs::Provider::stop_heading_updates()
204
 
{
205
 
    request_stop();
206
 
}