Merge lp:~thomas-voss/location-service/add-manual-example-for-network-based-positioning into lp:location-service/trunk

Proposed by Thomas Voß
Status: Needs review
Proposed branch: lp:~thomas-voss/location-service/add-manual-example-for-network-based-positioning
Merge into: lp:location-service/trunk
Diff against target: 371 lines (+229/-31)
7 files modified
debian/ubuntu-location-service-examples.install (+1/-0)
examples/CMakeLists.txt (+2/-1)
examples/connectivity/CMakeLists.txt (+7/-0)
examples/connectivity/connectivity.cpp (+188/-0)
src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp (+19/-19)
src/location_service/com/ubuntu/location/service/ichnaea_reporter.h (+7/-6)
tests/ichnaea_reporter_test.cpp (+5/-5)
To merge this branch: bzr merge lp:~thomas-voss/location-service/add-manual-example-for-network-based-positioning
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Pending
Ubuntu Phablet Team Pending
Review via email: mp+295709@code.launchpad.net

Commit message

Add a standalone example exercising the connectivity subsystem.

Description of the change

Add a standalone example exercising the connectivity subsystem.

To post a comment you must log in.
251. By Thomas Voß

Account for compiler differences.

252. By Thomas Voß

Adjust debian setup to install example.

253. By Thomas Voß

Print out full request body on exit.

254. By Thomas Voß

Adjust to changes in ichnaea json schema.

Unmerged revisions

254. By Thomas Voß

Adjust to changes in ichnaea json schema.

253. By Thomas Voß

Print out full request body on exit.

252. By Thomas Voß

Adjust debian setup to install example.

251. By Thomas Voß

Account for compiler differences.

250. By Thomas Voß

Add a standalone example exercising the connectivity subsystem.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/ubuntu-location-service-examples.install'
--- debian/ubuntu-location-service-examples.install 2014-05-20 09:45:02 +0000
+++ debian/ubuntu-location-service-examples.install 2016-05-25 21:01:56 +0000
@@ -1,3 +1,4 @@
1usr/lib/*/ubuntu-location-service/examples/connectivity
1usr/lib/*/ubuntu-location-service/examples/client2usr/lib/*/ubuntu-location-service/examples/client
2usr/lib/*/ubuntu-location-service/examples/service3usr/lib/*/ubuntu-location-service/examples/service
3usr/share/ubuntu-location-service4usr/share/ubuntu-location-service
45
=== modified file 'examples/CMakeLists.txt'
--- examples/CMakeLists.txt 2014-05-20 09:45:02 +0000
+++ examples/CMakeLists.txt 2016-05-25 21:01:56 +0000
@@ -1,5 +1,6 @@
1add_subdirectory(service)1add_subdirectory(service)
2add_subdirectory(connectivity)
23
3install(4install(
4 DIRECTORY standalone5 DIRECTORY standalone
5 DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}/examples)
6\ No newline at end of file6\ No newline at end of file
7 DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}/examples)
78
=== added directory 'examples/connectivity'
=== added file 'examples/connectivity/CMakeLists.txt'
--- examples/connectivity/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ examples/connectivity/CMakeLists.txt 2016-05-25 21:01:56 +0000
@@ -0,0 +1,7 @@
1add_executable(connectivity connectivity.cpp)
2target_link_libraries(connectivity ubuntu-location-service ubuntu-location-service-connectivity)
3
4install(
5 TARGETS connectivity
6 DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/examples/
7)
08
=== added file 'examples/connectivity/connectivity.cpp'
--- examples/connectivity/connectivity.cpp 1970-01-01 00:00:00 +0000
+++ examples/connectivity/connectivity.cpp 2016-05-25 21:01:56 +0000
@@ -0,0 +1,188 @@
1/*
2 * Copyright © 2016 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
19#include <com/ubuntu/location/connectivity/manager.h>
20#include <com/ubuntu/location/service/ichnaea_reporter.h>
21
22#include <core/net/http/client.h>
23#include <core/posix/signal.h>
24
25#include <iostream>
26
27namespace connectivity = com::ubuntu::location::connectivity;
28namespace ichnaea = com::ubuntu::location::service::ichnaea;
29namespace http = core::net::http;
30
31namespace com { namespace ubuntu { namespace location { namespace service { namespace ichnaea
32{
33class Client
34{
35public:
36 Client()
37 : client{http::make_client()},
38 worker{[this]() { client->run(); }},
39 request_config(http::Request::Configuration::from_uri_as_string("https://location.services.mozilla.com/v1/geolocate?key=test"))
40 {
41 request_config.ssl.verify_host = request_config.ssl.verify_peer = false;
42 }
43
44 ~Client()
45 {
46 client->stop();
47 if (worker.joinable()) worker.join();
48 }
49
50 void geolocate(const std::vector<connectivity::WirelessNetwork::Ptr>& wifis, const std::vector<connectivity::RadioCell::Ptr>& cells)
51 {
52 json::Object object = json::Object::create_object();
53
54 // Explicitly disable fallback methods to make sure that
55 // we are getting clear errors for the manual example and help with
56 // tracking down bugs.
57 json::Object fallbacks = json::Object::create_object();
58 fallbacks.put_boolean("lacf", false);
59 fallbacks.put_boolean("ipf", false);
60
61 json::Object cell_towers = json::Object::create_array();
62 json::Object wifi_access_points = json::Object::create_array();
63
64 ichnaea::Reporter::convert_cells_to_json(cells, cell_towers);
65 ichnaea::Reporter::convert_wifis_to_json(wifis, wifi_access_points);
66
67 object.put_array("cellTowers", cell_towers);
68 object.put_array("wifiAccessPoints", wifi_access_points);
69 object.put_object("fallbacks", fallbacks);
70
71 auto request = client->post(request_config, object.to_plain_string(), http::ContentType::json);
72 auto response = request->execute([](const http::Request::Progress& progress)
73 {
74 return http::Request::Progress::Next::continue_operation;
75 });
76
77 auto result = json::Object::parse_from_string(response.body);
78 auto location = result.get("location");
79 auto accuracy = result.get("accuracy");
80
81 std::cout << "Query for position estimate succeeded: " << std::endl
82 << " lat: " << location.get("lat").to_double() << std::endl
83 << " lng: " << location.get("lng").to_double() << std::endl
84 << " accuracy: " << accuracy.to_double() << std::endl;
85 }
86
87private:
88 std::shared_ptr<http::Client> client;
89 std::thread worker;
90 http::Request::Configuration request_config;
91};
92}}}}}
93
94// Sampler periodically requests scans for wireless networks.
95class Sampler
96{
97public:
98 // Sampler initializes a new instance with the given manager instance.
99 Sampler(const std::shared_ptr<connectivity::Manager>& manager)
100 : manager{manager},
101 running{true},
102 worker{[this]()
103 {
104 while (running)
105 {
106 Sampler::manager->request_scan_for_wireless_networks();
107 std::this_thread::sleep_for(std::chrono::seconds{15});
108 }
109 }}
110 {
111 }
112
113 ~Sampler()
114 {
115 running = false;
116 if (worker.joinable()) worker.join();
117 }
118
119private:
120 std::shared_ptr<connectivity::Manager> manager;
121 bool running;
122 std::thread worker;
123};
124
125int main(int, char)
126{
127 auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term});
128 trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); });
129
130 auto client = std::make_shared<ichnaea::Client>();
131 auto manager = connectivity::platform_default_manager();
132 auto sampler = std::make_shared<Sampler>(manager);
133
134 manager->state().changed().connect([](connectivity::State state)
135 {
136 std::cout << "State changed: " << state << std::endl;
137 });
138
139 manager->is_wifi_enabled().changed().connect([](bool b)
140 {
141 std::cout << "is_wifi_enabled changed: " << std::boolalpha << b << std::endl;
142 });
143
144 manager->is_wifi_hardware_enabled().changed().connect([](bool b)
145 {
146 std::cout << "is_wifi_hardware_enabled changed: " << std::boolalpha << b << std::endl;
147 });
148
149 manager->is_wwan_enabled().changed().connect([](bool b)
150 {
151 std::cout << "is_wwan_enabled changed: " << std::boolalpha << b << std::endl;
152 });
153
154 manager->is_wwan_hardware_enabled().changed().connect([](bool b)
155 {
156 std::cout << "is_wwan_hardware_enabled changed: " << std::boolalpha << b << std::endl;
157 });
158
159 manager->active_connection_characteristics().changed().connect([](connectivity::Characteristics characteristics)
160 {
161 std::cout << "Active connection characteristics changed: " << characteristics << std::endl;
162 });
163
164 std::weak_ptr<connectivity::Manager> wp{manager};
165 manager->wireless_network_scan_finished().connect([wp, client]()
166 {
167 std::cout << "Wireless network scan finished" << std::endl;
168 if (auto manager = wp.lock())
169 {
170 std::vector<connectivity::RadioCell::Ptr> cells;
171 manager->enumerate_connected_radio_cells([&cells](const connectivity::RadioCell::Ptr& cell)
172 {
173 cells.push_back(cell);
174 });
175
176 std::vector<connectivity::WirelessNetwork::Ptr> wifis;
177 manager->enumerate_visible_wireless_networks([&wifis](const connectivity::WirelessNetwork::Ptr& wifi)
178 {
179 wifis.push_back(wifi);
180 });
181
182 client->geolocate(wifis, cells);
183 }
184 });
185
186 trap->run();
187 return EXIT_SUCCESS;
188}
0189
=== modified file 'src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp'
--- src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp 2016-05-24 09:44:01 +0000
+++ src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp 2016-05-25 21:01:56 +0000
@@ -317,7 +317,7 @@
317 continue;317 continue;
318318
319 json::Object w = json::Object::create_object();319 json::Object w = json::Object::create_object();
320 w.put_string(Json::Wifi::key, wifi->bssid().get());320 w.put_string(Json::Wifi::mac_address, wifi->bssid().get());
321321
322 if (wifi->frequency().get().is_valid())322 if (wifi->frequency().get().is_valid())
323 w.put_int32(Json::Wifi::frequency, static_cast<int>(wifi->frequency().get()));323 w.put_int32(Json::Wifi::frequency, static_cast<int>(wifi->frequency().get()));
@@ -342,60 +342,60 @@
342 {342 {
343 case connectivity::RadioCell::Type::gsm:343 case connectivity::RadioCell::Type::gsm:
344 {344 {
345 c.put_string(Json::Cell::radio, "gsm");345 c.put_string(Json::Cell::radio_type, "gsm");
346346
347 const auto& details = cell->gsm();347 const auto& details = cell->gsm();
348348
349 if (details.mobile_country_code.is_valid())349 if (details.mobile_country_code.is_valid())
350 c.put_int32(Json::Cell::mcc, details.mobile_country_code.get());350 c.put_int32(Json::Cell::mobile_country_code, details.mobile_country_code.get());
351 if (details.mobile_network_code.is_valid())351 if (details.mobile_network_code.is_valid())
352 c.put_int32(Json::Cell::mnc, details.mobile_network_code.get());352 c.put_int32(Json::Cell::mobile_network_code, details.mobile_network_code.get());
353 if (details.location_area_code.is_valid())353 if (details.location_area_code.is_valid())
354 c.put_int32(Json::Cell::lac, details.location_area_code.get());354 c.put_int32(Json::Cell::location_area_code, details.location_area_code.get());
355 if (details.id.is_valid())355 if (details.id.is_valid())
356 c.put_int32(Json::Cell::cid, details.id.get());356 c.put_int32(Json::Cell::cell_id, details.id.get());
357 if (details.strength.is_valid())357 if (details.strength.is_valid())
358 c.put_int32(Json::Cell::asu, details.strength.get());358 c.put_int32(Json::Cell::signal_strength, details.strength.get());
359359
360 break;360 break;
361 }361 }
362 case connectivity::RadioCell::Type::umts:362 case connectivity::RadioCell::Type::umts:
363 {363 {
364 c.put_string(Json::Cell::radio, "umts");364 c.put_string(Json::Cell::radio_type, "umts");
365365
366 const auto& details = cell->umts();366 const auto& details = cell->umts();
367367
368 if (details.mobile_country_code.is_valid())368 if (details.mobile_country_code.is_valid())
369 c.put_int32(Json::Cell::mcc, details.mobile_country_code.get());369 c.put_int32(Json::Cell::mobile_country_code, details.mobile_country_code.get());
370 if (details.mobile_network_code.is_valid())370 if (details.mobile_network_code.is_valid())
371 c.put_int32(Json::Cell::mnc, details.mobile_network_code.get());371 c.put_int32(Json::Cell::mobile_network_code, details.mobile_network_code.get());
372 if (details.location_area_code.is_valid())372 if (details.location_area_code.is_valid())
373 c.put_int32(Json::Cell::lac, details.location_area_code.get());373 c.put_int32(Json::Cell::location_area_code, details.location_area_code.get());
374 if (details.id.is_valid())374 if (details.id.is_valid())
375 c.put_int32(Json::Cell::cid, details.id.get());375 c.put_int32(Json::Cell::cell_id, details.id.get());
376 if (details.strength.is_valid())376 if (details.strength.is_valid())
377 c.put_int32(Json::Cell::asu, details.strength.get());377 c.put_int32(Json::Cell::signal_strength, details.strength.get());
378378
379 break;379 break;
380 }380 }
381 case connectivity::RadioCell::Type::lte:381 case connectivity::RadioCell::Type::lte:
382 {382 {
383 c.put_string(Json::Cell::radio, "lte");383 c.put_string(Json::Cell::radio_type, "lte");
384384
385 const auto& details = cell->lte();385 const auto& details = cell->lte();
386386
387 if (details.mobile_country_code.is_valid())387 if (details.mobile_country_code.is_valid())
388 c.put_int32(Json::Cell::mcc, details.mobile_country_code.get());388 c.put_int32(Json::Cell::mobile_country_code, details.mobile_country_code.get());
389 if (details.mobile_network_code.is_valid())389 if (details.mobile_network_code.is_valid())
390 c.put_int32(Json::Cell::mnc, details.mobile_network_code.get());390 c.put_int32(Json::Cell::mobile_network_code, details.mobile_network_code.get());
391 if (details.tracking_area_code.is_valid())391 if (details.tracking_area_code.is_valid())
392 c.put_int32(Json::Cell::lac, details.tracking_area_code.get());392 c.put_int32(Json::Cell::location_area_code, details.tracking_area_code.get());
393 if (details.id.is_valid())393 if (details.id.is_valid())
394 c.put_int32(Json::Cell::cid, details.id.get());394 c.put_int32(Json::Cell::cell_id, details.id.get());
395 if (details.physical_id.is_valid())395 if (details.physical_id.is_valid())
396 c.put_int32(Json::Cell::psc, details.physical_id.get());396 c.put_int32(Json::Cell::psc, details.physical_id.get());
397 if (details.strength.is_valid())397 if (details.strength.is_valid())
398 c.put_int32(Json::Cell::asu, details.strength.get());398 c.put_int32(Json::Cell::signal_strength, details.strength.get());
399 break;399 break;
400 }400 }
401 default:401 default:
402402
=== modified file 'src/location_service/com/ubuntu/location/service/ichnaea_reporter.h'
--- src/location_service/com/ubuntu/location/service/ichnaea_reporter.h 2014-07-11 12:56:40 +0000
+++ src/location_service/com/ubuntu/location/service/ichnaea_reporter.h 2016-05-25 21:01:56 +0000
@@ -168,19 +168,20 @@
168168
169 struct Cell169 struct Cell
170 {170 {
171 static constexpr const char* radio{"radio"};171 static constexpr const char* radio_type{"radio_type"};
172 static constexpr const char* mcc{"mcc"};172 static constexpr const char* mobile_country_code{"mobileCountryCode"};
173 static constexpr const char* mnc{"mnc"};173 static constexpr const char* mobile_network_code{"mobileNetworkCode"};
174 static constexpr const char* lac{"lac"};174 static constexpr const char* location_area_code{"locationAreaCode"};
175 static constexpr const char* cid{"cid"};175 static constexpr const char* cell_id{"cellId"};
176 static constexpr const char* psc{"psc"};176 static constexpr const char* psc{"psc"};
177 static constexpr const char* asu{"asu"};177 static constexpr const char* signal_strength{"signalStrength"};
178 };178 };
179179
180 struct Wifi180 struct Wifi
181 {181 {
182 static constexpr const char* channel{"channel"};182 static constexpr const char* channel{"channel"};
183 static constexpr const char* frequency{"frequency"};183 static constexpr const char* frequency{"frequency"};
184 static constexpr const char* mac_address{"macAddress"};
184 static constexpr const char* key{"key"};185 static constexpr const char* key{"key"};
185 static constexpr const char* signal{"signal"};186 static constexpr const char* signal{"signal"};
186 };187 };
187188
=== modified file 'tests/ichnaea_reporter_test.cpp'
--- tests/ichnaea_reporter_test.cpp 2016-05-24 09:44:01 +0000
+++ tests/ichnaea_reporter_test.cpp 2016-05-25 21:01:56 +0000
@@ -200,11 +200,11 @@
200 EXPECT_EQ(1u, cells.array_size());200 EXPECT_EQ(1u, cells.array_size());
201201
202 auto cell = cells.get_object_for_index(0);202 auto cell = cells.get_object_for_index(0);
203 EXPECT_EQ(ref_cell->gsm().mobile_country_code.get(), cell.get(Reporter::Json::Cell::mcc).to_int32());203 EXPECT_EQ(ref_cell->gsm().mobile_country_code.get(), cell.get(Reporter::Json::Cell::mobile_country_code).to_int32());
204 EXPECT_EQ(ref_cell->gsm().mobile_network_code.get(), cell.get(Reporter::Json::Cell::mnc).to_int32());204 EXPECT_EQ(ref_cell->gsm().mobile_network_code.get(), cell.get(Reporter::Json::Cell::mobile_network_code).to_int32());
205 EXPECT_EQ(ref_cell->gsm().location_area_code.get(), cell.get(Reporter::Json::Cell::lac).to_int32());205 EXPECT_EQ(ref_cell->gsm().location_area_code.get(), cell.get(Reporter::Json::Cell::location_area_code).to_int32());
206 EXPECT_EQ(ref_cell->gsm().id.get(), cell.get(Reporter::Json::Cell::cid).to_int32());206 EXPECT_EQ(ref_cell->gsm().id.get(), cell.get(Reporter::Json::Cell::cell_id).to_int32());
207 EXPECT_EQ(ref_cell->gsm().strength.get(), cell.get(Reporter::Json::Cell::asu).to_int32());207 EXPECT_EQ(ref_cell->gsm().strength.get(), cell.get(Reporter::Json::Cell::signal_strength).to_int32());
208208
209 mg_send_status(conn, static_cast<int>(submit::success));209 mg_send_status(conn, static_cast<int>(submit::success));
210 return MG_TRUE;210 return MG_TRUE;

Subscribers

People subscribed via source and target branches