Data transfer over GSM

I am using Arduino Nano with a SIM800L module. Then used the Tiny GSM Sim800 sketch and all works fine.
My concern is how much data is being used. Every 500ms the Arduino sends AT+CIPRXGET=4,0 and the sim800 sends back CIPRXGET=4,0,0. Then Arduino sends AT+CIPSTATUS=0 and Sim replies with CIPSTATUS:0,0 TCP IPaddr CONNECTED.

My questions are the following -

  • How much data is being used with every packet sent?
  • Is it really needed for this to be sent every 500ms or could be done say every 5s?
  • I am sending some strings from Arduino to Blynk server - does this consume any download data or just upload?

Thanks
Julian

You should read this…

If you drop the text into Deepl translator it does quite a good job of making it understandable - assuming that you aren’t fluent in Russian.

Pete.

It depends on the data you send. The blynk packet itself is 5 bytes. So if you send a temperature like “27.44” it adds additional 5 bytes, so the message will be 10 bytes.

However, it still doesn’t mean that it’s all you’ll consume. Because when you send the data via TCP/IP protocol, you get additional 20 bytes for TCP, 20 bytes for IPv4. How your ISP provider calculates the traffic is unknown. Most likely they’ll add those 40 bytes. So “1 temperature” message would be ~50 bytes at least.

Another thing to consider is buffering (Nagle algorithm). Blynk sends every message one by one (Nagle is turned off). So in theory you can turn it on to save the TCP/IP packets overhead and group few messages within 1 packet. But that really depends on your use case.

It’s your project, so it’s up to you?

Just download, however, some Blynk commands may consume “upload” traffic, Like RTC API or login command response.

Thanks Dmitry that was the detailed answer I needed.

So now trying to understand the process - Is the following correct ?
-AT+CIPRXGET=4,0 == asks(polls) blynk server for value of Virtual pin?
-AT+CIPSTATUS=0 == get current connection status?

Now in Blynk_config.h I have
// Heartbeat period in seconds.
#ifndef BLYNK_HEARTBEAT
#define BLYNK_HEARTBEAT 45
#endif

So where could I set for a lower polling of say 10 seconds?

If you worry about the traffic that much we usually recommend gathering all the data during a day/hour and sending with one batch per day/hour via HTTP API.

In that case, you don’t need to handle the persistent connection.

Because the persistent connection by default consumes the data due to the heartbeat packets. Also, with GSM it would be almost impossible to keep it up and running, so you’ll have often disconnects and reconnects that will cause even more data consumption.

Thanks it is not only the traffic that concerns me but also the power consumption.
At the moment the packets are sent every 500ms while HEARTHBEAT is 45. Is there some other setting I could adjust?

Still can’t manage to lower the hearthbeat from the default 500ms. Any help please?

As you said I do get disconnects every few hours with GSM. Is NB-IOT more stable? I have the Sim7020 but cant find a library for it.

Did you read the link I provided?
Have you edited the BlynkConfig.h file?

Pete.

Yes read that link and conclusion was to set HEARTHBEAT in BlynkConfig.h
I set #define BLYNK_HEARTBEAT 600 in sketch, in BlynkConfig.h and in BlynkGSMClient.h but still packets are sent every 500ms

The only way I managed to lower hearthbeat was by adding a Delay in the main loop after Blynk.run() but this is not the recommended way.

Are you using Blynk Legacy or Blynk IoT?
What version of the Blynk library are you using?

If you add #define BLYNK_DEBUG near the top of your sketch, and turn-on “Show Timestamp” in your serial monitor what do you see?

This is what I see with an ESP32 + SIM800L (TTGO T-CALL).
It’s a legacy sketch, but compiled using the 1.0.1 library (it’s late and I couldn’t be bothered to downgrade to 0.6.1)
It has #define BLYNK_HEARTBEAT 30 in the sketch, but no changes to the library files…

00:20:11.260 ->     ___  __          __
00:20:11.260 ->    / _ )/ /_ _____  / /__
00:20:11.260 ->   / _  / / // / _ \/  '_/
00:20:11.260 ->  /____/_/\_, /_//_/_/\_\
00:20:11.260 ->         /___/ v1.0.1 on ESP32
00:20:11.260 -> 
00:20:11.295 -> [22163] Connecting to blynk-cloud.com:8080
00:20:12.135 -> [23013] <[1D|00|01|00] IREDACTED AUTH TOKEN
00:20:12.729 -> [23597] >[00|00|01|00|C8]
00:20:12.729 -> [23597] Ready (ping: 563ms).
00:20:12.798 -> [23664] <[11|00|02|00]Qver[00]1.0.1[00]h-beat[00]30[00]buff-in[00]1024[00]dev[00]ESP32[00]con[00]SIM800[00]build[00]Apr  5 2022 00:18:04[00]
00:20:13.428 -> [24300] >[00|00|02|00|C8]
00:20:42.825 -> [53691] <[06|00|03|00|00]
00:20:44.152 -> [55022] >[00|00|03|00|C8]
00:21:12.834 -> [83707] <[06|00|04|00|00]
00:21:14.231 -> [85114] >[00|00|04|00|C8]
00:21:42.848 -> [113726] <[06|00|05|00|00]  <<< Outbound Ping
00:21:44.142 -> [115037] >[00|00|05|00|C8]  >>> Response 1294 ms later
00:22:12.887 -> [143756] <[06|00|06|00|00]  <<< Outbound Ping 29.999 seconds after previous
00:22:14.208 -> [145080] >[00|00|06|00|C8]
00:22:42.898 -> [173772] <[06|00|07|00|00]
00:22:44.189 -> [175082] >[00|00|07|00|C8]
00:23:12.895 -> [203789] <[06|00|08|00|00]
00:23:14.292 -> [205157] >[00|00|08|00|C8]
00:23:42.938 -> [233807] <[06|00|09|00|00]
00:23:45.382 -> [236255] >[00|00|09|00|C8]
00:24:12.948 -> [263824] <[06|00|0A|00|00]
00:24:14.274 -> [265155] >[00|00|0A|00|C8]
00:24:42.945 -> [293841] <[06|00|0B|00|00]
00:24:44.306 -> [295174] >[00|00|0B|00|C8]
00:25:12.980 -> [323857] <[06|00|0C|00|00]
00:25:16.427 -> [327315] >[00|00|0C|00|C8]

Messages like this:

00:21:42.848 -> [113726] <[06|00|05|00|00]

mean that the device has sent a “06” (BLYNK_CMD_PING) command to the Blynk server.

The next line:

00:21:44.142 -> [115037] >[00|00|05|00|C8]

means that the server responded with a “C8” (BLYNK_SUCCESS) response. The serial monitor timestamp tells us that this was received 1294 milliseconds later.

This is then repeated with the next outbound ping command at almost exactly 30 seconds later.

How does this compare to what you’re seeing?

Pete.

1 Like

First adding a delay of 2 s in the main loop did not give any problems and actually the GSM connection was more stable as I did not get any disconnects for over 35hrs running.

I am using BlynkIoT app with Arduino Nano and library 1.0.1. Running in Debug mode (and delay removed) this is the log

11:10:39.546 -> Initializing modem...
11:10:49.076 -> Initialised modem...
11:10:49.076 -> [12518]
11:10:49.109 -> ___ __ __
11:10:49.109 -> / _ )/ /_ _____ / /__
11:10:49.142 -> / _ / / // / _ \/ '_/
11:10:49.175 -> /____/_/\_, /_//_/_/\_\
11:10:49.208 -> /___/ v1.0.1 on Arduino Nano
11:10:49.276 ->11:10:49.276 -> [12635] Modem init...
11:10:49.349 -> [12779] Connecting to network...
11:10:56.790 -> [20231] Network: Vodafone
11:10:56.790 -> [20231] Connecting to connect ...
11:11:07.636 -> [31086] Connected to GPRS
11:11:07.682 -> [31127] Connecting to blynk.cloud:80
11:11:12.108 -> [35545] <[1D|00|01|00] QN62xxxx
11:11:12.747 -> [36198] >[00|00|01|00|C8]
11:11:12.747 -> [36199] Ready (ping: 596ms).
11:11:12.778 -> [36200] Free RAM: 926
11:11:12.810 -> [36215] >[14|00|01|00|09]
11:11:12.857 -> [36243] >pm[00]12[00]out
11:11:12.896 -> [36270] <[11|00|02|00|8E]ver[00]1.0.1[00]h-beat[00]600[00]buff-in[00]256[00]dev[00]Arduino Nano[00]cpu[00]ATmega328P[00]con[00]SIM800[00]fw-type[00]TMPL_BOMm1f6[00]build[00]Apr 6 2022 10:59:16[00]tmpl[00]TMPL_BOMm1f6[00]
11:11:13.338 -> [36723] <[10|00|03|00|04]vr[00]1
11:11:14.044 -> [37485] >[00|00|02|00|C8]
11:11:14.135 -> [37577] >[14|00|03|00|06]
11:11:14.135 -> [37578] >vw[00]1[00]1
11:11:14.215 -> [37645] <[14|00|03|00|06]vw[00]3[00]1
11:11:14.366 -> [37793] <@[00|03|00|07]valveon
11:11:15.426 -> [38887] >[00|00|03|00|C8]
11:11:18.376 -> [41801] <[14|00|04|00|15]vw[00]4[00]000d/00h:00m:41s
11:11:18.485 -> [41921] <[14|00|05|00|10]vw[00]5[00]00h:00m:04
11:11:23.372 -> [46813] <[14|00|06|00|15]vw[00]4[00]000d/00h:00m:46s
11:11:23.506 -> [46934] <[14|00|07|00|10]vw[00]5[00]00h:00m:09s
11:11:28.390 -> [51822] <[14|00|08|00|15]vw[00]4[00]000d/00h:00m:51s
11:11:28.496 -> [51942] <[14|00|09|00|10]vw[00]5[00]00h:00m:14s
..
..
14:1:32.134 -> [55689] <[14|00|0B|00|06]vw[00]3[00]0
14:1:32.178 -> [55733] <@[00|0B|00|08]valveoff
14:1:32.812 -> [56374] >[00|00|0B|00|C8]
14:1:35.423 -> [58984] <[14|00|0E|00|15]vw[00]4[00]000d/00h:00m:58s
14:1:35.517 -> [59104] <[14|00|0F|00|10]vw[00]5[00]00h:00m:00s
14:1:40.425 -> [63993] <[14|00|10|00|15]vw[00]4[00]000d/00h:01m:03s
14:1:40.550 -> [64114] <[14|00|11|00|10]vw[00]5[00]00h:00m:00s
14:1:42.175 -> [65735] >[14|00|0D|00|06]
14:1:42.175 -> [65736] >vw[00]1[00]1
14:1:42.212 -> [65803] <[14|00|0D|00|06]vw[00]3[00]1
14:1:42.284 -> [65850] <@[00|0D|00|07]valveon
14:1:42.826 -> [66413] >[00|00|0D|00|C8]
14:1:45.330 -> [68912] <[14|00|12|00|15]vw[00]4[00]000d/00h:01m:08s
14:1:45.500 -> [69069] <[14|00|13|00|10]vw[00]5[00]00h:00m:03s
14:1:50.346 -> [73912] <[14|00|14|00|15]vw[00]4[00]000d/00h:01m:13s

So it seems the Heartbeat is 600 “h-beat[00]600[00]” and the data showing in the log are the DateTime strings sent from the arduino to blynk - these are sent every 5s as V4 and V5.
The last part shows the switching OFF/ON of Virtual pin 3 which also sends “valve ON” and “valve OFF” events.

However monitoring the serial interface with scope between arduino and Sim800 it still shows that packets are being send every 500ms

I think it’s time for you to share your sketch.

Pete.

So I removed the timer function and set Heartbeat = 60 now. This is the sketch but it is quite basic without timer function

#include <LowPower.h>



//#include <Blynk.h>


#define BLYNK_PRINT Serial

/* Fill-in your Template ID (only if using Blynk.Cloud) */
#define BLYNK_TEMPLATE_ID "TMPL_BOMm1f6"
#define BLYNK_DEVICE_NAME "NanoSim800"
#define BLYNK_AUTH_TOKEN "QN62Nm92_xxxxx"


// Select your modem:
#define TINY_GSM_MODEM_SIM800
//#define TINY_GSM_MODEM_SIM900
//#define TINY_GSM_MODEM_M590
//#define TINY_GSM_MODEM_A6
//#define TINY_GSM_MODEM_A7
//#define TINY_GSM_MODEM_BG96
//#define TINY_GSM_MODEM_XBEE

// Default heartbeat interval for GSM is 60
// If you want override this value, uncomment and set this option:
#define BLYNK_HEARTBEAT 60
#define BLYNK_DEBUG 


#include <TinyGsmClient.h>
#include <BlynkSimpleTinyGSM.h>


// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "QN62Nxxxxxxxxxxx";


// Your GPRS credentials
// Leave empty, if missing user or pass
char apn[]  = "connect";
char user[] = "";
char pass[] = "";

unsigned long onTime;
char timestr[18];
bool valveON;

// Hardware Serial on Mega, Leonardo, Micro
//#define SerialAT Serial1

// or Software Serial on Uno, Nano
#include <SoftwareSerial.h>
SoftwareSerial SerialAT(2, 3); // RX, TX

TinyGsm modem(SerialAT);
BlynkTimer timer;

void setup()
{
  // Debug console
  Serial.begin(9600);
  

  delay(10);
  pinMode(13,OUTPUT);

  // Set GSM module baud rate
  SerialAT.begin(19200);
  delay(3000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  Serial.println("Initializing modem...");
  modem.restart();

  Serial.println("Initialised modem...");
  // Unlock your SIM card with a PIN
  //modem.simUnlock("1234");

  
  Blynk.begin(auth, modem, apn, user, pass);

  //timer.setInterval(5000L, myTimerEvent);

}



void stime(long val){  

 long day = 86400000; // 86400000 milliseconds in a day
 long hour = 3600000; // 3600000 milliseconds in an hour
 long minute = 60000; // 60000 milliseconds in a minute
 long second =  1000; // 1000 milliseconds in a second
  
 int days = val / day ;                                //number of days
 int hours = (val % day) / hour;                       //the remainder from days division (in milliseconds) divided by hours, this gives the full hours
 int minutes = ((val % day) % hour) / minute ;         //and so on...
 int seconds = (((val % day) % hour) % minute) / second;


  sprintf(timestr, "%03dd/%02dh:%02dm:%02ds",days, hours, minutes, seconds);
  
}

void myTimerEvent()
{
  unsigned long valveONTime;
  if (valveON) valveONTime = millis()-onTime; else valveONTime = 0;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  stime(millis());
  
  //Serial.println(timestr);
  Blynk.virtualWrite(V4, timestr);
  stime(valveONTime);
  //Serial.println(timestr);
  char *p = &timestr[5]; // remove days
  Blynk.virtualWrite(V5, p);
  //delay(500);
  
}


// Every time we connect to the cloud...
BLYNK_CONNECTED() {
  // Request the latest state from the server
  Blynk.syncVirtual(V1);
  //Blynk.syncAll();
  // Alternatively, you could override server state using:
  //Blynk.virtualWrite(V2, ledState);
}

BLYNK_WRITE(V1)
{
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable

  if (pinValue == 1){
Blynk.virtualWrite(V3, 1);
digitalWrite(13,HIGH);
valveON = true;
onTime = millis();
Blynk.logEvent("valveon");
  } else{
Blynk.virtualWrite(V3, 0);
digitalWrite(13,LOW);
valveON = false;
onTime = 0;
Blynk.logEvent("valveoff");
  }
  // process received value
}

void loop()
{
  Blynk.run();
  timer.run(); // Initiates BlynkTimer

  //delay(2000);
  
}

This is the logging it produces

1:28:47.393 -> [25694] Connecting to blynk.cloud:80
1:28:55.612 -> [33916] <[1D|00|01|00] QN62Nm9xxxx
1:28:56.412 -> [34723] >[00|00|01|00|C8]
1:28:56.412 -> [34724] Ready (ping: 748ms).
1:28:56.457 -> [34724] Free RAM: 9731:28:56.492 -> [34740] >[14|00|01|00|09]
1:28:56.524 -> [34768] >pm[00]12[00]out
1:28:56.558 -> [34795] <[11|00|02|00|8D]ver[00]1.0.1[00]h-beat[00]60[00]buff-in[00]256[00]dev[00]
Arduino Nano[00]cpu[00]ATmega328P[00]con[00]SIM800[00]fw-type[00]TMPL_BOMm1f6[00]build[00]Apr 7 2022 0
1:28:06[00]tmpl[00]TMPL_BOMm1f6[00]
1:28:56.953 -> [35249] <[10|00|03|00|04]vr[00]1
1:28:58.637 -> [36954] >[00|00|02|00|C8]
1:28:58.683 -> [36997] >[14|00|03|00|06]
1:28:58.683 -> [36998] >vw[00]1[00]1
1:28:58.762 -> [37065] <[14|00|03|00|06]vw[00]3[00]1
1:28:58.794 -> [37110] <@[00|03|00|07]valveon
1:28:59.619 -> [37913] >[00|00|03|00|C8]
1:29:58.878 -> [97156] <[06|00|04|00|00]
1:30:00.251 -> [98538] >[00|00|04|00|C8]
1:30:58.937 -> [157199] <[06|00|05|00|00]

The HeartBeat packets are being sent every 60seconds as expected however I still get the same date on the serial port of Sim800 every 500ms. Here is the decoded serial data on the TX line from Arduino. It clearly shows the packets AT+CIPRXGET=4 0 and CIPSTATUS=0

Buffer Number	Packet	Start Time	End Time	Data	Parity	Parity Check	Max Voltage	Min Voltage	Voltage Delta	Packet Time
9	1	-0.50087698	-0.500356147	A						
9	2	-0.50034798	-0.499827147	T						
9	3	-0.49980898	-0.499288147	+						
9	4	-0.49927998	-0.498759147	C						
9	5	-0.49874498	-0.498224147	I						
9	6	-0.49821598	-0.497695147	P						
9	7	-0.49768098	-0.497160147	R						
9	8	-0.49715198	-0.496631147	X						
9	9	-0.49661698	-0.496096147	G						
9	10	-0.49608798	-0.495567147	E						
9	11	-0.49555298	-0.495032147	T						
9	12	-0.49502398	-0.494503147	=						
9	13	-0.49448898	-0.493968147	4						
9	14	-0.49395998	-0.493439147							
9	15	-0.49337898	-0.492858147	0						
9	16	-0.49284098	-0.492320147	CR						
9	17	-0.49230598	-0.491785147	LF						
9	18	-0.46974898	-0.469228147	A						
9	19	-0.46921398	-0.468693147	T						
9	20	-0.46868198	-0.468161147	+						
9	21	-0.46814698	-0.467626147	C						
9	22	-0.46761798	-0.467097147	I						
9	23	-0.46708298	-0.466562147	P						
9	24	-0.46655398	-0.466033147	S						
9	25	-0.46601898	-0.465498147	T						
9	26	-0.46548998	-0.464969147	A						
9	27	-0.46495398	-0.464433147	T						
9	28	-0.46442498	-0.463904147	U						
9	29	-0.46389098	-0.463370147	S						
9	30	-0.46336198	-0.462841147	=						
9	31	-0.46278098	-0.462260147	0						
9	32	-0.46224298	-0.461722147	CR						
9	33	-0.46170798	-0.461187147	LF						
9	34	-2.50E-05	0.000495852	A						
9	35	0.000504018	0.001024852	T						
9	36	0.001043018	0.001563852	+						
9	37	0.001571018	0.002091852	C						
9	38	0.002107018	0.002627852	I						
9	39	0.002636018	0.003156852	P						
9	40	0.003171018	0.003691852	R						
9	41	0.003700018	0.004220852	X						
9	42	0.004235018	0.004755852	G						
9	43	0.004764018	0.005284852	E						
9	44	0.005299018	0.005819852	T						
9	45	0.005828018	0.006348852	=						
9	46	0.006363018	0.006883852	4						
9	47	0.006892018	0.007412852							
9	48	0.007473018	0.007993852	0						
9	49	0.008011018	0.008531852	CR						
9	50	0.008546018	0.009066852	LF						
9	51	0.030908018	0.031428852	A						
9	52	0.031437018	0.031957852	T						
9	53	0.031975018	0.032495852	+						
9	54	0.032504018	0.033024852	C						
9	55	0.033039018	0.033559852	I						
9	56	0.033568018	0.034088852	P						
9	57	0.034104018	0.034624852	S						
9	58	0.034633018	0.035153852	T						
9	59	0.035168018	0.035688852	A						
9	60	0.035697018	0.036217852	T						
9	61	0.036232018	0.036752852	U						
9	62	0.036761018	0.037281852	S						
9	63	0.037296018	0.037816852	=						
9	64	0.037877018	0.038397852	0						
9	65	0.038414018	0.038934852	CR						
9	66	0.038949018	0.039469852	LF						
9	67	0.500898017	0.501418851	A						
9	68	0.501427017	0.501947851	T						
9	69	0.501965017	0.50248585	+						
9	70	0.502494017	0.50301485	C						
9	71	0.503029017	0.50354985	I						
9	72	0.503558017	0.50407885	P						
9	73	0.504093017	0.50461385	R						
9	74	0.504622017	0.50514285	X						
9	75	0.505158017	0.50567885	G						
9	76	0.505686017	0.50620685	E						
9	77	0.506222017	0.50674285	T						
9	78	0.506751017	0.50727185	=						
9	79	0.507285017	0.50780585	4						
9	80	0.507814017	0.50833485							
9	81	0.508396017	0.50891685	0						
9	82	0.508933017	0.50945385	CR						
9	83	0.509468017	0.50998885	LF						
9	84	0.531945017	0.53246585	A						
9	85	0.532474017	0.53299485	T						
9	86	0.533012017	0.53353285	+						
9	87	0.533541017	0.53406185	C						
9	88	0.534076017	0.53459685	I						
9	89	0.534611017	0.53513185	P						
9	90	0.535140017	0.53566085	S						
9	91	0.535675017	0.53619585	T						
9	92	0.536204017	0.53672485	A						
9	93	0.536740017	0.53726085	T						
9	94	0.537269017	0.53778985	U						
9	95	0.537803017	0.53832385	S						
9	96	0.538332017	0.53885285	=						
9	97	0.538914017	0.53943485	0						
9	98	0.539451017	0.53997185	CR						
9	99	0.539986017	0.54050685	LF						
9	100	1.002789016	1.003309849	A						
9	101	1.003318016	1.003838849	T						
9	102	1.003856016	1.004376849	+						
9	103	1.004385016	1.004905849	C						
9	104	1.004920016	1.005440849	I						
9	105	1.005449016	1.005969849	P						
9	106	1.005984016	1.006504849	R						
9	107	1.006513016	1.007033849	X						
9	108	1.007049016	1.007569849	G						
9	109	1.007577016	1.008097849	E						
9	110	1.008113016	1.008633849	T						
9	111	1.008642016	1.009162849	=						
9	112	1.009177016	1.009697849	4						
9	113	1.009706016	1.010226849							
9	114	1.010287016	1.010807849	0						
9	115	1.010825016	1.011345849	CR						
9	116	1.011360016	1.011880849	LF						
9	117	1.033756016	1.034276849	A						
9	118	1.034285016	1.034805849	T						
9	119	1.034823016	1.035343849	+						
9	120	1.035352016	1.035872849	C						
9	121	1.035887016	1.036407849	I						
9	122	1.036416016	1.036936849	P						
9	123	1.036952016	1.037472849	S						
9	124	1.037480016	1.038000849	T						
9	125	1.038015016	1.038535849	A						
9	126	1.038545016	1.039065849	T						
9	127	1.039080016	1.039600849	U						
9	128	1.039615016	1.040135849	S						
9	129	1.040144016	1.040664849	=						
9	130	1.040725016	1.041245849	0						
9	131	1.041262016	1.041782849	CR						
9	132	1.041797016	1.042317849	LF

Are you certain that this translates to data being sent/received over the cellular data network?

To me it just looks like internal handshake traffic between the Nano and the SIM800.

Pete.

So this brings me back to my first question.
What are these packets and are they really needed to be sent every 500ms?
After adding a delay of 2s the sketch still worked perfect if not better.
So which setting needs adjusting to have these packets send less frequently?

I don’t understand why you’re worried if these are simply internal serial communications, as opposed to “GSM data packets” as per your topic title.

Pete.

My aim is to put arduino to sleep when no data is being transferred (for say 30s). But due to these packets I’m not sure if it will break things.

I think that if you put the Arduino to sleep then you’ll need to re-establish the GSM connection, but you’ll need to try.

Pete.