25 #include "MGrblSim.hpp"
31 #include <ccut/utils.hpp>
32 #include <logger/Logger.hpp>
37 #include "Exception.hpp"
38 #include "GrblParser.hpp"
40 using namespace logger;
41 using namespace std::chrono;
47 static const std::string s_loggerCat{
"smc:mgrbldevice:sim"};
49 constexpr
size_t MGrblSim::defaultInstancesCount;
50 constexpr
size_t MGrblSim::axisCount;
52 MGrblSim::MGrblSim(
size_t instances) : trigArmed{false}
54 m_instances.reserve(instances);
55 m_layout.assign(axisCount, 0);
59 const std::string msg(
"CMGrbl 1.0\r\n");
60 ::strcpy(m_buffer.end(), msg.data());
61 m_buffer.fwd(msg.length());
71 for (std::unique_ptr<grbl::GrblSim> &instance : m_instances)
75 void MGrblSim::write(
const std::string &raw)
79 const char c = raw[0];
81 if (c >=
'0' && c <=
'9')
83 const size_t instance = c -
'0';
84 if (instance > m_instances.size())
86 error(s_loggerCat) <<
"unknown instance: " << c;
90 m_instances[instance]->write(raw.substr(1));
96 error(s_loggerCat) <<
"unknown command: " << raw;
101 void MGrblSim::wake()
103 if (m_instances.empty())
105 m_instances.at(0)->wake();
108 void MGrblSim::ctrlWrite(
const std::string &line)
118 bool MGrblSim::takeLine(std::string &line)
120 if (m_buffer.takeLine(line))
123 for (
size_t i = 0; i < m_instances.size(); ++i)
125 if (m_instances[i]->takeLine(line))
127 char c[2] = {
'0', 0};
137 bool MGrblSim::wait(
const std::chrono::milliseconds &timeout)
139 std::vector<struct pollfd> pfds;
140 pfds.reserve(m_instances.size() + 1);
143 for (
size_t i = 0; i < m_instances.size(); ++i)
145 pfds.emplace_back(pollfd{m_instances[i]->m_in, POLLIN | POLLERR, 0});
147 pfds.emplace_back(pollfd{m_instances[0]->m_wakeFd[0], POLLIN | POLLERR, 0});
149 if (::poll(pfds.data(), pfds.size(), timeout.count() + 1) >= 0)
151 if (pfds.back().revents & POLLIN)
153 std::vector<char> buffer(10);
154 ::read(m_instances[0]->m_wakeFd[0], buffer.data(), buffer.size());
157 for (
size_t i = 0; i < pfds.size(); ++i)
159 if (pfds[i].revents & POLLERR)
160 throw smc::make_errno_exception(smc::ErrorCode::IO);
161 ret = ret || (pfds[i].revents & POLLIN);
165 throw smc::make_errno_exception(smc::ErrorCode::IO);
169 void MGrblSim::processCtrl(
const std::string &line)
171 const std::string str = ccut::trim(line).substr(1);
174 if (ccut::startsWith(str,
"$layout="))
177 if ((!MGrblParser::parseLayout(str, layout)) ||
178 (layout.size() != m_layout.size()))
179 throw Exception(smc::ErrorCode::InvalidArguments,
180 "invalid layout (wrong instances count)");
181 for (
size_t idx : layout)
183 if (idx >= m_instances.size())
185 smc::ErrorCode::InvalidArguments,
186 "invalid layout (instance index out_of_range)");
188 m_layout.swap(layout);
191 else if (str ==
"$layout")
193 std::string layout(m_layout.size(),
'0');
194 for (
size_t i = 0; i < m_layout.size(); ++i)
195 layout[i] =
static_cast<char>(m_layout[i] +
'0');
197 ctrlWrite(
"$layout=" + layout);
200 else if (str ==
"$grblCount")
205 else if (str ==
"$I")
207 ctrlWrite(
"[VER:1.0]");
208 ctrlWrite(
"[INSTANCES:" +
std::to_string(m_instances.size()) +
"]");
211 else if (ccut::startsWith(str,
"$trigArm="))
215 for (std::unique_ptr<grbl::GrblSim>
const &instance :
217 instance->send(
"M64P0");
222 for (std::unique_ptr<grbl::GrblSim>
const &instance :
224 instance->send(
"M65P0");
229 else if (str ==
"$trigArm")
231 std::string res{
"$trigArm="};
232 res += (trigArmed ?
"1" :
"0");
236 else if (str ==
"$trigSoft")
239 for (std::unique_ptr<grbl::GrblSim>
const &instance : m_instances)
240 instance->send(
"M65P0");
245 throw Exception(smc::ErrorCode::InvalidArguments,
"unknown command");
249 error(s_loggerCat) << ex.what() <<
": " << str;
250 ctrlWrite(
"error:52");
Exception thrown by MotionController in case of issues with command.
const std::string & to_string(Axis::State state)
convert State to string
main motion-lib namespace