/*V1.2
project name : << Process of RO’s Waste Water Reuse & Water
Management in Society by Using IOT Automation >>
--------------------------------------------------------...................................
* Code programming (C++ , json) & Blynk cloud & circuit : Ali Haghighat Panah (AHP) ☻
*/
//-----------------[ON or OFF]
#define AHP_BLYNK_OFF //Me: trun off Blynk and "send_Data2Blynk" , actives "send_Data2File" for debugging
#define TWO_CHART_BLYNK_OFF // Me: Turn this off to use the "AHP BLYNK group 7 Ro pro" Blynk template insted of "2chart mode I AHP BLYNK group 7 Ro pro"
//==================[HEADER FILES]==================V
#include "DHTesp.h"
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
// -------[blynk]---------V
#ifdef AHP_BLYNK_OFF //temp
/* Fill-in information from Blynk Device Info here */
#ifdef TWO_CHART_BLYNK_OFF
//Me: bare behatar namayesh dadn chart model1 & modle 2 az in template estfade shode ast
#define BLYNK_TEMPLATE_ID "TMPL4KVxsrtc1"
#define BLYNK_TEMPLATE_NAME "2chart mode I AHP BLYNK group 7 Ro pro"
#define BLYNK_AUTH_TOKEN "61WRVghLI_-WTVDvNJmLs5pJkk4zB2gs"
#endif
#ifndef TWO_CHART_BLYNK_OFF
//Me: Template asli
#define BLYNK_TEMPLATE_ID "TMPL4HmeajZ2I"
#define BLYNK_TEMPLATE_NAME "AHP BLYNK group 7 Ro pro"
#define BLYNK_AUTH_TOKEN "VMJ_-HXz1_XBVfof2RaG1Fes5wKKIVoC"
#endif
#include <BlynkSimpleEsp32.h>
/* Comment this out to disable prints and save space */
// #define BLYNK_PRINT Serial
#endif
//==================[PIN DEFINE]==================V
#define DHT_PIN 15 // DHT22: temperature and humidity sensor
#define BUTTON_MODE 2 // Button
#define SOIL_MOIST_PIN 33 // potentiometer
#define PREST_MODE_LED 4 // LED
#define BLYNK_LED 32 //LED
#define RELAY_GURDAN_PUMP 12 // LED
#define RELAY_CITY_PUMP 14 // LED
#define TRIG_PIN 25 // Ultra Sonic sensor
#define ECHO_PIN 26 // Ultra Sonic sensor
//==================[Objects]==================V
LiquidCrystal_I2C Green_LCD = LiquidCrystal_I2C(0x26, 16, 2);
LiquidCrystal_I2C Blue_LCD = LiquidCrystal_I2C(0x27, 16, 2);
DHTesp dhtSensor; // set up DHT22 sensor
#ifdef AHP_BLYNK_OFF //temp
BlynkTimer timer;
#endif
//==================[Golbal variable AHP]==================V
//-----{WiFi Credentials}---------V
const char ssid[] = "Wokwi-GUEST";
const char pass[] = "";
//----{Blynk}------V
int Blynk_mode_get = 0;
int Plant_mode = 0;
//-----{pump}------V
bool pump_led_flag_CITY = false;
bool pump_led_flag_GURDAN = false;
//----{Timer}------V
int seconds = 0;
int minutes = 0;
int hours = 0;
bool list_flag = true;
//--{sensors}------V
float sensor_moist_data = 0;
float sensor_humidity_data = 0;
int sensor_temperature_data = 0;
int sensor_TankerVol = 0;
int sensor_waterLVL_data = 0;
float sensor_waterLVL_data_percent = 0;
float sensor_waterLVL_data_percent2 = 0; //temppp
//------{LCD)-----V
char line0[17];
char line1[17];
int green_lcd_state = 0;
int green_lcd_old_state = 0;
//---{tanker)----- V
//source: https://tankerplastic.com/%D9%85%D8%AE%D8%B2%D9%86-%D8%A2%D8%A8/
#define PI_NUM 3.14
uint8_t tanker_index = 2;
//مخزن آب عمودی
// const int tanker_volumes [] = { 80, 100, 150, 220, 350, 500, 550, 900, 1000, 1000, 1500, 1500, 2000, 3000, 4000, 5000, 5000, 6000, 8000, 10000, 15000, 20000};
//------- tanker_index : ---{ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21}
const int tanker_Diameter[] = { 50, 52, 55, 60, 69, 85, 72, 133, 88, 109, 121, 108, 132, 153, 183, 188, 222, 222, 195, 255, 255, 290 , 50 };
const int tanker_height [] = { 58, 75, 85, 102, 132, 119, 170, 132, 212, 145, 172, 200, 188, 208, 180, 225, 160, 190, 295, 235, 325, 335, 60 };
//------{date set)--------------------------------------------------------------------------------------------------
//**** Momenraty waterting corn dataset
float plant_water_usage_prest1 [] = {0.24,0.40,0.43,0.57,0.73,0.73,0.86,1.00,1.06,1.20,1.29,1.39,1.49,1.61,1.66,1.80,1.91,1.91,2.11,2.23,2.31,2.41,2.43,2.61,2.61,2.58,2.51,2.53,2.48,2.50,2.45,2.45,2.48,2.45,2.40,2.31,2.42,2.33,2.23,2.34,2.33,2.16,2.04,1.97,1.83,1.80,1.71,1.59,1.50,1.36,1.21,1.11,1.03,1.01,0.93,0.84,0.81,0.62,0.52,0.47};
int soil_moist_prest1 [] = {93.81,84.71,77.98,55.27,33.71,93.81,85.53,78.57,53.4,33.32,93.81,84.59,77.4,56.13,37.96,93.81,87.48,78.06,56.37,38.62,93.81,93.23,78.1,57.42,35.69,93.81,87.21,76.26,57.93,35.45,93.81,86.11,74.31,57.93,35.85,93.81,84.63,77.44,54.84,37.21,93.81,87.37,77.79,57.89,38.85,93.81,85.88,77.55,58.48,36.94,93.81,81.7,75.83,57.58,38.11,93.81,86.74,74.43,55.94,35.42};
//**** Night waterting corn dataset
float plant_water_usage_prest2 [] = {0.28,0.26,0.40,0.50,0.63,0.64,0.80,0.87,1.00,1.19,1.16,1.37,1.40,1.50,1.56,1.67,1.81,1.79,2.06,2.11,2.24,2.40,2.39,2.47,2.60,2.46,2.39,2.42,2.35,2.36,2.42,2.42,2.38,2.41,2.31,2.21,2.31,2.20,2.21,2.20,2.26,2.10,1.91,1.84,1.76,1.76,1.57,1.51,1.46,1.34,1.17,1.01,0.93,0.87,0.87,0.71,0.79,0.54,0.51,0.42};
int soil_moist_prest2 [] ={96.31,93.35,91.61,70.75,37.6,96.31,93.35,91.6,70.77,37.6,96.31,93.35,91.61,70.75,37.55,96.31,93.34,91.61,70.74,37.54,96.31,93.31,91.61,70.74,37.58,96.31,93.34,91.62,70.73,37.58,96.31,93.34,91.63,70.73,37.57,96.31,93.35,91.61,70.76,37.56,96.31,93.34,91.61,70.73,37.54,96.31,93.34,91.61,70.73,37.56,96.31,93.37,91.62,70.74,37.55,96.31,93.34,91.63,70.75,37.58};
int loop_time = sizeof(plant_water_usage_prest2)/sizeof(plant_water_usage_prest2[0]);
int current_time = 0;
//--------{genral flag}----------V
bool Prest_sensor_mode_flag = true;
bool end_send_flag = false;
//===========================[BLYNK : READ | WRITE | Functions]===========================V
#ifdef AHP_BLYNK_OFF //temp
//♦ اضافه هست
BLYNK_WRITE(V4) //Me: plant silder get data // Me: az site (Blynk) dade dar (ESP32) neveshte (write) mish
{
// Set incoming value from pin V0 to a variable
Plant_mode = param.asInt();
// Serial.println("Plant: " + String(value));
}
//♦ اضافه هست
BLYNK_WRITE(V5) //Me: plant swicth button get data
{
//Blynk Update state
Blynk_plant_mode (param.asInt());
}
#endif
//===========================[BLYNK : READ | WRITE | Functions]===========================V
//V==============V[♦ MAIN PORGRAM ♦}V==============V
void setup() {
Serial.begin(115200);
//---------------[pin mode]---------------V
pinMode(BUTTON_MODE, INPUT_PULLUP); //2 old button BUTTON_MODE = PUS_BUTTON
pinMode(RELAY_GURDAN_PUMP, OUTPUT); // 12
pinMode(RELAY_CITY_PUMP, OUTPUT); // 14
pinMode(BLYNK_LED, OUTPUT);
pinMode(TRIG_PIN, OUTPUT); // Sets the trigPin as an Output // 4
pinMode(ECHO_PIN, INPUT); // Sets the echoPin as an Input
pinMode(PREST_MODE_LED, OUTPUT); //4
//---------------[LCD config]---------------v
Green_LCD.init();
Green_LCD.backlight();
Green_LCD.clear();
Green_LCD.setCursor(0, 0);
Green_LCD.print("IOT Group 7");
Blue_LCD.init();
Blue_LCD.backlight();
Blue_LCD.clear();
Blue_LCD.setCursor(0, 0);
Blue_LCD.print("CODE & CIRCUIT:");
Blue_LCD.setCursor(0, 1);
Blue_LCD.print("A.HAGHIGHAT PANAH");
delay(6000);
Blue_LCD.clear();
Green_LCD.clear();
Green_LCD.setCursor(0, 0);
Green_LCD.print("S: --%");
Green_LCD.setCursor(0, 1);
Green_LCD.print("B: -");
//---------------[others config]---------------v
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
//-------------[WIFI]--------------------------------V
connectToWiFi(5);
//---------------[blynk]------------------------------V
#ifdef AHP_BLYNK_OFF //temp
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass); // turn on
timer.setInterval(1000L, send_Date2Bylnk); // turn on
timer.setInterval(2000L, checkBlynkStatus); // turn on
#endif
}
//__________________________________________________________________________
void loop() {
// Serial.println(digitalRead(BUTTON_MODE));
// delay(100);
#ifdef AHP_BLYNK_OFF //temp
Blynk.run();
timer.run();
#endif
// --------------------[wifi}--------------------V
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi connection lost. Reconnecting...");
connectToWiFi(5);
}
//♦FIX THIS ----- این خط رو در بخش ارسال به بلینک بگذار
/*
if(!Prest_sensor_mode_flag){
SoilSense(SOIL_MOIST_PIN);
//----------[water indictor(ultraSonic sensor) & tanker ]----V
int temp = ultraSonic();
// Serial.println(String(temp) + "cm");
tanker(temp);
}
*/
//-----------[pump]----V
if (pump_led_flag_GURDAN) digitalWrite(RELAY_GURDAN_PUMP, HIGH);
else digitalWrite(RELAY_GURDAN_PUMP, LOW);
if (pump_led_flag_CITY) digitalWrite(RELAY_CITY_PUMP, HIGH);
else digitalWrite(RELAY_CITY_PUMP, LOW);
//-----------[File date send]---V
#ifndef AHP_BLYNK_OFF
send_Data2File();
#endif
prestButtonSwicth(); // Me: this switch from sensor to prestMode (we use scripted event)
MomentaryOrNightMode();
//-------------- IN JA BARAE MHDOIT ZAMAN MA HASTESH
if(Prest_sensor_mode_flag && current_time >=loop_time) {
end_send_flag = true;
// while(1){
// Serial.println("WE ARE DONNEEEEEEEEEEEEEEEEE");
// delay(2000);
// }
}
}
//^==============^[♦ MAIN PORGRAM ♦}^==============^
// ====================[Functions]====================V
void prestButtonSwicth(){
static uint8_t ledState = LOW; // if off the sensor data will be send
// static uint8_t ledState = HIGH; // if on the preset data will be send
static uint32_t lastDebounceTime = 0; // the last time the output pin was toggled
static uint32_t debounceDelay = 50; // the debounce time; increase if the output flickers
static uint32_t previousMillis = 0; // the last time the LED was switched on
static int buttonState; // the current reading from the input pin
static int lastButtonState = LOW; // the previous reading from the input pin
// read the state of the switch into a local variable:
int reading = digitalRead(BUTTON_MODE);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState || end_send_flag) {
buttonState = reading;
// only toggle the LED if the new button state is active
if (buttonState == LOW || end_send_flag) {
ledState = !ledState;
}
// set the LED:
if (ledState){
digitalWrite(PREST_MODE_LED, HIGH);
Prest_sensor_mode_flag = true;
previousMillis = millis(); // remember the time when LED was switched on by button
// Serial.println("[[[["+String(reading)+"]]]]");
}
else{
digitalWrite(PREST_MODE_LED, LOW);
Prest_sensor_mode_flag = false;
current_time = 0;
end_send_flag = false;
// Serial.println("[[[["+String(reading)+"]]]]");
}
}
}
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}
//----------------[♦ AHP functions ♦]----------------V
//Me:
void SoilSense(int pin_soil) {
float soil_dry = 34.5; // the percent
float temp = map(analogRead(pin_soil), 0, 4095, 0, 10000);
sensor_moist_data = (temp/10000)*100;
//Me: replacment for Green_LCD,clear function lag for not having delay-------------V
green_lcd_state = sensor_moist_data;
if (green_lcd_state != green_lcd_old_state) { //Me: old Green_LCD print
Green_LCD.clear();
updateDisplay(2);
Green_LCD.setCursor(0, 0);
Green_LCD.print("S: " + String(sensor_moist_data)+"%");
}
delay(500);
green_lcd_old_state = green_lcd_state; // Me: {green_lcd_old_state} va {green_lcd_state} = (Global vars) hastand
if (sensor_moist_data < soil_dry) pump_led_flag_GURDAN = true;
else pump_led_flag_GURDAN = false;
}
//---{web and net function group)
#ifdef AHP_BLYNK_OFF //temp
void send_Date2Bylnk() {
// --------------------[DHT]--------------------V
TempAndHumidity dht = dhtSensor.getTempAndHumidity();
sensor_temperature_data = dht.temperature;
sensor_humidity_data = dht.humidity;
// --------------------[water and moimoisture ]--------------------V
SoilSense(SOIL_MOIST_PIN);
tanker(ultraSonic());
if(end_send_flag){
Serial.println("============[DataSet end]========^\nloop count reseted\n====================");
return;// return; // after the prest prom finished it will come out
}
Serial.println("-----["+String(current_time)+"]------^");
Blynk.virtualWrite(V7, sensor_temperature_data); // temperature
Blynk.virtualWrite(V8, sensor_humidity_data); // humidity
if(!Prest_sensor_mode_flag){ // mosit sensor senddata
Blynk.virtualWrite(V9, sensor_moist_data); // moisture
}
else { // mosit prest send data
#ifdef TWO_CHART_BLYNK_OFF
Blynk.virtualWrite(V9, soil_moist_prest1[current_time]);
Serial.println(String(soil_moist_prest1[current_time]));//temppp
Blynk.virtualWrite(V11, soil_moist_prest2[current_time]);
Serial.println(String(soil_moist_prest2[current_time])); //temppp
#endif
//..............................................................................
#ifndef TWO_CHART_BLYNK_OFF
if (Blynk_mode_get == 0) Blynk.virtualWrite(V9, soil_moist_prest1[current_time]);
else if (Blynk_mode_get == 1) Blynk.virtualWrite(V9, soil_moist_prest2[current_time]);
#endif
current_time++;
}
#ifdef TWO_CHART_BLYNK_OFF
Blynk.virtualWrite(V10, sensor_waterLVL_data_percent); // water level percentage
Blynk.virtualWrite(V12, sensor_waterLVL_data_percent2); // water level percentage //temppp
#endif
//..............................................................................
#ifndef TWO_CHART_BLYNK_OFF
if (Blynk_mode_get == 0) Blynk.virtualWrite(V10, sensor_waterLVL_data_percent); // water level percentage
else if (Blynk_mode_get == 1) Blynk.virtualWrite(V10, sensor_waterLVL_data_percent2); // water level percentage //temppp
#endif
}
//♦ اضافه هست
void Blynk_plant_mode(int plant_mode_button) { // me in bare swicth dar barname blynk hast ke har moghe 1 bode halte mesl eyk dokme amale kone va bade mode abe yari ghiyae ro zakhire kone
if (plant_mode_button == 1) {
Serial.println("sending : " + String(Plant_mode));
Blynk_mode_get = Plant_mode;
}
}
void MomentaryOrNightMode (){
Green_LCD.setCursor(0, 1);
#ifdef TWO_CHART_BLYNK_OFF
// --------------1234567890123456
Green_LCD.print("Mode: 2Chart use");
#endif
#ifndef TWO_CHART_BLYNK_OFF
if(Blynk_mode_get == 0) Green_LCD.print("Mode: Momentary");
else if (Blynk_mode_get == 1) Green_LCD.print("Mode: Night ");
else Green_LCD.print("Mode: NONE SET");
#endif
}
void checkBlynkStatus() { // called every 3 seconds by SimpleTimer
bool isconnected = Blynk.connected();
if (isconnected == true) {
digitalWrite(BLYNK_LED, HIGH);
} else if (isconnected == false) {
Serial.print("Blynk Not Connected ");
digitalWrite(BLYNK_LED, LOW);
//Serial.println("Blynk Connected");
}
}
#endif
void send_Data2File() {
if (list_flag) {
list_flag=false;
Serial.println("Time | Tanker Volume | Water level | Water level percent | Soil moisture level | Temperature level | Humidity level");
// ("00:00:00 | 10 | 10 | 10.00 | 1122 | 100 | 50.0 ")
Serial.println("------------------------------------------------------------------------------------------------------------------------------------");
} else {
Serial.print(String(hours)+":"+String(minutes)+":"+String(seconds));
Serial.print(" | "+String(sensor_TankerVol));
Serial.print(" | "+String(sensor_waterLVL_data));
Serial.print(" | "+String(sensor_waterLVL_data_percent));
Serial.print(" | "+String(sensor_moist_data));
Serial.print(" | "+String(sensor_temperature_data));
Serial.println(" | "+String(sensor_humidity_data));
seconds++;
if (seconds >= 59) {
minutes = minutes + 1;
seconds=0;
}
if (minutes > 59) {
hours = hours + 1;
minutes = 0;
}
delay(1000);
}
}
void connectToWiFi(int reconect_tries) {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass, 6);
while (WiFi.status() != WL_CONNECTED && reconect_tries < 10) {
delay(100);
Serial.print(".");
reconect_tries++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Green_LCD.setCursor(0, 0);
Green_LCD.print("Connecting WiFi");
Green_LCD.clear();
Green_LCD.print("Connected to:");
Green_LCD.setCursor(0, 1);
Green_LCD.print(WiFi.localIP());
delay(500);
Green_LCD.clear();
} else {
Serial.println("");
Serial.println("Failed to connect to WiFi");
}
}
//-----{tanker function group)-
int ultraSonic() { // MeE: this function converts sound wave to distance (CM)
long duration = 0;;
float distance = 0;;
// Clears the trigPin
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(ECHO_PIN, HIGH);
// Calculating the distance
distance = duration * 0.034 / 2; // MeE : (0.034) is the speed of sound
return Postive_round(distance);
}
void tanker (int Distance) { // MeE: this function works works with cylinder tanks volume
// Me: Tammi mohasebat ba estfade az vahad (Cm) hasteh
static int Distance_store = 0; //Me : این برای ذخیره متغیر محلی هست
static unsigned int tanker_radius;
static unsigned int tanker_capacity;
static float water_level;
static float water_level_percent;
static float water_level2; // temppp
static float water_level_percent2; //temppp
if(Distance != Distance_store ){
Distance_store = Distance;
// MeE: Here we are going to get the distance of the empty part of Tenaker
int empty_height = ( tanker_height [tanker_index] - Distance );
if (empty_height < 0) empty_height = 0; // Me: if the empty space was negative number it means it the tanker already empty so we give thw value [0]
//-----------------[ V = πr2 h]-------------------------V
//MeE: the reference had D: diameter we have to convert to radius first
tanker_radius = tanker_Diameter[tanker_index] / 2; // (r=d/2)
tanker_capacity =( PI_NUM * (tanker_radius * tanker_radius) * tanker_height [tanker_index])/1000; // (V1 = πr2 h1)
water_level = (PI_NUM * (tanker_radius * tanker_radius) * empty_height)/1000 ; // ( V2 = πr2 h2)
water_level_percent = ((float)water_level / (float)tanker_capacity) * 100;
water_level2 = water_level; //temppp
water_level_percent2 =water_level_percent;
// float water_level_percent = ((float)water_level / (float)tanker_capacity) * 100;
// --------------------[Conditions ]--------------------V
if(water_level_percent >= 85.0) pump_led_flag_CITY = true;
else pump_led_flag_CITY = false;
delay(1000);
}
else if (Prest_sensor_mode_flag){
water_level = water_level-plant_water_usage_prest1[current_time];
if(water_level<0) water_level =0;
water_level_percent = ((float)water_level / (float)tanker_capacity) * 100;
water_level2 = water_level2-plant_water_usage_prest2[current_time]; //temppp
if(water_level2<0) water_level2 =0;//temppp
water_level_percent2 = ((float)water_level2 / (float)tanker_capacity) * 100;//temppp
}
// --------------------[(LCD or Serial),print]--------------------V
float show_water;
float show_water_level_percent;
if(Blynk_mode_get == 1){
show_water = water_level2;
show_water_level_percent = water_level_percent2;
}
else{
show_water = water_level;
show_water_level_percent = water_level_percent;
}
Blue_LCD.setCursor(0, 0);
Blue_LCD.println("WL:" + String(show_water) + "L");
Blue_LCD.setCursor(10, 0);
Blue_LCD.println(String(show_water_level_percent) + "%");
// Blue_LCD.print(" ");
// Blue_LCD.println("WL:" + String(show_water) + "L " + String(show_water_level_percent) + "%");
Blue_LCD.setCursor(0, 1);
Blue_LCD.println("TANK_VOL:" + String(tanker_capacity )+"L");
updateDisplay(1); // clear lcd
Serial.println("WL:" + String(show_water) + "L");
Serial.println(String(show_water_level_percent) + "%");
Serial.println("TANK_VOL:" + String(tanker_capacity )+"L");
delayMicroseconds(1000);
// Serial.println("WL:" + String(show_water) + "L|" + String(show_water_level_percent) + "%");
// Serial.println("TANK_VOL:" + String(tanker_capacity)+"L");
sensor_TankerVol = tanker_capacity;
sensor_waterLVL_data = water_level;
sensor_waterLVL_data_percent = water_level_percent;
// sensor_waterLVL_data2 = water_level2; //temppp
sensor_waterLVL_data_percent2 = water_level_percent2; //temppp
}
int Postive_round(float value) { //MeE: this function rounds the number
int upperVal = value;
float decimalVal = value - upperVal;
if (decimalVal < 0.5) return upperVal;
else return upperVal + 1;
}
//-----{display function )
void updateDisplay(uint8_t address) {
if(address == 1){
Blue_LCD.setCursor(0,0);
Blue_LCD.print(line0);
Blue_LCD.print(line1);
} else if (address == 2){
Green_LCD.setCursor(0,0);
Green_LCD.print(line0);
Green_LCD.print(line1);
}
}