timesync.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //
  2. // The MIT License (MIT)
  3. //
  4. // Copyright (c) 2019 Livox. All rights reserved.
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. // SOFTWARE.
  23. //
  24. #include "timesync.h"
  25. #include <stdint.h>
  26. #include <string.h>
  27. #include <chrono>
  28. #include <cstdio>
  29. #include <functional>
  30. #include <thread>
  31. namespace livox_ros {
  32. using namespace std;
  33. TimeSync::TimeSync()
  34. : exit_poll_state_(false),
  35. start_poll_state_(false),
  36. exit_poll_data_(false),
  37. start_poll_data_(false) {
  38. fsm_state_ = kOpenDev;
  39. uart_ = nullptr;
  40. comm_ = nullptr;
  41. fn_cb_ = nullptr;
  42. client_data_ = nullptr;
  43. rx_bytes_ = 0;
  44. }
  45. TimeSync::~TimeSync() { DeInitTimeSync(); }
  46. int32_t TimeSync::InitTimeSync(const TimeSyncConfig &config) {
  47. config_ = config;
  48. if (config_.dev_config.type == kCommDevUart) {
  49. uint8_t baudrate_index = config_.dev_config.config.uart.baudrate;
  50. uint8_t parity_index = config_.dev_config.config.uart.parity;
  51. if ((baudrate_index < BRUnkown) && (parity_index < ParityUnkown)) {
  52. uart_ = new UserUart(baudrate_index, parity_index);
  53. } else {
  54. printf("Uart parameter error, please check the configuration file!\n");
  55. return -1;
  56. }
  57. } else {
  58. printf("Device type not supported, now only uart is supported!\n");
  59. return -1;
  60. }
  61. config_.protocol_config.type = kGps;
  62. comm_ = new CommProtocol(config_.protocol_config);
  63. t_poll_state_ =
  64. std::make_shared<std::thread>(std::bind(&TimeSync::PollStateLoop, this));
  65. t_poll_data_ =
  66. std::make_shared<std::thread>(std::bind(&TimeSync::PollDataLoop, this));
  67. return 0;
  68. }
  69. int32_t TimeSync::DeInitTimeSync() {
  70. StopTimesync();
  71. if (uart_) delete uart_;
  72. if (comm_) delete comm_;
  73. fn_cb_ = nullptr;
  74. client_data_ = nullptr;
  75. return 0;
  76. }
  77. void TimeSync::StopTimesync() {
  78. start_poll_state_ = false;
  79. start_poll_data_ = false;
  80. exit_poll_state_ = true;
  81. exit_poll_data_ = true;
  82. if (t_poll_state_) {
  83. t_poll_state_->join();
  84. t_poll_state_ = nullptr;
  85. }
  86. if (t_poll_data_) {
  87. t_poll_data_->join();
  88. t_poll_data_ = nullptr;
  89. }
  90. }
  91. void TimeSync::PollStateLoop() {
  92. while (!start_poll_state_) {
  93. /* waiting to start */
  94. }
  95. while (!exit_poll_state_) {
  96. if (fsm_state_ == kOpenDev) {
  97. FsmOpenDev();
  98. } else if (fsm_state_ == kPrepareDev) {
  99. FsmPrepareDev();
  100. } else if (fsm_state_ == kCheckDevState) {
  101. FsmCheckDevState();
  102. }
  103. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  104. }
  105. }
  106. void TimeSync::PollDataLoop() {
  107. while (!start_poll_data_) {
  108. /* waiting to start */
  109. }
  110. while (!exit_poll_data_) {
  111. if (uart_->IsOpen()) {
  112. uint32_t get_buf_size;
  113. uint8_t *cache_buf = comm_->FetchCacheFreeSpace(&get_buf_size);
  114. if (get_buf_size) {
  115. uint32_t read_data_size;
  116. read_data_size = uart_->Read((char *)cache_buf, get_buf_size);
  117. if (read_data_size) {
  118. comm_->UpdateCacheWrIdx(read_data_size);
  119. rx_bytes_ += read_data_size;
  120. CommPacket packet;
  121. memset(&packet, 0, sizeof(packet));
  122. while ((kParseSuccess == comm_->ParseCommStream(&packet))) {
  123. if (((fn_cb_ != nullptr) || (client_data_ != nullptr))) {
  124. if ((strstr((const char *)packet.data, "$GPRMC")) ||
  125. (strstr((const char *)packet.data , "$GNRMC"))){
  126. fn_cb_((const char *)packet.data, packet.data_len, client_data_);
  127. printf("RMC data parse success!.\n");
  128. }
  129. }
  130. }
  131. }
  132. }
  133. } else {
  134. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  135. }
  136. }
  137. }
  138. void TimeSync::FsmTransferState(uint8_t new_state) {
  139. if (new_state < kFsmDevUndef) {
  140. fsm_state_ = new_state;
  141. }
  142. transfer_time_ = chrono::steady_clock::now();
  143. }
  144. void TimeSync::FsmOpenDev() {
  145. if (!uart_->IsOpen()) {
  146. if (!uart_->Open(config_.dev_config.name)) {
  147. FsmTransferState(kPrepareDev);
  148. }
  149. } else {
  150. FsmTransferState(kPrepareDev);
  151. }
  152. }
  153. void TimeSync::FsmPrepareDev() {
  154. chrono::steady_clock::time_point t = chrono::steady_clock::now();
  155. chrono::milliseconds time_gap =
  156. chrono::duration_cast<chrono::milliseconds>(t - transfer_time_);
  157. /** delay some time when device is opened, 4s */
  158. if (time_gap.count() > 3000) {
  159. FsmTransferState(kCheckDevState);
  160. }
  161. }
  162. void TimeSync::FsmCheckDevState() {
  163. static uint32_t last_rx_bytes = 0;
  164. static chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
  165. chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
  166. chrono::milliseconds time_gap =
  167. chrono::duration_cast<chrono::milliseconds>(t2 - t1);
  168. if (time_gap.count() > 2000) { /* period : 2.5s */
  169. if (last_rx_bytes == rx_bytes_) {
  170. uart_->Close();
  171. FsmTransferState(kOpenDev);
  172. printf("Uart is disconnected, close it\n");
  173. }
  174. last_rx_bytes = rx_bytes_;
  175. t1 = t2;
  176. }
  177. }
  178. } // namespace livox_ros