~ci-train-bot/location-service/location-service-ubuntu-yakkety-1895

« back to all changes in this revision

Viewing changes to src/location_service/com/ubuntu/location/providers/skyhook/provider.cpp

  • Committer: Thomas Voß
  • Date: 2013-05-28 14:20:45 UTC
  • Revision ID: thomas.voss@canonical.com-20130528142045-kq5umqdmm4o53vwk
Initial push.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "com/ubuntu/location/providers/skyhook/provider.h"
 
2
 
 
3
#include "com/ubuntu/location/logging.h"
 
4
#include "com/ubuntu/location/provider_factory.h"
 
5
 
 
6
#include <wpsapi.h>
 
7
 
 
8
#include <map>
 
9
#include <thread>
 
10
 
 
11
namespace cul = com::ubuntu::location;
 
12
namespace culs = com::ubuntu::location::providers::skyhook;
 
13
 
 
14
namespace
 
15
{
 
16
static const std::map<int, std::string> return_code_lut =
 
17
{
 
18
    {WPS_OK, "WPS_OK"},
 
19
    {WPS_ERROR_SCANNER_NOT_FOUND, "WPS_ERROR_SCANNER_NOT_FOUND"},
 
20
    {WPS_ERROR_WIFI_NOT_AVAILABLE, "WPS_ERROR_WIFI_NOT_AVAILABLE"},
 
21
    {WPS_ERROR_NO_WIFI_IN_RANGE, "WPS_ERROR_NO_WIFI_IN_RANGE"},
 
22
    {WPS_ERROR_UNAUTHORIZED, "WPS_ERROR_UNAUTHORIZED"},
 
23
    {WPS_ERROR_SERVER_UNAVAILABLE, "WPS_ERROR_SERVER_UNAVAILABLE"},
 
24
    {WPS_ERROR_LOCATION_CANNOT_BE_DETERMINED, "WPS_ERROR_LOCATION_CANNOT_BE_DETERMINED"},
 
25
    {WPS_ERROR_PROXY_UNAUTHORIZED, "WPS_ERROR_PROXY_UNAUTHORIZED"},
 
26
    {WPS_ERROR_FILE_IO, "WPS_ERROR_FILE_IO"},
 
27
    {WPS_ERROR_INVALID_FILE_FORMAT, "WPS_ERROR_INVALID_FILE_FORMAT"},
 
28
    {WPS_ERROR_TIMEOUT, "WPS_ERROR_TIMEOUT"},
 
29
    {WPS_NOT_APPLICABLE, "WPS_NOT_APPLICABLE"},
 
30
    {WPS_GEOFENCE_ERROR, "WPS_GEOFENCE_ERROR"},
 
31
    {WPS_ERROR_NOT_TUNED, "WPS_ERROR_NOT_TUNED"},
 
32
    {WPS_NOMEM, "WPS_NOMEM"},
 
33
    {WPS_ERROR, "WPS_ERROR"}
 
34
};
 
35
}
 
36
 
 
37
struct culs::Provider::Private
 
38
{
 
39
    enum class State
 
40
    {
 
41
        stopped,
 
42
        started,
 
43
        stop_requested
 
44
    };
 
45
 
 
46
    static WPS_Continuation periodic_callback(
 
47
        void* context,
 
48
        WPS_ReturnCode code,
 
49
        const WPS_Location* location,
 
50
        const void*);
 
51
    
 
52
    Private(
 
53
        const culs::Provider::Configuration& config, 
 
54
        culs::Provider* parent)
 
55
            : parent(parent),
 
56
              config(config),
 
57
              state(State::stopped)
 
58
    {
 
59
    }
 
60
    
 
61
    void start()
 
62
    {
 
63
        if (state != State::stopped)
 
64
            return;
 
65
        
 
66
        if (worker.joinable())
 
67
            worker.join();
 
68
 
 
69
        static const unsigned infinite_iterations = 0;
 
70
        
 
71
        authentication.username = config.user_name.c_str();
 
72
        authentication.realm = config.realm.c_str();
 
73
        
 
74
        worker = std::move(std::thread([&]()
 
75
        {
 
76
            int rc = WPS_periodic_location(
 
77
                &authentication,
 
78
                WPS_NO_STREET_ADDRESS_LOOKUP,
 
79
                config.period.count(),
 
80
                infinite_iterations,
 
81
                culs::Provider::Private::periodic_callback,
 
82
                this);
 
83
 
 
84
            if (rc != WPS_OK)
 
85
                LOG(ERROR) << return_code_lut.at(rc);
 
86
        }));
 
87
 
 
88
        state = State::started;
 
89
    }
 
90
    
 
91
    void request_stop()
 
92
    {
 
93
        state = State::stop_requested;
 
94
    }
 
95
 
 
96
    culs::Provider* parent;
 
97
    Configuration config;
 
98
    State state;
 
99
    WPS_SimpleAuthentication authentication;
 
100
    std::thread worker;
 
101
};
 
102
 
 
103
WPS_Continuation culs::Provider::Private::periodic_callback(void* context,
 
104
                                                            WPS_ReturnCode code,
 
105
                                                            const WPS_Location* location,
 
106
                                                            const void*)
 
107
{
 
108
    if (code != WPS_OK)
 
109
    {
 
110
        LOG(WARNING) << return_code_lut.at(code);
 
111
        if (code == WPS_ERROR_WIFI_NOT_AVAILABLE)            
 
112
            return WPS_STOP;
 
113
 
 
114
        return WPS_CONTINUE;
 
115
    }
 
116
 
 
117
    auto thiz = static_cast<culs::Provider::Private*>(context);
 
118
 
 
119
    if (thiz->state == culs::Provider::Private::State::stop_requested)
 
120
    {
 
121
        LOG(INFO) << "Stop requested";
 
122
        thiz->state = culs::Provider::Private::State::stopped;
 
123
        return WPS_STOP;
 
124
    }
 
125
 
 
126
    cul::Position pos;
 
127
    pos.latitude(cul::wgs84::Latitude{location->latitude * cul::units::Degrees})
 
128
            .longitude(cul::wgs84::Longitude{location->longitude * cul::units::Degrees});
 
129
    if (location->altitude >= 0.f)
 
130
        pos.altitude(cul::wgs84::Altitude{location->altitude * cul::units::Meters});
 
131
 
 
132
    LOG(INFO) << pos;
 
133
 
 
134
    thiz->parent->deliver_position_updates(cul::Update<cul::Position>{pos, cul::Clock::now()});
 
135
        
 
136
    if (location->speed >= 0.f)
 
137
    {
 
138
        cul::Velocity v{location->speed * cul::units::MetersPerSecond};
 
139
        LOG(INFO) << v;
 
140
        thiz->parent->deliver_velocity_updates(cul::Update<cul::Velocity>{v, cul::Clock::now()});
 
141
    }
 
142
 
 
143
    if (location->bearing >= 0.f)
 
144
    {
 
145
        cul::Heading h{location->bearing * cul::units::Degrees};
 
146
        LOG(INFO) << h;
 
147
        thiz->parent->deliver_heading_updates(cul::Update<cul::Heading>{h, cul::Clock::now()});
 
148
    }
 
149
 
 
150
    return WPS_CONTINUE;
 
151
}
 
152
    
 
153
cul::Provider::Ptr culs::Provider::create_instance(const cul::ProviderFactory::Configuration& config)
 
154
{
 
155
    culs::Provider::Configuration configuration{"", "", std::chrono::milliseconds{100}};
 
156
    configuration.user_name = config.count("username") > 0 ? config.at("username") : "";
 
157
    configuration.realm = config.count("realm") > 0 ? config.at("realm") : "";
 
158
    if (config.count("period"))
 
159
    {
 
160
        int64_t value;
 
161
        std::stringstream ss(config.at("period"));
 
162
        ss >> value; configuration.period = std::chrono::milliseconds{value};
 
163
    }
 
164
    return cul::Provider::Ptr{new culs::Provider{configuration}};
 
165
}
 
166
 
 
167
const cul::Provider::FeatureFlags& culs::Provider::default_feature_flags()
 
168
{
 
169
    static const cul::Provider::FeatureFlags flags{"001"};
 
170
    return flags;
 
171
}
 
172
 
 
173
const cul::Provider::RequirementFlags& culs::Provider::default_requirement_flags()
 
174
{
 
175
    static const cul::Provider::RequirementFlags flags{"1010"};
 
176
    return flags;
 
177
}
 
178
 
 
179
culs::Provider::Provider(const culs::Provider::Configuration& config) 
 
180
        : com::ubuntu::location::Provider(culs::Provider::default_feature_flags(), culs::Provider::default_requirement_flags()),
 
181
          d(new Private(config, this))
 
182
{
 
183
}
 
184
 
 
185
culs::Provider::~Provider() noexcept
 
186
{
 
187
    d->request_stop();
 
188
}
 
189
 
 
190
bool culs::Provider::matches_criteria(const cul::Criteria&)
 
191
{
 
192
    return true;
 
193
}
 
194
 
 
195
void culs::Provider::start_position_updates()
 
196
{
 
197
    d->start();
 
198
}
 
199
 
 
200
void culs::Provider::stop_position_updates()
 
201
{
 
202
    d->request_stop();
 
203
}
 
204
 
 
205
void culs::Provider::start_velocity_updates()
 
206
{
 
207
    d->start();
 
208
}
 
209
 
 
210
void culs::Provider::stop_velocity_updates()
 
211
{
 
212
    d->request_stop();
 
213
}    
 
214
 
 
215
void culs::Provider::start_heading_updates()
 
216
{
 
217
    d->start();
 
218
}
 
219
 
 
220
void culs::Provider::stop_heading_updates()
 
221
{
 
222
    d->request_stop();
 
223
}