RN41/42 control lib. RN41/42 is bluetooth module with class 1 or 2.
Dependencies: StrLib myTimer RingBuffer
Diff: RN41.cpp
- Revision:
- 0:812e6b59aa54
- Child:
- 1:5ed110051e39
diff -r 000000000000 -r 812e6b59aa54 RN41.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RN41.cpp Tue Oct 20 01:32:17 2015 +0000 @@ -0,0 +1,339 @@ +#include "RN41.h" +//#include "SerialBase.h" + +//extern void sendHC05(string); + + + +const int RN41::NG= 0; +const int RN41::OK= 1; + +// PRIVATE +const int RN41::findCmp12= 100; +const int RN41::findCmp1= 101; +const int RN41::findCmp2= 102; + +// PUBLIC +const int RN41::ERR_AddrUnder12= 210; +const int RN41::ERR_AddrOver12= 211; +const int RN41::ERR_Connect= 220; +const int RN41::FAIL_Connect= 221; +const int RN41::ERR_EnterCmdMode= 230; +const int RN41::ERR_Disconnect= 240; + +const int RN41::ERR_NameSize= 310; + +/* +const int RN41::None= 10; +const int RN41::Odd= 11; +const int RN41::Even= 12; +*/ + + + +RN41::RN41(PinName TX, PinName RX, int baudrate, int bit, int parity, int stop, bool CRLN) + : rn41(TX, RX) +{ + rn41.baud(baudrate); + /* + Parity _parity= SerialBase::None; // enum + if(parity == 'O') + _parity= SerialBase::Odd; + if(parity == 'E') + _parity= SerialBase::Even; + rn41.format(bit, _parity, stop); // 8bit, NonParity, 1stopbit + */ + + // 力技 + if (parity == SerialBase::Odd) + rn41.format(bit, SerialBase::Odd, stop); + else if (parity == SerialBase::Even) + rn41.format(bit, SerialBase::Even, stop); // 8bit, NonParity, 1stopbit + else// if (parity == SerialBase::None) + rn41.format(bit, SerialBase::None, stop); // 8bit, NonParity, 1stopbit + + CR= '\r'; + if(CRLN) + CR= "\r\n"; +} + + +int RN41::connect(string addr) +{ + timerLocal.reset(); + timerLocal.start(); + + addr= toAlpanumeric(addr, true); + int idx= addr.size(); + // ex. 0006:66:72:6e05\r ->000666726e05. + if(idx < 12) + return ERR_AddrUnder12; + if(idx > 12) + return ERR_AddrOver12; + + if(!enterCMD()) + return ERR_EnterCmdMode; // CMD入れず +// sendHC05("test 100"); + if(!disconnect()) + return ERR_Disconnect; + if(!enterCMD()) + return ERR_EnterCmdMode; // CMD入れず + + // BT addr check success; + sendCMD("C,"+ addr); + int status; + +// wait(1.0);read();sendHC05("--"+ rxStr+ "**"); + + status= chkReply("TRYING\r", 1000, "ERR\r"); + if(status == findCmp2) + return ERR_Connect; + else if(status == findCmp1) { + // Trying to connect to remote Bluetooth dev. + +// wait(7.0); read(); sendHC05(rxStr); + timerLocal.reset(); + timerLocal.start(); + status= chkReply("CONNECT,", 10000, "CONNECT failed\r"); // wait 10s + +// sendHC05("Time of Create-Connection: "+ I2A(timerLocal.read_ms())+ " ms."); + + if(status == findCmp1) + return OK; + else if(status == findCmp2) + return FAIL_Connect; + } else { +// sendHC05("connect:"+ I2A(status)); + } + return 1234; +} + + + + +string RN41::getLine() +{ + read(); + // CRまでを返す + +//sendHC05("debug 10"); + if(str4GetLine.size()==0 && rxStr.size()==0) + return ""; + +// trying->Connect待ちをTickerにすると、そこんとの除外処理が必須。 +// sendHC05("debug 20"); + + // rxStr.size() > 0 + int idx= rxStr.rfind(CR); +// sendHC05("rxStr: "+ rxStr); sendHC05("idxCR: "+ I2A(idx)); + if(idx == string::npos) // not find CR! + return str4GetLine; // ダメじゃね?? + +// sendHC05("debug 30"); + // rxStr has CR. + idx += CR.size(); // \rなら+1、\r\nは+2 + string rtn= str4GetLine; + rtn += rxStr.substr(0, idx); // 切り取り + rxStr= rxStr.substr(idx); +// sendHC05("debug 40"); + return rtn; +} + + + +int RN41::setDev_Name(string str, bool usingAddr) +{ + int strSize= str.size(); + if((strSize==0) || (20<=strSize) || (usingAddr && 15<=strSize)) + return ERR_NameSize; + + // 特殊文字チェックは不要っぽい + + string cmd; + if(usingAddr) + cmd= "S-,"; + else + cmd= "SN,"; + + if(!enterCMD()) + return ERR_EnterCmdMode; // CMD入れず + + + sendCMD(cmd+ str); + int status; +// wait(1.0);read();sendHC05("--"+ rxStr+ "**"); + status= chkReply("AOK\r", 1000); + if(status == findCmp1) + return OK; + + return NG; +} + + +void RN41::sendCMD(string str, bool addCR) +{ + if(addCR) + str += '\r'; + rn41.printf(str.c_str()); + return; +} +void RN41::sendLINE(string str, bool addCR) +{ + if(addCR) + str += "\r\n"; + rn41.printf(str.c_str()); + return; +} + + + +bool RN41::enterCMD() +{ + sendCMD("$$$", false); + if(chkReply("CMD\r", 500) == findCmp1) { // 500ms +// sendHC05("returned CMD."); + return true; + } + + sendCMD("\r", false); // 既にCMDモード + if(chkReply("?\r", 500) == findCmp1) { +// sendHC05("Already CmdMode."); + return true; + } + return false; +} + + + +bool RN41::disconnect() +{ + // if(!enterCMD()) return false; // CMD入れず + + sendCMD("K,"); // rtn KILL ? / ERR ? + int status; +// wait(6.0); read(); sendHC05("in disconnect; \t"+ rxStr); + + status= chkReply("KILL\r", 500, "ERR\r"); + if(status == findCmp2) { // 既に切断されている + sendCMD("---"); // exit CMD mode. + if(chkReply("END\r", 500) == findCmp1) + return true; + else// { leds.ON(4); + return false; // どういう状況か不明 + } else if(status == findCmp1) { +// if(chkReply("DISCONNECT", 2000) == findCmp1) + if(chkReply_woCR("DISCONNECT", 5000)) // CR無いかも? + return true; + else //{ leds.ON(3); + return false; // どういう状況か不明 + }// else { return false; } + return false; +} + + + + +int RN41::chkReply(string cmp1, int timeout, string cmp2) +{ + timerLocal.reset(); + timerLocal.start(); + + int cmp2Size= cmp2.size(); + int idxCR, idx1, idx2;//= string::npos; + bool find1, find2; + for(;;) { + if(timerLocal.read_ms() > timeout) + return NG; + + read(); + idxCR= rxStr.find_first_of('\r'); + if(idxCR != string::npos) { // CR found. + idx1= idx2= string::npos; // -1 + find1= find2= false; + idx1= rxStr.find(cmp1); + if(cmp2Size != 0) + idx2= rxStr.find(cmp2); + + // idx1: 0< or npos, idx2: 0< or npos(notfined or size0) + int idxCut; + //idx1(~CR) -> idx2(~CR) + if(idx1 != string::npos) + if(idx1 < idxCR) + find1= true; + if(idx2 != string::npos) + if(idx2 < idxCR) + find2= true; + +//sendHC05("++"+ rxStr+ "**"); +//sendHC05("idx1:"+cmp1+":"+ I2A(idx1)+ "\tidx2:"+cmp2+":"+ I2A(idx2)+ "\tidxCR:"+ I2A(idxCR)); + + // CRまで切り取り。findならば切り捨て、見つからなければコピー後切り捨て + idxCut= idxCR+ 1; + if(rxStr[idxCut] == '\n') + idxCut++; + // 切り捨てはidxからの切り取りを上書き。コピーは文字数なので、idxが-1まで。 + if(!(find1 || find2)) + str4GetLine= rxStr.substr(0, idxCut); + rxStr= rxStr.substr(idxCut); // 切り取りは共通。 + + if(find1 && find2) // find1有、find2有 + return findCmp12; + if(find1) + return findCmp1; + if(find2) + return findCmp2; + // CR内にCMP無い場合は、ループへ + } + } // end for +} + + +bool RN41::chkReply_woCR(string cmp, int timeout) +{ + timerLocal.reset(); + timerLocal.start(); + + int idx; + for(;;) { + if(timerLocal.read_ms() > timeout) { +// sendHC05("in chkReply; "+ rxStr); + return false; + } + read(); + idx= rxStr.find(cmp); + if(idx != string::npos) { + // めんどいから消去する。 + idx= rxStr.find_first_of('\r'); + if(idx == string::npos) + rxStr= ""; + else { + idx++; + if(rxStr[idx] == '\n') + idx++; + rxStr= rxStr.substr(idx); + } +// rxStr= ""; + return true; + } + } +} + + + + +void RN41::read() +{ + if(!rn41.readable()) + return; + + // Bufferを吸い尽くす +// char ch; + for(;;) { +// char ch= rn41.getc(); // 1文字取る +// ch= rn41.getc(); // 1文字取る +// rxStr += ch; // 上書き前に退避 + rxStr += (char)rn41.getc(); + if(!rn41.readable()) + return; //break; // Bufferになくなった + } // end for +} \ No newline at end of file