A7672S based GNSS Tracker by VALTRACK (V4-VTS-ESP32-C3)

A GNSS Tracker based on ESP32-C3 + A7672S 4G Module

You should find majority of the details needed for using the hardware here

⚡ Introduction

VALTRACK-V4-VTS-ESP32-C3 as the name itself depicts, is a fully configurable low power Vehicle Tracking System device. It was designed to be versatile and flexible enough to fit into any vehicle tracking scenario, be it for tracking 🚲 Bikes, 🚗 Cars or 🚚 Trucks.

  • Features
  • Specifications
  • Getting Started
  • Programming Details
  • Schematics
  • Firmware 
  • Purchase link

Features

Here you will get a brief idea on what the device is capable of and the important features

Power section :

The device has two power inputs,

VALTRACK-V4-VTS Power section

1) Main Power input - VCHG :

This is the main power input of the device and is usually connected to the vehicles battery. Right now the device supports from 12VDC to 42VDC input range. When you power the device from VCHG it also charges the battery connected to VBAT input. The main power chip used here is the TPS54240 switching regulator.

2) Backup battery power input - VBAT

This is the back up battery input and a 3.7V to 4.2V LiPo battery has to be connected to it. Use at least 400mAH battery. The main power chip used here is the MP2617 switching battery charger with power path management.

To understand the power section of the device, look at the block diagram.

Specifications

Model No. VALTRACK-V4-VTS [ESP32-C3]
Operating Voltage
  • Main Power Input : 12V to 42V DC [Connect to 12V Lead Acid Battery]
Has Reverse Polarity Protection
Backup Battery Input : 3.7V to 4.2V DC [Connect a single cell 3.7V-4.2V Li-Po or Li-Ion Battery] ⚠Doesn't have Reverse Polarity Protection
Dimensions With Enclosure - Length: 52mm * Width: 65mm * Height: 30 mm
PCB Dimensions - Length: 34mm * Width: 43mm * Thickness: 1.6 mm
Battery Support
  • 3.7V-4.2V DC Li-Po backup battery is supported.
  • Use > 400mAH capacity battery.
  • MP2617 Charger chip is used to handle the battery charging.
Cellular module A7672S - 4G-LTE-CAT1 / 2G - For India & Asia
A7672E - 4G-LTE-CAT1 /2G - For Europe
Australia
Navigation hardware Inbuilt GNSS of A7672x
A7672x has inbuilt GNSS hardware which needs passive or external active antenna [Bias is already provided to the GNSS U.FL connector]
Aux Inputs None
Aux Outputs None
Operating Modes HTTP, SMS, MQTT/TCP
Configuration Methods USB / Bluetooth (Yet to be implemented)
Processor Espressif ESP32-C3FH4 RISC-V chipset
Motion Sensor LIS3DH 12-bit, 3-axis Accelerometer
Memory 4MB inbuilt flash of ESP32-C3FH4
Antenna 📶 Cellular : U.FL Connector
  • 1.5 dBi gain Flexible PCB antenna comes attached
A7672x GNSS : U.FL Connector
  • Patch antenna comes attached
External GNSS is enabled on request only !
Connectivity Bluetooth, GPRS, SMS, Call
SIM connector Nano SIM card connector available
Flashing options Micro USB
Enclosure Device ships in a standard IP67 rated enclosure if ordered.

Purchase info

Board purchase information

Product variants

  • Without Enclosure
  • With Enclosure

GNSS Antenna Selection

  • Internal Patch antenna
  • External antenna

We offer the device with above options, You can order the device only if you want to use it in some other instrument along with other hardware or you can order the device with a IP67 enclosure. 

We also offer the device with internal GNSS patch antenna or external antenna. If you choose external antenna, we provide a SMA connector on the enclosure(if ordered) and add a bias resistor to power the external active antenna. Then you can connect a external antenna to the board via the U.FL connector. External GNSS antenna option is helpful when you want to install devices in places where there is no direct satellite view. In such cases you can use the external GNSS active antenna shown in below image.

VALTRACK-V4-VTS-ESP32-C3 enclosures with and without external antenna option
From Left, (External GNSS antenna device, External GNSS antenna device, Internal GNSS Patch antenna device)

Getting Started

Opening the enclosure

You need to remove the four screws present in the bottom of the enclosure to open it. Use a star head screw driver.

Inserting the SIM card

Get a Nano-SIM card and insert it into the boards push-pull type SIM card slot.

Power should not be connected to the device during SIM card insertion

Powering the device

VALTRACK-V4-VTS-ESP32-C3 can run from any of the two power sources,

Main Power Input
[VCHG connector]
  • Can take 12V to 42V DC [Connect to 12V Lead Acid Battery]
  • Its a JST type connector
Has Reverse Polarity Protection
Backup Battery Input
[VBAT connector]
  • Can take 3.7V to 4.2V DC [Connect a single cell 3.7V-4.2V Li-Po or Li-Ion Battery]
  • Use at least 500mAH and above capacity batteries
  • The battery connected to this port automatically gets charged by VCHG.
  • Its a JST-XH type connector
Doesn't have Reverse Polarity Protection

Device can start functioning with any of above power sources.

LED Indicators

  • Once the device is powered ON, The LED will show up and start with all RED .
  • Once the SIM is registered to the network, the NETWORK LED turns GREEN .
  • Once the GNSS module gets a location sync, the LOCATION LED turns GREEN .
  • After 30 seconds of inactivity, all LED will turn OFF to save power and turn ON again on movement detected by Accelerometer.
  • POWER LED remains RED all the time

Configuration

Configuration is not yet implented in firmware, but can be done using USB and Bluetooth or WiFi

Programming

Here you will find the details needed for develop your own firmware for the device

If you are interested in writing firmware for the VALTRACK-V4-VTS device, you will need to know where is each pin of MCU is connected to.

Since the schematics of the device is not yet openly available, We are providing the MCU pin connection details, which should be able to help you in determining how is the whole architecture laid out. Watching our device intro video would also help to get an overall idea on the hardware present on board.

MCU Pinout Details

Pin Number Pin Name Net Name Connected to
2, 3, 11, 17, 18, 31, 32 VDD3P3, VDD3P3_RTC, VDD3P3_CPU, VDD_SPI, VDDA 3V3DC 3.3VDC output of LDO
19, 20, 21, 22, 23, 24 SPIHD, SPIWP, SPICS0, SPICLK, SPID, SPIQ CLK_IN 32.768 KHz crystal
1 LNA_IN RF_ANTENNA Bluetooth / WiFi Chip antenna via matching network
4 GPIO0 LPUART1_TX Cellular module RXD input pin through level translator.
5 GPIO1 LPUART1_RX Cellular module TXD output pin through level translator.
6 GPIO2 ANALOG_IN VCHG input through voltage divider resistor network.
  • R22,R33 govern the voltage at this pin.
  • Default values : R22 = 100K, R33 = 3.3K
7 CHIP_PU CHIP_PU CHIP_PU line
9 GPIO4 TPS_ENABLE Enable input of switching regulator TPS54240
  • Making this pin high powers the system via VCHG connector.
This will cause system into reset loop if no alternate backup battery power available
Do no activate this pin without connecting a 3,7V battery to avoid Race around condition
10 GPIO5 IIC_DATA I2C data of LIS3DH Accelerometer
12 GPIO6 IIC_CLK I2C clock of LIS3DH Accelerometer
13 GPIO7 SIM_PWRKEY_3V3 Cellular module PWRKEY pin through N channel MOSFET.
  • Making this pin HIGH pulls PWRKEY pin to GND
14 GPIO8 LED_SIGNAL WS2812B battery LED input
15 GPIO9 GPIO9 Tactile switch input
  • Pulled up, filtered and Active LOW
16 GPIO10 GSM_ENABLE Enable input of power gating MOSFET for Cellular module
  • Making this pin high provides ~4VDC to Cellular module
14 GPIO8 LED_SIGNAL WS2812B battery LED input
25 GPIO18 USB_DN USB DP line
27 GPIO20 U0RXD Drawn to test points
28 GPIO21 U0TXD Drawn to test points
29 XTAL_N OSC_OUT 40 MHz crystal
30 XTAL_P OSC_IN 40 MHz crystal
26 GPIO19 USB_DP USB DN line
33 GND GND POWER PAD GND

J62 - VCHG Connector [SMT pads] - Pinout Details

Pin Number Pin Name Connected to
1 VCHG VCHG input of system through FUSE and diode
  • 12VDC to 42VDC input
2 GND System Ground

J41 - VBAT Connector [SMT pads] - Pinout Details

Pin Number Pin Name Connected to
1 VBAT VBAT input of system or Backup battery input
  • 3.7V to 4.2V battery input
2 GND System Ground

Schematics

Firmware

https://github.com/ValetronSystems/VALTRACK-V4-ESP32-C3.git

Link to ESP-IDF based firmware

GitHub - ValetronSystems/VALTRACK-V4-ESP32-C3: Source code for VALTRACK-V4-VTS-ESP32-C3 & VALTRACK-V4-MFW-ESP32C3 designs

Arduino example sketch with hardware initializations to get started

// #include "main.h"
// UART1 TX-----0
// UART1 RX-----1
// ANALOG IN----2
// INT1---------3
// TPS-ENABLE---4
// IIC-DATA-----5
// IIC-CLOCK----6
// PWRKEY-------7
// LED-SIGNAL---8
// SWITCH-SW2---9
// GSM-ENABLE---10
// USB DN-------18
// USB_DP-------19
// UART0 RX-----20
// UART0 TX-----21
​

 #define TINY_GSM_MODEM_SIM7600
​
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
​
// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1
​
​
// Increase RX buffer to capture the entire response
// Chips without internal buffering (A6/A7, ESP8266, M590)
// need enough space in the buffer for the entire response
// else data will be lost (and the http library will fail).
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 1024
#endif
​
// See all AT commands, if wanted
// #define DUMP_AT_COMMANDS
​
// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon
// #define LOGGING  // <- Logging is for the HTTP library
​
// Range to attempt to autobaud
// NOTE:  DO NOT AUTOBAUD in production code.  Once you've established
// communication, set a fixed baud rate using modem.setBaud(#).
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200
​
// Add a reception delay, if needed.
// This may be needed for a fast processor at a slow baud rate.
// #define TINY_GSM_YIELD() { delay(2); }
​
// Define how you're planning to connect to the internet
// These defines are only for this example; they are not needed in other code.
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
​
// set GSM PIN, if any
#define GSM_PIN ""
​
// Your GPRS credentials, if any
const char apn[]      = "www";
const char gprsUser[] = "";
const char gprsPass[] = "";
​
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "SSID";
const char wifiPass[] = "password";
​
// Server details
const char server[]   = "xyz.in";
const char resource[] = "";
const int  port       = 80;
​
#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
​
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm        modem(debugger);
#else
TinyGsm        modem(SerialAT);
#endif
​
TinyGsmClient client(modem);
HttpClient    http(client, server, port);
​
​
​
/////////////////////////////////////////////////////////////////////////////////////////////
​
// PWRKEY 7
// GSM ENABLE 10
// LED SIGNAL 8
// TPS ENABLE 4 //OR CHG IN
// INT1 3
// ANALOG IN 2
// IIC DATA 5
// IIC CLOCK 6
#define GPIO_IIC_DATA   5
#define GPIO_IIC_CLOCK  6
#define GPIO_PWRKEY     7
#define GPIO_GSM_ENABLE 10
#define GPIO_TPS_ENABLE 4
#define GPIO_INT1       3
#define GPIO_SOS        9
#define GPIO_CHG_IN     4
#define GPIO_LED_SIGNAL 8
​
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(3, GPIO_LED_SIGNAL, NEO_GRB + NEO_KHZ800);
​
#define BATTERY_LED  0
#define NETWORK_LED  1
#define LOCATION_LED 2
​
#define RED   0
#define GREEN 1
#define BLUE  2
​
#define BRIGHTNESS 64
void UpdateLED(int LED, int Color, int Brightness )
{
​
  switch(Color)
  {
    case RED : 
      pixels.setPixelColor(LED, pixels.Color(Brightness, 0, 0)); 
    break;
    case GREEN : 
      pixels.setPixelColor(LED, pixels.Color(0, Brightness, 0)); 
    break;
    case BLUE : 
      pixels.setPixelColor(LED, pixels.Color(0, 0, Brightness)); 
    break;
    default:
      pixels.setPixelColor(LED, pixels.Color(0, 0, 0)); 
    break;
  }
  pixels.show(); // This sends the updated pixel color to the hardware.
}
void EnableGSM(void)
{
    digitalWrite(GPIO_GSM_ENABLE, 1);// 10 GSM_ENABLE &LED_ENABLE
}
void DisableGSM(void)
{
    digitalWrite(GPIO_GSM_ENABLE, 0);// 10 GSM_DISABLE & LED_DISABLE
}
void InitGPIO(void)
{
  pinMode(GPIO_PWRKEY, OUTPUT);
  pinMode(GPIO_GSM_ENABLE, OUTPUT);
}
void InitLED(void)
{
  // pixels.begin(); // This initializes the NeoPixel library.
​
  UpdateLED(BATTERY_LED,RED, BRIGHTNESS);
  UpdateLED(NETWORK_LED,GREEN, BRIGHTNESS);
  UpdateLED(LOCATION_LED,BLUE, BRIGHTNESS);  
}
void InitGSM(void)
{
  // !!!!!!!!!!!
  digitalWrite(GPIO_PWRKEY, 0);
  digitalWrite(GPIO_PWRKEY, 1);
  delay(1000);
  digitalWrite(GPIO_PWRKEY, 0);
  // Set your reset, enable, power pins here
  // !!!!!!!!!!!
}
void InitUART0(void)
{
  Serial.begin(115200);
}
void InitUART1(void)
{
  Serial1.begin(115200,SERIAL_8N1,1,0);
}
​
​
#define REG_CTRL_REG1  0x20
#define  REG_CTRL_REG2  0x21
#define  REG_CTRL_REG3  0x22
#define  REG_CTRL_REG4  0x23
#define  REG_CTRL_REG5  0x24
#define  REG_CTRL_REG6  0x25
#define  REG_INT1_CFG  0x30
#define  REG_INT1_SRC  0x31
#define  REG_INT1_THS  0x32
#define  REG_INT1_DURATION  0x33
​
#define ACCLEROMETER_I2C_ADDRESS 0x19  //LIS3D
​
uint8_t I2C_RdReg(uint8_t RegisterAddress)
{
  
  Wire.beginTransmission(ACCLEROMETER_I2C_ADDRESS);
  Wire.write(RegisterAddress);
  Wire.endTransmission();
  Wire.requestFrom(ACCLEROMETER_I2C_ADDRESS, 1); 
  delay(2); 
  
  return  (uint8_t)Wire.read();
}
void I2C_WrReg(uint8_t RegisterAddress, uint8_t Data)
{
  Wire.beginTransmission(ACCLEROMETER_I2C_ADDRESS);
  Wire.write(RegisterAddress);
  Wire.write(Data);
  Wire.endTransmission();
}
void InitAccelerometer(void)
{
  uint8_t VALREAD=0;
​
  Wire.begin(GPIO_IIC_DATA,GPIO_IIC_CLOCK);
  VALREAD = I2C_RdReg(0x26);
​
  VALREAD = I2C_RdReg(0x0F);//VALREAD = I2C_RdReg(0x0D);
  Serial.print("Motion Sensor = ");
  if(VALREAD == 0x33)
  {
    Serial.println("LIS3DH Found");    
  }
  else
  {
     Serial.println("LIS3DH Not Found"); 
  }
   
  I2C_WrReg(REG_CTRL_REG1, 0x57);
  I2C_WrReg(REG_CTRL_REG4, 0x08);
  
  delay(200);
  //  VALREAD = I2C_RdReg(REG_CTRL_REG1);
  I2C_WrReg(REG_CTRL_REG2, 0x05);
  I2C_WrReg(REG_CTRL_REG3, 0x40);//    I2C_WrReg(MMA8652_CTRL_REG3, 0x39);
  
  I2C_WrReg(REG_CTRL_REG5, 0x08);
  // VALREAD = I2C_RdReg(REG_CTRL_REG5);
  I2C_WrReg(REG_CTRL_REG6, 0x02);
  //I2C_WrReg(REG_CTRL_REG6, 0xFF);
  I2C_WrReg(REG_INT1_THS,0x18);
  I2C_WrReg(REG_INT1_DURATION,0x00);
  I2C_WrReg(REG_INT1_CFG,0x2A);
​
  for(uint8_t i=0x07;i<=0x3F;i++)
  {
    VALREAD = I2C_RdReg(i);      
  }  
​
}
void setup() {
 
  delay(5000);
  InitGPIO();
  InitUART0();
  InitUART1();  
  EnableGSM();
  InitLED();
  InitAccelerometer();
​
  InitGSM();
  
  
​
  Serial.println("Wait...");
  
  Serial.println("Wait...1");
  // Set GSM module baud rate
  //TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX);
  //SerialAT.begin(115200,SERIAL_8N1,1,0);
  delay(6000);
  Serial.println("Hello\r\n");
  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();
  // modem.init();
​
  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem Info: ");
  SerialMon.println(modemInfo);
​
#if TINY_GSM_USE_GPRS
  // Unlock your SIM card with a PIN if needed
  if (GSM_PIN && modem.getSimStatus() != 3) { modem.simUnlock(GSM_PIN); }
#endif
​
​
   modemInfo = modem.getSignalQuality();
  SerialMon.print("Signal Quality: ");
  SerialMon.println(modemInfo);
  //xTaskCreate(ADCTask, "ADCTask", 2048, NULL, 10, NULL);
    // xTaskCreate(StartTimerTask, "StartTimerTask", 4096, NULL, 10, NULL);   
    // xTaskCreate(StartMainTask, "StartMainTask", 8192, NULL, 10, NULL); //TIMER_TASK_STACK_SIZE
​
    //thisModem().sendAT(GF("+IPR="), baud);
    modem.sendAT(GF("+IPR?"));
    modem.waitResponse(10000,"+IPR");
​
    
}
​
​
void loop() {
#if TINY_GSM_USE_WIFI
  // Wifi connection parameters must be set before waiting for the network
  SerialMon.print(F("Setting SSID/password..."));
  if (!modem.networkConnect(wifiSSID, wifiPass)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");
#endif
​
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_XBEE
  // The XBee must run the gprsConnect function BEFORE waiting for network!
  modem.gprsConnect(apn, gprsUser, gprsPass);
#endif
​
  SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork()) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");
​
  if (modem.isNetworkConnected()) { SerialMon.println("Network connected"); }
​
#if TINY_GSM_USE_GPRS
  // GPRS connection parameters are usually set after network registration
  SerialMon.print(F("Connecting to "));
  SerialMon.print(apn);
  if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");
​
  if (modem.isGprsConnected()) { SerialMon.println("GPRS connected"); }
#endif
​
​
​
  SerialMon.print(F("Performing HTTP GET request... "));
  int err = http.get(resource);
  if (err != 0) {
    SerialMon.println(F("failed to connect"));
    delay(10000);
    return;
  }
​
  int status = http.responseStatusCode();
  SerialMon.print(F("Response status code: "));
  SerialMon.println(status);
  if (!status) {
    delay(10000);
    return;
  }
​
  SerialMon.println(F("Response Headers:"));
  while (http.headerAvailable()) {
    String headerName  = http.readHeaderName();
    String headerValue = http.readHeaderValue();
    SerialMon.println("    " + headerName + " : " + headerValue);
  }
​
  int length = http.contentLength();
  if (length >= 0) {
    SerialMon.print(F("Content length is: "));
    SerialMon.println(length);
  }
  if (http.isResponseChunked()) {
    SerialMon.println(F("The response is chunked"));
  }
​
  String body = http.responseBody();
  SerialMon.println(F("Response:"));
  SerialMon.println(body);
​
  SerialMon.print(F("Body length is: "));
  SerialMon.println(body.length());
​
  // Shutdown
​
  http.stop();
  SerialMon.println(F("Server disconnected"));
​
#if TINY_GSM_USE_WIFI
  modem.networkDisconnect();
  SerialMon.println(F("WiFi disconnected"));
#endif
#if TINY_GSM_USE_GPRS
  modem.gprsDisconnect();
  SerialMon.println(F("GPRS disconnected"));
#endif

  // Do nothing forevermore
  while (true) { delay(1000); }
}

Google Sheets - Script

App script info to append VALTRACK-V4 HTTP post data to Google sheets

In firmware a define in  has to be enabled, which makes the HTTP function wait for 302 Moved Temporarily response.  Google App script gives 302 response instead of 200 so enable this #define. When you want to use custom response string, you can comment this line.

#define SHEETS_ENABLED

Sample packet to test

{"resource":[{"devid":"123095050300182","time":"2023-03-29 12:30:44","etype":"REBOOT","lat":"15.200000","lon":"75.32000","vbat":"0.000000","speed":"0.000000"}]}

Script to be pasted in Google sheets extension

function doPost(req) {
  
  var logid=0;
  var devid=0;
  var lat=0;
  var lon=0;
  var time=0;
  var server_time=0;
  var etype=0;
  var speed=0;
  var vbat=0;
  var vmbat=0;
  var pInt=0;
  var nlat=0;
  var nlon=0;
  var ncsq=0;
  var ltype=0;
  var coach_num=0;
  var fuel=0;
  var origin=0;
  var engine=0;

  var output;
  var data = JSON.parse(req.postData.contents);
  var sheet = SpreadsheetApp.getActiveSheet();
  
  let datenow = new Date();
  
  var packet = data.resource;
  for(var i=0;i<packet.length;i++)
  {

    try{
        
        sheet.appendRow([
          
          packet[i].logid,
          packet[i].devid,
          packet[i].lat,
          packet[i].lon,
          packet[i].time,
          datenow,
          packet[i].etype,
          packet[i].speed,
          packet[i].vbat,
          packet[i].vmbat,
          packet[i].pInt,
          'http://maps.google.com/maps?z=18amp;&q='+packet[i].lat+','+packet[i].lon,
          packet[i].nlat,
          packet[i].nlon,
          packet[i].ncsq,
          packet[i].ltype,    
          packet[i].coach_num,
          packet[i].fuel,
          packet[i].origin,
          packet[i].engine,
          'VALTRACK-V4-VTS-ESP32-C3'
          
          ]);
    }
    catch(error)
    {
      output = error;

    }
      
  }  
  return ContentService.createTextOutput(JSON.stringify({data:output})).setMimeType(ContentService.MimeType.JSON);
}


Post a Comment