Components and supplies
1
Jumper wires (generic)
1
Arduino Nano R3
1
ESP8266 ESP-01
1
Speaker, Piezo
1
Pushbutton Switch, Push-Pull
1
Real Time Clock (RTC)
Apps and platforms
1
Arduino IDE
Project description
Code
ClockServer.java
java
1/* 2BR,AC 3RESET 4GETTIME 5SETTIME,TODAY 6SETTIME,15,13,20,04,23,12 7SETALARM,2 //Set alarm for 2 second 8*/ 9 10import java.net.*; 11import java.io.*; 12import java.util.*; 13import java.time.*; 14import java.time.format.*; 15public class ClockServer 16{ 17ServerSocket serverSocket; 18Socket socket; 19int i=0; 20char c; 21String request,response; 22String nanoClockTime="Loading.."; 23List<String> commands; 24ClockServer() 25{ 26commands = new ArrayList<>(); 27} 28 29public void start() throws Exception 30{ 31serverSocket = new ServerSocket(8090); 32while(true) 33{ 34System.out.println("Clock server is ready at 8090"); 35socket = serverSocket.accept(); 36InputStreamReader isr = new InputStreamReader(socket.getInputStream()); 37StringBuffer sb = new StringBuffer(); 38System.out.println("Request received.."); 39while(true) 40{ 41c= (char)isr.read(); 42if(c=='#') break; 43sb.append(c); 44} 45request = sb.toString().toUpperCase(); 46System.out.println("Request: "+request); 47String split[] = request.split(","); 48if(split[0].equals("BR")) 49{ 50if(split[1].equals("RD")) 51{ 52System.out.println("Thanks for Registering Board..."); 53OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 54osr.write("Board Registered#"); 55osr.flush(); 56}else if(split[1].equals("AC")) 57{ 58nanoClockTime = split[2]+"/"+split[3]+"/"+split[4]+" "+split[5]+":"+split[6]+":"+split[7]; 59response=""; 60i=0; 61for(String cmd:commands) 62{ 63if(i>0) response = response +"!"; 64response = response + cmd;//TODO 65i++; 66} 67commands.clear(); 68response = response +"#"; 69OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 70osr.write(response); 71osr.flush(); 72System.out.println("Sending response:"+response ); 73} 74}else if(split[0].equals("RESET")) 75{ 76commands.add("01,01,00,00,00,00");//SETTIME,01,01,00,00,00,00 77OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 78osr.write("Command registered#"); 79osr.flush(); 80}else if(split[0].equals("GETTIME")) 81{ 82OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 83osr.write(nanoClockTime+"#"); 84osr.flush(); 85}else if(split[0].equals("SETTIME")) 86{ 87OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 88try 89{ 90if(split[1].equals("TODAY")) 91{ 92DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd,MM,yy,HH,mm,ss"); 93LocalDateTime today = LocalDateTime.now(); 94System.out.println(dtf.format(today)); 95commands.add(dtf.format(today)); 96osr.write("Command registered#"); 97}else 98{ 99commands.add(split[1]+","+split[2]+","+split[3]+","+split[4]+","+split[5]+","+split[6]);//SETTIME,01,01,00,00,00,00 100osr.write("Command registered#"); 101} 102}catch(Exception e) 103{ 104System.out.println(e); 105osr.write("Invalid command#"); 106} 107osr.flush(); 108}else if(split[0].equals("SETALARM")) 109{ 110commands.add("SETALARM,"+split[1]); 111OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 112osr.write("Command registered#"); 113osr.flush(); 114} 115socket.close(); 116} 117} 118public static void main(String aerp[]) 119{ 120try 121{ 122new ClockServer().start(); 123}catch(Exception e) 124{ 125System.out.println(e); 126} 127} 128}
ClockController.java
java
1import java.net.*; 2import java.io.*; 3class ClockController 4{ 5String request; 6Socket socket; 7char c; 8String response; 9public void start() throws Exception 10{ 11while(true) 12{ 13System.out.print("iot-clock>"); 14InputStreamReader isr = new InputStreamReader(System.in); 15BufferedReader br = new BufferedReader(isr); 16request = br.readLine().toUpperCase(); 17if(request.equals("EXIT")) break; 18if(request.equals("HELP")) 19{ 20System.out.println("RESET : For reset time to factory mode"); 21System.out.println("GETTIME : To get time"); 22System.out.println("SETTIME dd MM yy HH mm ss : To set time"); 23System.out.println("TODAY : To set current time\ 24"); 25continue; 26} 27socket = new Socket("localhost",8090); 28OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 29 30if(request.contains("SETALARM FOR ")) 31{ 32request = "SETALARM,"+request.substring(13,request.indexOf("SEC")); 33System.out.println(request); 34}else{ 35request = request.replaceAll(" ",","); 36} 37osr.write(request+"#"); 38osr.flush(); 39isr = new InputStreamReader(socket.getInputStream()); 40response = ""; 41while(true) 42{ 43c= (char)isr.read(); 44if(c=='#') break; 45response += c; 46} 47socket.close(); 48System.out.println(response); 49} 50} 51public static void main(String a[]) 52{ 53try 54{ 55new ClockController().start(); 56}catch(Exception e){System.out.println(e);} 57} 58}
ClockServer.java
java
1/* 2BR,AC 3RESET 4GETTIME 5SETTIME,TODAY 6SETTIME,15,13,20,04,23,12 7SETALARM,2 //Set alarm for 2 second 8*/ 9 10import java.net.*; 11import java.io.*; 12import java.util.*; 13import java.time.*; 14import java.time.format.*; 15public class ClockServer 16{ 17ServerSocket serverSocket; 18Socket socket; 19int i=0; 20char c; 21String request,response; 22String nanoClockTime="Loading.."; 23List<String> commands; 24ClockServer() 25{ 26commands = new ArrayList<>(); 27} 28 29public void start() throws Exception 30{ 31serverSocket = new ServerSocket(8090); 32while(true) 33{ 34System.out.println("Clock server is ready at 8090"); 35socket = serverSocket.accept(); 36InputStreamReader isr = new InputStreamReader(socket.getInputStream()); 37StringBuffer sb = new StringBuffer(); 38System.out.println("Request received.."); 39while(true) 40{ 41c= (char)isr.read(); 42if(c=='#') break; 43sb.append(c); 44} 45request = sb.toString().toUpperCase(); 46System.out.println("Request: "+request); 47String split[] = request.split(","); 48if(split[0].equals("BR")) 49{ 50if(split[1].equals("RD")) 51{ 52System.out.println("Thanks for Registering Board..."); 53OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 54osr.write("Board Registered#"); 55osr.flush(); 56}else if(split[1].equals("AC")) 57{ 58nanoClockTime = split[2]+"/"+split[3]+"/"+split[4]+" "+split[5]+":"+split[6]+":"+split[7]; 59response=""; 60i=0; 61for(String cmd:commands) 62{ 63if(i>0) response = response +"!"; 64response = response + cmd;//TODO 65i++; 66} 67commands.clear(); 68response = response +"#"; 69OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 70osr.write(response); 71osr.flush(); 72System.out.println("Sending response:"+response ); 73} 74}else if(split[0].equals("RESET")) 75{ 76commands.add("01,01,00,00,00,00");//SETTIME,01,01,00,00,00,00 77OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 78osr.write("Command registered#"); 79osr.flush(); 80}else if(split[0].equals("GETTIME")) 81{ 82OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 83osr.write(nanoClockTime+"#"); 84osr.flush(); 85}else if(split[0].equals("SETTIME")) 86{ 87OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 88try 89{ 90if(split[1].equals("TODAY")) 91{ 92DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd,MM,yy,HH,mm,ss"); 93LocalDateTime today = LocalDateTime.now(); 94System.out.println(dtf.format(today)); 95commands.add(dtf.format(today)); 96osr.write("Command registered#"); 97}else 98{ 99commands.add(split[1]+","+split[2]+","+split[3]+","+split[4]+","+split[5]+","+split[6]);//SETTIME,01,01,00,00,00,00 100osr.write("Command registered#"); 101} 102}catch(Exception e) 103{ 104System.out.println(e); 105osr.write("Invalid command#"); 106} 107osr.flush(); 108}else if(split[0].equals("SETALARM")) 109{ 110commands.add("SETALARM,"+split[1]); 111OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 112osr.write("Command registered#"); 113osr.flush(); 114} 115socket.close(); 116} 117} 118public static void main(String aerp[]) 119{ 120try 121{ 122new ClockServer().start(); 123}catch(Exception e) 124{ 125System.out.println(e); 126} 127} 128}
Arduino nano code
c_cpp
1/* 2 * USE OF WIFI MODULE, RTC MODULE, PUSHBUTTON, SPEAKER 3 * D3 for blink when time is not set 4*/ 5#include<SoftwareSerial.h> 6#include<DS3231.h> 7SoftwareSerial wifi(6,9); 8DS3231 clock; 9RTClib realTimeClock; 10DateTime currTime ; 11int i=0; 12int x=0; 13char request[50]; 14 15char response[51]; 16int interval =0; 17byte isDateTimeSetMode = 0; 18byte isDateTimeUpdated = 0; 19byte isYearSetMode = 0; 20byte isMonthSetMode = 0; 21byte isDateSetMode= 0; 22byte isHourSetMode = 0; 23byte isMinuteSetMode = 0; 24byte isSecondSetMode=0; 25int date = 0, currDate = 0; 26int month = 0, currMonth = 0; 27int year = 0, currYear = 0; 28int hour = 0, currHour = 0; 29int minute =0, currMinute = 0; 30int second = 0, currSecond = 0; 31boolean isKeyReleased = true; 32byte isToneEnabled = 0; 33int minInterval =150; 34void setup() { 35delay(4000); 36pinMode(5,OUTPUT); 37pinMode(3,OUTPUT); 38pinMode(13,INPUT); 39 40wifi.begin(9600); 41Serial.begin(9600); 42Wire.begin(); 43//clock.setYear((byte)00); 44setupWifi(); 45} 46 47void setupWifi() 48{ 49wifi.begin(9600); 50while(!wifi); 51Serial.println("Wifi Module is initialized"); 52Serial.print("Doing Reset"); 53wifi.print("AT+RST\ \ 54"); 55//while(!wifi.available()) Serial.print("."); 56delay(2000); 57while(wifi.available()) wifi.read(); 58Serial.println(); 59Serial.println("Reset Done"); 60Serial.println("\ 61"); 62Serial.print("AT Testing"); 63wifi.print("AT\ \ 64");//OK 65delay(3000); 66while(wifi.available()) wifi.read(); 67Serial.println(); 68Serial.println("Testing Done"); 69Serial.println(); 70Serial.print("Change mode to station"); 71wifi.print("AT+CWMODE=1\ \ 72");//OK 73delay(3000); 74//while(wifi.available()) wifi.read(); 75Serial.println(); 76Serial.println("Mode to Station mode Done"); 77Serial.println(); 78Serial.print("Let wifi connected to any AP if want"); 79i=10; 80while(i>=0) 81{ 82delay(1000); 83Serial.print(" "); 84Serial.print(i); 85i--; 86} 87Serial.println("\ 88"); 89Serial.print("Disconnecting to all APs"); 90wifi.print("AT+CWQAP\ \ 91"); 92 93delay(3000); 94Serial.println(); 95Serial.println("Wifi module not connected to any AP"); 96Serial.println(); 97Serial.print("Wifi module connecting to Anis"); 98wifi.print("AT+CWJAP_CUR=\\"Anis\\",\\"******\\"\ \ 99");//Set actual SSID and password 100i = 0; 101while(i<=10) 102{ 103delay(1000); 104Serial.print("."); 105if(wifi.find((char *)"OK")) 106{ 107 Serial.println("Connected"); 108 break; 109} 110i++; 111} 112if(i==11) 113{ 114 Serial.println("Unable to connect to Poco X3"); 115 return; 116} 117Serial.println("----------------------------Setup complete............................."); 118 119 } 120 121 122 123void loop() 124{ 125 126 clockModuleManual();//TO SET CLOCK MODULE MANUALLY 127 if(!isDateTimeSetMode) 128 wifiOperations();//TO SET CLOCK MODULE REMOTELY 129 } 130 131 132 133void clockModuleManual() { 134digitalWrite(3,0); 135// RFDriver.send(0,1); 136if(!isDateTimeSetMode && isRTCInDefaultMode()) 137 { 138// while(i<1000){ 139 140 digitalWrite(3,HIGH); 141 // RFDriver.send(1,1); 142 143 //delay(100); 144 //analogWrite(3,0); 145 //delay(100); 146 interval = 0; 147 while(digitalRead(13)) 148 { 149 // analogWrite(3,100); 150 if(interval >= minInterval) 151 { 152 isDateTimeSetMode = 1; 153 isDateSetMode = 1; 154 digitalWrite(3,LOW); 155 digitalWrite(5,HIGH); 156 // RFDriver.send(0,1); 157 } 158 interval ++; 159 delay(10); 160 } 161 162 //analogWrite(3,0); 163 digitalWrite(5,LOW); 164 if(isDateTimeSetMode) 165 { 166// break; 167 } 168 // i++; 169 //} 170 } 171 172 if(isDateTimeSetMode) 173 { 174 if(isDateSetMode) 175 { 176 interval = 0; 177 while(digitalRead(13)) 178 { 179 if(interval >= minInterval) 180 { 181 digitalWrite(5,HIGH); 182 isDateSetMode = 0; 183 isMonthSetMode = 1; 184 } 185 186 if(!isToneEnabled){tone(11,100); isToneEnabled = 1;} 187 if(isKeyReleased) 188 { 189 date++; 190 isKeyReleased =false; 191 } 192 interval ++; 193 delay(10); 194 } 195 digitalWrite(5,LOW); 196 noTone(11); 197 isToneEnabled = 0; 198 isKeyReleased = true; 199 }else if(isMonthSetMode) 200 { 201 interval = 0; 202 while(digitalRead(13)) 203 { 204 if(interval >= minInterval) 205 { 206 digitalWrite(5,HIGH); 207 isMonthSetMode = 0; 208 isYearSetMode = 1; 209 } 210 211 if(!isToneEnabled){tone(11,100); isToneEnabled = 1;} 212 if(isKeyReleased) 213 { 214 month++; 215 isKeyReleased =false; 216 } 217 interval ++; 218 delay(10); 219 } 220 digitalWrite(5,LOW); 221 noTone(11); 222 isToneEnabled = 0; 223 isKeyReleased = true; 224 }else if(isYearSetMode){ 225 interval = 0; 226 while(digitalRead(13)) 227 { 228 if(interval >= minInterval) 229 { 230 digitalWrite(5,HIGH); 231 isYearSetMode = 0; 232 isHourSetMode = 1; 233 } 234 235 if(!isToneEnabled){tone(11,100); isToneEnabled = 1;} 236 if(isKeyReleased) 237 { 238 year++; 239 isKeyReleased =false; 240 } 241 interval ++; 242 delay(10); 243 } 244 digitalWrite(5,LOW); 245 noTone(11); 246 isToneEnabled = 0; 247 isKeyReleased = true; 248 }else if(isHourSetMode){ 249 interval = 0; 250 while(digitalRead(13)) 251 { 252 if(interval >= minInterval) 253 { 254 digitalWrite(5,HIGH); 255 isHourSetMode = 0; 256 isMinuteSetMode = 1; 257 } 258 259 if(!isToneEnabled){tone(11,100); isToneEnabled = 1;} 260 if(isKeyReleased) 261 { 262 hour++; 263 isKeyReleased =false; 264 } 265 interval ++; 266 delay(10); 267 } 268 digitalWrite(5,LOW); 269 noTone(11); 270 isToneEnabled = 0; 271 isKeyReleased = true; 272 }else if(isMinuteSetMode){ 273 interval = 0; 274 while(digitalRead(13)) 275 { 276 if(interval >= minInterval) 277 { 278 digitalWrite(5,HIGH); 279 isMinuteSetMode = 0; 280 isSecondSetMode = 1; 281 } 282 283 if(!isToneEnabled){tone(11,100); isToneEnabled = 1;} 284 if(isKeyReleased) 285 { 286 minute++; 287 isKeyReleased =false; 288 } 289 interval ++; 290 delay(10); 291 } 292 digitalWrite(5,LOW); 293 noTone(11); 294 isToneEnabled = 0; 295 isKeyReleased = true; 296 }else if(isSecondSetMode){ 297 interval = 0; 298 while(digitalRead(13)) 299 { 300 if(interval >= minInterval) 301 { 302 digitalWrite(5,HIGH); 303 isSecondSetMode = 0; 304 } 305 306 if(!isToneEnabled){tone(11,100); isToneEnabled = 1;} 307 if(isKeyReleased) 308 { 309 second++; 310 isKeyReleased =false; 311 } 312 interval ++; 313 delay(10); 314 } 315 digitalWrite(5,LOW); 316 noTone(11); 317 isToneEnabled = 0; 318 isKeyReleased = true; 319 }else if(!isDateTimeUpdated){ 320 date--; 321 month--; 322 year--; 323 hour--; 324 minute--; 325 second--; 326 updateDateTime(); 327 isDateTimeSetMode = 0; 328 } 329 }else if(!isDateTimeUpdated){ 330 331 } 332 333delay(10); 334} 335 336void wifiOperations() 337{ 338Serial.println("Wifi Operations"); 339wifi.print("AT+CIPSTART=\\"TCP\\",\\"192.168.0.104\\",8090\ \ 340"); 341delay(2000); 342while(!wifi.available()); 343//while(wifi.available())Serial.print((char)wifi.read()); 344if(!wifi.find((char *)"OK")) 345{ 346 Serial.println("ERROR: AT+CIPSTART=\\"TCP\\",\\"192.168.43.222\\",8090 response is not OK"); 347 return; 348} 349 350while(wifi.available())(char)wifi.read(); 351getCurrTimeRTC(); 352sprintf(request,"BR,AC,%d,%d,%d,%d,%d,%d#",currDate,currMonth,currYear,currHour,currMinute,currSecond);//WHEN EVER ASKING COMMAND IT SEND CURRENT RTC TIME TO SERVER 353char request2[50]; 354sprintf(request2,"AT+CIPSEND=%d\ \ 355",strlen(request)); 356wifi.print(request2); 357delay(1000); 358while(!wifi.available()); 359 360if(!wifi.find((char *)"OK")) 361{ 362 Serial.println("ERROR: AT+CIPSEND=25 response is not OK"); 363 //return; 364} 365//while(wifi.available())(char)wifi.read(); 366 367Serial.println(request); 368wifi.print(request) ; 369while(!wifi.available()); 370delay(1000); 371if(!wifi.find((char *)"+IPD,")) 372{ 373 while(wifi.available())wifi.read(); 374 Serial.println("IPD not found"); 375 return; 376} 377char c; 378while(wifi.available() && wifi.read()!=':'); 379i=0; 380int a; 381while(true) 382{ 383 a = wifi.available(); 384 Serial.print(" "); 385 Serial.print(a); 386 if(!a || i>=199) 387 { 388 //break; 389 }else{ 390 x = (char)wifi.read(); 391 if(x=='#') 392 { 393 Serial.println("Breaking from loop"); 394 break; 395 } 396 response[i]=x; 397 i++; 398 } 399} 400response[i]='\\0'; 401Serial.println(); 402Serial.print("Response::: "); 403Serial.println(response); 404while(wifi.available())wifi.read(); 405if(x!='#') 406{Serial.println("Response does not contains terminator"); 407 return; 408} 409if(i==0) 410{ 411 Serial.println("No command to execute"); 412}else{ 413 Serial.print("Command: "); 414 Serial.println(response); 415 416//HARDCODE FOR NOW WILL CHANGE LATER ON 417//FOR BELOW CODE, REQUEST WILL ALAWAYS BE LIKE - 15,09,20,11,12,34# <- less then 21 chars 418 Serial.println(response[0]); 419 Serial.println(response[1]); 420 date = (response[0]-48)*10+(response[1]-48); 421 month = (response[3]-48)*10+(response[4]-48); 422 year = (response[6]-48)*10+(response[7]-48); 423 hour = (response[9]-48)*10+(response[10]-48); 424 minute=(response[12]-48)*10+(response[13]-48); 425 second =(response[15]-48) *10+(response[16]-48); 426 updateDateTime(); 427 428//FOR BELOW CODE, REQUEST WILL ALAWAYS BE LIKE - SETTIME,15,09,20,11,12,34# 429//COMMENTTED BELOW CODE SINCE ANABLE TO READ FROM WIFI IF STRING HAVING MORE THAN 21 CHARS 430 /* 431 int i1=0; 432 int i2=0; 433 while(response[i2]!='\\0') 434 { 435 if(response[i2]=='!') i1=i2+1; 436 if(response[i2]==',') 437 { 438 response[i2]='\\0'; 439 i2++; 440 //x = response[i2]; 441 date = response[0]*10+response[1]; 442 month = response[3]*10+response[4]; 443 year = response[6]*10+response[7]; 444 hour = response[9]*10+response[10]; 445 minute=response[12]*10+response[13]; 446 second =response[15]*10+response[16]; 447 updateDateTime(); 448 449 } 450 i2++; 451 } 452 */ 453 } 454 455 } 456 457 458boolean isRTCInDefaultMode() 459{ 460 getCurrTimeRTC(); 461 462if(currTime.year()==2000) 463{ 464 return true; 465 } 466 return false; 467} 468 469void getCurrTimeRTC() 470{ 471currTime = realTimeClock.now(); 472currDate = currTime.day(); 473currMonth = currTime.month(); 474currYear = currTime.year(); 475currHour = currTime.hour(); 476currMinute = currTime.minute(); 477currSecond = currTime.second(); 478 479} 480 481void updateDateTime() 482{ 483 484 Serial.print(date);Serial.print("/");Serial.print(month);Serial.print("/");Serial.print(year);Serial.print(" "); 485 Serial.print(hour);Serial.print(":");Serial.print(minute);Serial.print(":");Serial.println(second); 486 clock.setClockMode(false); 487 clock.setDate((byte)date); 488 clock.setMonth((byte)month); 489 clock.setYear((byte)year); 490 clock.setHour((byte)hour); 491 clock.setMinute((byte)minute); 492 clock.setSecond((byte)second); 493 isDateTimeUpdated = 1; 494 //analogWrite(3,100); 495 digitalWrite(5,HIGH); 496 497}
ClockController.java
java
1import java.net.*; 2import java.io.*; 3class ClockController 4{ 5String request; 6Socket socket; 7char c; 8String response; 9public void start() throws Exception 10{ 11while(true) 12{ 13System.out.print("iot-clock>"); 14InputStreamReader isr = new InputStreamReader(System.in); 15BufferedReader br = new BufferedReader(isr); 16request = br.readLine().toUpperCase(); 17if(request.equals("EXIT")) break; 18if(request.equals("HELP")) 19{ 20System.out.println("RESET : For reset time to factory mode"); 21System.out.println("GETTIME : To get time"); 22System.out.println("SETTIME dd MM yy HH mm ss : To set time"); 23System.out.println("TODAY : To set current time\ 24"); 25continue; 26} 27socket = new Socket("localhost",8090); 28OutputStreamWriter osr = new OutputStreamWriter(socket.getOutputStream()); 29 30if(request.contains("SETALARM FOR ")) 31{ 32request = "SETALARM,"+request.substring(13,request.indexOf("SEC")); 33System.out.println(request); 34}else{ 35request = request.replaceAll(" ",","); 36} 37osr.write(request+"#"); 38osr.flush(); 39isr = new InputStreamReader(socket.getInputStream()); 40response = ""; 41while(true) 42{ 43c= (char)isr.read(); 44if(c=='#') break; 45response += c; 46} 47socket.close(); 48System.out.println(response); 49} 50} 51public static void main(String a[]) 52{ 53try 54{ 55new ClockController().start(); 56}catch(Exception e){System.out.println(e);} 57} 58}
Comments
Only logged in users can leave comments