text: /*
    LoRaWAN.h
    2013 Copyright (c) Seeed Technology Inc.  All right reserved.
  
    Author: Wayne Weng
    Date: 2016-10-17
  
    add rgb backlight fucnction @ 2013-10-15
    
    The MIT License (MIT)
  
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
  
    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.
  
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.1  USA
  */
  
  #ifndef _LORAWAN_H_
  #define _LORAWAN_H_
  
  
  #include <Arduino.h>
  
  #define SerialUSB   Serial
  #define SerialLoRa  Serial1     //used with GPS module and changed UART port for LoRaWAN module
  //#define SerialLoRa  Serial2   //used this if unchanged UART port for LoRaWAN module and without GPS module
  
  #define _DEBUG_SERIAL_      1
  #define DEFAULT_TIMEOUT     5 // second
  #define DEFAULT_TIMEWAIT    100 // millisecond
  #define DEFAULT_DEBUGTIME   1 // second
  
  #define BEFFER_LENGTH_MAX    256
  
  
  enum _class_type_t { CLASS_A = 0, CLASS_C };
  enum _physical_type_t { EU434 = 0, EU868, US915, US915HYBRID, AU915, AU915OLD, CN470, CN779, AS923, KR920, IN865 };
  enum _device_mode_t { LWABP = 0, LWOTAA, TEST };
  enum _otaa_join_cmd_t { JOIN = 0, FORCE };
  enum _window_delay_t { RECEIVE_DELAY1 = 0, RECEIVE_DELAY2, JOIN_ACCEPT_DELAY1, JOIN_ACCEPT_DELAY2 };
  enum _band_width_t { BW125 = 125, BW250 = 250, BW500 = 500 };
  enum _spreading_factor_t { SF12 = 12, SF11 = 11, SF10 = 10, SF9 = 9, SF8 = 8, SF7 = 7 };
  enum _data_rate_t { DR0 = 0, DR1, DR2, DR3, DR4, DR5, DR6, DR7, DR8, DR9, DR10, DR11, DR12, DR13, DR14, DR15 };
                      
                      
  /*****************************************************************
  Type    DataRate    Configuration   BitRate| TxPower Configuration 
  EU434   0           SF12/125 kHz    250    | 0       10dBm
          1           SF11/125 kHz    440    | 1       7 dBm
          2           SF10/125 kHz    980    | 2       4 dBm
          3           SF9 /125 kHz    1760   | 3       1 dBm
          4           SF8 /125 kHz    3125   | 4       -2dBm
          5           SF7 /125 kHz    5470   | 5       -5dBm
          6           SF7 /250 kHz    11000  | 6:15    RFU
          7           FSK:50 kbps     50000  | 
          8:15        RFU                    |     
  ******************************************************************
  Type    DataRate    Configuration   BitRate| TxPower Configuration 
  EU868   0           SF12/125 kHz    250    | 0       20dBm
          1           SF11/125 kHz    440    | 1       14dBm
          2           SF10/125 kHz    980    | 2       11dBm
          3           SF9 /125 kHz    1760   | 3       8 dBm
          4           SF8 /125 kHz    3125   | 4       5 dBm
          5           SF7 /125 kHz    5470   | 5       2 dBm
          6           SF7 /250 kHz    11000  | 6:15    RFU
          7           FSK:50 kbps     50000  | 
          8:15        RFU                    | 
  ******************************************************************
  Type    DataRate    Configuration   BitRate| TxPower Configuration
  US915   0           SF10/125 kHz    980    | 0       30dBm
          1           SF9 /125 kHz    1760   | 1       28dBm
          2           SF8 /125 kHz    3125   | 2       26dBm
          3           SF7 /125 kHz    5470   | 3       24dBm
          4           SF8 /500 kHz    12500  | 4       22dBm
          5:7         RFU                    | 5       20dBm
          8           SF12/500 kHz    980    | 6       18dBm
          9           SF11/500 kHz    1760   | 7       16dBm
          10          SF10/500 kHz    3900   | 8       14dBm
          11          SF9 /500 kHz    7000   | 9       12dBm
          12          SF8 /500 kHz    12500  | 10      10dBm
          13          SF7 /500 kHz    21900  | 11:15   RFU
          14:15       RFU                    | 
  *******************************************************************/
  
  
  class LoRaWanClass
  {
      public:
    
          bool dutycycle = false;
      
          LoRaWanClass(void);
          
          /**
           *  \brief Initialize the conmunication interface
           *  
           *  \return Return null
           */
          void init(void);
          
          /**
           *  \brief Read the version from device
           *  
           *  \param [in] *buffer The output data cache
           *  \param [in] length The length of data cache
           *  \param [in] timeout The over time of read
           *  
           *  \return Return null.
           */
          void getVersion(char *buffer, short length, unsigned char timeout = DEFAULT_TIMEOUT);
          
          /**
           *  \brief Read the ID from device
           *  
           *  \param [in] *buffer The output data cache
           *  \param [in] length The length of data cache
           *  \param [in] timeout The over time of read
           *  
           *  \return Return null.
           */
          void getId(char *buffer, short length, unsigned char timeout = DEFAULT_TIMEOUT);
  
          /**
           *  \brief Set the ID
           *  
           *  \param [in] *DevAddr The end-device address
           *  \param [in] *DevEUI The end-device identifier
           *  \param [in] *AppEUI The application identifier
           *  
           *  \return Return null.
           */
          void setId(char *DevAddr, char *DevEUI, char *AppEUI);
          
          /**
           *  \brief Set the key
           *  
           *  \param [in] *NwkSKey The network session key
           *  \param [in] *AppSKey The application session key
           *  \param [in] *AppKey The Application key
           *  
           *  \return Return null.
           */
          void setKey(char *NwkSKey, char *AppSKey, char *AppKey);
          
          /**
           *  \brief Set the data rate
           *  
           *  \param [in] dataRate The date rate of encoding
           *  \param [in] physicalType The type of ISM
           *  
           *  \return Return null.
           */        
          void setDataRate(_data_rate_t dataRate = DR0, _physical_type_t physicalType = EU434); 
          
          /**
           *  \brief ON/OFF adaptive data rate mode
           *  
           *  \param [in] command The date rate of encoding
           *  
           *  \return Return null.
           */ 
          void setAdaptiveDataRate(bool command);
          
          /**
           *  \brief Set the output power
           *  
           *  \param [in] power The output power value
           *  
           *  \return Return null.
           */
          void setPower(short power);
          
          /**
           *  \brief Set the port number
           *  
           *  \param [in] port The port number, range from 1 to 255
           *  
           *  \return Return null.
           */
          void setPort(int port);
          
          /**
           *  \brief Set the channel parameter
           *  
           *  \param [in] channel The channel number, range from 0 to 71
           *  \param [in] frequency The frequency value
           *  
           *  \return Return null.
           */
          void setChannel(unsigned char channel, float frequency);
          /**
           *  \brief Set the channel parameter
           *  
           *  \param [in] channel The channel number, range from 0 to 71
           *  \param [in] frequency The frequency value. Set frequecy zero to disable one channel
           *  \param [in] dataRata The date rate of channel
           *  
           *  \return Return null.
           */
          void setChannel(unsigned char channel, float frequency, _data_rate_t dataRata);
          /**
           *  \brief Set the channel parameter
           *  
           *  \param [in] channel The channel number, range from 0 to 71
           *  \param [in] frequency The frequency value
           *  \param [in] dataRataMin The minimum date rate of channel
           *  \param [in] dataRataMax The maximum date rate of channel
           *  
           *  \return Return null.
           */
          void setChannel(unsigned char channel, float frequency, _data_rate_t dataRataMin, _data_rate_t dataRataMax);
          
          /**
           *  \brief Transfer the data
           *  
           *  \param [in] *buffer The transfer data cache
           *  \param [in] timeout The over time of transfer
           *  
           *  \return Return bool. Ture : transfer done, false : transfer failed
           */
          bool transferPacket(char *buffer, unsigned char timeout = DEFAULT_TIMEOUT);
          /**
           *  \brief Transfer the data
           *  
           *  \param [in] *buffer The transfer data cache
           *  \param [in] length The length of data cache
           *  \param [in] timeout The over time of transfer
           *  
           *  \return Return bool. Ture : transfer done, false : transfer failed
           */
          bool transferPacket(unsigned char *buffer, int length, unsigned char timeout = DEFAULT_TIMEOUT);
          /**
           *  \brief Transfer the packet data
           *  
           *  \param [in] *buffer The transfer data cache
           *  \param [in] timeout The over time of transfer
           *  
           *  \return Return bool. Ture : Confirmed ACK, false : Confirmed NOT ACK
           */
          bool transferPacketWithConfirmed(char *buffer, unsigned char timeout = DEFAULT_TIMEOUT);
          /**
           *  \brief Transfer the data
           *  
           *  \param [in] *buffer The transfer data cache
           *  \param [in] length The length of data cache
           *  \param [in] timeout The over time of transfer
           *  
           *  \return Return bool. Ture : Confirmed ACK, false : Confirmed NOT ACK
           */
          bool transferPacketWithConfirmed(unsigned char *buffer, int length, unsigned char timeout = DEFAULT_TIMEOUT);
  
          bool transferPacketLinkCheckReq(unsigned char timeout = DEFAULT_TIMEOUT);
  
          /**
           *  \brief Receive the data
           *  
           *  \param [in] *buffer The receive data cache
           *  \param [in] length The length of data cache
           *  \param [in] *rssi The RSSI cache
           *  
           *  \return Return Receive data number
           */
          short receivePacket(char *buffer, int length, short *rssi, float *snr, short *gwcnt);
          
          /**
           *  \brief Transfer the proprietary data
           *  
           *  \param [in] *buffer The transfer data cache
           *  \param [in] timeout The over time of transfer
           *  
           *  \return Return bool. Ture : transfer done, false : transfer failed
           */
          bool transferProprietaryPacket(char *buffer, unsigned char timeout = DEFAULT_TIMEOUT);
          /**
           *  \brief Transfer the proprietary data
           *  
           *  \param [in] *buffer The transfer data cache
           *  \param [in] length The length of data cache
           *  \param [in] timeout The over time of transfer
           *  
           *  \return Return bool. Ture : transfer done, false : transfer failed
           */
          bool transferProprietaryPacket(unsigned char *buffer, unsigned char length, unsigned char timeout = DEFAULT_TIMEOUT);
          
          /**
           *  \brief Set device mode
           *  
           *  \param [in] mode The mode of device
           *  
           *  \return Return null
           */
          void setDeviceMode(_device_mode_t mode);
          
          /**
           *  \brief Set device join a network
           *  
           *  \param [in] command The type of join
           *  \param [in] timeout The over time of join
           *  
           *  \return Return bool. True : join OK, false : join NOT OK
           */
          bool setOTAAJoin(_otaa_join_cmd_t command, unsigned char timeout = DEFAULT_TIMEOUT);
          
          /**
           *  \brief Set message unconfirmed repeat time
           *  
           *  \param [in] time The repeat time, range from 1 to 15
           *  
           *  \return Return null
           */
          void setUnconfirmedMessageRepeatTime(unsigned char time);
          
          /**
           *  \brief Set message retry times time
           *  
           *  \param [in] time The retry time, range from 0 to 254
           *  
           *  \return Return null
           */
          void setConfirmedMessageRetryTime(unsigned char time);
          
          /**
           *  \brief ON/OFF receice window 1
           *  
           *  \param [in] command The true : ON, false OFF
           *  
           *  \return Return null
           */
          void setReceiveWindowFirst(bool command);
          /**
           *  \brief Set receice window 1 channel mapping
           *  
           *  \param [in] channel The channel number, range from 0 to 71
           *  \param [in] frequency The frequency value of channel
           *  
           *  \return Return null
           */
          void setReceiveWindowFirst(unsigned char channel, float frequency);
          
          /**
           *  \brief Set receice window 2 channel mapping
           *  
           *  \param [in] frequency The frequency value of channel
           *  \param [in] dataRate The date rate value
           *  
           *  \return Return null
           */
          void setReceiveWindowSecond(float frequency, _data_rate_t dataRate);
          
          /**
           *  \brief Set receice window 2 channel mapping
           *  
           *  \param [in] frequency The frequency value of channel
           *  \param [in] spreadingFactor The spreading factor value
           *  \param [in] bandwidth The band width value
           *  
           *  \return Return null
           */
          void setReceiveWindowSecond(float frequency, _spreading_factor_t spreadingFactor, _band_width_t bandwidth);
          
          /**
           *  \brief ON/OFF duty cycle limitation
           *  
           *  \param [in] command The true : ON, false OFF
           *  
           *  \return Return null
           */
          void setDutyCycle(bool command);
          
          /**
           *  \brief ON/OFF join duty cycle limitation
           *  
           *  \param [in] command The true : ON, false OFF
           *  
           *  \return Return null
           */
          void setJoinDutyCycle(bool command);
          
          /**
           *  \brief Set receice window delay
           *  
           *  \param [in] command The delay type
           *  \param [in] _delay The delay value(millisecond)
           *  
           *  \return Return null
           */
          void setReceiveWindowDelay(_window_delay_t command, unsigned short _delay);
          
          /**
           *  \brief Set LoRaWAN class type
           *  
           *  \param [in] type The class type
           *  
           *  \return Return null
           */
          void setClassType(_class_type_t type);
          
          /**
           *  \brief Set device into low power mode
           *  
           *  \return Return null
           */
          void setDeviceLowPower(void);
    
          /**
           *  \brief Send Ping command
           *  
           *  \return Return null
           */
          void sendDevicePing(void);
          
          /**
           *  \brief Reset device
           *  
           *  \return Return null
           */
          void setDeviceReset(void);
          
          /**
           *  \brief Setup device default
           *  
           *  \return Return null
           */
          void setDeviceDefault(void);
          
          /**
           *  \brief Initialize device into P2P mode
           * 
           *  \param [in] frequency The ISM frequency value
           *  \param [in] spreadingFactor The spreading factor value
           *  \param [in] bandwidth The band width value
           *  \param [in] txPreamble The transfer packet preamble number
           *  \param [in] rxPreamble The receive packet preamble number
           *  \param [in] power The output power
           *  
           *  \return Return null
           */
          void initP2PMode(unsigned short frequency = 433, _spreading_factor_t spreadingFactor = SF12, _band_width_t bandwidth = BW125, 
                           unsigned char txPreamble = 8, unsigned char rxPreamble = 8, short power = 20); 
          
          /**
           *  \brief Transfer the data
           *  
           *  \param [in] *buffer The transfer data cache
           *  
           *  \return Return bool. Ture : transfer done, false : transfer failed
           */
          bool transferPacketP2PMode(char *buffer, unsigned char timeout = DEFAULT_TIMEOUT); 
          /**
           *  \brief Transfer the data
           *  
           *  \param [in] *buffer The transfer data cache
           *  \param [in] length The length of data cache
           *  
           *  \return Return bool. Ture : transfer done, false : transfer failed
           */
          bool transferPacketP2PMode(unsigned char *buffer, unsigned char length, unsigned char timeout = DEFAULT_TIMEOUT);
          /**
           *  \brief Receive the data
           *  
           *  \param [in] *buffer The receive data cache
           *  \param [in] length The length of data cache
           *  \param [in] *rssi The RSSI cache
           *  \param [in] timeout The over time of receive
           *  
           *  \return Return Receive data number
           */
          short receivePacketP2PMode(unsigned char *buffer, int length, short *rssi, unsigned char timeout = DEFAULT_TIMEOUT);
          
          /**
           *  \brief LoRaWAN raw data
           *  
           *  \return Return null
           */
          void loraDebug(void);
  #if _DEBUG_SERIAL_
          void loraDebugPrint(unsigned char timeout);  
  #endif  
  
          
          
      private:
          void sendCommand(char *command);
          short readBuffer(char* buffer, int length, unsigned char timeout = DEFAULT_TIMEOUT);
          bool waitForResponse(char* response, unsigned char timeout = DEFAULT_TIMEOUT);
          bool sendCommandAndWaitForResponse(char* command, char *response, unsigned char timeout = DEFAULT_TIMEOUT);
          
          char _buffer[256];
  
  };
  
  
  extern LoRaWanClass lora;
  
  
  #endif
  