00001 #include <iostream>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <fcntl.h>
00005 #include <errno.h>
00006 #include <termios.h>
00007 #include <time.h>
00008 #include <sstream>
00009
00010 #include "RoboteqDevice.h"
00011 #include "ErrorCodes.h"
00012
00013 using namespace std;
00014
00015 #define BUFFER_SIZE 1024
00016 #define MISSING_VALUE -1024
00017
00018 RoboteqDevice::RoboteqDevice()
00019 {
00020 handle = RQ_INVALID_HANDLE;
00021 }
00022 RoboteqDevice::~RoboteqDevice()
00023 {
00024 Disconnect();
00025 }
00026
00027 bool RoboteqDevice::IsConnected()
00028 {
00029 return handle != RQ_INVALID_HANDLE;
00030 }
00031 int RoboteqDevice::Connect(string port)
00032 {
00033 if(IsConnected())
00034 {
00035 cout<<"Device is connected, attempting to disconnect."<<endl;
00036 Disconnect();
00037 }
00038
00039
00040 cout<<"Opening port: '"<<port<<"'...";
00041 handle = open(port.c_str(), O_RDWR |O_NOCTTY | O_NDELAY);
00042 if(handle == RQ_INVALID_HANDLE)
00043 {
00044 cout<<"failed."<<endl;
00045 return RQ_ERR_OPEN_PORT;
00046 }
00047
00048 cout<<"succeeded."<<endl;
00049 fcntl (handle, F_SETFL, O_APPEND | O_NONBLOCK);
00050
00051 cout<<"Initializing port...";
00052 InitPort();
00053 cout<<"...done."<<endl;
00054
00055 int status;
00056 string response;
00057 cout<<"Detecting device version...";
00058 status = IssueCommand("?", "$1E", 10, response);
00059 if(status != RQ_SUCCESS)
00060 {
00061 cout<<"failed (issue ?$1E response: "<<status<<")."<<endl;
00062 Disconnect();
00063 return RQ_UNRECOGNIZED_DEVICE;
00064 }
00065
00066 if(response.length() < 12)
00067 {
00068 cout<<"failed (unrecognized version)."<<endl;
00069 Disconnect();
00070 return RQ_UNRECOGNIZED_VERSION;
00071 }
00072
00073 cout<<response.substr(8, 4)<<"."<<endl;
00074 return RQ_SUCCESS;
00075 }
00076 void RoboteqDevice::Disconnect()
00077 {
00078 if(IsConnected())
00079 close(handle);
00080
00081 handle = RQ_INVALID_HANDLE;
00082 }
00083
00084 void RoboteqDevice::InitPort()
00085 {
00086 if(!IsConnected())
00087 return;
00088
00089
00090 int BAUDRATE = B115200;
00091 struct termios newtio;
00092 tcgetattr (handle, &newtio);
00093
00094
00095 cfsetospeed (&newtio, (speed_t)BAUDRATE);
00096 cfsetispeed (&newtio, (speed_t)BAUDRATE);
00097
00098
00099 newtio.c_iflag = IGNBRK;
00100 newtio.c_lflag = 0;
00101 newtio.c_oflag = 0;
00102 newtio.c_cflag |= (CLOCAL | CREAD);
00103
00104
00105 newtio.c_cflag &= ~CSIZE;
00106 newtio.c_cflag |= CS7;
00107 newtio.c_cflag |= PARENB;
00108 newtio.c_cflag &= ~PARODD;
00109
00110
00111
00112
00113
00114 tcsetattr (handle, TCSANOW, &newtio);
00115 }
00116
00117 int RoboteqDevice::Write(string str)
00118 {
00119 if(!IsConnected())
00120 return RQ_ERR_NOT_CONNECTED;
00121
00122
00123 int countSent = write(handle, str.c_str(), str.length());
00124
00125
00126 if(countSent < 0)
00127 return RQ_ERR_TRANSMIT_FAILED;
00128
00129 return RQ_SUCCESS;
00130 }
00131 int RoboteqDevice::ReadAll(string &str)
00132 {
00133 int countRcv;
00134 if(!IsConnected())
00135 return RQ_ERR_NOT_CONNECTED;
00136
00137 char buf[BUFFER_SIZE + 1] = "";
00138
00139 str = "";
00140
00141 while((countRcv = read(handle, buf, BUFFER_SIZE)) > 0)
00142 {
00143 str.append(buf, countRcv);
00144
00145
00146 if(countRcv < BUFFER_SIZE)
00147 break;
00148 }
00149
00150 if(countRcv < 0)
00151 {
00152 if(errno == EAGAIN)
00153 return RQ_ERR_SERIAL_IO;
00154 else
00155 return RQ_ERR_SERIAL_RECEIVE;
00156 }
00157
00158 return RQ_SUCCESS;
00159 }
00160
00161 int RoboteqDevice::IssueCommand(string commandType, string command, string args, int waitms, string &response, bool isplusminus)
00162 {
00163
00164 int status;
00165 string read;
00166 response = "";
00167
00168 if(args == "")
00169 status = Write(commandType + command + "\r");
00170 else
00171 status = Write(commandType + command + " " + args + "\r");
00172
00173 if(status != RQ_SUCCESS)
00174 return status;
00175
00176 usleep(waitms * 1000l);
00177
00178 status = ReadAll(read);
00179 if(status != RQ_SUCCESS)
00180 return status;
00181
00182 if(isplusminus)
00183 {
00184 if(read.length() < 2)
00185 return RQ_INVALID_RESPONSE;
00186
00187 response = read.substr(read.length() - 2, 1);
00188 return RQ_SUCCESS;
00189 }
00190
00191
00192 string::size_type pos = read.rfind(command + "=");
00193 if(pos == string::npos)
00194 return RQ_INVALID_RESPONSE;
00195
00196 pos += command.length() + 1;
00197
00198 string::size_type carriage = read.find("\r", pos);
00199 if(carriage == string::npos)
00200 return RQ_INVALID_RESPONSE;
00201
00202 response = read.substr(pos, carriage - pos);
00203
00204 return RQ_SUCCESS;
00205 }
00206 int RoboteqDevice::IssueCommand(string commandType, string command, int waitms, string &response, bool isplusminus)
00207 {
00208 return IssueCommand(commandType, command, "", waitms, response, isplusminus);
00209 }
00210
00211 int RoboteqDevice::SetConfig(int configItem, int index, int value)
00212 {
00213 string response;
00214 char command[10];
00215 char args[50];
00216
00217 if(configItem < 0 || configItem > 255)
00218 return RQ_INVALID_CONFIG_ITEM;
00219
00220 sprintf(command, "$%02X", configItem);
00221 sprintf(args, "%i %i", index, value);
00222 if(index == MISSING_VALUE)
00223 {
00224 sprintf(args, "%i", value);
00225 index = 0;
00226 }
00227
00228 if(index < 0)
00229 return RQ_INDEX_OUT_RANGE;
00230
00231 int status = IssueCommand("^", command, args, 10, response, true);
00232 if(status != RQ_SUCCESS)
00233 return status;
00234 if(response != "+")
00235 return RQ_SET_CONFIG_FAILED;
00236
00237 return RQ_SUCCESS;
00238 }
00239 int RoboteqDevice::SetConfig(int configItem, int value)
00240 {
00241 return SetConfig(configItem, MISSING_VALUE, value);
00242 }
00243
00244 int RoboteqDevice::SetCommand(int commandItem, int index, int value)
00245 {
00246 string response;
00247 char command[10];
00248 char args[50];
00249
00250 if(commandItem < 0 || commandItem > 255)
00251 return RQ_INVALID_COMMAND_ITEM;
00252
00253 sprintf(command, "$%02X", commandItem);
00254 sprintf(args, "%i %i", index, value);
00255 if(index == MISSING_VALUE)
00256 {
00257 if(value != MISSING_VALUE)
00258 sprintf(args, "%i", value);
00259 index = 0;
00260 }
00261
00262 if(index < 0)
00263 return RQ_INDEX_OUT_RANGE;
00264
00265 int status = IssueCommand("!", command, args, 10, response, true);
00266 if(status != RQ_SUCCESS)
00267 return status;
00268 if(response != "+")
00269 return RQ_SET_COMMAND_FAILED;
00270
00271 return RQ_SUCCESS;
00272 }
00273 int RoboteqDevice::SetCommand(int commandItem, int value)
00274 {
00275 return SetCommand(commandItem, MISSING_VALUE, value);
00276 }
00277 int RoboteqDevice::SetCommand(int commandItem)
00278 {
00279 return SetCommand(commandItem, MISSING_VALUE, MISSING_VALUE);
00280 }
00281
00282 int RoboteqDevice::GetConfig(int configItem, int index, int &result)
00283 {
00284 string response;
00285 char command[10];
00286 char args[50];
00287
00288 if(configItem < 0 || configItem > 255)
00289 return RQ_INVALID_CONFIG_ITEM;
00290
00291 if(index < 0)
00292 return RQ_INDEX_OUT_RANGE;
00293
00294 sprintf(command, "$%02X", configItem);
00295 sprintf(args, "%i", index);
00296
00297 int status = IssueCommand("~", command, args, 10, response);
00298 if(status != RQ_SUCCESS)
00299 return status;
00300
00301 istringstream iss(response);
00302 iss>>result;
00303
00304 if(iss.fail())
00305 return RQ_GET_CONFIG_FAILED;
00306
00307 return RQ_SUCCESS;
00308 }
00309 int RoboteqDevice::GetConfig(int configItem, int &result)
00310 {
00311 return GetConfig(configItem, 0, result);
00312 }
00313
00314 int RoboteqDevice::GetValue(int operatingItem, int index, int &result)
00315 {
00316 string response;
00317 char command[10];
00318 char args[50];
00319
00320 if(operatingItem < 0 || operatingItem > 255)
00321 return RQ_INVALID_OPER_ITEM;
00322
00323 if(index < 0)
00324 return RQ_INDEX_OUT_RANGE;
00325
00326 sprintf(command, "$%02X", operatingItem);
00327 sprintf(args, "%i", index);
00328
00329 int status = IssueCommand("?", command, args, 10, response);
00330 if(status != RQ_SUCCESS)
00331 return status;
00332
00333 istringstream iss(response);
00334 iss>>result;
00335
00336 if(iss.fail())
00337 return RQ_GET_VALUE_FAILED;
00338
00339 return RQ_SUCCESS;
00340 }
00341 int RoboteqDevice::GetValue(int operatingItem, int &result)
00342 {
00343 return GetValue(operatingItem, 0, result);
00344 }
00345
00346
00347 string ReplaceString(string source, string find, string replacement)
00348 {
00349 string::size_type pos = 0;
00350 while((pos = source.find(find, pos)) != string::npos)
00351 {
00352 source.replace(pos, find.size(), replacement);
00353 pos++;
00354 }
00355
00356 return source;
00357 }
00358
00359 void sleepms(int milliseconds)
00360 {
00361 usleep(milliseconds / 1000);
00362 }