1
// Copyright (C) 2016 Thomas Voss <thomas.voss.bochum@gmail.com>
3
// This library is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU Lesser General Public License as published
5
// by the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
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 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
#include <location/providers/ubx/_8/scanner.h>
18
#include <location/providers/ubx/_8/codec.h>
19
#include <location/providers/ubx/_8/magic.h>
20
#include <location/providers/ubx/_8/message.h>
30
namespace _8 = location::providers::ubx::_8;
35
template<std::uint8_t class_id, std::uint8_t message_id>
36
std::tuple<std::uint8_t, std::uint8_t> make_tuple()
38
return std::make_tuple(class_id, message_id);
43
_8::Scanner::Scanner()
44
: next{Expect::sync_char_1},
48
payload_iterator{payload.end()}
50
factories[make_tuple<ack::Ack::class_id, ack::Ack::message_id>()] =
51
[](const std::vector<std::uint8_t>& payload) { return decode_message<ack::Ack>(payload); };
52
factories[make_tuple<ack::Nak::class_id, ack::Nak::message_id>()] =
53
[](const std::vector<std::uint8_t>& payload) { return decode_message<ack::Nak>(payload); };
54
factories[make_tuple<cfg::Gnss::class_id, cfg::Gnss::message_id>()] =
55
[](const std::vector<std::uint8_t>&) { return cfg::Gnss{}; };
56
factories[make_tuple<cfg::Msg::class_id, cfg::Msg::message_id>()] =
57
[](const std::vector<std::uint8_t>&) { return cfg::Msg{}; };
58
factories[make_tuple<nav::Pvt::class_id, nav::Pvt::message_id>()] =
59
[](const std::vector<std::uint8_t>& payload) { return decode_message<nav::Pvt>(payload); };
60
factories[make_tuple<nav::Sat::class_id, nav::Sat::message_id>()] =
61
[](const std::vector<std::uint8_t>& payload) { return decode_message<nav::Sat>(payload); };
64
std::tuple<_8::Scanner::Expect, bool> _8::Scanner::update(std::uint8_t c)
66
bool consumed = false;
68
// TODO(tvoss): This lacks a lot of validiation and verification.
69
// UBX allows us to partially parse while we scan and carry out online
70
// checksum calculation. Ideally, we would have a common class State that
71
// captures behavior and transition logic.
74
case Expect::sync_char_1:
77
next = Expect::sync_char_2;
81
case Expect::sync_char_2:
84
next = Expect::class_;
97
next = Expect::length_1;
100
case Expect::length_1:
103
next = Expect::length_2;
106
case Expect::length_2:
108
expected_size |= (c << 8);
109
payload.resize(expected_size);
110
payload_iterator = payload.begin();
111
next = Expect::payload;
114
case Expect::payload:
116
*payload_iterator = c;
118
next = payload_iterator == payload.end()
130
next = Expect::nothing_more;
138
return std::make_tuple(next, consumed);
141
_8::Message _8::Scanner::finalize()
143
if (next != Expect::nothing_more)
144
throw std::logic_error{"Not ready for extraction."};
146
if (ck_a != checksum.ck_a() || ck_b != checksum.ck_b())
147
throw std::runtime_error{"Verification failed."};
149
auto it = factories.find(std::make_tuple(class_id, message_id));
151
if (it == factories.end())
152
throw std::runtime_error{"Could not decode message."};
154
auto result = it->second(payload);
156
checksum = Checksum{};
157
next = Expect::sync_char_1;
162
payload_iterator = payload.end();