MotionLib  1.0.0
SamBuCa motion library
MGrblDeviceBase.hxx
1 /*
2 ** Copyright (C) 2022 CERN
3 **
4 ** This software is provided 'as-is', without any express or implied
5 ** warranty. In no event will the authors be held liable for any damages
6 ** arising from the use of this software.
7 **
8 ** Permission is granted to anyone to use this software for any purpose,
9 ** including commercial applications, and to alter it and redistribute it
10 ** freely, subject to the following restrictions:
11 **
12 ** 1. The origin of this software must not be misrepresented; you must not
13 ** claim that you wrote the original software. If you use this software
14 ** in a product, an acknowledgment in the product documentation would be
15 ** appreciated but is not required.
16 ** 2. Altered source versions must be plainly marked as such, and must not be
17 ** misrepresented as being the original software.
18 ** 3. This notice may not be removed or altered from any source distribution.
19 **
20 ** Created on: 2022-09-22T16:00:46
21 ** Author: Sylvain Fargier <sylvain.fargier@cern.ch>
22 */
23 
24 #ifndef MGRBLDEVICEBASE_CPP__
25 #define MGRBLDEVICEBASE_CPP__
26 
27 #include <chrono>
28 
29 #include <logger/Logger.hpp>
30 
31 #include "GrblParser.hpp"
32 #include "MGrblDeviceBase.hpp"
33 
34 namespace grbl {
35 
36 template<typename DeviceBase>
37 grbl::ErrorCode MGrblDeviceBase<DeviceBase>::send(
38  const std::string &cmd,
39  std::function<bool(const std::string &)> msg,
40  const std::chrono::milliseconds &timeout)
41 {
42  static const std::string s_loggerCat{"smc:mgrbldevice"};
43 
44  const std::chrono::steady_clock::time_point deadline =
45  std::chrono::steady_clock::now() + timeout;
46  logger::debug(s_loggerCat) << "--> " << cmd;
47  if (cmd.empty())
48  return 3;
49 
50  this->write(cmd + "\r\n");
51  const char sender = cmd[0];
52 
53  bool msgConfirmed = false;
54  do
55  {
56  std::chrono::steady_clock::time_point now =
57  std::chrono::steady_clock::now();
58  const std::chrono::milliseconds remaining = (now < deadline) ?
59  std::chrono::duration_cast<std::chrono::milliseconds>(deadline -
60  now) :
61  std::chrono::milliseconds::zero();
62 
63  this->wait(remaining);
64  this->read();
65  std::string line;
66  while (this->takeLine(line))
67  {
68  logger::debug(s_loggerCat) << "<-- " << line;
69  if (line[0] == sender)
70  {
71  if (line.compare(1, 2, "ok") == 0)
72  {
73  if (msg && !msgConfirmed)
74  return grbl::CustomErrorCode::NoPayload;
75  return 0;
76  }
77  else if (line.compare(1, 6, "error:") == 0)
78  {
79  grbl::ErrorCode errorCode;
80  if (GrblParser::parseErrorReply(line.substr(1), errorCode))
81  return errorCode;
82  logger::error(s_loggerCat)
83  << "Cannot parse error code: " << line;
84  return grbl::CustomErrorCode::InternalError;
85  }
86  }
87  try
88  {
89  if (bool(msg) && msg(line))
90  msgConfirmed = true;
91  else
92  this->dataSignal(line);
93  }
94  catch (grbl::ErrorCode &rc)
95  {
96  return rc;
97  }
98  catch (std::exception &ex)
99  {
100  logger::error(s_loggerCat)
101  << "exception in client callback: " << ex.what();
102  }
103  }
104  } while (std::chrono::steady_clock::now() <= deadline);
105  return grbl::CustomErrorCode::Timeout;
106 }
107 
108 } // namespace grbl
109 
110 #endif
static bool parseErrorReply(const std::string &line, grbl::ErrorCode &errorCode)
parse an error message
Definition: GrblParser.cpp:103