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>
19
#include <com/ubuntu/location/service/ichnaea_reporter.h>
21
#include <com/ubuntu/location/logging.h>
23
#include <core/net/http/client.h>
24
#include <core/net/http/content_type.h>
25
#include <core/net/http/request.h>
26
#include <core/net/http/response.h>
27
#include <core/net/http/status.h>
29
#include <json/json.h>
33
namespace json = Json;
34
namespace location = com::ubuntu::location;
36
location::service::ichnaea::Reporter::Reporter(
37
const location::service::ichnaea::Reporter::Configuration& configuration)
38
: http_client(core::net::http::make_client())
40
auto uri = configuration.uri +
41
ichnaea::submit::resource +
44
submit_request_config = core::net::http::Request::Configuration::from_uri_as_string(uri);
45
submit_request_config.ssl.verify_host = false;
46
submit_request_config.ssl.verify_peer = false;
48
if (not configuration.nick_name.empty())
49
submit_request_config.header.add(Reporter::nick_name_header, configuration.nick_name);
52
location::service::ichnaea::Reporter::~Reporter()
57
void location::service::ichnaea::Reporter::start()
59
http_client_worker = std::move(
69
void location::service::ichnaea::Reporter::stop()
73
if (http_client_worker.joinable())
74
http_client_worker.join();
77
void location::service::ichnaea::Reporter::report(
78
const location::Update<location::Position>& update,
79
const std::vector<location::connectivity::WirelessNetwork::Ptr>& wifis,
80
const std::vector<location::connectivity::RadioCell::Ptr>& cells)
85
item[Json::radio] = "gsm"; // We currently only support gsm radio types.
86
item[Json::lat] = update.value.latitude.value.value();
87
item[Json::lon] = update.value.longitude.value.value();
89
if (update.value.accuracy.horizontal)
90
item[Json::accuracy] = (*update.value.accuracy.horizontal).value();
91
if (update.value.altitude)
92
item[Json::altitude] = (*update.value.altitude).value.value();
93
if (update.value.accuracy.vertical)
94
item[Json::altitude_accuracy] = (*update.value.accuracy.vertical).value();
97
ichnaea::Reporter::convert_wifis_to_json(wifis, item[Json::wifi]);
100
ichnaea::Reporter::convert_cells_to_json(cells, item[Json::cell]);
102
submit[Json::items].append(item);
104
json::FastWriter writer;
106
VLOG(10) << "Submitting: " << writer.write(submit);
108
auto request = http_client->post(
109
submit_request_config,
110
writer.write(submit),
111
core::net::http::ContentType::json);
113
request->async_execute(
114
core::net::http::Request::Handler()
115
.on_response([](const core::net::http::Response& response)
117
if (response.status != ichnaea::submit::success)
118
LOG(ERROR) << "Error submitting to ichnaea: " << response.body;
120
LOG(INFO) << "Succesfully submitted to ichnaea.";
122
.on_error([](const core::net::Error& e)
124
LOG(ERROR) << "Networking error while submitting to ichnaea: " << e.what();
128
void location::service::ichnaea::Reporter::convert_wifis_to_json(
129
const std::vector<location::connectivity::WirelessNetwork::Ptr>& wifis,
130
json::Value& destination)
132
for (const auto& wifi : wifis)
134
// We do not harvest any Wifi marked with '_nomap'.
135
if (wifi->ssid().get().find("_nomap") != std::string::npos)
139
w[Json::Wifi::key] = wifi->bssid().get();
141
if (wifi->frequency().get().is_valid())
142
w[Json::Wifi::frequency] = static_cast<int>(wifi->frequency().get());
144
// We have a relative signal strength percentage in the wifi record.
145
// TODO(tvoss): Check how that could be translated to RSSI.
146
//wifi[Json::Wifi::signal] = -50;
148
destination.append(w);
152
void location::service::ichnaea::Reporter::convert_cells_to_json(
153
const std::vector<location::connectivity::RadioCell::Ptr>& cells,
154
json::Value& destination)
156
for (const auto& cell : cells)
160
switch (cell->type())
162
case connectivity::RadioCell::Type::gsm:
164
c[Json::Cell::radio] = "gsm";
166
const auto& details = cell->gsm();
168
if (details.mobile_country_code.is_valid())
169
c[Json::Cell::mcc] = details.mobile_country_code.get();
170
if (details.mobile_network_code.is_valid())
171
c[Json::Cell::mnc] = details.mobile_network_code.get();
172
if (details.location_area_code.is_valid())
173
c[Json::Cell::lac] = details.location_area_code.get();
174
if (details.id.is_valid())
175
c[Json::Cell::cid] = details.id.get();
176
if (details.strength.is_valid())
177
c[Json::Cell::asu] = details.strength.get();
181
case connectivity::RadioCell::Type::umts:
183
c[Json::Cell::radio] = "umts";
185
const auto& details = cell->umts();
187
if (details.mobile_country_code.is_valid())
188
c[Json::Cell::mcc] = details.mobile_country_code.get();
189
if (details.mobile_network_code.is_valid())
190
c[Json::Cell::mnc] = details.mobile_network_code.get();
191
if (details.location_area_code.is_valid())
192
c[Json::Cell::lac] = details.location_area_code.get();
193
if (details.id.is_valid())
194
c[Json::Cell::cid] = details.id.get();
195
if (details.strength.is_valid())
196
c[Json::Cell::asu] = details.strength.get();
200
case connectivity::RadioCell::Type::lte:
202
c[Json::Cell::radio] = "lte";
204
const auto& details = cell->lte();
206
if (details.mobile_country_code.is_valid())
207
c[Json::Cell::mcc] = details.mobile_country_code.get();
208
if (details.mobile_network_code.is_valid())
209
c[Json::Cell::mnc] = details.mobile_network_code.get();
210
if (details.tracking_area_code.is_valid())
211
c[Json::Cell::lac] = details.tracking_area_code.get();
212
if (details.id.is_valid())
213
c[Json::Cell::cid] = details.id.get();
214
if (details.physical_id.is_valid())
215
c[Json::Cell::psc] = details.physical_id.get();
216
if (details.strength.is_valid())
217
c[Json::Cell::asu] = details.strength.get();
224
destination.append(c);