This software is a test tool for the XBee Library 'XBee Coord API'. I'll check to pass the test when release the library.

Dependencies:   TextLCD mbed xbee

Please refer to the following site for the details:

main.cpp

Committer:
bokunimowakaru
Date:
2014-09-21
Revision:
0:60ca8c579d80
Child:
3:e815df43e269

File content as of revision 0:60ca8c579d80:

#define ARM_MBED
//#define DEBUG       // D8(PA_9)からログをUART(38400baud)出力します
/*********************************************************************
XBee ライブラリ・自動システム試験ツール

 元々、XBeeライブラリ「ZB Coord API」のリリース用のテストツールとして
 作成して、使用していたものです。
 XBeeライブラリを用いた時の評価用に公開することにいたしました。
 電波環境が悪いと100%になりません。
 Arduino用PC用ともにキーを押すとエラー数と合格回数、テスト回数、最後の
 エラーの内容を表示します。

本ソースリストおよびソフトウェアは、ライセンスフリーです。
利用、編集、再配布等が自由に行えますが、著作権表示の改変は禁止します。

                               Copyright (c) 2010-2014 Wataru KUNINO
                               http://www.geocities.jp/bokunimowakaru/
*********************************************************************/

/*********************************************************************

●試験項目●
        ①ローカルATコマンド試験
        ②ローカルxbeeライブラリ用コマンド試験
        ③リモートATコマンド試験
        ④リモートxbeeライブラリ管理コマンド試験
        ⑤リモートxbeeライブラリ応答待ちコマンド試験
        ⑥ループバック試験

●試験環境●
        ○本ソフトを動かす親機用ArduinoまたはPC
        ○親機用XBee ZBモジュール【ファーム=ZIGBEE COORDINATOR API】
        ○子機用XBee ZBモジュール【ファーム=ZIGBEE ROUTER AT】
        ○子機のUARTはループバック接続が必要です。(DINとDOUTを接続)
*/

//  #define DEBUG           //DEBUGをdefineするとライブラリの動作ログが出力されます。
//  #define DEBUG_TX        //送信データ表示
//  #define     ERRLOG
#define     EASY_SENSOR
#define     XBEE_ERROR_TIME
#define     PASSED          0
#define     FAILED          1
#ifdef ARDUINO
    #define     SIZEOF_LOG_S    36  // 33以上
#else
    #ifdef ARM_MBED
        #define     SIZEOF_LOG_S    80
    #else // PC
        #define     SIZEOF_LOG_S    80
    #endif
#endif

#ifdef ARDUINO
    #include <xbee.h>
    #include <Wire.h>
    #include <Adafruit_MCP23017.h>
    #include <Adafruit_RGBLCDShield.h>
    Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
#else
    #ifdef ARM_MBED
        #include <xbee.h>
        #include "TextLCD.h"
        #include <ctype.h>
        TextLCD lcd(PA_9, PC_7, PB_5, PB_4, PB_10, PA_8); // rs, e, d4-d7
        DigitalIn mybutton(USER_BUTTON);
    #else // PC
        #include "../libs/xbee.c"
        #include <ctype.h>                  // isgraph
        #include "../libs/kbhit.c"
    #endif
#endif

byte dev[8];
byte my[8];
byte myt[8];
byte panid[8];
byte panidt[8];
byte TEST_COUNT=0;
byte ERROR_COUNT=0;
byte ERROR_TOTAL=0;
char ERROR_S[SIZEOF_LOG_S];
unsigned int pan;
byte nc,rnc=0xFF,dd=0xFF;

static const char UARTDATA[] = "0123456789ABCDEF";
char *sprint_FAIL(char *s,const char *text){
    sprintf(s,"%s:FAIL####",text);
    return s;
}

void aging_delay(unsigned int ms){
    #ifdef ARDUINO
        delay((unsigned long)ms);
    #else
        #ifdef ARM_MBED
            wait((float)ms/1000.);
        #else // PC
            wait_millisec(ms);
        #endif
    #endif
}

#if defined(ARDUINO)
void prints(char *s){
    byte x,y;
    byte c=1;
    for(y=0;y<2;y++){
        lcd.setCursor(0, y);
        for(x=0;x<16;x++){
            if(s[16*y+x]=='\0') c=0;
            if(isgraph(s[16*y+x]) && c) lcd.print(s[16*y+x]);
            else lcd.print(' ');
        }
    }
}
#endif
#if defined(ARM_MBED)
void prints(char *s){
    byte x,y;
    byte c=1;
    for(y=0;y<2;y++){
        lcd.locate(0, y);
        for(x=0;x<16;x++){
            if(s[16*y+x]=='\0') c=0;
            if(isgraph(s[16*y+x]) && c) lcd.printf("%c",s[16*y+x]);
            else lcd.printf(" ");
        }
    }
}
#endif

void aging_key(void){
    #ifdef ARDUINO
        if( lcd.readButtons() ){
            lcd.clear();
            lcd.print(ERROR_COUNT,DEC);                 // 3
            lcd.print("errs ");                         // 5
            lcd.print((TEST_COUNT-ERROR_TOTAL),DEC);    // 3
            lcd.print('/');                             // 1
            lcd.print(TEST_COUNT,DEC);                  // 3
            lcd.setCursor(0, 1);
            if(ERROR_COUNT || ERROR_TOTAL){
                lcd.print(ERROR_S);
            }
            delay(100);
            while( lcd.readButtons() );
            delay(100);
            while( !lcd.readButtons() );
            prints(ERROR_S);
            delay(3000);
            while( lcd.readButtons() );
        }
    #else
        #ifdef ARM_MBED
        if( mybutton==0 ){      // Button is pressed
            lcd.cls();
            lcd.printf("%d",ERROR_COUNT);                 // 3
            lcd.printf("errs ");                         // 5
            lcd.printf("%d",TEST_COUNT-ERROR_TOTAL);    // 3
            lcd.printf("/");                             // 1
            lcd.printf("%d",TEST_COUNT);                  // 3
            lcd.locate(0, 1);
            if(ERROR_COUNT || ERROR_TOTAL){
                lcd.printf(ERROR_S);
            }
            aging_delay(100);
            while( !mybutton );
            aging_delay(100);
            while( mybutton );
            prints(ERROR_S);
            aging_delay(3000);
            while( !mybutton );
        }           
        #else // PC
            if( kbhit() ){
                getchar();
                printf("----------------------------------------------------------------\n");
                printf("ERROR=%d(TEST:%d/%d) ",ERROR_COUNT,TEST_COUNT-ERROR_TOTAL,TEST_COUNT);
                if(ERROR_COUNT || ERROR_TOTAL){
                    printf("%s",ERROR_S);
                }
                printf("\n----------------------------------------------------------------\n");
                aging_delay(3000);
            }
        #endif
    #endif
}

void aging_log(char *s){
    #if defined(ARDUINO) || defined(ARM_MBED)
        prints(s);
    #else // PC
        time_t error_time;
        struct tm *error_time_st;
        
        time(&error_time);
        error_time_st = localtime(&error_time);
        printf("%4d/%02d/%02d %02d:%02d:%02d %s\n",
            error_time_st->tm_year+1900,
            error_time_st->tm_mon+1,
            error_time_st->tm_mday,
            error_time_st->tm_hour,
            error_time_st->tm_min,
            error_time_st->tm_sec,
            s
        );
    #endif
    aging_key();
}

void error_log(char *s){
    #ifndef ARDUINO
    #ifndef ARM_MBED // PC
        FILE *fp;
        time_t error_time;
        struct tm *error_time_st;
        
        time(&error_time);
        error_time_st = localtime(&error_time);
        if( (fp=fopen("err.log","a")) != NULL ){
            fprintf(fp,"%4d/%02d/%02d %02d:%02d:%02d %s\n",
                error_time_st->tm_year+1900,
                error_time_st->tm_mon+1,
                error_time_st->tm_mday,
                error_time_st->tm_hour,
                error_time_st->tm_min,
                error_time_st->tm_sec,
                s
            );
            fclose(fp);
        }
    #endif
    #endif
    aging_log(s);
    strcpy(ERROR_S,s);
    ERROR_COUNT++;
    aging_delay(1000);
    aging_key();
}

void aging_results(void){
    char s[SIZEOF_LOG_S];
    TEST_COUNT++;
    if(ERROR_COUNT==0){
        //         012345678901234567890123456 28~30bytes
        sprintf(s,"###TEST:PASSED  (%d/%d)####",TEST_COUNT-ERROR_TOTAL,TEST_COUNT);
        aging_log(s);
    }else{
        ERROR_TOTAL++;
        //         01234567890123456789012345678 30~33bytes
        sprintf(s,"###TEST:FAILED  %d(%d/%d)####",ERROR_COUNT,TEST_COUNT-ERROR_TOTAL,TEST_COUNT);
        aging_log(s);
        #ifndef ARDUINO
        #ifndef ARM_MBED // PC
            strcpy(s,ERROR_S);
            aging_log(s);
        #endif
        #endif
        ERROR_COUNT=0;
    }
    aging_delay(3000);
}

void aging_print(char *text,byte ret,byte target,byte judge){
    char s[SIZEOF_LOG_S];
    if( (judge==PASSED && target == ret) || 
        (judge==FAILED && target != ret)
    ){
        sprintf(s,"%s:PASS(%02X)",text,ret);
        aging_log(s);
    }else{
        //         0-789012345678901--234--  26bytes
        sprintf(s,"%sret=%02X:%02X",sprint_FAIL(s,text),ret,target);
        error_log(s);
    }
}

void aging_rx_resp(char *text,char *at,byte n){
    XBEE_RESULT xbee_result;
    byte data;
    byte i,j;
    char s[SIZEOF_LOG_S];
    for(i=0;i<n;i++){
        data=xbee_rx_call( &xbee_result );
        if( (   xbee_result.MODE==MODE_RESP &&
                xbee_result.STATUS == STATUS_OK &&
                xbee_result.AT[0] == 'I' &&
                xbee_result.AT[1] == 'S' &&
                bytecmp(dev,xbee_result.FROM,8)==0
            )
        //  || (
        //      xbee_result.MODE==MODE_GPIN &&
        //      bytecmp(dev,xbee_result.FROM,8)==0
        //  )
        ){
            sprintf(s,"%s:PASS(%02X)",text,data);
            for(j=0;j<8;j++){
                if( (data>>(7-j))&0x01 ) s[16+j]='1';
                else s[16+j]='0';
            }
            s[24]='\0';
            aging_log(s);
            return;
        }
    }
    error_log(sprint_FAIL(s,text));
}

void aging_rx_uart(char *text,const char *uart,byte n){
    XBEE_RESULT xbee_result;
    byte i,j;
    byte len;
    char s[SIZEOF_LOG_S];
    byte data[SIZEOF_LOG_S];
    
    for(i=0;i<n;i++){
        len=xbee_rx_call( &xbee_result );
        if( xbee_result.MODE==MODE_UART &&
            bytecmp(dev,xbee_result.FROM,8)==0
        ){
            for(j=0;j<SIZEOF_LOG_S;j++) data[j]=(byte)uart[j];
            if(len>SIZEOF_LOG_S) len=SIZEOF_LOG_S;
            if(bytecmp(data,xbee_result.DATA,len)==0){
                sprintf(s,"%s:PASS(%02d)  ",text,len);
                for(j=16;j<32;j++){
                    if(isgraph(xbee_result.DATA[j-16])){
                        s[j]=(char)xbee_result.DATA[j-16];
                    }else s[j]=' ';
                }
                s[32]='\0';
                aging_log(s);
                if(len!=strlen(uart)){
                    sprintf(s,"%s:WARNING txLen=%d,rx=%d",text,strlen(uart),len);
                    aging_log(s);
                }
                return;
            }else{
                sprintf(s,"%s:FAIL(%02d)################",text,len);
                for(j=16;j<24;j++){
                    if(xbee_result.DATA[j-16]>16){
                        s[j]=(char)xbee_result.DATA[j-16];
                    }else s[j]=' ';
                }
                error_log(s);
                return;
            }
        }
    }
    error_log(sprint_FAIL(s,text));
}

byte s2bytes(byte *bytes,const char *s){
    byte i;
    for(i=0;i<strlen(s);i++) bytes[i]=s[i];
    return(i);
}

void aging_rx_batt(char *text,byte n){
    XBEE_RESULT xbee_result;
    byte i;
    char s[SIZEOF_LOG_S];
    for(i=0;i<n;i++){
        xbee_rx_call( &xbee_result );
        if( xbee_result.MODE==MODE_BATT &&
            xbee_result.STATUS == STATUS_OK &&
            bytecmp(dev,xbee_result.FROM,8)==0 &&
            xbee_result.ADCIN[0] > 1000
        ){
            sprintf(s,"%s:PASS(00)%d[mV]",text,xbee_result.ADCIN[0]);
            aging_log(s);
            return;
        }
    }
    error_log(sprint_FAIL(s,text));
}

char byte2a(byte in, byte i){
    char ret;
    if(i) in /= 16;
    ret = (char)(in%16);
    if(ret<10) ret += '0';
    else ret += 'A' -10;
    return( ret );
}

byte pairing(byte *dev,byte n){
    XBEE_RESULT xbee_result;
    char s[SIZEOF_LOG_S];

    byte i,len;
    for(i=0;i<n;i++){
        xbee_rx_call( &xbee_result );
        if( xbee_result.MODE==MODE_IDNT ){
            sprintf(s,"Pairing:PASS(%02X)",xbee_result.STATUS);
            len=strlen(s);
            for(i=0;i<8;i++){
                dev[i]=xbee_result.FROM[i];
                s[len]  =byte2a(dev[i],1);
                s[len+1]=byte2a(dev[i],0);
                len+=2;
            }
            s[len]='\0';
            aging_log(s);
            return(1);
        }
    }
    return(0);
}

void aging_rx_none(char *text,byte n){
    XBEE_RESULT xbee_result;
    byte i;
    char s[SIZEOF_LOG_S];
    for(i=0;i<n;i++){
        xbee_rx_call( &xbee_result );
        if( xbee_result.MODE != 0x00 ){
            sprintf(s,"%smode=%02X stat=%02X",sprint_FAIL(s,text),xbee_result.MODE,xbee_result.STATUS);
            error_log(s);
            return;
        }
    }
    sprintf(s,"%s:PASS",text);
    aging_log(s);
}

void aging_init(void){
    char s[SIZEOF_LOG_S];
    byte i;
    
    xbee_atnj(0xFF);
    aging_delay(1000);
    aging_log("Press Commiss.SW");
    /* ペアリング&宛先アドレス取得 */
    while(pairing(dev,100)==0);
    sprintf(s,"DestAdr:");
    for(i=0;i<4;i++){
        s[8+2*i]=byte2a(dev[i+4],1);
        s[9+2*i]=byte2a(dev[i+4],0);
    }
    s[16]='\0';
    aging_log(s);
    xbee_atnj(0);
    aging_delay(1000);
    /* 自分のアドレス */
    xbee_myaddress(my);
    sprintf(s,"MyAdr  :");
    for(i=0;i<4;i++){
        s[8+2*i]=byte2a(my[i+4],1);
        s[9+2*i]=byte2a(my[i+4],0);
    }
    s[16]='\0';
    aging_log(s);
    aging_delay(1000);
    /* PAN ID */
    pan=xbee_atop(panid);
    sprintf(s,"PAN ID :%d        ",pan);
    for(i=0;i<8;i++){
        s[16+2*i]=byte2a(panid[i],1);
        s[17+2*i]=byte2a(panid[i],0);
    }
    s[32]='\0';
    aging_log(s);
    aging_delay(1000);
    /* 子機数など */
    nc=xbee_atnc();
    while(rnc==0xFF){
        rnc=xbee_ratnc(dev);
    }
    while(dd==0xFF){
        dd=xbee_ping(dev);
    }
    sprintf(s,"nOfChld:%d,%d,%02X",10-nc,12-rnc,dd);
    aging_log(s);
    aging_delay(1000);
}

void loop(){
    byte data[SIZEOF_LOG_S];
    byte i,len;

    aging_log("Started:========");

    // ①ローカルATコマンド試験
    #ifndef ARDUINO
    #ifndef ARM_MBED  // PCのみ試験
        for(i=0;i<10;i++){
            aging_print("LocAt L",xbee_at("ATP004"),STATUS_OK,PASSED);
            aging_print("LocAt H",xbee_at("ATP005"),STATUS_OK,PASSED);
        }
    #endif
    #endif
    aging_print("LocAt -",xbee_at("ATP001"),STATUS_OK,PASSED);
    
    // ②ローカルxbeeライブラリ用コマンド試験
//  aging_print("reset  ",xbee_reset(),0,FAILED);
    aging_print("atcb   ",xbee_atcb(1),0,PASSED);
    for(i=0;i<3;i++){
        aging_print("myAdr  ",xbee_myaddress(myt),0,FAILED);
        aging_print("myAdCmp",bytecmp(my,myt,8),0,PASSED);
        aging_print("atvr   ",xbee_atvr(),ZB_TYPE_COORD,PASSED);
        aging_print("atai   ",xbee_atai(),0,PASSED);
        aging_print("atop   ",(byte)xbee_atop(panidt),(byte)pan,PASSED);
        aging_print("atopCmp",bytecmp(panid,panidt,8),0,PASSED);
        aging_print("atnc   ",xbee_atnc(),nc,PASSED);           // ncと一致すること
    }

    // ③リモートATコマンド試験
    #ifndef ARDUINO
    #ifndef ARM_MBED  // PCのみ試験
        for(i=0;i<10;i++){
            aging_print("RemAt L",xbee_rat(dev,"ATP104"),STATUS_OK,PASSED);     // 0xFF=ERROR
            aging_print("RemAt H",xbee_rat(dev,"ATP105"),STATUS_OK,PASSED);     // 0xFF=ERROR
        }
    #endif
    #endif
    aging_print("LocAt -",xbee_at("ATP100"),STATUS_OK,PASSED);

    // ④リモートxbeeライブラリ管理コマンド試験
    aging_print("ratd   ",xbee_ratd(dev, my),0xFF,FAILED);  // 0xFF=ERROR
    aging_print("ratdMyA",xbee_ratd_myaddress(dev),0xFF,FAILED);    // 0xFF=ERROR
    aging_print("ratnc  ",xbee_ratnc(dev),rnc,PASSED);      // rncと一致すること
    aging_print("ping   ",xbee_ping(dev),dd,PASSED);        // ddと一致すること
    aging_print("batt   ",(byte)(xbee_batt(dev)<0),0,PASSED);
    aging_print("gpioIni",xbee_gpio_init(dev),dd,PASSED);   // ddと一致すること
    #if defined(ARDUINO) || defined(ARM_MBED)
        aging_print("gpi 1  ",xbee_gpi(dev,1),0xFF,FAILED);
        aging_print("adc 1  ",(byte)(xbee_adc(dev,1)==0xFFFF),0,PASSED);
    #else // PCのみ試験
        for(i=0;i<3;i++){
            aging_print("gpi 1  ",xbee_gpi(dev,1),0xFF,FAILED);
            aging_print("gpi 2  ",xbee_gpi(dev,2),0xFF,FAILED);
            aging_print("gpi 3  ",xbee_gpi(dev,3),0xFF,FAILED);
        }
        for(i=0;i<3;i++){
            aging_print("adc 1  ",(byte)(xbee_adc(dev,1)==0xFFFF),0,PASSED);
            aging_print("adc 2  ",(byte)(xbee_adc(dev,2)==0xFFFF),0,PASSED);
            aging_print("adc 3  ",(byte)(xbee_adc(dev,3)==0xFFFF),0,PASSED);
        }
        for(i=0;i<3;i++){
            aging_print("sensorL",(byte)(xbee_sensor(dev,LIGHT)<0),0,PASSED);
            aging_print("sensorT",(byte)(xbee_sensor(dev,LIGHT)<0),0,PASSED);
            aging_print("sensorH",(byte)(xbee_sensor(dev,LIGHT)<0),0,PASSED);
        }
    #endif

    // ⑤リモートxbeeライブラリ応答待ちコマンド試験
    for(i=0;i<3;i++){
        aging_print("force  ",xbee_force(dev),0x00,FAILED);
        aging_rx_resp("rxResp ","IS",200);      // STATUS_OKのIS応答を200受信分、待つ
        aging_print("batForc",xbee_batt_force(dev),0x00,FAILED);    
        aging_rx_batt("rxBatt ",200);
    //  aging_print("ratForc",xbee_rat_force(dev,"ATIS"),0x00,FAILED);
    //  aging_rx_resp("rxResp ","IS",200);      // STATUS_OKのIS応答を200受信分、待つ
    }
    for(i=0;i<5;i++){
        aging_print("gpo11,0",xbee_gpo(dev,11,0),0,FAILED);
        aging_rx_none("rxNo110",10);
        aging_print("gpo11,1",xbee_gpo(dev,11,1),0,FAILED);
        aging_rx_none("rxNo111",10);
        #ifndef ARDUINO
        #ifndef ARM_MBED  // PCのみ試験
            aging_print("gpo12,0",xbee_gpo(dev,12,0),0,FAILED);
            aging_rx_none("rxNo120",10);
            aging_print("gpo12,1",xbee_gpo(dev,12,1),0,FAILED);
            aging_rx_none("rxNo121",10);
        #endif
        #endif
    }
    aging_rx_none("rxNone ",100);

    // ⑥ループバック試験
    for(i=0;i<3;i++){
        aging_print("uartTx ",xbee_uart(dev,UARTDATA),0,FAILED);
        aging_rx_uart("rxUart ",UARTDATA,200);  // UART応答を200受信分、待つ
        len=s2bytes(data,UARTDATA);
        aging_print("byteTx ",xbee_bytes(dev,data,len),0,FAILED);
        aging_rx_uart("rxByte ",UARTDATA,200);  // UART応答を200受信分、待つ
    }
    
    // 試験結果
    aging_results();
}

#ifdef ARDUINO
    void setup(){
        byte i;
        
        lcd.begin(16, 2);
        lcd.clear();
        lcd.print("XBee Aging");
        lcd.setCursor(0, 1);
        lcd.print(COPYRIGHT);
        xbee_init(0);
        aging_init();
        for(i=0;i<SIZEOF_LOG_S;i++) ERROR_S[i]='\0';
    }
#endif

#ifndef ARDUINO
    #ifdef ARM_MBED
        int main()
    #else
        int main(int argc,char **argv)
    #endif
    {
        byte port=0;
        byte i;
        
        #ifdef ARM_MBED
            lcd.cls();
            lcd.printf("XBee Aging");
            lcd.locate(0, 1);
            lcd.printf(COPYRIGHT);
        #else
            if( argc==2 ) port = (byte)(atoi(argv[1]));
        #endif
        xbee_init( port );                  // XBee用COMポートの初期化(引数はポート番号)
        aging_init();
        for(i=0;i<SIZEOF_LOG_S;i++) ERROR_S[i]='\0';
        
        while(1)loop();
        exit(1);
    }
#endif