Documente Academic
Documente Profesional
Documente Cultură
Lucrare de licență
Control de tip multi user pentru echipamente convenționale
folosind tehnici de tip remote
autorul lucrării
Control de tip multi user pentru echipamente convenționale folosind tehnici
de tip remote
1. Introducere
1.1. Context
1.2. Prezentarea pe scurt a aplicației
1.3. Descrierea capitolelor
2. Resurse software
2.1. Limbajul de programare JAVA
2.1.1. Noțiuni generale
2.1.2. Programare în rețea
2.1.3. Socket-uri
2.1.4.Threads
2.1.5. Swing
2.2. Intellij IDEA
3. Arhitectura aplicației
3.1. Module componente
3.2. Mod de funcționare
3.3. Modalități de dezvoltare
4. Concluzii
5. Bibliografie
6. Anexe
1. Introducere
1.1. Context
La nivel mondial se poate observa tendința de a automatiza majoritatea proceselor ce implică un
cadru de muncă monoton și activități repetitive. Pentru a crește eficiența, pentru a evita apariția
defectelor produse de om, dar și pentru a diminua cheltuielile dintr-o companie, prin micșorarea
numărului de angajați, se construiesc diferiți algoritmi ce imită anumite tipare, cu ajutorul cărora
să se înlocuiască o parte dintre meserii. [1]
Acest lucru nu este întotdeauna posibil, de aceea regăsim și astăzi unele locuri de muncă ce nu
pot fi înlocuite în totalitate de mașini, în schimb, pentru a ușura munca operatorilor ce trebuie să
administreze aparatura, se folosesc diferite aplicații ce permit controlul de la distanță a acestora.
Când vine vorba de aplicații, putem observa cum programatorii crează interfețe cât mai inedite
cu ajutorul cărora un utilizator poate controla cu ușurință anumiți parametri, fără a depune efort
sau fără să îi fie necesare cunoștințe avansate în prealabil.
Mare parte dintre aceste aplicații folosesc tehnologia client/server, ce prezintă posibilitatea de a
controla de la distanță, utilizatorul trimițând către “server” solicitarea de a se folosi de anumiți
parametri, urmând ca acesta să aștepte să primească confirmarea.
Diferite sisteme implementează rețele întregi de echipamente ce comunică între ele și pot fi
setate dintr-un singur computer, pentru a eficientiza modul în care sunt utilizate resursele, cât
și pentru fi mai ușor de urmărit și de asigurat mentenanța acestora.
În aplicația pe care urmează să o prezint, vom simula un sistem specific dispozitivelor de tip
HVAC (Heating, ventilation, and air conditioning), mai exact, un utilizator poate să aleagă o
anumită temperatură, umiditate, sau de ce nu, luminozitate, pentru a fi sigur că are parte de
condițiile optime de muncă
HVAC este o parte importantă a structurilor rezidențiale, cum ar fi casele unifamiliale, clădirile
de apartamente, hotelurile, clădirile industriale și de birouri de dimensiuni mari până la zgârie-
nori și spitale, vehicule precum mașini, trenuri, avioane, nave și submarine și în medii marine,
unde condițiile de construcție sigure și sănătoase sunt reglementate în ceea ce privește
temperatura și umiditatea, folosind aer proaspăt din aer liber.
Ventilarea sau ventilația este procesul de schimb sau de înlocuire a aerului în orice spațiu pentru
a oferi o calitate ridicată a aerului interior, care implică controlul temperaturii, reumplerea
oxigenului și eliminarea umidității, mirosurilor, fumului, căldurii, prafului, bacteriilor aeriene,
dioxid de carbon și alte gaze. Ventilarea elimină mirosurile neplăcute și umiditatea excesivă,
introduce aer exterior, menține circulația aerului din interior și previne stagnarea acestuia.
Deși HVAC este executat în clădiri individuale sau în alte spații închise, echipamentul implicat
este, în unele cazuri, o extindere a unei rețele de dispozitive. În astfel de cazuri, aspectele de
operare și întreținere sunt simplificate, iar contorizarea devine necesară pentru a factura energia
consumată și, în unele cazuri, energia care este returnată sistemului mai mare. De exemplu, la un
moment dat, o clădire poate utiliza apă rece pentru aer condiționat, iar apa caldă pe care o
returnează poate fi utilizată într-o altă clădire pentru încălzire.
Utilizarea HVAC pe o rețea mai mare ajută la asigurarea unei economii de scară care nu este
adesea posibilă pentru clădirile individuale, pentru utilizarea surselor de energie regenerabilă,
cum ar fi căldura solară, frigul de iarnă, potențialul de răcire în unele locuri de lacuri sau apă de
mare pentru răcire gratuită și funcția de activare a stocării sezoniere a energiei termice. [2]
Am ales să vorbesc despre acest topic deoarece reprezintă un domeniu de interes, iar după cum
voi prezenta și în capitolele următoare, sunt de părere că rețelele de comunicare între
dispozitive vor deveni tot mai avansate în anii ce vor urma, iar cunoștințele în ceea ce privește
acest domeniu vor fi indispensabile unui inginer.
Aplicația pe care o voi prezenta pe parcursul acestei lucrări descrie modul de funcționare al
unui sistem ce asigură un mediu plăcut într-o clădire, permițându-le utilizatorilor să seteze
anumiți parametri cum ar fi temperatura sau umiditatea, pentru a-și crea condiții optime de
lucru.
Am folosit această tehnologie gândindu-mă că, într-o clădire precum sunt cele de birouri, există
un departament ce se ocupă de facilitățile de care au nevoie angajații. Având în vedere că spre
exemplu, într-un etaj pot să lucreze mai mulți oameni în funcție de departamentul în care
activează, sau, există anumite aparate ce au nevoie să fie întreținute în anumite condiții, vor
avea nevoie de altă temperatura, sau mai bine zis, de alți parametri care să le producă un
mediu plăcut.
Această aplicație simulează această activitate prin faptul că redă comunicarea în rețea a
dispozitivelor de aer condiționat, ce sunt conectate la un server ce se asigură că acestea sunt în
uz în momentul în care în clădire se lucrează.
Aplicația este formată din două module, ChatServer și ChatUser, fiecare fiind compusă din trei,
respectiv șase clase. ChatServer l-am denumit în cadrul proiectului “localhost” și comunică cu
ceilalți clienți prin portul 8818. ChatUser pentru a se conecta la server, are impusă condiția de a
se folosi de un nume de utilizator și o parolă, ambele fiind prestabilite.
Am creat o interfață cu ajutorul Java Swing, care să arate câte dispozitive sunt conectate la
server, deși, pentru a simula comunicarea cu un client, la început am folosit comanda “telnet”
în Command Prompt.
Un utilizator va trimite solicitarea către server, iar iar în același timp, ceilalți clienți conectați vor
fi capabili să vadă solicitarea nou creată.
Atât despre tehnologiile folosite, cât și despre componentele aplicației voi dezvolta în capitolele
ce urmează.
Capitolul 2. În acest capitol am prezentat resursele software ce mi-au fost necesare în realizarea
acestei lucrări. Am prezentat limbajul de programare JAVA și descris pe scurt conceptele de
care m-am folosit în realizarea aplicației . Am prezentat mediul de dezvoltare Intellij IDEA pe
care l-am folosit la compilare.
Capitolul 4. Sunt prezentate concluziile cu care am rămas după întocmirea acestei lucrări. Am
prezentat pe scurt și modul în care voi continua să dezvolt aplicația.
2. Tehnologii folosite
Limbajul de programare Java a fost folosit la dezvoltarea unor tehnologii dedicate rezolvării
unor probleme din cele mai diverse domenii. Aceste tehnologii au fost grupate în așa numitele
platforme de lucru, ce reprezintă seturi de librării scrise în limbajul Java, precum și diverse
programe utilitare, folosite pentru dezvoltarea de aplicații sau componente destinate unei
anume categorii de utilizatori.
Clasele din acest pachet oferă o modalitate facilă de programare în rețea, fără a fi nevoie de
cunoștințe prealabile referitoare la comunicarea efectivă între calculatoare. Cu toate acestea, sunt
necesare câteva noțiuni fundamentale referitoare la rețele cum ar fi: protocol, adresa IP, port,
socket.
- TCP (Transport Control Protocol) este un protocol ce furnizează un flux sigur de date între
două calculatoare aflate în rețea. Acest protocol asigură stabilirea unei conexiuni permanente
între cele două calculatoare pe parcursul comunicației.
- UDP (User Datagram Protocol) este un protocol bazat pe pachete independente de date, numite
datagrame, trimise de la un calculator către altul fără a se garanta în vreun fel ajungerea acestora
la destinație sau ordinea în care acestea ajung. Acest protocol nu stabilește o conexiune
permanentă între cele două calculatoare.
2.1.3. Socket-uri
Un socket (soclu) este o abstracțiune software folosită pentru a reprezenta fiecare din cele două
”capete” ale unei conexiuni între două procese ce rulează într-o rețea. Fiecare socket este atașat
unui port astfel încât să poată identifica unic programul căruia îi sunt destinate datele.
Programele de tip server sunt cele care oferă diverse servicii eventualilor clienți, fiind în stare de
așteptare atâta vreme cât niciun client nu le solicită serviciile. Programele de tip client sunt cele
care inițiază conversația cu un server, solicitând un anumit serviciu. Uzual, un server trebuie să
fie capabil să trateze mai mulți clienți simultan ¸și, din acest motiv, fiecare cerere adresată
serverului va fi tratată într-un fir de execuție separat.
Legătura între un client și un server se realizează prin intermediul a două obiecte de tip Socket,
câte unul pentru fiecare capăt al ”canalului” de comunicație dintre cei doi. La nivelul clientului
crearea socketului se realizează specificând adresa IP a serverului și portul la care rulează
acesta, constructorul uzual folosit fiind:
La nivelul serverului, acesta trebuie să creeze întâi un obiect de tip ServerSocket. Acest tip de
socket nu asigură comunicarea efectivă cu clienții ci este responsabil cu ”ascultarea” rețelei și
crearea unor obiecte de tip Socket pentru fiecare cerere apărută, prin intermediul căruia va fi
realizată legătura cu clientul. Crearea unui obiect de tip ServerSocket se face specificând portul
la care rulează serverul, constructorul folosit fiind:
ServerSocket(int port)
Metoda clasei ServerSocket care așteaptă ”ascultă” rețeaua este accept. Această blochează
procesul părinte până la apariția unui cereri și returnează un nou obiect de tip Socket ce va
asigura comunicarea cu clientul. Blocarea poate să nu fie permanentă ci doar pentru o anumită
perioada de timp - aceasta va fi specificată prin metoda setSoTimeout, cu argumentul dat în
milisecunde.
Pentru fiecare din cele două socket-uri deschise pot fi create apoi două fluxuri pe octeți pentru
citirea, respectiv scrierea datelor. Acest lucru se realizează prin intermediul metodelor
getInputStream, respectiv getOutputStream. Fluxurile obținute vor fi folosite împreună cu
fluxuri de procesare care să asigure o comunicare facilă între cele două procese. În funcție de
specificul aplicației acestea pot fi perechile:
2.1.4. Threads
Firele de execuție fac trecerea de la programarea secvențială la programarea concurentă. Un
program secvențial reprezintă modelul clasic de program: are un început, o secvență de
execuție a instrucțiunilor sale și un sfârșit. Cu alte cuvinte, la un moment dat programul are un
singur punct de execuție. Un program aflat în execuție se numește proces. Un sistem de
operare monotasking, cum ar fi fi MS-DOS, nu este capabil să execute decât un singur proces la
un moment dat, în timp ce un sistem de operare multitasking, cum ar fi UNIX sau Windows,
poate rula oricâte procese în același timp (concurent), folosind diverse strategii de alocare a
procesorului fiecăruia dintre acestea.
Un fir de execuție este similar unui proces secvențial, în sensul că are un început, o secvență de
execuție și un sfârșit. Diferența dintre un fir de execuție și un proces constă în faptul că un fir de
execuție nu poate rula independent ci trebuie să ruleze în cadrul unui proces.
Ca orice alt obiect Java, un fir de execuție este o instanță a unei clase. Firele de execuție definite
de o clasă vor avea același cod și, prin urmare, aceeași secvență de instrucțiuni. Crearea unei
clase care să definească fire de execuție poate fi făcută prin două modalități:
super(nume);
...
Prima metodă a clasei este constructorul, care primește ca argument un șir ce va reprezenta
numele firului de execuție. În cazul în care nu vrem să dăm nume firelor pe care le creăm,
atunci putem renunța la supradefinirea acestui constructor și să folosim constructorul implicit,
fără argumente, care creează un fir de execuție fără niciun nume. Ulterior, acesta poate primi
un nume cu metodă setName. Evident, se pot defini și alți constructori, aceștia fiind utili atunci
când vrem să trimitem diverși parametri de inițializare firului nostru. A doua metodă este
metoda run, ”inima” oricărui fir de execuție, în care scriem efectiv codul care trebuie să se
execute.
Un fir de execuție creat nu este automat pornit, lansarea să fiind realizată de metodă start,
definită în clasa Thread.
// Lansăm în execuție
fir.start();
2.1.5. Swing
Tehnologia Swing face parte dintr-un proiect mai amplu numit JFC (Java Foundation Classes)
care pune la dispoziție o serie întreagă de facilități pentru scrierea de aplicații cu o interfață
grafică mult îmbogățită funcțional și estetic față de vechiul model AWT.
Unul din principalele obiective ale tehnologiei Swing a fost să pună la dispoziție un set de
componente GUI extensibile care să permită dezvoltarea rapidă de aplicații Java cu interfață
grafică competitivă din punct de vedere comercial. Pentru a realiza acest lucru, API-ul oferit de
Swing este deosebit de complex având 17 pachete în care se găsesc sute de clase și interfețe,
cel mai important și care conține componentele de baza fiind javax.swing.[3]
- drept memorie RAM, sunt necesari minim 2 GB sau 8 GB pentru un developer Android;
IntelliJ IDEA oferă anumite caracteristici cum ar fi completarea codului prin analizarea
contextului, navigarea codului, care permite saltul la o clasă, refactorizarea codului, alinarea și
opțiunile pentru a remedia inconsecvențele prin sugestii.
Suporta sisteme de control a versiunilor precum Git, Mercurial, Perforce și SVN. Baze de date
precum Microsoft SQL Server, Oracle, PostgreSQL, SQLite și MySQL pot fi accesate direct de la
IDE în ediția Ultimate.[4]
3. Arhitectura aplicației
Proiectul este compus din două module, ChatServer, care descrie modul în care acționează
serverul, și ChatClient, cel care asigura comunicarea cu acesta.
Am atașat mai jos o captura unde sunt afișate cele două module împreună cu interfețele și
clasele din care sunt formate.
Fig. 1. Meniul ce conține cele două module și clasele asociate acestora
ChatServer este format din trei clase componente: ServerMain, ServerWorker și Server, pe când
ChatClient conține patru clase și două interfețe: ChatClient, UserListPane, LoginWindow,
MessagePane, UserStatusListener și MessageListener.
Clasa ServerMain conține metoda principală main(), în care am declarat portul, am creat un
constructor care să facă legătura cu celelalte clase din pachet și am pornit firul de execuție.
Pentru a nu o încărca, am adăugat în celelalte clase metodele prin care se realizează
comunicarea cu utilizatorii conectați la server. Am atașat mai jos codul acesteia.
package main.java.com.muc;
Clasele ServerWorker și Server conțin cele mai importante metode deoarece acestea fac
legătura cu utilizatorii.
}
}
clientSocket.close();
}
În realizarea aplicației am avut nevoie și de o librărie de la Apache, apache commons lang 3.9,
cu ajutorul căreia am putut folosi comanda StringUtils.split, ce împarte un String, în cazul nostru
“tokens”, într-o arie de alte Stringuri.[5]
Metoda handleLogin cuprinde cele două seturi de date de autentificare, totodată fiind atașate
și condițiile necesare ca un utilizator să poată vedea statusul unui utilizator care se conectează
sau se deconectează de la server.
Clasa Server conține metoda care face legătura cu ceilalți clienți și prin care serverul așteaptă să
primească un mesaj de la utilizatori, și anume “accept()”. Am atașat mai jos secvența ce
cuprinde această metodă.
Pentru a se conecta la server, am creat metoda “connect” pe care am prezentat-o mai jos.
Prin această secvență, utilizatorul primește și trimite informații către server. În capitolul
următor voi prezenta și modul în care lucrează cu ceilalți utilizatori.
În clasa UserListPane am folosit pentru prima dată tehnologia Swing, pentru a crea o listă unde
să fie afișați toți utilizatorii conectați în acel moment la server. Sunt de părere că se mai poate
lucra la ea, și pentru a induce mai mult ideea de sistem cu dispozitive HVAC integrate, ar putea
să fie afișați toți utilizatorii ce trebuie conectați la server, împreună cu statusul în care se află,
fie online, fie offline.
Fereastra unde sunt afișați utilizatorii este prezentată prin programul afișat mai jos.
frame.getContentPane().add(userListPane, BorderLayout.CENTER);
frame.setVisible(true);
if (client.connect()) {
try {
client.login("guest", "guest");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public LoginWindow() {
super("Login");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(p, BorderLayout.CENTER);
pack();
setVisible(true);
}
package com.muc;
package com.muc;
Pentru a avea mai mult control, m-am gândit că ar fi indicat impun condiția că userii să se
conecteze printr-un set de date de autentificare prestabilite. Seturile de date introduse
momentan în aplicație sunt “guest” și “alind”, acestea fiind folosite atât pentru numele de
utilizator, cât și pentru parolă. Bineînțeles că acestea ar putea fi schimbate în “parter” și “etaj1”
în caz de vrem să facem referire la o clădire, sau de ce nu, să se impună o condiție cu ajutorul
căreia să se conecteze mai mulți utilizatori.
Pentru a afișa comunicarea dintre utilizatori, am folosit comanda “telnet” in Command Prompt.
Telnet este un protocol de rețea care oferă o interfață de linie de comandă pentru a comunica
cu un dispozitiv. Este utilizat cel mai adesea pentru gestionarea de la distanță, dar și uneori
pentru configurarea inițială pentru unele dispozitive, în special hardware-ul de rețea, cum ar fi
switch-urile și punctele de acces. Telnet este de asemenea utilizat pentru a gestiona fișierele de
pe un site web.
Fig. 2. Comanda în Command Prompt
Telnet a fost folosit inițial pe terminale. Aceste computere necesită doar o tastatură, deoarece
totul pe ecran se afișează ca text. Terminalul oferă o modalitate de a te conecta de la distanță la
un alt dispozitiv, la fel ca și cum ai fi așezat în fața lui și l-ai folosi ca orice alt computer.
În zilele noastre, Telnet poate fi utilizat de la un terminal virtual, sau un emulator de terminale,
care este în esență un computer modern care comunică cu același protocol Telnet. Un exemplu
în acest sens este comanda telnet, disponibilă de la promptul de comandă din Windows.
Comanda telnet utilizează protocolul Telnet pentru a comunica cu un dispozitiv sau sistem de la
distanță.
Comenzile Telnet pot fi executate și pe alte sisteme de operare, cum ar fi Linux, Mac și Unix, în
același mod în care sunt executate comenzi telnet în Windows.
Telnet nu este la fel ca alte protocoale TCP / IP, cum ar fi HTTP, care transferă fișierele către și
de pe un server. În schimb, protocolul Telnet vă permite să vă conectați la un server ca și cum
ați fi un utilizator efectiv, apoi vă acordă controlul direct și toate aceleași drepturi asupra
fișierelor și aplicațiilor ca și utilizatorul la care v-ați autentificat.[6]
Totodată, serverul ne va anunța și dacă mai sunt alți utilizatori conectați, sau în caz de nu sunt
în momentul respectiv, va afișa un mesaj “online” și numele utilizatorului (care poate purta
denumirea unei săli sau poate a unui etaj, spre exemplu) în momentul în care acesta se
conectează. Atunci când se deconectează de la server, vom primi un mesaj de genul “offline” și
numele utilizatorului, pentru a fi la curent cu statusul în care se află.
Fig. 5. Status utilizator
} else {
if (sendTo.equalsIgnoreCase(worker.getLogin())) {
String outMsg = "msg " + login + " " + body + "\n";
worker.send(outMsg);
}
}
}
}
Pentru a folosi aceste metode am instantiat un HashSet, sub denumirea de topicSet. HashSet
implementează interfața Set, susținută de o instanță HashMap. Nu oferă garanții cu privire la
ordinea de iterație a setului; în special, nu garantează dacă o comandă va rămâne constantă în
timp. Această clasă permite elementul null.
Această clasă oferă performanțe de timp constante pentru operațiunile de bază (add, remove,
contain și size), presupunând că funcția de hash împrăștie elementele în mod corespunzător.
Iterarea acestui set necesită timp proporțional cu suma dimensiunii instanței HashSet (numărul
de elemente), plus "capacitatea" instanței HashMap de rezervă. [7]
În același fel, putem trimite un mesaj prin care anunțăm că modificăm umiditatea, după cum
am afișat mai jos.
Pentru a realiza aceste lucruri, nu avem nevoie de ajutorul altei clase, deoarece “telnet” ne
pune la dispoziție această interfață ce simulează clientul.
Cu toate acestea, am vrut să construiesc o clasă ce va face același lucru, iar aici intervine
modulul ChatClient.
După cum am prezentat anterior, acest modul conține trei clase ce interacționează cu serverul,
iar în continuare, voi descrie ceea ce este afișat în terminal, sau, în cazul claselor UserListPane și
LoginWindow, voi atașa capturi cu ferestrele create cu ajutorul Java Swing.
Clasa ChatClient, a fost prima clasa creată cu scopul de a comunica cu serverul. După cum am
prezentat și anterior, aceasta se folosește de setul de date “guest” pentru a se conecta la
server. În momentul în care o rulăm, în terminal va fi afișată următoarea secvență:
Fig. 9. Clasa ChatClient în terminal
În cadrul acestei clase, utilizatorul poate să primească și mesaje după o anumită structură.
Pentru a fi realizabil acest lucru, am folosit interfața MessageListener pe care am creat-o și pe
care am prezentat-o anterior. Metoda de care m-am folosit, am atașat-o dedesubt.
client.addMessageListener(new MessageListener() {
@Override
public void onMessage(String fromLogin, String msgBody) {
System.out.println("You got a message from: " + fromLogin + " ==> " + msgBody);
}
});
După cum se poate vedea mai jos, în momentul în care am trimis un mesaj utilizatorului cu setul
de date “guest”, acesta a apărut și în terminal, împreună cu numele utilizatorului de la care
provine.
Totodată, un utilizator se conectează utilizând setul de date “guest”, iar dacă nu am mai rulat
nicio altă clasa și ceilalți utilizatori sunt deconectați, pe ecran va apărea fereastra de mai jos,
fără să conțină vreun nume afișat. Aici ar trebui să adaug anumite modificări, deoarece un
utilizator nu poate să se vadă pe el în acea listă, lucru care nu se întâmplă într-o rețea de
dispozitive HVAC.
Pe lângă asta, ar putea fi introduse toate dispozitivele ce sunt sau care ar trebui conectate la
server, împreună cu statusul în care se află, fie online, fie offline.
Fig. 12. Fereastra aparuta dupa rularea clasei UserListPane
Diferența cu care vine în plus clasa LoginWindow este că, atunci când o rulăm, va apărea
următoarea fereastră unde va trebui să introducem datele de autentificare:
Fig. 13. Interfața unde se pot introduce datele de logare
În captura de mai jos vedem un utilizator conectat deoarece am folosit în prealabil setul de date
“alind” prin telnet, iar acum, introducând setul de date “guest”, am regăsit celălalt utilizator
conectat la server.
Fig. 14. Interfața unde sunt afișați ceilalți utilizatori
Așadar, acum că am parcurs toate clasele ce fac parte din modulul ChatClient, putem spune că
am risipit toate metodele create, care să producă o legătură între server și utilizatori.
Aplicația în sine poate fi dezvoltată prin asocierea cu o baza de date care să salveze aceste
informații, cât și prin implementarea unor metode de a crea anumite rapoarte unde să se afle
temperatura medie într-o zi, poate să se facă o comparație între anotimpuri (spre exemplu:
comparația între vară și iarnă), astfel să se tragă anumite concluzii și să se caute metode prin
care să fie economisită energie.
Am putea primi informații cu privire la starea în care se află, dacă răspunde sau nu la comenzile
serverului, pentru a ști dacă un dispozitiv se află în stare de bună funcționare.
Pentru a îmbunătăți aplicația ar putea fi setate anumite condiții în cod cum ar fi, în caz că se
depășește o anumită valoare, severul să nu accepte (spre exemplu: să nu fie de acord să fie
setată o temperatura de peste 30 de grade, dacă în acea încăpere lucrează oameni), atunci
când userul se conectează la server, să fie întrebat căror parametri dorește să le schimbe
valoarea.
Acestea reprezintă doar câteva modalități prin care mă gândesc că aplicația ar putea fi
îmbunătățită, și totodată, prin aceste modificări ar putea induce și mai mult ideea de sistem ce
simulează comunicarea între un server și dispozitive de tip HVAC. Acesta e și scopul meu pe
viitor, să dezvolt și mai mult acest proiect pentru a-l face cât mai compact și totodată, să-mi
îmbogățesc cunoștințele pe care le-am dobândit în timp ce l-am realizat.
Această aplicație reprezintă doar o simulare, însă acest este deja dezvoltat cu succes cu ajutorul
unor tehnologii pe care le-am prezentat în mare mai jos. Cu ajutorul lor au fost create rețele de
dispozitive ce comunică și distribuie informații către server.
JACE (Java Application Control Engine) – Pentru a integra sisteme diverse, este necesară o
conexiune fizică la rețeaua unui dispozitiv. Un JACE este un mecanism / dispozitiv care asigură
conectivitate la sisteme (HVAC, electric, chiar și securitate în unele cazuri) în cadrul unei mașini
cu ajutorul Niagara Framework, care permite driverelor să integreze sisteme de control pentru
o gama mare de producători. Prin conectarea protocoalelor de rețea comune, cum ar fi
LonWorks, BACnet și Modbus, împreună cu multe rețele proprii, apare un sistem compact. Un
JACE poate găzdui, de asemenea, interfața utilizatorului cu sistemul de control în multe cazuri.
BACnet (Building Automation and Control networks) – a fost realizat pentru a permite
comunicarea construcțiilor automate și a sistemelor de control pentru aplicații precum
încălzirea, ventilarea, și controlul aerului condiționat (HVAC), controlul iluminatului, controlul
accesului și în cazul sistemelor de detectare a incendiilor și echipamentele asociate acestora.
Protocolul BACnet oferă mecanisme pentru dispozitivele automatizate să facă schimb de
informații, indiferent de serviciul pe care îl oferă.[9]
Am atașat o schemă ce prezintă în mare modul în care funcționează un sistem ce are JACE
integrat:
Proiectul acesta m-a ajutat să-mi îmbogățesc cunoștințele de Java și totodată, prin realizarea
acestei aplicații m-am familiarizat cu acest concept, aplicațiile de tip client/server. Suntem în
secolul vitezei, iar căile de comunicare se doresc a fi cât mai rapide și bine întreținute pentru a
putea distribui eficient informația. Comunicarea dintre un server și dispozitivele asociate
ușurează modul de operare al acestora, plus că ajută și la monitorizare, deoarece dacă un
dispozitiv nu apare în sistem, lipsa acestuia este sesizată, așa că este mai simplu de asigurat și
mentenanța acestora.
Cu toate că aplicația reușește să simuleze modul în care comunică dispozitivele de tip HVAC cu
un server, sunt de părere că poate fi mult îmbunătățită. După cum am prezentat mai sus, pe
lângă asocierea cu o baza de date unde să fie stocate anumite informații, sunt anumite condiții
ce ar putea fi adăugate în cod pentru a crea anumite limitări în ceea ce privește gama de
parametri ce urmează a fi setați. Aplicația are momentan destul de multe bug-uri ce pot fi
înlăturate, în schimb pentru a fi cât mai compactă, mai trebuie dezvoltată.
Acesta reprezintă și scopul meu în momentul de față, pentru a-mi finaliza lucrarea, sunt
conștient că are nevoie de mai multe îmbunătățiri și de aceea îmi propun ca pe viitor să
implementez schimbările pe care le-am menționat, și poate să mă folosesc și de anumite
metode mai eficiente, pentru a nu încarcă foarte mult proiectul. Îmi propun să creez și o
interfață ceva mai prietenoasă și care să-mi permită interacționez mai mult cu serverul.
După cum am prezentat și mai sus, tehnologia această este implementată în diverse aplicații, cu
ajutorul dispozitivelor de tip Java Application Control Engine (JACE), așa că scopul meu ar putea
fi să achizitionez un astfel de dispozitiv, pentru a mă familiariza mai mult cu acest domeniu.
Având în vedere tendința din ultimii ani, putem trage concluzia că o tehnologie similară va fi
implementată și pentru controlul automobilelor autonome/infrastructura necesară utilizării
unor astfel de mașini, deoarece tendința este ca pe viitor, un server să dețină informații cât și să
seteze viteza autoturismelor ce nu vor avea nevoie de șofer. [10]
Indiferent de cum vor evolua lucrurile, subiectul acestei lucrări, sau mai ales, tehnologia folosită
în conceperea acestei aplicații, client/server, va fi mereu de interes în societatea actuală.
5. Bibliografie
[1] Alex Ciutacu, “Robotii vor lasa oamenii fara locuri de munca” https://www.zf.ro/business-
international/robotii-vor-lasa-800-de-milioane-de-oameni-fara-loc-de-munca-pana-in-2030-iar-
problema-va-fi-mai-grava-in-cadrul-tarilor-bogate-care-sunt-primele-meserii-care-vor-fi-
afectate-16842078
ServerMain
package main.java.com.muc;
server.start();
ServerWorker
package main.java.com.muc;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.net.Socket;
import java.sql.SQLOutput;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
this.server = server;
this.clientSocket = clientSocket;
@Override
try {
handleClientSocket();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
this.outputStream = clientSocket.getOutputStream();
String line;
if ("logoff".equals(cmd) || "quit".equalsIgnoreCase(cmd)) {
handleLogoff();
break;
} else if ("login".equalsIgnoreCase(cmd)) {
handleLogin(outputStream, tokens);
} else if ("msg".equalsIgnoreCase(cmd)) {
handleMessage(tokensMsg);
} else if ("join".equalsIgnoreCase(cmd)) {
handleJoin(tokens);
} else if ("leave".equalsIgnoreCase(cmd)) {
handleLeave(tokens);
} else {
outputStream.write(msg.getBytes());
clientSocket.close();
if (tokens.length > 1) {
return topicSet.contains(topic);
if (tokens.length > 1) {
topicSet.add(topic);
if (isTopic) {
if (worker.isMemberOfTopic(sendTo)) {
String outMsg = "msg " + sendTo + ": " + login + ": " + body + "\n";
worker.send(outMsg);
} else {
if (sendTo.equalsIgnoreCase(worker.getLogin())) {
worker.send(outMsg);
server.removeWorker(this);
if (!login.equals(worker.getLogin())) {
worker.send(onlineMsg);
clientSocket.close();
return login;
if (tokens.length == 3) {
this.login = login;
if (worker.getLogin() != null) {
if (!login.equals(worker.getLogin())) {
send(msg2);
if (!login.equals(worker.getLogin())) {
worker.send(onlineMsg);
}
} else {
outputStream.write(msg.getBytes());
if (login != null) {
outputStream.write(msg.getBytes());
Server
package main.java.com.muc;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
this.serverPort = serverPort;
return workerList;
@Override
try {
ServerSocket serverSocket = new ServerSocket(serverPort);
while (true) {
workerList.add(worker);
worker.start();
} catch (IOException e) {
e.printStackTrace();
workerList.remove(serverWorker);
ChatClient:
ChatClient
package com.muc;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
this.serverName = serverName;
this.serverPort = serverPort;
}
client.addUserStatusListener(new UserStatusListener() {
@Override
@Override
});
client.addMessageListener(new MessageListener() {
@Override
System.out.println("You got a message from: " + fromLogin + " ==> " + msgBody);
}
});
if (!client.connect()) {
System.err.println("Connect failed!");
} else {
System.out.println("Connect successful!");
if (client.login("guest", "guest")) {
System.out.println("Login successful");
} else {
System.err.println("Login failed");
//client.logoff();
serverOut.write(cmd.getBytes());
if ("ok login".equalsIgnoreCase(response)) {
startMessageReader();
return true;
} else {
return false;
serverOut.write(cmd.getBytes());
}
private void startMessageReader() {
@Override
readMessageLoop();
};
t.start();
try {
String line;
if ("online".equalsIgnoreCase(cmd)) {
handleOnline(tokens);
} else if ("offline".equalsIgnoreCase(cmd)) {
handleOffline(tokens);
} else if ("msg".equalsIgnoreCase(cmd)) {
handleMessage(tokensMsg);
ex.printStackTrace();
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
listener.offline(login);
listener.online(login);
try {
this.serverIn = socket.getInputStream();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
userStatusListeners.add(listener);
userStatusListeners.remove(listener);
messageListeners.add(listener);
}
public void removeMessageListener(MessageListener listener) {
messageListeners.remove(listener);
UserListPane
package com.muc;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
this.client = client;
this.client.addUserStatusListener(this);
setLayout(new BorderLayout());
userListUI.addMouseListener(new MouseAdapter() {
@Override
if (e.getClickCount() > 1) {
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setSize(500,500);
f.getContentPane().add(messagePane, BorderLayout.CENTER);
f.setVisible(true);
}
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 600);
frame.getContentPane().add(userListPane, BorderLayout.CENTER);
frame.setVisible(true);
if (client.connect()) {
try {
client.login("guest", "guest");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
userListModel.addElement(login);
@Override
userListModel.removeElement(login);
MessageListener
package com.muc;
}
UserStatusListener
package com.muc;
MessagePane
package com.muc;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
this.client = client;
this.login = login;
client.addMessageListener(this);
setLayout(new BorderLayout());
add(inputField, BorderLayout.SOUTH);
inputField.addActionListener(new ActionListener() {
@Override
try {
client.msg(login, text);
ex.printStackTrace();
});
@Override
if (login.equalsIgnoreCase(fromLogin)) {
listModel.addElement(line);
LoginWindow
package com.muc;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
public LoginWindow() {
super("Login");
client.connect();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p.add(loginField);
p.add(passwordField);
p.add(loginButton);
loginButton.addActionListener(new ActionListener() {
@Override
doLogin();
});
getContentPane().add(p, BorderLayout.CENTER);
pack();
setVisible(true);
if (client.login(login, password)) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 600);
frame.getContentPane().add(userListPane, BorderLayout.CENTER);
frame.setVisible(true);
setVisible(false);
} else {
} catch (IOException e) {
e.printStackTrace();
}
public static void main(String[] args) {
loginWin.setVisible(true);