Goby3 3.2.3
2025.05.13
Loading...
Searching...
No Matches
iridium_driver_fsm.h
Go to the documentation of this file.
1// Copyright 2013-2025:
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// Community contributors (see AUTHORS file)
5// File authors:
6// Toby Schneider <toby@gobysoft.org>
7//
8//
9// This file is part of the Goby Underwater Autonomy Project Libraries
10// ("The Goby Libraries").
11//
12// The Goby Libraries are free software: you can redistribute them and/or modify
13// them under the terms of the GNU Lesser General Public License as published by
14// the Free Software Foundation, either version 2.1 of the License, or
15// (at your option) any later version.
16//
17// The Goby Libraries are distributed in the hope that they will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU Lesser General Public License for more details.
21//
22// You should have received a copy of the GNU Lesser General Public License
23// along with Goby. If not, see <http://www.gnu.org/licenses/>.
24
25#ifndef GOBY_ACOMMS_MODEMDRIVER_IRIDIUM_DRIVER_FSM_H
26#define GOBY_ACOMMS_MODEMDRIVER_IRIDIUM_DRIVER_FSM_H
27
28#include <algorithm> // for for_each
29#include <iostream> // for basic_ost...
30#include <locale> // for locale
31#include <string> // for string
32#include <utility> // for move, pair
33#include <vector> // for vector
34
35#include <boost/algorithm/string/classification.hpp> // for is_any_ofF
36#include <boost/algorithm/string/split.hpp> // for split
37#include <boost/algorithm/string/trim.hpp> // for trim
38#include <boost/bind/bind.hpp> // for bind_t, arg
39#include <boost/circular_buffer.hpp> // for circular_...
40#include <boost/lexical_cast/bad_lexical_cast.hpp> // for bad_lexic...
41#include <boost/mpl/list.hpp> // for list
42#include <boost/smart_ptr/intrusive_ptr.hpp> // for intrusive...
43#include <boost/statechart/custom_reaction.hpp>
44#include <boost/statechart/event.hpp> // for event
45#include <boost/statechart/in_state_reaction.hpp> // for in_state_...
46#include <boost/statechart/result.hpp> // for reaction_...
47#include <boost/statechart/simple_state.hpp> // for simple_st...
48#include <boost/statechart/state.hpp> // for state
49#include <boost/statechart/state_machine.hpp> // for state_mac...
50#include <boost/statechart/transition.hpp> // for transition
51
52#include "goby/acomms/modemdriver/iridium_driver_common.h" // for OnCallBase
53#include "goby/acomms/protobuf/driver_base.pb.h" // for DriverConfig
54#include "goby/acomms/protobuf/iridium_driver.pb.h" // for Config
55#include "goby/acomms/protobuf/modem_message.pb.h" // for ModemTran...
57#include "goby/util/as.h" // for as
58#include "goby/util/debug_logger/flex_ostream.h" // for FlexOstream
59#include "goby/util/debug_logger/flex_ostreambuf.h" // for DEBUG1, WARN
60#include "goby/util/debug_logger/logger_manipulators.h" // for operator<<
61
62namespace goby
63{
64namespace acomms
65{
66namespace iridium
67{
68inline unsigned sbd_csum(const std::string& data)
69{
70 unsigned int csum = 0;
71 for (char it : data) csum += it & 0xFF;
72 return csum;
73}
74
75namespace fsm
76{
78{
79 StateNotify(std::string name) : name_(std::move(name))
80 {
81 glog.is(goby::util::logger::DEBUG1) && glog << group("iridiumdriver") << name_ << std::endl;
82 }
84 {
85 glog.is(goby::util::logger::DEBUG1) && glog << group("iridiumdriver") << "~" << name_
86 << std::endl;
87 }
88
89 private:
90 std::string name_;
91};
92
93// events
95{
96 std::string line;
97};
99{
100};
101
103{
104 std::string line;
105};
107{
108};
109
111{
112 EvAck(std::string response) : response_(std::move(response)) {}
113
114 std::string response_;
115};
116
118{
119};
121{
122};
123
125{
126};
128{
129};
131{
132};
133
135{
136};
137
139{
140};
142{
143};
145{
146};
147
149{
150};
151
153{
154};
156{
157 EvSBDBeginData(std::string data = "", bool in_response_to_ring_alert = false)
158 : data_(std::move(data)), in_response_to_ring_alert_(in_response_to_ring_alert)
159 {
160 }
161 std::string data_;
163};
164
165struct EvSBDSendBufferCleared : boost::statechart::event<EvSBDSendBufferCleared>
166{
167};
168
170{
171};
173{
174};
175struct EvSBDTransmitComplete : boost::statechart::event<EvSBDTransmitComplete>
176{
177 EvSBDTransmitComplete(std::string sbdi) : sbdi_(std::move(sbdi)) {}
178 std::string sbdi_;
179};
180struct EvSBDReceiveComplete : boost::statechart::event<EvSBDReceiveComplete>
181{
182};
183
184struct EvSBDCheckWriteTimeout : boost::statechart::event<EvSBDCheckWriteTimeout>
185{
186};
187
188// pre-declare
189struct Active;
190struct Command;
191struct Configure;
192struct Ready;
193struct Answer;
194struct Dial;
195struct Online;
196struct OnCall;
197struct NotOnCall;
198struct SBD;
199struct SBDReady;
200struct SBDClearBuffers;
201struct SBDWrite;
202struct SBDTransmit;
203struct SBDReceive;
204
205// state machine
206struct IridiumDriverFSM : boost::statechart::state_machine<IridiumDriverFSM, Active>
207{
208 private:
209 struct CIEVData
210 {
211 int rssi{-1};
212 bool service_available{false};
213 };
214
215 public:
217 : serial_tx_buffer_(SERIAL_BUFFER_CAPACITY),
218 received_(RECEIVED_BUFFER_CAPACITY),
219 driver_cfg_(driver_cfg),
220 data_out_(DATA_BUFFER_CAPACITY)
221 {
222 ++count_;
223 glog_ir_group_ = "iridiumdriver::" + goby::util::as<std::string>(count_);
224 }
225
227
228 // messages for the serial line at next opportunity
229 boost::circular_buffer<std::string>& serial_tx_buffer() { return serial_tx_buffer_; }
230
231 // received messages to be passed up out of the ModemDriver
232 boost::circular_buffer<goby::acomms::protobuf::ModemTransmission>& received()
233 {
234 return received_;
235 }
236
237 // data that should (eventually) be sent out across the Iridium connection
238 boost::circular_buffer<goby::acomms::protobuf::ModemTransmission>& data_out()
239 {
240 return data_out_;
241 }
242
243 const goby::acomms::protobuf::DriverConfig& driver_cfg() const { return driver_cfg_; }
248
249 const std::string& glog_ir_group() const { return glog_ir_group_; }
250
251 const CIEVData& ciev_data() const { return ciev_data_; }
252
253 void parse_ciev(const std::string& ciev);
254
255 private:
256 enum
257 {
258 SERIAL_BUFFER_CAPACITY = 10
259 };
260 enum
261 {
262 RECEIVED_BUFFER_CAPACITY = 10
263 };
264
265 boost::circular_buffer<std::string> serial_tx_buffer_;
266 boost::circular_buffer<goby::acomms::protobuf::ModemTransmission> received_;
267 const goby::acomms::protobuf::DriverConfig& driver_cfg_;
268
269 enum
270 {
271 DATA_BUFFER_CAPACITY = 5
272 };
273 boost::circular_buffer<goby::acomms::protobuf::ModemTransmission> data_out_;
274
275 std::string glog_ir_group_;
276
277 static int count_;
278
279 CIEVData ciev_data_;
280};
281
282struct Active : boost::statechart::simple_state<Active, IridiumDriverFSM,
283 boost::mpl::list<Command, NotOnCall>>
284{
285 typedef boost::mpl::list<boost::statechart::transition<EvReset, Active>> reactions;
286};
287
288// Command
289struct Command : boost::statechart::simple_state<Command, Active::orthogonal<0>,
290 boost::mpl::list<Configure, SBD>>,
292{
293 public:
296 void in_state_react(const EvAck&);
297
298 Command() : StateNotify("Command"), at_out_(AT_BUFFER_CAPACITY) {}
299 ~Command() override = default;
300
301 using reactions = boost::mpl::list<
302 boost::statechart::in_state_reaction<EvRxSerial, Command, &Command::in_state_react>,
303 boost::statechart::in_state_reaction<EvTxSerial, Command, &Command::in_state_react>,
304 boost::statechart::transition<EvOnline, Online>,
305 boost::statechart::in_state_reaction<EvAck, Command, &Command::in_state_react>>;
306
308 {
309 ATSentenceMeta() = default;
311 int tries_{0};
312 };
313
314 void push_at_command(const std::string& cmd)
315 {
316 at_out_.push_back(std::make_pair(ATSentenceMeta(), cmd));
317 }
318
319 boost::circular_buffer<std::pair<ATSentenceMeta, std::string>>& at_out() { return at_out_; }
320
321 void clear_sbd_rx_buffer() { sbd_rx_buffer_.clear(); }
322
323 void handle_sbd_rx(const std::string& in);
324
325 private:
326 enum
327 {
328 AT_BUFFER_CAPACITY = 100
329 };
330 boost::circular_buffer<std::pair<ATSentenceMeta, std::string>> at_out_;
331 enum
332 {
333 COMMAND_TIMEOUT_SECONDS = 2,
334 DIAL_TIMEOUT_SECONDS = 60,
335 SBDIX_TIMEOUT_SECONDS = DIAL_TIMEOUT_SECONDS,
336 TRIPLE_PLUS_TIMEOUT_SECONDS = 6,
337 HANGUP_TIMEOUT_SECONDS = 10,
338 ANSWER_TIMEOUT_SECONDS = 30
339 };
340
341 enum
342 {
343 RETRIES_BEFORE_RESET = 3
344 };
345 std::string sbd_rx_buffer_;
346};
347
348struct Configure : boost::statechart::state<Configure, Command::orthogonal<0>>, StateNotify
349{
350 using reactions = boost::mpl::list<boost::statechart::transition<EvAtEmpty, Ready>>;
351
352 Configure(my_context ctx) : my_base(std::move(ctx)), StateNotify("Configure")
353 {
354 context<Command>().push_at_command("");
355 const auto& iridium_driver_config = context<IridiumDriverFSM>().iridium_driver_cfg();
356 for (int i = 0, n = iridium_driver_config.config_size(); i < n; ++i)
357 {
358 context<Command>().push_at_command(iridium_driver_config.config(i));
359 }
360 }
361
363};
364
365struct Ready : boost::statechart::simple_state<Ready, Command::orthogonal<0>>, StateNotify
366{
367 public:
368 Ready() : StateNotify("Ready") {}
369 ~Ready() override = default;
370
371 boost::statechart::result react(const EvDial&)
372 {
373 if (state_downcast<const NotOnCall*>() != 0)
374 {
375 return transit<Dial>();
376 }
377 else
378 {
380 glog << group("iridiumdriver") << "Not dialing since we are already on a call."
381 << std::endl;
382 return discard_event();
383 }
384 }
385
386 using reactions = boost::mpl::list<boost::statechart::transition<EvRing, Answer>,
387 boost::statechart::custom_reaction<EvDial>>;
388
389 private:
390};
391
392struct HangingUp : boost::statechart::state<HangingUp, Command::orthogonal<0>>, StateNotify
393{
394 public:
395 HangingUp(my_context ctx) : my_base(std::move(ctx)), StateNotify("HangingUp")
396 {
397 context<Command>().push_at_command("+++");
398 context<Command>().push_at_command("H");
399 }
400 ~HangingUp() override = default;
401
402 using reactions = boost::mpl::list<boost::statechart::transition<EvAtEmpty, Ready>>;
403
404 private:
405};
406
407struct PostDisconnected : boost::statechart::state<PostDisconnected, Command::orthogonal<0>>,
409{
410 public:
411 PostDisconnected(my_context ctx) : my_base(std::move(ctx)), StateNotify("PostDisconnected")
412 {
414 glog << group("iridiumdriver") << "Disconnected; checking error details: " << std::endl;
415 context<Command>().push_at_command("+CEER");
416 }
417 ~PostDisconnected() override = default;
418
419 using reactions = boost::mpl::list<boost::statechart::transition<EvAtEmpty, Ready>>;
420
421 private:
422};
423
424struct Dial : boost::statechart::state<Dial, Command::orthogonal<0>>, StateNotify
425{
426 using reactions = boost::mpl::list<boost::statechart::custom_reaction<EvNoCarrier>>;
427
428 Dial(my_context ctx) : my_base(std::move(ctx)), StateNotify("Dial"), dial_attempts_(0)
429 {
430 dial();
431 }
432 ~Dial() override = default;
433
434 boost::statechart::result react(const EvNoCarrier&);
435 void dial();
436
437 private:
438 int dial_attempts_;
439};
440
441struct Answer : boost::statechart::state<Answer, Command::orthogonal<0>>, StateNotify
442{
443 using reactions = boost::mpl::list<boost::statechart::transition<EvNoCarrier, Ready>>;
444
445 Answer(my_context ctx) : my_base(std::move(ctx)), StateNotify("Answer")
446 {
447 context<Command>().push_at_command("A");
448 }
449 ~Answer() override = default;
450};
451
452// Online
453struct Online : boost::statechart::simple_state<Online, Active::orthogonal<0>>, StateNotify
454{
455 Online() : StateNotify("Online") {}
456 ~Online() override = default;
457
460
461 using reactions = boost::mpl::list<
462 boost::statechart::transition<EvHangup, HangingUp>,
463 boost::statechart::transition<EvDisconnect, PostDisconnected>,
464 boost::statechart::in_state_reaction<EvRxSerial, Online, &Online::in_state_react>,
465 boost::statechart::in_state_reaction<EvTxSerial, Online, &Online::in_state_react>>;
466};
467
468// Orthogonal on-call / not-on-call
469struct NotOnCall : boost::statechart::simple_state<NotOnCall, Active::orthogonal<1>>, StateNotify
470{
471 using reactions = boost::mpl::list<boost::statechart::transition<EvConnect, OnCall>>;
472
473 NotOnCall() : StateNotify("NotOnCall") {}
474 ~NotOnCall() override = default;
475};
476
477struct OnCall : boost::statechart::state<OnCall, Active::orthogonal<1>>, StateNotify, OnCallBase
478{
479 public:
480 OnCall(my_context ctx) : my_base(std::move(ctx)), StateNotify("OnCall")
481 {
482 // add a brief identifier that is *different* than the "~" which is what PPP uses
483 // add a carriage return to clear out any garbage
484 // at the *beginning* of transmission
485 context<IridiumDriverFSM>().serial_tx_buffer().push_front("goby\r");
486
487 // connecting necessarily puts the DTE online
489 }
490 ~OnCall() override
491 {
492 // signal the disconnect event for the command state to handle
493 glog.is(goby::util::logger::DEBUG1) && glog << group("iridiumdriver") << "Sent "
494 << total_bytes_sent() << " bytes on this call."
495 << std::endl;
497 }
498
502
503 using reactions = boost::mpl::list<
504 boost::statechart::transition<EvNoCarrier, NotOnCall>,
505 boost::statechart::in_state_reaction<EvRxOnCallSerial, OnCall, &OnCall::in_state_react>,
506 boost::statechart::in_state_reaction<EvTxOnCallSerial, OnCall, &OnCall::in_state_react>,
507 boost::statechart::in_state_reaction<EvSendBye, OnCall, &OnCall::in_state_react>>;
508
509 private:
510};
511
512struct SBD : boost::statechart::simple_state<SBD, Command::orthogonal<1>, SBDReady>, StateNotify
513{
514 SBD() : StateNotify("SBD") {}
515 ~SBD() override = default;
516
518 {
519 set_data(e.data_);
520 in_response_to_ring_alert_ = e.in_response_to_ring_alert_;
521 }
522 void clear_data() { data_.clear(); }
523 const std::string& data() const { return data_; }
524 bool in_response_to_ring_alert() const { return in_response_to_ring_alert_; }
525
526 private:
527 void set_data(const std::string& data)
528 {
529 if (data.empty())
530 data_ = data;
531 else
532 {
533 unsigned int csum = sbd_csum(data);
534
535 const int bits_in_byte = 8;
536 data_ = data + std::string(1, (csum & 0xFF00) >> bits_in_byte) +
537 std::string(1, (csum & 0xFF));
538 }
539 }
540
541 private:
542 std::string data_;
543 bool in_response_to_ring_alert_;
544};
545
546/* struct SBDConfigure : boost::statechart::simple_state<SBDConfigure, SBD >, StateNotify */
547/* { */
548/* typedef boost::mpl::list< */
549/* boost::statechart::transition< EvConfigured, SBDReady > */
550/* > reactions; */
551
552/* SBDConfigure() : StateNotify("SBDConfigure") */
553/* { */
554/* } */
555/* ~SBDConfigure() { */
556/* } */
557
558/* }; */
559
561{
562 using reactions = boost::mpl::list<
563 boost::statechart::transition<EvSBDBeginData, SBDClearBuffers, SBD, &SBD::set_data>>;
564
565 SBDReady() : StateNotify("SBDReady") {}
566
567 ~SBDReady() override = default;
568};
569
571{
572 using reactions =
573 boost::mpl::list<boost::statechart::transition<EvSBDSendBufferCleared, SBDWrite>>;
574
575 SBDClearBuffers(my_context ctx) : my_base(std::move(ctx)), StateNotify("SBDClearBuffers")
576 {
577 context<Command>().clear_sbd_rx_buffer();
578 context<Command>().push_at_command("+SBDD2");
579 }
580
581 ~SBDClearBuffers() override = default;
582};
583
585{
586 SBDWrite(my_context ctx) : my_base(std::move(ctx)), StateNotify("SBDWrite")
587 {
588 if (context<SBD>().data().empty())
589 {
590 glog.is(goby::util::logger::DEBUG1) && glog << group("iridiumdriver")
591 << "Mailbox Check." << std::endl;
592 post_event(EvSBDWriteComplete()); // Mailbox Check
593 }
594 else
595 {
596 glog.is(goby::util::logger::DEBUG1) && glog << group("iridiumdriver") << "Writing data."
597 << std::endl;
598
599 const int csum_bytes = 2;
600 context<Command>().push_at_command(
601 "+SBDWB=" + goby::util::as<std::string>(context<SBD>().data().size() - csum_bytes));
602 }
603 entry_time_ = goby::time::SteadyClock::now();
604 }
605
607 {
608 context<IridiumDriverFSM>().serial_tx_buffer().push_back(context<SBD>().data());
609 }
610
612
613 ~SBDWrite() override = default;
614
615 using reactions = boost::mpl::list<
616 boost::statechart::in_state_reaction<EvSBDWriteReady, SBDWrite, &SBDWrite::in_state_react>,
617 boost::statechart::in_state_reaction<EvSBDCheckWriteTimeout, SBDWrite,
619 boost::statechart::transition<EvSBDWriteComplete, SBDTransmit>>;
620
621 private:
623};
624
626{
627 using reactions = boost::mpl::list<boost::statechart::custom_reaction<EvSBDTransmitComplete>>;
628 SBDTransmit(my_context ctx) : my_base(std::move(ctx)), StateNotify("SBDTransmit")
629 {
630 if (context<SBD>().in_response_to_ring_alert())
631 context<Command>().push_at_command("+SBDIXA");
632 else
633 context<Command>().push_at_command("+SBDIX");
634 }
635 ~SBDTransmit() override { context<SBD>().clear_data(); }
636
637 std::string mo_status_as_string(int code)
638 {
639 switch (code)
640 {
641 // success
642 case 0: return "MO message, if any, transferred successfully";
643 case 1:
644 return "MO message, if any, transferred successfully, but the MT message in the "
645 "queue was too big to be transferred";
646 case 2:
647 return "MO message, if any, transferred successfully, but the requested Location "
648 "Update was not accepted";
649 case 3:
650 case 4:
651 return "Reserved, but indicate MO session success if used";
652
653 // failure
654 case 5:
655 case 6:
656 case 7:
657 case 8:
658 case 9:
659 case 20:
660 case 21:
661 case 22:
662 case 23:
663 case 24:
664 case 25:
665 case 26:
666 case 27:
667 case 28:
668 case 29:
669 case 30:
670 case 31:
671 case 33:
672 case 34:
673 case 36:
674 default: return "Reserved, but indicate MO session failure if used";
675 case 10: return "GSS reported that the call did not complete in the allowed time";
676 case 11: return "MO message queue at the GSS is full";
677 case 12: return "MO message has too many segments";
678 case 13: return "GSS reported that the session did not complete";
679 case 14: return "Invalid segment size";
680 case 15: return "Access is denied";
681 case 16: return "Modem has been locked and may not make SBD calls";
682 case 17: return "Gateway not responding (local session timeout)";
683 case 18: return "Connection lost (RF drop)";
684 case 19: return "Link failure (A protocol error caused termination of the call)";
685 case 32: return "No network service, unable to initiate call";
686 case 35: return "Iridium 9523 is busy, unable to initiate call";
687 }
688 }
689
690 boost::statechart::result react(const EvSBDTransmitComplete& e)
691 {
692 // +SBDIX:<MO status>,<MOMSN>,<MT status>,<MTMSN>,<MT length>,<MT queued>
693 std::vector<std::string> sbdi_fields;
694 boost::algorithm::split(sbdi_fields, e.sbdi_, boost::is_any_of(":,"));
695
696 std::for_each(
697 sbdi_fields.begin(), sbdi_fields.end(),
698 boost::bind(&boost::trim<std::string>, boost::placeholders::_1, std::locale()));
699
700 if (sbdi_fields.size() != 7)
701 {
702 glog.is(goby::util::logger::DEBUG1) && glog << group("iridiumdriver")
703 << "Invalid +SBDI response: " << e.sbdi_
704 << std::endl;
705 return transit<SBDReady>();
706 }
707 else
708 {
709 enum
710 {
711 MO_STATUS = 1,
712 MOMSN = 2,
713 MT_STATUS = 3,
714 MTMSN = 4,
715 MT_LENGTH = 5,
716 MT_QUEUED = 6
717 };
718 enum
719 {
720 MT_STATUS_NO_MESSAGE = 0,
721 MT_STATUS_RECEIVED_MESSAGE = 1,
722 MT_STATUS_ERROR = 2
723 };
724
725 // 0-4 OK, 5-36 FAILURE
726 enum
727 {
728 MO_STATUS_SUCCESS_MAX = 4,
729 MO_STATUS_FAILURE_MIN = 5
730 };
731
732 int mo_status = goby::util::as<int>(sbdi_fields[MO_STATUS]);
733 if (mo_status <= MO_STATUS_SUCCESS_MAX)
734 {
736 glog << group("iridiumdriver")
737 << "Success sending SBDIX: " << mo_status_as_string(mo_status)
738 << std::endl;
739 }
740 else
741 {
743 glog << group("iridiumdriver")
744 << "Error sending SBD packet: " << mo_status_as_string(mo_status)
745 << std::endl;
746 return transit<SBDReady>();
747 }
748
749 int mt_status = goby::util::as<int>(sbdi_fields[MT_STATUS]);
750 if (mt_status == MT_STATUS_RECEIVED_MESSAGE)
751 return transit<SBDReceive>();
752 else
753 return transit<SBDReady>();
754 }
755 }
756};
757
759{
760 using reactions =
761 boost::mpl::list<boost::statechart::transition<EvSBDReceiveComplete, SBDReady>>;
762 SBDReceive(my_context ctx) : my_base(std::move(ctx)), StateNotify("SBDReceive")
763 {
764 context<Command>().push_at_command("+SBDRB");
765 }
766 ~SBDReceive() override = default;
767};
768
769} // namespace fsm
770} // namespace iridium
771} // namespace acomms
772} // namespace goby
773
775
776#endif
void post_event(const event_base_ptr_type &pEvent)
_proto_TypeTraits::Singular::ConstType GetExtension(const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< DriverConfig, _proto_TypeTraits, _field_type, _is_packed > &id) const
bool is(goby::util::logger::Verbosity verbosity)
goby::util::logger::GroupSetter group(std::string n)
extern ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< ::goby::acomms::protobuf::DriverConfig, ::PROTOBUF_NAMESPACE_ID::internal::MessageTypeTraits< ::goby::acomms::iridium::protobuf::Config >, 11, false > config
unsigned sbd_csum(const std::string &data)
The global namespace for the Goby project.
extern ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< ::PROTOBUF_NAMESPACE_ID::MessageOptions, ::PROTOBUF_NAMESPACE_ID::internal::MessageTypeTraits< ::goby::GobyMessageOptions >, 11, false > msg
util::FlexOstream glog
Access the Goby logger through this object.
STL namespace.
boost::mpl::list< boost::statechart::transition< EvReset, Active > > reactions
boost::mpl::list< boost::statechart::transition< EvNoCarrier, Ready > > reactions
boost::circular_buffer< std::pair< ATSentenceMeta, std::string > > & at_out()
void in_state_react(const EvRxSerial &)
void in_state_react(const EvTxSerial &)
void in_state_react(const EvAck &)
void push_at_command(const std::string &cmd)
boost::mpl::list< boost::statechart::in_state_reaction< EvRxSerial, Command, &Command::in_state_react >, boost::statechart::in_state_reaction< EvTxSerial, Command, &Command::in_state_react >, boost::statechart::transition< EvOnline, Online >, boost::statechart::in_state_reaction< EvAck, Command, &Command::in_state_react > > reactions
void handle_sbd_rx(const std::string &in)
boost::mpl::list< boost::statechart::transition< EvAtEmpty, Ready > > reactions
boost::mpl::list< boost::statechart::custom_reaction< EvNoCarrier > > reactions
boost::statechart::result react(const EvNoCarrier &)
EvSBDBeginData(std::string data="", bool in_response_to_ring_alert=false)
boost::mpl::list< boost::statechart::transition< EvAtEmpty, Ready > > reactions
const goby::acomms::iridium::protobuf::Config & iridium_driver_cfg() const
const goby::acomms::protobuf::DriverConfig & driver_cfg() const
boost::circular_buffer< goby::acomms::protobuf::ModemTransmission > & received()
void buffer_data_out(const goby::acomms::protobuf::ModemTransmission &msg)
boost::circular_buffer< std::string > & serial_tx_buffer()
boost::circular_buffer< goby::acomms::protobuf::ModemTransmission > & data_out()
void parse_ciev(const std::string &ciev)
IridiumDriverFSM(const goby::acomms::protobuf::DriverConfig &driver_cfg)
boost::mpl::list< boost::statechart::transition< EvConnect, OnCall > > reactions
boost::mpl::list< boost::statechart::transition< EvNoCarrier, NotOnCall >, boost::statechart::in_state_reaction< EvRxOnCallSerial, OnCall, &OnCall::in_state_react >, boost::statechart::in_state_reaction< EvTxOnCallSerial, OnCall, &OnCall::in_state_react >, boost::statechart::in_state_reaction< EvSendBye, OnCall, &OnCall::in_state_react > > reactions
void in_state_react(const EvSendBye &)
void in_state_react(const EvRxOnCallSerial &)
void in_state_react(const EvTxOnCallSerial &)
void in_state_react(const EvTxSerial &)
boost::mpl::list< boost::statechart::transition< EvHangup, HangingUp >, boost::statechart::transition< EvDisconnect, PostDisconnected >, boost::statechart::in_state_reaction< EvRxSerial, Online, &Online::in_state_react >, boost::statechart::in_state_reaction< EvTxSerial, Online, &Online::in_state_react > > reactions
void in_state_react(const EvRxSerial &)
boost::mpl::list< boost::statechart::transition< EvAtEmpty, Ready > > reactions
boost::statechart::result react(const EvDial &)
boost::mpl::list< boost::statechart::transition< EvRing, Answer >, boost::statechart::custom_reaction< EvDial > > reactions
boost::mpl::list< boost::statechart::transition< EvSBDSendBufferCleared, SBDWrite > > reactions
boost::mpl::list< boost::statechart::transition< EvSBDBeginData, SBDClearBuffers, SBD, &SBD::set_data > > reactions
boost::mpl::list< boost::statechart::transition< EvSBDReceiveComplete, SBDReady > > reactions
boost::statechart::result react(const EvSBDTransmitComplete &e)
boost::mpl::list< boost::statechart::custom_reaction< EvSBDTransmitComplete > > reactions
boost::mpl::list< boost::statechart::in_state_reaction< EvSBDWriteReady, SBDWrite, &SBDWrite::in_state_react >, boost::statechart::in_state_reaction< EvSBDCheckWriteTimeout, SBDWrite, &SBDWrite::in_state_react >, boost::statechart::transition< EvSBDWriteComplete, SBDTransmit > > reactions
void in_state_react(const EvSBDCheckWriteTimeout &)
void in_state_react(const EvSBDWriteReady &)
const std::string & data() const
void set_data(const EvSBDBeginData &e)
std::chrono::time_point< SteadyClock > time_point
static time_point now() noexcept
Returns the current steady time unless SimulatorSettings::using_sim_time == true in which case a simu...