title: Error Posting Message with status code 302 to google app script from Loriot
body: <p>I'm trying to set up a LoRa communication network. </p>
  
  <p>I have a gateway module RHF0M301-915, PRI 2 Bridge RHF4T002 with raspberry pi 3 B (as Lora gateway); a seeeduino board with GPS, RHF76-052AM. </p>
  
  <p>Both registered in the Loriot Server.</p>
  
  <p>I managed to send GPS data from seeeduino board to the Loriot server's dashboard via ABP method. I want to output the data to my android mobile application to show users where are the end node located on the map. </p>
  
  <p>I choose to use HTTP Push (one of the output option provided by the Loriot server). </p>
  
  <p>I followed these <a href="https://blog.squix.org/2017/11/using-seeeduino-lorawan-with-gps-and-loriot-io.html" rel="nofollow noreferrer">guidelines</a>. </p>
  
  <p>I able to send GPS data to the Loriot Server but the HTTP push cannot push the data to the google sheets created as in the guidelines. I get the following error messages in the log of the Loriot server:</p>
  
  <blockquote>
    <p>Error POSTing message | "err":"POSTing message to
    \"<a href="https://script.google.com/macros/s/AKfycbyUaIl4t8PZxoXswCW2kc0I-ZfUl5DVucsD0CwtW3Rn4YAP2qpo/exec" rel="nofollow noreferrer">https://script.google.com/macros/s/AKfycbyUaIl4t8PZxoXswCW2kc0I-ZfUl5DVucsD0CwtW3Rn4YAP2qpo/exec</a>\"
    failed with 302 status
    code","appid":3195667320,"url":"<a href="https://script.google.com/macros/s/AKfycbyUaIl4t8PZxoXswCW2kc0I-ZfUl5DVucsD0CwtW3Rn4YAP2qpo/exec" rel="nofollow noreferrer">https://script.google.com/macros/s/AKfycbyUaIl4t8PZxoXswCW2kc0I-ZfUl5DVucsD0CwtW3Rn4YAP2qpo/exec</a>","seqno":132,"deveui":"4786C58B003C002A","data":{"statusCode":302},"message":"POSTing
    message to
    \"<a href="https://script.google.com/macros/s/AKfycbyUaIl4t8PZxoXswCW2kc0I-ZfUl5DVucsD0CwtW3Rn4YAP2qpo/exec" rel="nofollow noreferrer">https://script.google.com/macros/s/AKfycbyUaIl4t8PZxoXswCW2kc0I-ZfUl5DVucsD0CwtW3Rn4YAP2qpo/exec</a>\"
    failed with 302 status
    code","targetUrl":"<a href="https://script.google.com/macros/s/AKfycbyUaIl4t8PZxoXswCW2kc0I-ZfUl5DVucsD0CwtW3Rn4YAP2qpo/exec" rel="nofollow noreferrer">https://script.google.com/macros/s/AKfycbyUaIl4t8PZxoXswCW2kc0I-ZfUl5DVucsD0CwtW3Rn4YAP2qpo/exec</a>","statusCode":302,"reqBody":null,"errName":"Error","instance":"nwk-1"</p>
  </blockquote>
  
  <p>The following code sent the data to google sheet:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>// 2017 by Daniel Eichhorn, https://blog.squix.org
  // Inspired by https://gist.github.com/bmcbride/7069aebd643944c9ee8b
  // Create or open an existing Sheet and click Tools &gt; Script editor and enter the code below
  // 1. Enter sheet name where data is to be written below
  var SHEET_NAME = "Sheet1";
  // 2. Publish &gt; Deploy as web app
  //    - enter Project Version name and click 'Save New Version'
  //    - set security level and enable service (most likely execute as 'me' and access 'anyone, even anonymously)
  // 3. Copy the 'Current web app URL' and post this in your form/script action
  
  var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
  
  // If you don't want to expose either GET or POST methods you can comment out the appropriate function
  function doGet(e){
    return handleResponse(e);
  }
  
  function doPost(e){
    return handleResponse(e);
  }
  
  function handleResponse(e) {
    Logger.log("arrived in handleResponse");
    var jsonData = JSON.parse(e.postData.contents);
    
    try {
      // next set where we write the data - you could write to multiple/alternate destinations
      var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
      var sheet = doc.getSheetByName(SHEET_NAME); 
  
      var nextRow = sheet.getLastRow()+1; // get next row
      var row = [];
      var headerRow = [];
  
      row.push(jsonData.rssi);
      row.push(jsonData.seqno);
      row.push(jsonData.data);
      var humidityHex = jsonData.data.substring(0, 2);
      row.push(parseInt(humidityHex, 16));
      var tempHex = jsonData.data.substring(2, 4);
      row.push(parseInt(tempHex, 16) - 100);
      var latHex = jsonData.data.substring(4, 10);
      var lonHex = jsonData.data.substring(10, 16);
      var latEncoded = parseInt(latHex, 16);
      var lonEncoded = parseInt(lonHex, 16);
      row.push((latEncoded / 8388606) * 90);
      row.push((lonEncoded / 8388606) * 180);
  
      row.push(jsonData.freq);
      row.push(jsonData.ack);
      row.push(jsonData.fcnt);
      row.push(jsonData.dr);
      row.push(jsonData.bat);
      row.push(jsonData.port);
      row.push(jsonData.snr);
      row.push(jsonData.EUI);
      row.push(jsonData.cmd);
      row.push(jsonData.ts);
  
      // more efficient to set values as [][] array than individually
      sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
      // return json success results
      return ContentService
            .createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
            .setMimeType(ContentService.MimeType.JSON);
    } catch(e) {
      // if error return this
      return ContentService
            .createTextOutput(JSON.stringify({"result":"error", "error": e}))
            .setMimeType(ContentService.MimeType.JSON);
    } 
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p>This is the code to command the seeeduino board to send gps data to the Loriot server.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>#include &lt;TinyGPS++.h&gt;
  #include &lt;LoRaWan.h&gt;
  #include "DHT.h"
  
  
  TinyGPSPlus gps;
  #define DHTPIN A0 // what pin we're connected to
  
  #define DHTTYPE DHT11 // DHT 11
   
  DHT dht(DHTPIN, DHTTYPE);
  char buffer[256];
  
  
  void setup(void)
  {
      SerialUSB.begin(115200);
      Serial.begin(9600);
      
      lora.init();
      
      memset(buffer, 0, 256);
      lora.getVersion(buffer, 256, 1);
      SerialUSB.print(buffer); 
      
      memset(buffer, 0, 256);
      lora.getId(buffer, 256, 1);
      SerialUSB.print(buffer);
      SerialUSB.println("That was the id");
      // void setId(char *DevAddr, char *DevEUI, char *AppEUI);
      lora.setId("00C4E57D", "4786C58B003C002A", "526973696E674846");
      // setKey(char *NwkSKey, char *AppSKey, char *AppKey);
      lora.setKey("2B7E151628AED2A6ABF7158809CF4F3C", "2B7E151628AED2A6ABF7158809CF4F3C", "8413360695ABE271EB2A515386F0093E ");
      
      lora.setDeciveMode(LWOTAA);
      lora.setDataRate(DR2, AS923);
      
      lora.setChannel(0, 923.0);
      lora.setChannel(1, 923.2);
      lora.setChannel(2, 923.4);
      lora.setChannel(3, 923.6);
      lora.setChannel(4, 923.8);
      lora.setChannel(5, 924.0);
      lora.setChannel(6, 924.2);
      lora.setChannel(7, 924.4);
      
      lora.setReceiceWindowFirst(2, 923.0);
      lora.setReceiceWindowSecond(923.2, DR2);
      lora.setAdaptiveDataRate(false);
      
      lora.setPower(10);
      
      while(!lora.setOTAAJoin(JOIN, 20000));
      SerialUSB.println("After OTAA join");
  
      // Start DHT sensor
      dht.begin();
  }
  
  void loop(void)
  {   
      while (Serial.available() &gt; 0) {
        gps.encode(Serial.read());
      }
      if (gps.altitude.isUpdated()) {
        SerialUSB.println(gps.altitude.meters());
        SerialUSB.print("LAT=");  SerialUSB.println(gps.location.lat(), 6);
        SerialUSB.print("LONG="); SerialUSB.println(gps.location.lng(), 6);
        SerialUSB.print("ALT=");  SerialUSB.println(gps.altitude.meters());
        long latEncoded = (gps.location.lat() * 8388606) / 90;
        long lonEncoded = (gps.location.lng() * 8388606) / 180;
        SerialUSB.print("Lat encoded: "); 
        SerialUSB.println(latEncoded);
        SerialUSB.print("Lon encoded: "); 
        SerialUSB.println(lonEncoded);
        float h = dht.readHumidity();
        float t = dht.readTemperature();
        SerialUSB.print("Humidity is: ");
        SerialUSB.print(h);
        SerialUSB.print(", Temperature: ");
        SerialUSB.print(t);
        bool result = false;
        byte data[10] = {0};
        data[0] = h;
        data[1] = t + 100;
        data[2] = (byte) (latEncoded &gt;&gt; 16);
        data[3] = (byte) (latEncoded &gt;&gt; 8);
        data[4] = (byte) latEncoded;
        
        data[5] = (byte) (lonEncoded &gt;&gt; 16);
        data[6] = (byte) (lonEncoded &gt;&gt; 8);
        data[7] = (byte) lonEncoded;
  
        result = lora.transferPacket(data, 10);
        //result = lora.transferPacket(data, 10, 10);
        
        if(result)
        {
            short length;
            short rssi;
            
            memset(buffer, 0, 256);
            length = lora.receivePacket(buffer, 256, &amp;rssi);
            
            if(length)
            {
                SerialUSB.print("Length is: ");
                SerialUSB.println(length);
                SerialUSB.print("RSSI is: ");
                SerialUSB.println(rssi);
                SerialUSB.print("Data is: ");
                for(unsigned char i = 0; i &lt; length; i ++)
                {
                    SerialUSB.print("0x");
                    SerialUSB.print(buffer[i], HEX);
                    SerialUSB.print(" ");
                }
                SerialUSB.println();
            }
            delay(1000 * 60 * 5);
        }
      }
      
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p>How can I handle the status code 302, I know that it has to do with redirect the target URL that I used to some temporary URL. But I have no idea how to handle it.</p>