Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 3 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 3 | |||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
| |||||
![]() |
|
The project was made by Matthieu CATOIRE and Karl EDIMO as part of our engineering studies in Networks and Connected Objects at UniLaSalle Amiens.https://www.unilasalle.fr/our school training (RIOC): https://www.unilasalle.fr/parcours-reseaux-informatiques-et-objets-connectes
It all starts with the teacher creating a room, selecting a matrix corresponding to the students' desired layout.
At the end of this process, a unique random code is generated, which the teacher shares with the students.
When students use this unique code to access the room, they then assign their place within the matrix (of the room) previously defined by the teacher.
Each student has an individual module, which displays a unique code randomly generated by the JAVA server after sending a request. This code enables the student to associate the module with his or her place in the TP room, which is recorded in the database.
Once installed, the module allows students to use the physical buttons on the module.
It is also possible to use the web/mobile version of the application independently of the module.
These buttons offer different functionalities to facilitate interaction with the teacher and management of the practical sessions.
The three buttons on the module allow students to signal different needs:
- "ASSISTANCE" calls on the teacher to ask a question or submit a problem, equivalent to raising a hand in the traditional way.
- "VALIDATION" is a call to the teacher to validate a step in their practical work.
- "INTERVENTION" is a request for the teacher to take charge of a student, reserved for the teacher. This signals and saves that the teacher has taken charge of the student.
All these actions are displayed in real time on the screen, enabling students to track their position in the queue. A queue management algorithm, chosen in advance by the teacher, regulates priority according to various criteria, such as waiting time, the nature of the call or the frequency of each student's requests.
The teacher has the option of video-projecting the room overview with all students displayed. This page shows how many people are waiting, who, where and how long they've been waiting.
There's also a column on the side showing the number of people who have already been helped, how many and for how long.
This can be used by teachers to prioritize people who have asked for little or no help, in conjunction with the queue priority system.
In this way, IoTeach offers a sophisticated and adaptable solution for the management of classrooms, enhancing the learning experience for students while facilitating the work of teachers in a dynamic and evolving educational environment.
#include <TheThingsNetwork.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
const char *appEui = "F1EF486F16EA655F";
const char *appKey = "74FCB360D71B83C387861468FB75956F";
#define loraSerial Serial1
#define debugSerial Serial
#define freqPlan TTN_FP_EU868
TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan);
int lbs_VALIDATION = LOW;
int lbs_ASSISTANCE = LOW;
int lbs_DONE = LOW;
int state_ASSISTANCE = LOW;
int state_VALIDATION = LOW;
int state_DONE = LOW;
unsigned long time = 0; // the last time the output pin was toggled
unsigned long debounce = 200UL; // the debounce time, increase if the output flickers
int stateCHANGE = 0;
byte payload[5];
String codeUnique = "";
bool LINKED = false;
void setup()
{
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
loraSerial.begin(57600);
debugSerial.begin(9600);
lcd.init();
lcd.backlight();
// Wait a maximum of 10s for Serial Monitor
while (!debugSerial && millis() < 8000)
;
ttn.onMessage(message);
debugSerial.println("-- STATUS");
ttn.showStatus();
debugSerial.println("-- JOIN");
ttn.join(appEui, appKey);
}
void loop(){
if (LINKED == false){
payload[0] = payload[0] + 1;
payload[1] = 0;
payload[2] = 5;
payload[3] = 5;
payload[4] = 5;
PrintPAYLOAD();
PrintSCREEN("En attente de code...", "none");
ttn.sendBytes(payload, sizeof(payload));
delay(4000);
} else { // LINKED TRUE
int bs_ASSISTANCE = digitalRead(3);
int bs_VALIDATION = digitalRead(4);
int bs_DONE = digitalRead(5);
if (bs_ASSISTANCE == 0 && lbs_ASSISTANCE == LOW && millis() - time > debounce) {
state_ASSISTANCE = (state_ASSISTANCE == HIGH) ? LOW : HIGH;
state_VALIDATION = LOW;
state_DONE = LOW;
time = millis();
stateCHANGE = 1;
}
if (bs_VALIDATION == 0 && lbs_VALIDATION == LOW && millis() - time > debounce) {
state_VALIDATION = (state_VALIDATION == HIGH) ? LOW : HIGH;
state_ASSISTANCE = LOW;
state_DONE = LOW;
time = millis();
stateCHANGE = 1;
}
if (bs_DONE == 0 && lbs_DONE == LOW && millis() - time > debounce) {
state_DONE = (state_DONE == HIGH) ? LOW : HIGH;
state_ASSISTANCE = LOW;
state_VALIDATION = LOW;
time = millis();
stateCHANGE = 1;
}
lbs_ASSISTANCE = bs_ASSISTANCE;
lbs_VALIDATION = bs_VALIDATION;
lbs_DONE = bs_DONE;
if (stateCHANGE == 1){
PrintPAYLOAD();
payload[0] = payload[0] + 1;
payload[1] = 0;
payload[2] = state_ASSISTANCE;
payload[3] = state_VALIDATION;
payload[4] = state_DONE;
PrintSCREEN("envoie...", "none");
ttn.sendBytes(payload, sizeof(payload));
PrintSCREEN("envoye.", "none");
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(getLEDfromBTN(payload), HIGH);
stateCHANGE = 0;
}
PrintPAYLOAD();
delay(100);
}
}
int getLEDfromBTN(const uint8_t *pl){
int led = 0;
led = (pl[2] == 1 && led == 0) ? 7 : led;
led = (pl[3] == 1 && led == 0) ? 8 : led;
led = (pl[4] == 1 && led == 0) ? 9 : led;
return led;
}
void poll(){
payload[0] = payload[0] + 1;
payload[1] = 0;
payload[2] = state_ASSISTANCE;
payload[3] = state_VALIDATION;
payload[4] = state_DONE;
ttn.sendBytes(payload, sizeof(payload));
}
void message(const uint8_t *payload, size_t size, port_t port)
{
debugSerial.println("------ MESSAGE (");
debugSerial.print(size);
debugSerial.print(")");
debugSerial.print("Received " + String(size) + " bytes on port " + String(port) + ":");
for (int i = 0; i < size; i++){
debugSerial.print(" " + String(payload[i]));
}
if (size == 5){ // code
String code = ConvertCODE(payload, size, "dec");
codeUnique = code;
Serial.println("CODE: " + code);
PrintSCREEN(code, "code");
LINKED = true;
} else {
String ASCIImessage = ConvertCODE(payload, size, "dec");
Serial.println(ASCIImessage);
Serial.println(ASCIImessage.substring(0,5));
if(codeUnique != ""){
if(ASCIImessage.substring(0,5) == codeUnique){
if (ASCIImessage.substring(5,6) == 1){
Serial.println("euh");
}
}
}
}
debugSerial.println();
}
void PrintPAYLOAD(){
debugSerial.print("{code: ");
debugSerial.print(codeUnique);
debugSerial.print(", assistance: ");
debugSerial.print(state_ASSISTANCE);
debugSerial.print(", validation: ");
debugSerial.print(state_VALIDATION);
debugSerial.print(", done: ");
debugSerial.print(state_DONE);
debugSerial.println("}");
delay(20);
}
void PrintSCREEN(String message, String type){
lcd.clear();
if (type == "code"){
lcd.setCursor(0,0);
lcd.print("CODE:");
lcd.setCursor(11,1);
lcd.print(message);
} else {
if (message.length() > 16) {
int lastSpaceIndex = message.lastIndexOf(' ');
if (lastSpaceIndex != -1) {
lcd.print(message.substring(0, lastSpaceIndex));
lcd.setCursor(0, 1);
lcd.print(message.substring(lastSpaceIndex + 1));
} else {
lcd.print(message.substring(0, 16));
lcd.setCursor(0, 1);
lcd.print(message.substring(16));
}
} else {
lcd.print(message);
}
}
delay(20);
}
String ConvertCODE(byte payload[], size_t size, String format){
String code = "";
String StringPayload = "";
if (format == "hex"){
for (int i = 0; i < size; i++){
StringPayload += String(payload[i], HEX);
}
int length = StringPayload.length();
for (int i = 0; i < length; i += 2) {
String hex = StringPayload.substring(i, i + 2);
char asciiChar = (char)strtol(hex.c_str(), NULL, 16);
code += asciiChar;
}
} else if (format == "dec"){
for (int i = 0; i < size; i++) {
char asciihexChar = (char)payload[i];
if (asciihexChar != ' ') {
code += asciihexChar;
}
}
}
return code;
}
<?php
session_start();
include("assets/php/bddconnect.php");
if (isset($_POST['tpcode'])) {
if (!empty($_POST['tpcode'])) {
$_SESSION['tpcode'] = $_POST['tpcode'];
if ($_POST['tppassword'] == $_POST['tpreppassword']) {
$reqPASSWORD = $bdd->prepare("SELECT password FROM salle WHERE tpcode = ?");
$reqPASSWORD->execute(array($_SESSION['tpcode']));
$reqResult = $reqPASSWORD->fetch();
if ($reqResult['password'] != $_POST['tppassword']) {
header('Location: index.php');
}
} else {
header('Location: index.php');
}
} else {
header('Location: index.php');
}
} else if (!isset($_SESSION['tpcode'])) {
header('Location: index.php');
}
$tpcode = $_SESSION['tpcode'];
$reqRetrieveMatrice = $bdd->prepare("SELECT matrice FROM salle WHERE tpcode = ?");
$reqRetrieveMatrice->execute(array($tpcode));
$data = $reqRetrieveMatrice->fetch();
?>
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="assets/css/main.css">
<link rel="stylesheet" href="assets/css/popup.css">
<link rel="stylesheet" href="assets/css/proj.css">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;600&display=swap" rel="stylesheet">
<script src="https://rawgit.com/moment/moment/2.2.1/min/moment.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://code.jquery.com/mobile/1.5.0-rc1/jquery.mobile-1.5.0-rc1.js"></script>
<script src="https://kit.fontawesome.com/97bee1f2fa.js" crossorigin="anonymous"></script>
<title>IoTeach</title>
</head>
<body>
<header>
<h1>IoTeach</h1>
<?php if (isset($tpcode)) { ?>
<span class="code"><?= $tpcode; ?></span>
<?php } ?>
</header>
<main>
<div class="main-container">
<div class="stats-container">
<div class="stats">
<span>Personnes en attente:</span>
<h1 id="nb_people_waiting">3</h1>
</div>
</div>
<?php
$matrice = explode('x', $data['matrice']);
$matrice_col = $matrice[0];
$matrice_row = $matrice[1];
$sum = $matrice_col * $matrice_row;
?>
<style media="screen">
div.grid-salle-container{
grid-template: repeat(<?= $matrice_row; ?>, 70px) / repeat(<?= $matrice_col; ?>, 1fr);
}
</style>
<div class="grid-salle-container">
<?php
$i = 1;
while ($i <= $sum) { ?>
<div class="student-container" id="place_<?= $i; ?>">
<div class="name-container">
<h1 id="student1_name"></h1>
<h1 id="student2_name"></h1>
</div>
<span class="waiting_count"></span>
<span class="statut"></span>
</div>
<?php
$i++;
} ?>
</div>
</div>
<div class="side-container">
</div>
<div class="sort_window" onclick="SortSettings()">
<div class="param">
<div class="priority-container">
<label class="custom-radio"><input type="radio" name="prio_by" value="waiting_time" checked>Temps d'attente</label>
<label class="custom-radio"><input type="radio" name="prio_by" value="waiting_time_desc" checked>Temps d'attente DESC</label>
<label class="custom-radio"><input type="radio" name="prio_by" value="asking">Demande d'aide DESC</label>
<label class="custom-radio"><input type="radio" name="prio_by" value="type_va">Type de demande (prio Validation)</label>
<label class="custom-radio"><input type="radio" name="prio_by" value="type_av">Type de demande (prio Assistance)</label>
</div>
</div>
<span class="sort_icon">
<i class="fa-solid fa-filter"></i>
</span>
<span class="close_window">
<i class="fa-solid fa-xmark"></i>
</span>
</div>
<script type="text/javascript">
let code = "<?= strval($tpcode); ?>";
function getData(){
$.ajax({
type: 'POST',
url:'assets/php/projection/retrieve_students.php',
data: "tpcode="+code,
success: function(response){
var result = jQuery.parseJSON(response);
result.students.forEach((item, i) => {
writeData(item);
});
}
});
var prio_by = $("input[name='prio_by']:checked").val();
$.ajax({
type: 'POST',
url:'assets/php/projection/getInfo.php',
data: "tpcode="+code+"&prio_by="+prio_by,
success: function(response){
var result = jQuery.parseJSON(response);
var nextPlace = result.nextPlace;
var nbPeopleWaiting = result.nbPeopleWaiting;
var arrayPeopleUnderAssist = result.underAssist;
$("div.student-container").css('background', 'unset')
$("#place_"+nextPlace).css('background', '#851414');
$.each(arrayPeopleUnderAssist, function(id,val) {
$("#place_"+val).css('background', '#167527');
});
$("#nb_people_waiting").text(nbPeopleWaiting);
}
});
}
setInterval(getData, 1000);
setInterval(() => {
$("div.side-container").load("assets/page/sidecontainer.php");
}, 1000);
function writeData(array){
var name1 = array[0];
var name2 = array[1];
var place = array[2];
var datetime_start = array[3];
var statut = array[4];
$("#place_"+place).find("h1#student1_name").text(name1);
$("#place_"+place).find("h1#student2_name").text(name2);
if (datetime_start != null) {
var dateSpecifiqueStr = datetime_start;
var dateSpecifique = moment(dateSpecifiqueStr, "YYYY-MM-DD HH:mm:ss");
var dateActuelle = moment();
var differenceEnSecondes = dateActuelle.diff(dateSpecifique, 'seconds');
var minutes = Math.floor(differenceEnSecondes / 60);
var seconds = differenceEnSecondes % 60;
}
if (statut != null) {
$("#place_"+place).find("span.statut").css('display', 'block');
if (statut == 1) {
$("#place_"+place).find("span.statut").html('<i class="fa-solid fa-hand"></i>');
} else if (statut == 2) {
$("#place_"+place).find("span.statut").html('<i class="fa-solid fa-circle-check"></i>');
} else {
$("#place_"+place).find("span.statut").css('display', 'none');
}
} else {
$("#place_"+place).find("span.statut").css('display', 'none');
}
if (datetime_start != null) {
$("#place_"+place).find("span.waiting_count").css('display', 'block');
$("#place_"+place).find("span.waiting_count").text(minutes.toString().padStart(2, '0') + ":" + seconds.toString().padStart(2, '0'));
} else {
$("#place_"+place).find("span.waiting_count").css('display', 'none');
}
}
function SortSettings(){
if ($("div.sort_window").hasClass('open')) {
$("div.sort_window").removeClass('open');
$("div.param").css('display', 'none');
$("span.sort_icon").css('display', 'block');
$("span.close_window").css('display', 'none');
} else {
$("div.sort_window").addClass('open');
$("div.param").css('display', 'block');
$("span.sort_icon").css('display', 'none');
$("span.close_window").css('display', 'block');
}
}
</script>
</main>
</body>
</html>
Java Server (3 .class)
Java___________________________________________
++---------------------------------------++
|| Server ||
|| * main file ||
++---------------------------------------++
import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import java.io.StringReader;
import java.lang.reflect.Array;
import java.net.Socket;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Hashtable;
public class Serveur {
public static void main(String[] args) {
String CODE = "";
int port = 8060;
String ipAddress = "0.0.0.0";
String code_retrieved = null;
Paho PAHOinstance = new Paho();
HTTPGET HTTPinstance = new HTTPGET();
try {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Serveur en attente de connexions sur l'adresse IP : " + ipAddress + " et le port : " + port);
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("Nouvelle connexion cliente reçue depuis : " + clientSocket.getInetAddress().getHostAddress());
Hashtable tableau = handleClientData(clientSocket);
System.out.println(tableau.get("compteur") + " [" + tableau.get("button_01") + ", " + tableau.get("button_02") + ", " + tableau.get("button_03") + "]");
System.out.println("code: " + tableau.get("code"));
System.out.println("compteur: " + tableau.get("compteur"));
int[] buttons = {(int) tableau.get("button_01"), (int) tableau.get("button_02"), (int) tableau.get("button_03")};
switch (Arrays.toString(buttons)) {
case "[1, 0, 0]":
System.out.println("button_01");
HTTPinstance.updateBTN(CODE, "button_01");
break;
case "[0, 1, 0]":
System.out.println("button_02");
HTTPinstance.updateBTN(CODE, "button_02");
break;
case"[0, 0, 1]":
System.out.println("button_03");
HTTPinstance.updateBTN(CODE, "button_03");
break;
case"[0, 0, 0]":
System.out.println("reset");
HTTPinstance.updateBTN(CODE, "reset");
break;
case "[5, 5, 5]":
System.out.println("initialisation - CODE: " + code_retrieved);
if (code_retrieved == null){
code_retrieved = HTTPinstance.GetNewCODE("api.php", "target=code" ,"code");
}
if (code_retrieved != null){
PAHOinstance.SendData(code_retrieved, "################");
CODE = code_retrieved;
System.out.println(code_retrieved);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static Hashtable handleClientData(Socket clientSocket) {
try {
InputStream inputStream = clientSocket.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead;
StringBuilder receivedData = new StringBuilder();
while ((bytesRead = inputStream.read(buffer)) != -1) {
receivedData.append(new String(buffer, 0, bytesRead, "UTF-8"));
}
int startIndex = receivedData.indexOf("{");
int endIndex = receivedData.lastIndexOf("}");
String json = receivedData.substring(startIndex, endIndex + 1);
JsonParser parser = new JsonParser();
Gson gson = new GsonBuilder().setLenient().create();
JsonReader reader = new JsonReader(new StringReader(json));
reader.setLenient(true);
JsonObject jsonObject = parser.parse(reader).getAsJsonObject();
String decodedPayloadString = jsonObject.getAsJsonObject("uplink_message").getAsJsonObject("decoded_payload").toString();
JsonObject decodedPayload = gson.fromJson(decodedPayloadString, JsonObject.class);
int compteur = decodedPayload.get("compteur").getAsInt();
int button_01 = decodedPayload.get("button_01").getAsInt();
int button_02 = decodedPayload.get("button_02").getAsInt();
int button_03 = decodedPayload.get("button_03").getAsInt();
int code = decodedPayload.get("code").getAsInt();
Hashtable tableau = new Hashtable();
tableau.put("compteur", compteur);
tableau.put("button_01", button_01);
tableau.put("button_02", button_02);
tableau.put("button_03", button_03);
tableau.put("code", code);
return tableau;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
___________________________________________
++---------------------------------------++
|| PAHO ||
|| * MQTT Library for TTN ||
++---------------------------------------++
import org.eclipse.paho.client.mqttv3.*;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
public class Paho implements MqttCallback {
MqttClient client;
public Paho() {
}
public void SendData(String data, String eui) {
try {
String username = "proj-gest-salle-tp@ttn";
String password = "######################";
String serverurl = "tcp://eu1.cloud.thethings.network:1883";
String clientId = MqttClient.generateClientId();
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setUserName(username);
options.setPassword(password.toCharArray());
client = new MqttClient(serverurl, clientId, null);
client.connect(options);
client.setCallback(this);
String topic = "v3/proj-gest-salle-tp@ttn/devices/eui-" + eui + "/down/push";
List sList = new ArrayList();
JSONObject jsonmsg = new JSONObject();
JSONObject jdownlinks = new JSONObject();
jdownlinks.put("f_port", 1);
jdownlinks.put("frm_payload", Base64.getEncoder().encodeToString(data.getBytes()));
jdownlinks.put("priority", "NORMAL");
sList.add(jdownlinks);
jsonmsg.put("downlinks",sList);
System.out.print("sendDownlink ");
System.out.println(jsonmsg);
client.publish(topic, jsonmsg.toString().getBytes("utf-8"), 0, false);
} catch (MqttException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
@Override
public void connectionLost(Throwable cause) {
// TODO Auto-generated method stub
}
@Override
public void messageArrived(String topic, MqttMessage message)
throws Exception {
System.out.println(message);
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
// TODO Auto-generated method stub
}
}
___________________________________________
++---------------------------------------++
|| HTTPGET ||
|| * for web request ||
++---------------------------------------++
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONObject;
public class HTTPGET {
public String GetNewCODE(String webpage, String param, String nodeKey) {
JSONObject json = GetJSON_from("http://localhost/" + webpage + "?" + param);
String code = json.getString(nodeKey);
System.out.println(code);
return code;
}
private static JSONObject GetJSON_from(String url) {
try {
URL url_add = new URL(url);
HttpURLConnection connection = (HttpURLConnection) url_add.openConnection();
connection.setRequestMethod("GET");
JSONObject json = null;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
json = new JSONObject(response.toString());
}
connection.disconnect();
return json;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void updateBTN(String code, String button_pushed) throws IOException {
URL obj = new URL("http://localhost/api.php?target=updateBTN&code=" + code + "&button=" + button_pushed);
System.out.println("http://localhost/api.php?target=updateBTN&code=" + code + "&button=" + button_pushed);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
int responseCode = con.getResponseCode();
System.out.println("GET Response Code :: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) { // success
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
System.out.println(response.toString());
} else {
System.out.println("GET request did not work.");
}
}
}
Comments
Please log in or sign up to comment.