RokubiminiSerialCommunication.cpp
Go to the documentation of this file.
1 
3 #include <ros/ros.h>
4 
5 namespace rokubimini
6 {
7 namespace serial
8 {
10  const configuration::SensorConfiguration& sensorConfiguration, const uint8_t& dataFormat, const uint8_t& baudRate)
11  : sensorConfiguration_(sensorConfiguration), dataFormat_(dataFormat), baudRate_(baudRate)
12 {
13 }
14 
15 bool RokubiminiSerialCommandCommSetup::formatCommand(std::string& formattedString)
16 {
17  char buffer[100];
18  int bytes_count = sprintf(buffer, formatString_.c_str(), sensorConfiguration_.getTemperatureCompensationActive(),
20 
21  if (bytes_count < 0)
22  {
23  ROS_ERROR("Failed to format communication setup command");
24  return false;
25  }
26  formattedString.clear();
27  formattedString.assign(buffer, bytes_count);
28  return true;
29 }
30 
32  : filter_(filter)
33 {
34 }
35 
36 bool RokubiminiSerialCommandFilter::formatCommand(std::string& formattedString)
37 {
38  char buffer[100];
39  int bytes_count = sprintf(buffer, formatString_.c_str(), filter_.getSincFilterSize(), filter_.getChopEnable(),
41 
42  if (bytes_count < 0)
43  {
44  ROS_ERROR("Failed to format filters command");
45  return false;
46  }
47  formattedString.clear();
48  formattedString.assign(buffer, bytes_count);
49  return true;
50 }
51 
52 RokubiminiSerialCommandOffset::RokubiminiSerialCommandOffset(const Eigen::Matrix<double, 6, 1>& forceTorqueOffset)
53  : forceTorqueOffset_(forceTorqueOffset)
54 {
55 }
56 
57 bool RokubiminiSerialCommandOffset::formatCommand(std::string& formattedString)
58 {
59  char buffer[100];
60  int bytes_count =
61  sprintf(buffer, formatString_.c_str(), forceTorqueOffset_(0, 0), forceTorqueOffset_(1, 0),
63 
64  if (bytes_count < 0)
65  {
66  ROS_ERROR("Failed to format offset command");
67  return false;
68  }
69  formattedString.clear();
70  formattedString.assign(buffer, bytes_count);
71  return true;
72 }
73 
75  const double& sensorCalibration1, const double& sensorCalibration2, const double& sensorCalibration3,
76  const double& sensorCalibration4, const double& sensorCalibration5, const double& sensorCalibration6,
77  const uint32_t& row)
78  : sensorCalibration1_(sensorCalibration1)
79  , sensorCalibration2_(sensorCalibration2)
80  , sensorCalibration3_(sensorCalibration3)
81  , sensorCalibration4_(sensorCalibration4)
82  , sensorCalibration5_(sensorCalibration5)
83  , sensorCalibration6_(sensorCalibration6)
84  , row_(row)
85 {
86 }
87 
89 {
90  char buffer[100];
91  int bytes_count = sprintf(buffer, formatString_.c_str(), row_, sensorCalibration1_, sensorCalibration2_,
93 
94  if (bytes_count < 0)
95  {
96  ROS_ERROR("Failed to format offset command");
97  return false;
98  }
99  formattedString.clear();
100  formattedString.assign(buffer, bytes_count);
101  return true;
102 }
103 
104 bool RokubiminiSerialCommandHardReset::formatCommand(std::string& formattedString)
105 {
106  formattedString.clear();
107  formattedString.assign(formatString_);
108  return true;
109 }
110 
111 bool RokubiminiSerialCommandSoftReset::formatCommand(std::string& formattedString)
112 {
113  formattedString.clear();
114  formattedString.assign(formatString_);
115  return true;
116 }
117 
118 bool RokubiminiSerialCommandConfig::formatCommand(std::string& formattedString)
119 {
120  formattedString.clear();
121  formattedString.assign(formatString_);
122  return true;
123 }
124 
125 bool RokubiminiSerialCommandRun::formatCommand(std::string& formattedString)
126 {
127  formattedString.clear();
128  formattedString.assign(formatString_);
129  return true;
130 }
131 
132 bool RokubiminiSerialCommandSave::formatCommand(std::string& formattedString)
133 {
134  formattedString.clear();
135  formattedString.assign(formatString_);
136  return true;
137 }
138 
139 bool RokubiminiSerialCommandLoad::formatCommand(std::string& formattedString)
140 {
141  formattedString.clear();
142  formattedString.assign(formatString_);
143  return true;
144 }
145 
146 bool RokubiminiSerialCommandPrint::formatCommand(std::string& formattedString)
147 {
148  formattedString.clear();
149  formattedString.assign(formatString_);
150  return true;
151 }
152 
154 {
155  bool success = false;
156  std::smatch matches;
157  success = regex_search(str, matches, stringRegex_);
158  if (matches.empty() || !matches.ready())
159  {
160  return false;
161  }
162  ROS_DEBUG("Match size is: %zu", matches.size());
163  for (unsigned i = 0; i < matches.size(); ++i)
164  {
165  ROS_DEBUG_STREAM("match " << i << ": " << matches[i]);
166  ROS_DEBUG_STREAM(" (with a length of " << matches[i].length() << ")");
167  }
168  std::string s = matches[0];
169  char temp_comp, calibration, data_format, baud_rate;
170  ROS_DEBUG_STREAM("String is: " << s << " and format is: " << format_);
171  int bytes_count = sscanf(s.c_str(), format_.c_str(), &temp_comp, &calibration, &data_format, &baud_rate);
172  if (bytes_count < 4)
173  {
174  ROS_ERROR("Failed to format communication setup fields");
175  return false;
176  }
177  // use character arithmetic for extracting integer from ASCII codes.
178  tempComp_ = temp_comp - '0';
179  calibration_ = calibration - '0';
180  dataFormat_ = data_format - '0';
181  baudRate_ = baud_rate - '0';
182  ROS_DEBUG("Baud rate is: %u, data format is: %u, temp comp: %u, calibration: %u", getBaudRate(), getDataFormat(),
184  return success;
185 }
186 
188 {
189  bool success = false;
190  std::smatch matches;
191  success = regex_search(str, matches, stringRegex_);
192  if (matches.empty() || !matches.ready())
193  {
194  return false;
195  }
196  ROS_DEBUG("Match size is: %zu", matches.size());
197  for (unsigned i = 0; i < matches.size(); ++i)
198  {
199  ROS_DEBUG_STREAM("match " << i << ": " << matches[i]);
200  ROS_DEBUG_STREAM(" (with a length of " << matches[i].length() << ")");
201  }
202  std::string s = matches[0];
203  char first_number, return_code;
204  ROS_DEBUG_STREAM("String is: " << s << " and format is: " << format_.c_str());
205  int bytes_count = sscanf(s.c_str(), format_.c_str(), &first_number, &command_, &return_code);
206  if (bytes_count < 3)
207  {
208  ROS_ERROR("Failed to format ACK fields");
209  return false;
210  }
211  // use character arithmetic for extracting integer from ASCII codes.
212  firstNumber_ = first_number - '0';
213  returnCode_ = return_code - '0';
214  ROS_DEBUG("First number is: %u, command is: %c, return code: %u", getFirstNumber(), getCommand(), getReturnCode());
215  return success;
216 }
217 
219 {
220  bool success = false;
221  std::smatch matches;
222  success = regex_search(str, matches, stringRegex_);
223  if (matches.empty() || !matches.ready())
224  {
225  return false;
226  }
227  ROS_DEBUG("Match size is: %zu", matches.size());
228  for (unsigned i = 0; i < matches.size(); ++i)
229  {
230  ROS_DEBUG_STREAM("match " << i << ": " << matches[i]);
231  ROS_DEBUG_STREAM(" (with a length of " << matches[i].length() << ")");
232  }
233  std::string s = matches[0];
234  char product_name[20];
235  ROS_DEBUG_STREAM("String is: " << s << " and format is: " << format_);
236  int ret = sscanf(s.c_str(), format_.c_str(), &product_name);
237  if (ret < 1)
238  {
239  ROS_ERROR("Failed to format product name");
240  return false;
241  }
242  productName_.assign(product_name);
243  ROS_DEBUG("Product name is: %s", getProductName().c_str());
244  return success;
245 }
246 
248 {
249  bool success = false;
250  std::smatch matches;
251  success = regex_search(str, matches, stringRegex_);
252  if (matches.empty() || !matches.ready())
253  {
254  return false;
255  }
256  ROS_DEBUG("Match size is: %zu", matches.size());
257  for (unsigned i = 0; i < matches.size(); ++i)
258  {
259  ROS_DEBUG_STREAM("match " << i << ": " << matches[i]);
260  ROS_DEBUG_STREAM(" (with a length of " << matches[i].length() << ")");
261  }
262  std::string s = matches[0];
263  ROS_DEBUG_STREAM("String is: " << s << " and format is: " << format_);
264  int ret = sscanf(s.c_str(), format_.c_str(), &serialNumber_);
265  if (ret < 1)
266  {
267  ROS_ERROR("Failed to format serial number");
268  return false;
269  }
270  ROS_DEBUG("Serial number is: %u", getSerialNumber());
271  return success;
272 }
273 
275 {
276  bool success = false;
277  std::smatch matches;
278  success = regex_search(str, matches, stringRegex_);
279  if (matches.empty() || !matches.ready())
280  {
281  return false;
282  }
283  ROS_DEBUG("Match size is: %zu", matches.size());
284  for (unsigned i = 0; i < matches.size(); ++i)
285  {
286  ROS_DEBUG_STREAM("match " << i << ": " << matches[i]);
287  ROS_DEBUG_STREAM(" (with a length of " << matches[i].length() << ")");
288  }
289  std::string s = matches[0];
290  char firmware_version[25];
291  ROS_DEBUG_STREAM("String is: " << s << " and format is: " << format_);
292  int ret = sscanf(s.c_str(), format_.c_str(), &firmware_version);
293  if (ret < 1)
294  {
295  ROS_ERROR("Failed to format firmware version");
296  return false;
297  }
298  firmwareVersion_.assign(firmware_version);
299  ROS_DEBUG("Firmware version is: %s", getFirmwareVersion().c_str());
300  return success;
301 }
302 
304 {
305  bool success = false;
306  std::smatch matches;
307  success = regex_search(str, matches, stringRegex_);
308  if (matches.empty() || !matches.ready())
309  {
310  return false;
311  }
312  ROS_DEBUG("Match size is: %zu", matches.size());
313  for (unsigned i = 0; i < matches.size(); ++i)
314  {
315  ROS_DEBUG_STREAM("match " << i << ": " << matches[i]);
316  ROS_DEBUG_STREAM(" (with a length of " << matches[i].length() << ")");
317  }
318  std::string s = matches[0];
319  ROS_DEBUG_STREAM("String is: " << s);
320 
321  return success;
322 }
323 } // namespace serial
324 } // namespace rokubimini
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::getCalibration
const uint8_t & getCalibration()
Definition: RokubiminiSerialCommunication.hpp:195
rokubimini::serial::RokubiminiSerialResponseRegexBoot::stringRegex_
const std::regex stringRegex_
Definition: RokubiminiSerialCommunication.hpp:290
rokubimini::serial::RokubiminiSerialResponseRegexProductName::getProductName
const std::string & getProductName()
Definition: RokubiminiSerialCommunication.hpp:217
rokubimini::serial::RokubiminiSerialCommandCommSetup::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:15
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::sensorCalibration6_
double sensorCalibration6_
Definition: RokubiminiSerialCommunication.hpp:91
rokubimini::serial::RokubiminiSerialResponseRegexFirmwareVersion::stringRegex_
const std::regex stringRegex_
Definition: RokubiminiSerialCommunication.hpp:279
rokubimini::serial::RokubiminiSerialResponseRegexBoot::matchInString
bool matchInString(const std::string &str) override
Definition: RokubiminiSerialCommunication.cpp:303
rokubimini::serial::RokubiminiSerialCommandHardReset::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:103
rokubimini::serial::RokubiminiSerialCommandFilter::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:56
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::sensorCalibration3_
double sensorCalibration3_
Definition: RokubiminiSerialCommunication.hpp:88
rokubimini::serial::RokubiminiSerialResponseRegexAck::returnCode_
std::uint8_t returnCode_
Definition: RokubiminiSerialCommunication.hpp:251
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::getBaudRate
const uint8_t & getBaudRate()
Definition: RokubiminiSerialCommunication.hpp:191
rokubimini::serial::RokubiminiSerialCommandCommSetup::sensorConfiguration_
configuration::SensorConfiguration sensorConfiguration_
Definition: RokubiminiSerialCommunication.hpp:42
rokubimini::serial::RokubiminiSerialCommandSoftReset::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:111
s
XmlRpcServer s
ros.h
rokubimini::serial::RokubiminiSerialResponseRegexSerialNumber::getSerialNumber
const uint32_t & getSerialNumber()
Definition: RokubiminiSerialCommunication.hpp:258
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::sensorCalibration1_
double sensorCalibration1_
Definition: RokubiminiSerialCommunication.hpp:86
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::stringRegex_
const std::regex stringRegex_
Definition: RokubiminiSerialCommunication.hpp:205
rokubimini::serial::RokubiminiSerialCommandSoftReset::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:115
rokubimini::serial::RokubiminiSerialResponseRegexAck::getReturnCode
const uint8_t & getReturnCode()
Definition: RokubiminiSerialCommunication.hpp:241
RokubiminiSerialCommunication.hpp
rokubimini::serial::RokubiminiSerialResponseRegexFirmwareVersion::matchInString
bool matchInString(const std::string &str) override
Definition: RokubiminiSerialCommunication.cpp:274
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::row_
uint32_t row_
Definition: RokubiminiSerialCommunication.hpp:92
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::sensorCalibration2_
double sensorCalibration2_
Definition: RokubiminiSerialCommunication.hpp:87
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::baudRate_
uint8_t baudRate_
Definition: RokubiminiSerialCommunication.hpp:209
rokubimini::serial::RokubiminiSerialCommandLoad::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:163
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::RokubiminiSerialCommandSensorCalibrationRow
RokubiminiSerialCommandSensorCalibrationRow()=delete
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::dataFormat_
uint8_t dataFormat_
Definition: RokubiminiSerialCommunication.hpp:208
rokubimini::serial::RokubiminiSerialCommandOffset::RokubiminiSerialCommandOffset
RokubiminiSerialCommandOffset()=delete
rokubimini::serial::RokubiminiSerialCommandCommSetup::RokubiminiSerialCommandCommSetup
RokubiminiSerialCommandCommSetup()=delete
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::tempComp_
uint8_t tempComp_
Definition: RokubiminiSerialCommunication.hpp:207
rokubimini::serial::RokubiminiSerialCommandOffset::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:57
rokubimini::serial::RokubiminiSerialResponseRegexAck::stringRegex_
const std::regex stringRegex_
Definition: RokubiminiSerialCommunication.hpp:247
rokubimini::serial::RokubiminiSerialCommandRun::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:125
rokubimini::serial::RokubiminiSerialCommandCommSetup::baudRate_
uint8_t baudRate_
Definition: RokubiminiSerialCommunication.hpp:44
rokubimini::serial::RokubiminiSerialCommandFilter::RokubiminiSerialCommandFilter
RokubiminiSerialCommandFilter()=delete
rokubimini::configuration::ForceTorqueFilter
ROS_DEBUG
#define ROS_DEBUG(...)
rokubimini::serial::RokubiminiSerialResponseRegexFirmwareVersion::format_
const std::string format_
Definition: RokubiminiSerialCommunication.hpp:280
rokubimini::serial::RokubiminiSerialCommandFilter::filter_
configuration::ForceTorqueFilter filter_
Definition: RokubiminiSerialCommunication.hpp:57
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::sensorCalibration5_
double sensorCalibration5_
Definition: RokubiminiSerialCommunication.hpp:90
rokubimini::serial::RokubiminiSerialResponseRegexAck::getCommand
const char & getCommand()
Definition: RokubiminiSerialCommunication.hpp:237
rokubimini::serial::RokubiminiSerialResponseRegexFirmwareVersion::getFirmwareVersion
const std::string & getFirmwareVersion()
Definition: RokubiminiSerialCommunication.hpp:273
rokubimini::serial::RokubiminiSerialResponseRegexProductName::stringRegex_
const std::regex stringRegex_
Definition: RokubiminiSerialCommunication.hpp:223
rokubimini::serial::RokubiminiSerialResponseRegexAck::format_
const std::string format_
Definition: RokubiminiSerialCommunication.hpp:248
rokubimini::serial::RokubiminiSerialResponseRegexProductName::matchInString
bool matchInString(const std::string &str) override
Definition: RokubiminiSerialCommunication.cpp:218
rokubimini::serial::RokubiminiSerialCommandRun::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:139
rokubimini
System dependencies.
rokubimini::serial::RokubiminiSerialCommandPrint::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:146
rokubimini::serial::RokubiminiSerialResponseRegexSerialNumber::serialNumber_
uint32_t serialNumber_
Definition: RokubiminiSerialCommunication.hpp:266
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::format_
const std::string format_
Definition: RokubiminiSerialCommunication.hpp:206
rokubimini::serial::RokubiminiSerialResponseRegexAck::matchInString
bool matchInString(const std::string &str) override
Definition: RokubiminiSerialCommunication.cpp:187
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::getDataFormat
const uint8_t & getDataFormat()
Definition: RokubiminiSerialCommunication.hpp:187
rokubimini::configuration::SensorConfiguration::getCalibrationMatrixActive
uint8_t getCalibrationMatrixActive() const
rokubimini::serial::RokubiminiSerialResponseRegexAck::getFirstNumber
const uint8_t & getFirstNumber()
Definition: RokubiminiSerialCommunication.hpp:233
rokubimini::serial::RokubiminiSerialResponseRegexSerialNumber::format_
const std::string format_
Definition: RokubiminiSerialCommunication.hpp:265
rokubimini::configuration::ForceTorqueFilter::getSincFilterSize
uint16_t getSincFilterSize() const
rokubimini::serial::RokubiminiSerialCommandConfig::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:127
rokubimini::serial::RokubiminiSerialResponseRegexAck::firstNumber_
uint8_t firstNumber_
Definition: RokubiminiSerialCommunication.hpp:249
rokubimini::serial::RokubiminiSerialCommandFilter::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:36
rokubimini::serial::RokubiminiSerialResponseRegexAck::command_
char command_
Definition: RokubiminiSerialCommunication.hpp:250
rokubimini::serial::RokubiminiSerialCommandHardReset::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:104
rokubimini::serial::RokubiminiSerialResponseRegexSerialNumber::stringRegex_
const std::regex stringRegex_
Definition: RokubiminiSerialCommunication.hpp:264
rokubimini::configuration::ForceTorqueFilter::getChopEnable
uint8_t getChopEnable() const
rokubimini::serial::RokubiminiSerialCommandSave::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:151
rokubimini::serial::RokubiminiSerialResponseRegexProductName::productName_
std::string productName_
Definition: RokubiminiSerialCommunication.hpp:225
ROS_ERROR
#define ROS_ERROR(...)
rokubimini::configuration::ForceTorqueFilter::getSkipEnable
uint8_t getSkipEnable() const
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:85
rokubimini::serial::RokubiminiSerialResponseRegexProductName::format_
const std::string format_
Definition: RokubiminiSerialCommunication.hpp:224
rokubimini::configuration::SensorConfiguration
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::calibration_
uint8_t calibration_
Definition: RokubiminiSerialCommunication.hpp:210
rokubimini::configuration::ForceTorqueFilter::getFastEnable
uint8_t getFastEnable() const
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::matchInString
bool matchInString(const std::string &str) override
Definition: RokubiminiSerialCommunication.cpp:153
rokubimini::serial::RokubiminiSerialCommandLoad::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:139
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:88
rokubimini::serial::RokubiminiSerialCommandConfig::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:118
rokubimini::serial::RokubiminiSerialResponseRegexSerialNumber::matchInString
bool matchInString(const std::string &str) override
Definition: RokubiminiSerialCommunication.cpp:247
rokubimini::serial::RokubiminiSerialCommandCommSetup::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:41
rokubimini::serial::RokubiminiSerialResponseRegexFirmwareVersion::firmwareVersion_
std::string firmwareVersion_
Definition: RokubiminiSerialCommunication.hpp:281
rokubimini::serial::RokubiminiSerialCommandOffset::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:69
rokubimini::serial::RokubiminiSerialResponseRegexCommSetup::getTempComp
const uint8_t & getTempComp()
Definition: RokubiminiSerialCommunication.hpp:183
rokubimini::configuration::SensorConfiguration::getTemperatureCompensationActive
uint8_t getTemperatureCompensationActive() const
rokubimini::serial::RokubiminiSerialCommandOffset::forceTorqueOffset_
const Eigen::Matrix< double, 6, 1 > forceTorqueOffset_
Definition: RokubiminiSerialCommunication.hpp:70
rokubimini::serial::RokubiminiSerialCommandPrint::formatString_
const std::string formatString_
Definition: RokubiminiSerialCommunication.hpp:175
rokubimini::serial::RokubiminiSerialCommandCommSetup::dataFormat_
uint8_t dataFormat_
Definition: RokubiminiSerialCommunication.hpp:43
rokubimini::serial::RokubiminiSerialCommandSensorCalibrationRow::sensorCalibration4_
double sensorCalibration4_
Definition: RokubiminiSerialCommunication.hpp:89
rokubimini::serial::RokubiminiSerialCommandSave::formatCommand
bool formatCommand(std::string &formattedString) override
Definition: RokubiminiSerialCommunication.cpp:132


rokubimini_serial
Author(s):
autogenerated on Sat Apr 15 2023 02:53:58