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

Proposed by Thomas Voß on 2016-05-25
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 2016-05-25 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ß on 2016-05-25

Account for compiler differences.

252. By Thomas Voß on 2016-05-25

Adjust debian setup to install example.

253. By Thomas Voß on 2016-05-25

Print out full request body on exit.

254. By Thomas Voß on 2016-05-25

Adjust to changes in ichnaea json schema.

Unmerged revisions

254. By Thomas Voß on 2016-05-25

Adjust to changes in ichnaea json schema.

253. By Thomas Voß on 2016-05-25

Print out full request body on exit.

252. By Thomas Voß on 2016-05-25

Adjust debian setup to install example.

251. By Thomas Voß on 2016-05-25

Account for compiler differences.

250. By Thomas Voß on 2016-05-25

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
1=== modified file 'debian/ubuntu-location-service-examples.install'
2--- debian/ubuntu-location-service-examples.install 2014-05-20 09:45:02 +0000
3+++ debian/ubuntu-location-service-examples.install 2016-05-25 21:01:56 +0000
4@@ -1,3 +1,4 @@
5+usr/lib/*/ubuntu-location-service/examples/connectivity
6 usr/lib/*/ubuntu-location-service/examples/client
7 usr/lib/*/ubuntu-location-service/examples/service
8 usr/share/ubuntu-location-service
9
10=== modified file 'examples/CMakeLists.txt'
11--- examples/CMakeLists.txt 2014-05-20 09:45:02 +0000
12+++ examples/CMakeLists.txt 2016-05-25 21:01:56 +0000
13@@ -1,5 +1,6 @@
14 add_subdirectory(service)
15+add_subdirectory(connectivity)
16
17 install(
18 DIRECTORY standalone
19- DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}/examples)
20\ No newline at end of file
21+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}/examples)
22
23=== added directory 'examples/connectivity'
24=== added file 'examples/connectivity/CMakeLists.txt'
25--- examples/connectivity/CMakeLists.txt 1970-01-01 00:00:00 +0000
26+++ examples/connectivity/CMakeLists.txt 2016-05-25 21:01:56 +0000
27@@ -0,0 +1,7 @@
28+add_executable(connectivity connectivity.cpp)
29+target_link_libraries(connectivity ubuntu-location-service ubuntu-location-service-connectivity)
30+
31+install(
32+ TARGETS connectivity
33+ DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/examples/
34+)
35
36=== added file 'examples/connectivity/connectivity.cpp'
37--- examples/connectivity/connectivity.cpp 1970-01-01 00:00:00 +0000
38+++ examples/connectivity/connectivity.cpp 2016-05-25 21:01:56 +0000
39@@ -0,0 +1,188 @@
40+/*
41+ * Copyright © 2016 Canonical Ltd.
42+ *
43+ * This program is free software: you can redistribute it and/or modify it
44+ * under the terms of the GNU Lesser General Public License version 3,
45+ * as published by the Free Software Foundation.
46+ *
47+ * This program is distributed in the hope that it will be useful,
48+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
49+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50+ * GNU Lesser General Public License for more details.
51+ *
52+ * You should have received a copy of the GNU Lesser General Public License
53+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
54+ *
55+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
56+ */
57+
58+#include <com/ubuntu/location/connectivity/manager.h>
59+#include <com/ubuntu/location/service/ichnaea_reporter.h>
60+
61+#include <core/net/http/client.h>
62+#include <core/posix/signal.h>
63+
64+#include <iostream>
65+
66+namespace connectivity = com::ubuntu::location::connectivity;
67+namespace ichnaea = com::ubuntu::location::service::ichnaea;
68+namespace http = core::net::http;
69+
70+namespace com { namespace ubuntu { namespace location { namespace service { namespace ichnaea
71+{
72+class Client
73+{
74+public:
75+ Client()
76+ : client{http::make_client()},
77+ worker{[this]() { client->run(); }},
78+ request_config(http::Request::Configuration::from_uri_as_string("https://location.services.mozilla.com/v1/geolocate?key=test"))
79+ {
80+ request_config.ssl.verify_host = request_config.ssl.verify_peer = false;
81+ }
82+
83+ ~Client()
84+ {
85+ client->stop();
86+ if (worker.joinable()) worker.join();
87+ }
88+
89+ void geolocate(const std::vector<connectivity::WirelessNetwork::Ptr>& wifis, const std::vector<connectivity::RadioCell::Ptr>& cells)
90+ {
91+ json::Object object = json::Object::create_object();
92+
93+ // Explicitly disable fallback methods to make sure that
94+ // we are getting clear errors for the manual example and help with
95+ // tracking down bugs.
96+ json::Object fallbacks = json::Object::create_object();
97+ fallbacks.put_boolean("lacf", false);
98+ fallbacks.put_boolean("ipf", false);
99+
100+ json::Object cell_towers = json::Object::create_array();
101+ json::Object wifi_access_points = json::Object::create_array();
102+
103+ ichnaea::Reporter::convert_cells_to_json(cells, cell_towers);
104+ ichnaea::Reporter::convert_wifis_to_json(wifis, wifi_access_points);
105+
106+ object.put_array("cellTowers", cell_towers);
107+ object.put_array("wifiAccessPoints", wifi_access_points);
108+ object.put_object("fallbacks", fallbacks);
109+
110+ auto request = client->post(request_config, object.to_plain_string(), http::ContentType::json);
111+ auto response = request->execute([](const http::Request::Progress& progress)
112+ {
113+ return http::Request::Progress::Next::continue_operation;
114+ });
115+
116+ auto result = json::Object::parse_from_string(response.body);
117+ auto location = result.get("location");
118+ auto accuracy = result.get("accuracy");
119+
120+ std::cout << "Query for position estimate succeeded: " << std::endl
121+ << " lat: " << location.get("lat").to_double() << std::endl
122+ << " lng: " << location.get("lng").to_double() << std::endl
123+ << " accuracy: " << accuracy.to_double() << std::endl;
124+ }
125+
126+private:
127+ std::shared_ptr<http::Client> client;
128+ std::thread worker;
129+ http::Request::Configuration request_config;
130+};
131+}}}}}
132+
133+// Sampler periodically requests scans for wireless networks.
134+class Sampler
135+{
136+public:
137+ // Sampler initializes a new instance with the given manager instance.
138+ Sampler(const std::shared_ptr<connectivity::Manager>& manager)
139+ : manager{manager},
140+ running{true},
141+ worker{[this]()
142+ {
143+ while (running)
144+ {
145+ Sampler::manager->request_scan_for_wireless_networks();
146+ std::this_thread::sleep_for(std::chrono::seconds{15});
147+ }
148+ }}
149+ {
150+ }
151+
152+ ~Sampler()
153+ {
154+ running = false;
155+ if (worker.joinable()) worker.join();
156+ }
157+
158+private:
159+ std::shared_ptr<connectivity::Manager> manager;
160+ bool running;
161+ std::thread worker;
162+};
163+
164+int main(int, char)
165+{
166+ auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term});
167+ trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); });
168+
169+ auto client = std::make_shared<ichnaea::Client>();
170+ auto manager = connectivity::platform_default_manager();
171+ auto sampler = std::make_shared<Sampler>(manager);
172+
173+ manager->state().changed().connect([](connectivity::State state)
174+ {
175+ std::cout << "State changed: " << state << std::endl;
176+ });
177+
178+ manager->is_wifi_enabled().changed().connect([](bool b)
179+ {
180+ std::cout << "is_wifi_enabled changed: " << std::boolalpha << b << std::endl;
181+ });
182+
183+ manager->is_wifi_hardware_enabled().changed().connect([](bool b)
184+ {
185+ std::cout << "is_wifi_hardware_enabled changed: " << std::boolalpha << b << std::endl;
186+ });
187+
188+ manager->is_wwan_enabled().changed().connect([](bool b)
189+ {
190+ std::cout << "is_wwan_enabled changed: " << std::boolalpha << b << std::endl;
191+ });
192+
193+ manager->is_wwan_hardware_enabled().changed().connect([](bool b)
194+ {
195+ std::cout << "is_wwan_hardware_enabled changed: " << std::boolalpha << b << std::endl;
196+ });
197+
198+ manager->active_connection_characteristics().changed().connect([](connectivity::Characteristics characteristics)
199+ {
200+ std::cout << "Active connection characteristics changed: " << characteristics << std::endl;
201+ });
202+
203+ std::weak_ptr<connectivity::Manager> wp{manager};
204+ manager->wireless_network_scan_finished().connect([wp, client]()
205+ {
206+ std::cout << "Wireless network scan finished" << std::endl;
207+ if (auto manager = wp.lock())
208+ {
209+ std::vector<connectivity::RadioCell::Ptr> cells;
210+ manager->enumerate_connected_radio_cells([&cells](const connectivity::RadioCell::Ptr& cell)
211+ {
212+ cells.push_back(cell);
213+ });
214+
215+ std::vector<connectivity::WirelessNetwork::Ptr> wifis;
216+ manager->enumerate_visible_wireless_networks([&wifis](const connectivity::WirelessNetwork::Ptr& wifi)
217+ {
218+ wifis.push_back(wifi);
219+ });
220+
221+ client->geolocate(wifis, cells);
222+ }
223+ });
224+
225+ trap->run();
226+ return EXIT_SUCCESS;
227+}
228
229=== modified file 'src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp'
230--- src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp 2016-05-24 09:44:01 +0000
231+++ src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp 2016-05-25 21:01:56 +0000
232@@ -317,7 +317,7 @@
233 continue;
234
235 json::Object w = json::Object::create_object();
236- w.put_string(Json::Wifi::key, wifi->bssid().get());
237+ w.put_string(Json::Wifi::mac_address, wifi->bssid().get());
238
239 if (wifi->frequency().get().is_valid())
240 w.put_int32(Json::Wifi::frequency, static_cast<int>(wifi->frequency().get()));
241@@ -342,60 +342,60 @@
242 {
243 case connectivity::RadioCell::Type::gsm:
244 {
245- c.put_string(Json::Cell::radio, "gsm");
246+ c.put_string(Json::Cell::radio_type, "gsm");
247
248 const auto& details = cell->gsm();
249
250 if (details.mobile_country_code.is_valid())
251- c.put_int32(Json::Cell::mcc, details.mobile_country_code.get());
252+ c.put_int32(Json::Cell::mobile_country_code, details.mobile_country_code.get());
253 if (details.mobile_network_code.is_valid())
254- c.put_int32(Json::Cell::mnc, details.mobile_network_code.get());
255+ c.put_int32(Json::Cell::mobile_network_code, details.mobile_network_code.get());
256 if (details.location_area_code.is_valid())
257- c.put_int32(Json::Cell::lac, details.location_area_code.get());
258+ c.put_int32(Json::Cell::location_area_code, details.location_area_code.get());
259 if (details.id.is_valid())
260- c.put_int32(Json::Cell::cid, details.id.get());
261+ c.put_int32(Json::Cell::cell_id, details.id.get());
262 if (details.strength.is_valid())
263- c.put_int32(Json::Cell::asu, details.strength.get());
264+ c.put_int32(Json::Cell::signal_strength, details.strength.get());
265
266 break;
267 }
268 case connectivity::RadioCell::Type::umts:
269 {
270- c.put_string(Json::Cell::radio, "umts");
271+ c.put_string(Json::Cell::radio_type, "umts");
272
273 const auto& details = cell->umts();
274
275 if (details.mobile_country_code.is_valid())
276- c.put_int32(Json::Cell::mcc, details.mobile_country_code.get());
277+ c.put_int32(Json::Cell::mobile_country_code, details.mobile_country_code.get());
278 if (details.mobile_network_code.is_valid())
279- c.put_int32(Json::Cell::mnc, details.mobile_network_code.get());
280+ c.put_int32(Json::Cell::mobile_network_code, details.mobile_network_code.get());
281 if (details.location_area_code.is_valid())
282- c.put_int32(Json::Cell::lac, details.location_area_code.get());
283+ c.put_int32(Json::Cell::location_area_code, details.location_area_code.get());
284 if (details.id.is_valid())
285- c.put_int32(Json::Cell::cid, details.id.get());
286+ c.put_int32(Json::Cell::cell_id, details.id.get());
287 if (details.strength.is_valid())
288- c.put_int32(Json::Cell::asu, details.strength.get());
289+ c.put_int32(Json::Cell::signal_strength, details.strength.get());
290
291 break;
292 }
293 case connectivity::RadioCell::Type::lte:
294 {
295- c.put_string(Json::Cell::radio, "lte");
296+ c.put_string(Json::Cell::radio_type, "lte");
297
298 const auto& details = cell->lte();
299
300 if (details.mobile_country_code.is_valid())
301- c.put_int32(Json::Cell::mcc, details.mobile_country_code.get());
302+ c.put_int32(Json::Cell::mobile_country_code, details.mobile_country_code.get());
303 if (details.mobile_network_code.is_valid())
304- c.put_int32(Json::Cell::mnc, details.mobile_network_code.get());
305+ c.put_int32(Json::Cell::mobile_network_code, details.mobile_network_code.get());
306 if (details.tracking_area_code.is_valid())
307- c.put_int32(Json::Cell::lac, details.tracking_area_code.get());
308+ c.put_int32(Json::Cell::location_area_code, details.tracking_area_code.get());
309 if (details.id.is_valid())
310- c.put_int32(Json::Cell::cid, details.id.get());
311+ c.put_int32(Json::Cell::cell_id, details.id.get());
312 if (details.physical_id.is_valid())
313 c.put_int32(Json::Cell::psc, details.physical_id.get());
314 if (details.strength.is_valid())
315- c.put_int32(Json::Cell::asu, details.strength.get());
316+ c.put_int32(Json::Cell::signal_strength, details.strength.get());
317 break;
318 }
319 default:
320
321=== modified file 'src/location_service/com/ubuntu/location/service/ichnaea_reporter.h'
322--- src/location_service/com/ubuntu/location/service/ichnaea_reporter.h 2014-07-11 12:56:40 +0000
323+++ src/location_service/com/ubuntu/location/service/ichnaea_reporter.h 2016-05-25 21:01:56 +0000
324@@ -168,19 +168,20 @@
325
326 struct Cell
327 {
328- static constexpr const char* radio{"radio"};
329- static constexpr const char* mcc{"mcc"};
330- static constexpr const char* mnc{"mnc"};
331- static constexpr const char* lac{"lac"};
332- static constexpr const char* cid{"cid"};
333+ static constexpr const char* radio_type{"radio_type"};
334+ static constexpr const char* mobile_country_code{"mobileCountryCode"};
335+ static constexpr const char* mobile_network_code{"mobileNetworkCode"};
336+ static constexpr const char* location_area_code{"locationAreaCode"};
337+ static constexpr const char* cell_id{"cellId"};
338 static constexpr const char* psc{"psc"};
339- static constexpr const char* asu{"asu"};
340+ static constexpr const char* signal_strength{"signalStrength"};
341 };
342
343 struct Wifi
344 {
345 static constexpr const char* channel{"channel"};
346 static constexpr const char* frequency{"frequency"};
347+ static constexpr const char* mac_address{"macAddress"};
348 static constexpr const char* key{"key"};
349 static constexpr const char* signal{"signal"};
350 };
351
352=== modified file 'tests/ichnaea_reporter_test.cpp'
353--- tests/ichnaea_reporter_test.cpp 2016-05-24 09:44:01 +0000
354+++ tests/ichnaea_reporter_test.cpp 2016-05-25 21:01:56 +0000
355@@ -200,11 +200,11 @@
356 EXPECT_EQ(1u, cells.array_size());
357
358 auto cell = cells.get_object_for_index(0);
359- EXPECT_EQ(ref_cell->gsm().mobile_country_code.get(), cell.get(Reporter::Json::Cell::mcc).to_int32());
360- EXPECT_EQ(ref_cell->gsm().mobile_network_code.get(), cell.get(Reporter::Json::Cell::mnc).to_int32());
361- EXPECT_EQ(ref_cell->gsm().location_area_code.get(), cell.get(Reporter::Json::Cell::lac).to_int32());
362- EXPECT_EQ(ref_cell->gsm().id.get(), cell.get(Reporter::Json::Cell::cid).to_int32());
363- EXPECT_EQ(ref_cell->gsm().strength.get(), cell.get(Reporter::Json::Cell::asu).to_int32());
364+ EXPECT_EQ(ref_cell->gsm().mobile_country_code.get(), cell.get(Reporter::Json::Cell::mobile_country_code).to_int32());
365+ EXPECT_EQ(ref_cell->gsm().mobile_network_code.get(), cell.get(Reporter::Json::Cell::mobile_network_code).to_int32());
366+ EXPECT_EQ(ref_cell->gsm().location_area_code.get(), cell.get(Reporter::Json::Cell::location_area_code).to_int32());
367+ EXPECT_EQ(ref_cell->gsm().id.get(), cell.get(Reporter::Json::Cell::cell_id).to_int32());
368+ EXPECT_EQ(ref_cell->gsm().strength.get(), cell.get(Reporter::Json::Cell::signal_strength).to_int32());
369
370 mg_send_status(conn, static_cast<int>(submit::success));
371 return MG_TRUE;

Subscribers

People subscribed via source and target branches