#include <SoftwareSerial.h>
byte incomePacket[80];                               // bufor na dane przychodzące
char incomeData [64];                                // przechowanie przeanalizowanych danych
byte replyPacket[80];                                // bufor do budowy pakietu
byte sourceADR[10];                                  // adres źródłowy
int datalen;                                         // długość odebranych danych
int count;                                           // całkowita długość odebranego pakietu
int length;                                          // przechowywanie długości różnych danych
byte calcsum ;                                       // suma kontrolna
SoftwareSerial softSerial(2, 3);           // główny programowy interfejs szeregowy
SoftwareSerial softSerFl(4, 5);            // reset programowego interfejsu szeregowego
void setup()  {
   Serial.begin(57600);      // port szeregowy do monitorowania
   softSerial.begin(9600);   // port szeregowy do XBee
   softSerFl.begin(400);     // reset programowego interfejsu szeregowego 
   Serial.println("Gotowy");
} // koniec setup 
void loop(){
   softSerial.listen(); // sprawdzenie, czy bufor jest gotowy do nasłuchu
   delay (25); 
   if (softSerial.available() && 0x7E == softSerial.peek() ) { // sprawdzenie bajtu startowego
      count = 0 ;
         while (softSerial.available()){ 
            incomePacket[count] =  softSerial.read();  // odebranie pakietu
            count ++;  // zliczanie danych przychodzących
         }  // koniec while (softSerial.available())
      Serial.println ("Odebrany nowy pakiet");   
      Serial.print ("Zawartość pakietu: ");
          for (int i = 0 ; i < count-1 ; i++){   // wyświetlenie nieobrobionego pakietu
          Serial.print (incomePacket[i],HEX);
          Serial.print (' ');
          }  
       Serial.println (incomePacket[count-1],HEX);   // ostatni bajt nieobrobionego pakietu
           calcsum =0;     // początek obliczeń sumy kontrolnej przychodzącego pakietu
           length = incomePacket[1] +incomePacket[2];
           for (int i = 3 ; i <= length+2 ; i++){
               calcsum = calcsum + incomePacket[i];
           }
                calcsum = 0xFF - calcsum;  // zakończenie obliczeń sumy kontrolnej
        if (calcsum == incomePacket[count-1]){  // wywołanie błędu, jeżeli suma kontrolna nie zgadza się
           Serial.println ("Pakiet ma poprawną sumę kontrolną");
               switch (incomePacket[3]){  // sprawdzenie typu pakietu i odpowiedź
                 case 0x90:
                   Serial.println ("To jest pakiet danych"); // informacja o typie pakietu
                    for (int i = 4 ; i <= 13 ; i++){  // pobranie obu adresów urządzenia źródłowego
                       sourceADR[i-4]= incomePacket[i];
                    }
                   datalen = count - 16 ;  // zmniejszenie do długości danych w celu ich pobrania
                    for (int i = 15 ; i < datalen+15 ; i++){
                       incomeData [i-15] = incomePacket[i]; // przetworzenie danych
                    }
             Serial.print ("adres źródłowy: ");  // rozpoczęcie wyświetlania adresu 64-bitowego
                 for (int i =0 ; i < 7 ; i++){ 
                 Serial.print (sourceADR[i],HEX);
                 Serial.print (' ');
             }  
             Serial.println (sourceADR[7],HEX); // zakończenie wyświetlania adresu 64-bitowego
             Serial.print ("adres sieciowy: "); // rozpoczęcie wyświetlania adresu 16-bitowego
             Serial.print(sourceADR[8] ,HEX);
             Serial.print (' ');
             Serial.println(sourceADR[9] ,HEX); // zakończenie wyświetlania adresu 16-bitowego
             Serial.print ("pakiet zawiera: "); // rozpoczęcie wyświetlania danych z pakietu
               for (int i =0 ; i < datalen ; i++){ 
             Serial.print (incomeData [i]);   
             }  
             Serial.println (" : Dla danych"); // zakończenie wyświetlania danych
             Serial.println ("Budowanie pakietu odpowiedzi"); // informacja o budowie pakietu
            // początek dodawania danych do bufora z pakietem z odpowiedzią
             replyPacket[0] = 0x7E;    // bajt startowy
             replyPacket[1] = 0; // pierwszy bajt adresu jest równy 0 z bieżącymi ograniczeniami
             replyPacket[3] = 0x10;    // typ ramki 
             replyPacket[4] =  1;         // identyfikator ramki
             for (int i =5 ; i <= 14 ; i++){     // dodanie adresów
                replyPacket[i] = sourceADR[i-5] ; 
             }  
                 replyPacket[15] = 0 ;          // ustawienie obu opcji
                 replyPacket[16] = 0 ;
                 for (int i =17 ; i < datalen+17 ; i++){   
                 replyPacket[i] =  incomeData [i-17];  // dodanie danych do pakietu
                 }
             replyPacket[2] = 14 + datalen ;      // ustawienie młodszego bajtu długości
             calcsum = 0; // początek obliczeń sumy kontrolnej
             for (int i = 3 ; i <= replyPacket[2]+3 ; i++){ 
                 calcsum = calcsum + replyPacket[i];
               }  
             replyPacket[17 + datalen]= 0xFF - calcsum; // zapisanie sumy kontrolnej i zakończenie pakietu
              Serial.print ("Zawartość pakietu: ");  // początek wyświetlania nieobrobionego pakietu przed wysłaniem
              for (int i =0 ; i < replyPacket[2]+3 ; i++){ 
              Serial.print (replyPacket[i],HEX);
              Serial.print (' ');
              }  
              Serial.println (replyPacket[17 + datalen],HEX); // koniec wyświetlania pakietu 
             Serial.println ("Wysyłanie pakietu"); // początek wysyłania pakietu do pierwotnego nadawcy
             for (int i =0 ; i <= 17 + datalen ; i++){
                   softSerial.write ( replyPacket[i]);
             }
             softSerFl.listen(); // zakończenie wysyłania i wyczyszczenie bufora programowanego 
             break; // koniec obróbki odebranego pakietu
            case 0x8B: // wysłanie danych w odpowiedzi na odebrany pakiet
               Serial.println ("Odebrana odpowiedź");
              break;         
            default : // informacje o nieznanym typie pakietu
              Serial.println ("błąd: nieznany typ pakietu");
         } // koniec switch
   } // koniec processPacket()
   else { 
   Serial.println ("Błąd, uszkodzony pakiet"); // błąd, jeżeli pakiet jest uszkodzony
   softSerFl.listen(); // w przypadku błędu wyczyść bufor 
  }
} // koniec looking for start byte
} // koniec loop
