A libery to connect to telegesis zigbee module. Bassed on implemtation of XBEE

Fork of xbee_lib by Tristan Hughes

telegesis.cpp

Committer:
gert_lauritsen
Date:
2015-03-05
Revision:
34:1b57f1110d59
Parent:
33:101f953225a6
Child:
35:4dec73b3e5a0

File content as of revision 34:1b57f1110d59:

#include "telegesis.h"
#define CR 0x0D
#define LF 0x0A
#define IRQCtrl

zigbee::zigbee(PinName tx, PinName rx): _zbee(tx, rx)
{
    _tx = tx;
    _rx = rx;
    _zbee.baud(19200);
    Ok=1; PacketAck=1;
#ifdef IRQCtrl
    _zbee.attach(this, &zigbee::SeePacket, Serial::RxIrq);
#endif
}

size_t zigbee::comma_parse ( char *line, char *list[], size_t size )
{
  char   *p;
  size_t n;
 
  p = line;
  n = 0;
  for ( ; ; ) {
    /* Ditch leading commas */
    while ( *p == ',' )
      p++;
    /* Nothing of use */
    if ( *p == '\0' )
      return n;
    /* Save the string */
    list[n++] = p;
    /* Find the next field */
    while ( *p != ',' && *p != '\0' )
      p++;
    /* Nothing else of use or too many fields */
    if ( *p == '\0' || n >= size )
      return n;
    /* Split the field */
    *p++ = '\0';
  }
}


zigbee::~zigbee()
{
}

bool zigbee::Work()
{
    //read and waits for the packet
#ifndef IRQCtrl    //dette skal kun kaldes hvis vi vi køre i pull mode
    bool datain=false;
    b=0;
    if (_zbee.readable()) {
            datain=true;
            SeePacket();
    }
    return datain;
#endif    
}

bool zigbee::wait4str(char *p) //joinpan
{
    Timer t;
    t.reset();
    t.start();
    while ((strstr(_responseFrameString,p)==0) && (t.read_ms() < 5000)) readPacket();
    t.stop();
    return (strstr(_responseFrameString,p)>0);
}


bool zigbee::wait4JPAN() //joinpan
{
    Timer t;
    t.reset();
    t.start();
    readPacket();
    while ((strstr(_responseFrameString,"JPAN")==0) && (t.read_ms() < 5000)) readPacket();
    t.stop();
    return (strstr(_responseFrameString,"JPAN")>0);
}


bool zigbee::wait4Offline()
{
    Timer t;
    t.reset();
    t.start();
    readPacket();
    while ((PanOnline>0) && (t.read_ms() < 3000)) readPacket();
    t.stop();
    return PanOnline;
}


bool zigbee::wait4OK()
{
    Timer t;
    t.reset();
    t.start();
    readPacket();
    while ((strstr(_responseFrameString,"OK")==0) && (t.read_ms() < 500)) readPacket();
    t.stop();
    return (strstr(_responseFrameString,"OK")>0);
}

int zigbee::GetSerial()
{
    /** comes with something like this
    Telegesis ETRX357-LRS
    R305C
    000D6F0000D5F06A
    OK
    */
    _zbee.printf("ATI\r");
    wait4str("Telegesis");
    sscanf(_responseFrameString,"Telegesis %s",HWType);
    readPacket(); //Typen
    readPacket(); //ID
    strcpy(LocalID,_responseFrameString); //vi lægger den bare over i stringformat. Så kan man altid senere convertere
    wait4OK();
    //   LocalID=hextoint(_responseFrameString);
    //   wait_ms(5);
    return 1;
}
bool zigbee::ReadReg(char *Reg){  
   _zbee.printf("ATS%s?\r",Reg);
   readPacket();  
   readPacket();  
   readPacket();  
   strcpy(RegData,_responseFrameString);  
   return wait4OK();
}    

int zigbee::SetKey(char* key)
{
    /**
    S09:  the link key.  Write the same 128-bit number (32 hexadecimal characters) into every device

    S0A: security configuration.  You must set bit 4 in the coordinator, and set bit 8 in all other devices.
    For more security set bit 2 also in the coordinator.  The devices ignore the bits that are not relevant
    for them, so it is easiest to just set bits 8, 4, and 2 in all devices which gives S0A=0114.
    */
    char psw[50];
    sprintf(psw,"ATS09=%s:password\r",key);
    _zbee.printf(psw);
    wait4OK();
    _zbee.printf("ATS0A=0114:password\r"); //(For simplicity, you can set bits 8, 4 and 2 of S0A on every device
    wait4OK();    
    return 1;
}



void zigbee::RecieveData(char *data_buf, int numchar)
{
    int count=0;
    if(numchar == 0) {
        numchar = sizeof(data_buf);
    }

    while(numchar!=count) {
        if(_zbee.readable()) {
            *data_buf = _zbee.getc();
            data_buf+=1;
            count++;
        }

    }
}

int zigbee::Reset()
{
    PacketAck=0;
    _zbee.printf("ATZ\r");
    wait4OK();
    
    return 1;
}

int zigbee::ATI()
{
    PacketAck=0;
    GetSerial();
    return 1;
}


int zigbee::PingOut()
{
    //just return a OK (sends it ID out out the pan)
    PacketAck=0;
    _zbee.printf("AT+ANNCE\r");
    wait4OK();
    return 1;
}


int zigbee::PanScan()
{
    //
    PacketAck=0; NPanVisible=0;
    _zbee.printf("AT+PANSCAN\r");
    wait4OK();    
    return 1;
}


int zigbee::Establish_Network()
{
    //
    PacketAck=0;
    _zbee.printf("AT+EN\r");
    wait4JPAN();
    wait4OK();
    return 1;
}

int zigbee::SetOutputLevel()
{
    PacketAck=0;
    _zbee.printf("ATS01=-7\r");
    return wait4OK();
}

int zigbee::LeaveNetwork()
{
    PacketAck=0;
    _zbee.printf("AT+DASSL\r");
    wait4OK();
    wait4Offline();
    return 1;
}

int zigbee::JoinNetwork()
{
    PacketAck=0;
    _zbee.printf("AT+JN\r");
    Ok=0;
    return 1;
}

int zigbee::ScanNetwork()
{
    PacketAck=0;
    _zbee.printf("AT+SN\r");
    Ok=0;
    return 1;  
}

int zigbee::NetworkInfo()
{
//Return something like this "+N=COO,12,-11,29F0,55C0E0DCE605C522"
    PacketAck=0;
    _zbee.printf("AT+N\r");
    Ok=wait4OK();
    return 1;
}

int zigbee::UniCast(char *adr,char *payload)  //Ascii mode with null terminated string
{
    PacketAck=0;
    _zbee.printf("AT+UCAST:%s=%s\r",adr,payload);
    strcpy(LastDestination,adr);
    Ok=0;
    return 1;
}

int zigbee::UniCastb(char *adr,char *payload, char payloadSize) //sends data in binary format
{
    PacketAck=0;
    _zbee.printf("AT+UCASTB:%X,%s\r",adr,payloadSize);
    //_zbee.scanf ("%*s");
    return 1;
}

//-----------------------Handle incoming data------------------------------

unsigned long zigbee::hextolong(const char *hex)
{
    //return 32 bit
    unsigned long result = 0;
    while (*hex) { //så længe det ikke er null
        if (*hex >= '0' && *hex <= '9')
            result += (*hex - '0');
        else if (*hex >= 'A' && *hex <= 'F')
            result += (*hex - 'A' +10);
        else if (*hex >= 'a' && *hex <= 'f')
            result += (*hex - 'a'+ 10);

        if (*++hex) //if the neext isn't a null
            result <<= 4;
    }
    return result;
}


unsigned int zigbee::hextoint(const char *hex)
{
    //return 16 bit
    unsigned int result = 0;
    while (*hex) { //så længe det ikke er null
        if (*hex >= '0' && *hex <= '9')
            result += (*hex - '0');
        else if (*hex >= 'A' && *hex <= 'F')
            result += (*hex - 'A' +10);
        else if (*hex >= 'a' && *hex <= 'f')
            result += (*hex - 'a'+ 10);

        if (*++hex) //if the neext isn't a null
            result <<= 4;
    }
    return result;
}
//---------------------------------------------------------------


void zigbee::SeePacket()
{
    char *p;
    static uint8_t _pos;
    b = _zbee.getc();
              
    if ((b!=CR) && (b!=LF)) {
        _responseFrameString[_pos]=b;
        _pos=(_pos+1) % MAX_FRAME_DATA_SIZE;
    }
    if (b==CR) {
        GotFrame=1;
        _responseFrameString[_pos]=0; //Nul terminate
        _pos=0;

        if (strstr(_responseFrameString,"+UCAST:")) { //returns on that we have sendt something
            //Do something
        } else if (strstr(_responseFrameString,"UCAST:")) { //checke for incoming UCAST data
            //if (sscanf (_responseFrameString,"UCAST:%X,%X=%s ",&EUI64,&framesize,Zdata)>0)
            p=strstr(_responseFrameString,"UCAST:");
            p=p+6;
            strncpy(In.ID,p,16);
            In.ID[16]=0;
            //Zdat=1;
            p=strstr(_responseFrameString,"=");
            if (p) {
                p++;
                strcpy(In.Data,p);
                In.Ready=1;
            }
        }
        if (strstr(_responseFrameString,"+PANSCAN:")) { //info om nærliggende pan
            p=strstr(_responseFrameString,":"); p++; //P indholder nu SEQ nummer
            comma_parse(p,list,ZdataSize);
            PanVisible[NPanVisible].channel=atoi(list[0]);  
            strcpy(PanVisible[NPanVisible].PID,list[1]);
            NPanVisible++;        
        }    
        if (strstr(_responseFrameString,"LeftPAN")) PanOnline=0;  //Local node has left the Pan
        if (strstr(_responseFrameString,"LostPAN")) PanOnline=0;  //Local node has left the Pan
        if (strstr(_responseFrameString,"ERROR:")) {
            p=strstr(_responseFrameString,":");
            p++; //P indholder nu SEQ nummer
            ErrorCode=hextoint(p);
        }

        if (strstr(_responseFrameString,"NEWNODE:")) { //NEWNODE: <NodeID>,<EUI64>,<Parent NodeID>
            //new node on the pan
            p=strstr(_responseFrameString,"NEWNODE:");
            p=p+13;
            NetInfo=1;
            strncpy(NetNodeID,p,16);
        }

        if ((strstr(_responseFrameString,"OK")>0) && (strstr(_responseFrameString,"TOKDUMP")==0) ) {
            //if (ScriptState) ConnectScript();
            Ok=1; 
            //Cmd=0; LineNo=0;
        }
        if (strstr(_responseFrameString,"FFD:")) {
            //FFD:000D6F00026C5BEA,0000
            p=strstr(_responseFrameString,"FFD:");
            p=p+4;
            NetInfo=1;
            strncpy(NetNodeID,p,16);            
        }
        if (strstr(_responseFrameString,"+N=")) {
            //        sscanf (_responseFrameString,"+N=%s,%d,%d,%4X,",Devicetype,&channel,&NodeID,&EPID);
            size_t n;
            p=strstr(_responseFrameString,"=");
            p++;
            n=comma_parse(p,list,ZdataSize);
            strcpy(Devicetype,list[0]);
            AktuelPan.channel=atoi(list[1]);
            strncpy(AktuelPan.PID,list[3],4);  
        }
        if (strstr(_responseFrameString,"ACK")) { //
            PacketAck=1;
            p=strstr(_responseFrameString,":");
            p++; //P indholder nu SEQ nummer
            SeqNumber=hextoint(p);
        }
        if (strstr(_responseFrameString,"NACK")) { //Besked kom ikke igennem
            PacketAck=0;
            p=strstr(_responseFrameString,":");
            p++; //P indholder nu SEQ nummer
            NackNumber=hextoint(p);            
        }
        if (strstr(_responseFrameString,"SEQ")) { //Besked er afsendt
            p=strstr(_responseFrameString,":");
            p++; //P indholder nu SEQ nummer
            SeqNumber=hextoint(p);
        }
        if (strstr(_responseFrameString,"JPAN:")) {
            //JPAN:<channel>,<PID>,<EPID>       
            p=strstr(_responseFrameString,":"); p++;
            comma_parse(p,list,ZdataSize);
            strcpy(Devicetype,list[0]);
            AktuelPan.channel=atoi(list[1]);
            strcpy(AktuelPan.PID,list[2]);
            PanOnline=1;    
        }
     }   
}

//-----------------------NON IRQ mode --------------------------------------------------------------------
void zigbee::readPacket()
{
    //read and waits for the packet

    Timer t;
    t.reset();
    t.start();
    b=0;
#ifndef IRQCtrl    
    while((b!=CR) && (t.read_ms() < 1000))
        if (_zbee.readable()) SeePacket();
    t.stop();
#else  
    while((b!=CR) && (t.read_ms() < 1000)) {} //vent       
    t.stop();  
#endif  
}




void zigbee::SletZdata(void){
int i;
  for (i=0; i<ZdataSize ; i++) In.Data[i]=0;    
}