MotionLib  1.0.0
SamBuCa motion library
GrblDeviceBase.cpp
1 /*
2 ** Copyright (C) 2020 Sylvain Fargier
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-02-13T22:52:09+01:00
21 ** Author: Sylvain Fargier <fargie_s> <sylvain.fargier@cern.ch>
22 **
23 */
24 
25 #include "GrblDeviceBase.hpp"
26 
27 #include <ccut/Regex.hpp>
28 #include <ccut/utils.hpp>
29 #include <logger/Logger.hpp>
30 
31 #include "GrblParser.hpp"
32 
33 using namespace grbl;
34 using namespace std::chrono;
35 using namespace logger;
36 
37 static const std::string s_loggerCat{"smc:grbldevice"};
38 static const std::string s_crnl("\r\n");
39 
40 const milliseconds GrblDeviceBase::defaultSendTimeout(1000);
41 
42 void GrblDeviceBase::fetch(const std::chrono::milliseconds &timeout)
43 {
44  if (wait(timeout))
45  {
46  read();
47  std::string line;
48  while (takeLine(line))
49  {
50  debug(s_loggerCat) << "<~- " << line;
51  dataSignal(line);
52  }
53  }
54 }
55 
56 grbl::ErrorCode GrblDeviceBase::send(const std::string &cmd,
57  std::function<bool(const std::string &)> msg,
58  const std::chrono::milliseconds &timeout)
59 {
60  const steady_clock::time_point deadline = steady_clock::now() + timeout;
61 
62  debug(s_loggerCat) << "--> " << cmd;
63  if (cmd.length() > 0)
64  {
65  write(cmd);
66  write(s_crnl);
67  }
68  bool msgConfirmed = false;
69  while (steady_clock::now() <= deadline)
70  {
71  steady_clock::time_point now = steady_clock::now();
72  const milliseconds remaining = (now < deadline) ?
73  duration_cast<milliseconds>(deadline - now) :
74  milliseconds::zero();
75 
76  wait(remaining);
77  read();
78  std::string line;
79  while (this->takeLine(line))
80  {
81  debug(s_loggerCat) << "<-- " << line;
82  switch (GrblParser::getLineType(line))
83  {
84  case GrblParser::LineType::OkReply:
85  {
86  if (msg && !msgConfirmed)
87  return grbl::CustomErrorCode::NoPayload;
88  return 0;
89  }
90  case GrblParser::LineType::ErrorReply:
91  {
92  ErrorCode errorCode;
93  if (GrblParser::parseErrorReply(line, errorCode))
94  return errorCode;
95  error(s_loggerCat) << "Cannot parse error code: " << line;
96  return grbl::CustomErrorCode::InternalError;
97  }
98  default:
99  try
100  {
101  if (bool(msg) && msg(line))
102  msgConfirmed = true;
103  else
104  dataSignal(line);
105  }
106  catch (const grbl::ErrorCode &rc)
107  {
108  return rc;
109  }
110  catch (std::exception &ex)
111  {
112  error(s_loggerCat)
113  << "exception in client callback: " << ex.what();
114  }
115  break;
116  }
117  }
118  }
119  return grbl::CustomErrorCode::Timeout;
120 }
121 
123  const std::string &cmd,
124  std::function<bool(const std::string &)> msg,
125  const std::chrono::milliseconds &timeout)
126 {
127  const steady_clock::time_point deadline = steady_clock::now() + timeout;
128 
129  debug(s_loggerCat) << "->> " << cmd;
130  if (cmd.length() > 0)
131  write(cmd);
132  if (!msg)
133  return grbl::ErrorCode{0};
134 
135  while (steady_clock::now() <= deadline)
136  {
137  steady_clock::time_point now = steady_clock::now();
138  const milliseconds remaining = (now < deadline) ?
139  duration_cast<milliseconds>(deadline - now) :
140  milliseconds::zero();
141 
142  wait(remaining);
143  read();
144  std::string line;
145  while (this->takeLine(line))
146  {
147  debug(s_loggerCat) << "<<- " << line;
148  try
149  {
150  if (!msg(line))
151  dataSignal(line);
152  }
153  catch (const grbl::ErrorCode &rc)
154  {
155  return rc;
156  }
157  catch (std::exception &ex)
158  {
159  error(s_loggerCat)
160  << "exception in client callback: " << ex.what();
161  }
162  }
163  }
164  return grbl::CustomErrorCode::Timeout;
165 }
166 
167 bool GrblDeviceBase::takeLine(std::string &line)
168 {
169  return m_buffer.takeLine(line);
170 }
virtual grbl::ErrorCode sendRealtime(const std::string &cmd, std::function< bool(const std::string &)> msg={}, const std::chrono::milliseconds &timeout=defaultSendTimeout)
send a realtime-command wait for reply
virtual bool takeLine(std::string &line)
consume line from buffer
virtual grbl::ErrorCode send(const std::string &cmd, std::function< bool(const std::string &)> msg={}, const std::chrono::milliseconds &timeout=defaultSendTimeout)
send a command wait for reply
void fetch(const std::chrono::milliseconds &timeout)
wait for data and process it
static LineType getLineType(const std::string &line)
detect line type
Definition: GrblParser.cpp:51
static bool parseErrorReply(const std::string &line, grbl::ErrorCode &errorCode)
parse an error message
Definition: GrblParser.cpp:103