Protocolul Nmea
Introducere
Gestiunea flotelor
Gestiunea flotei sau managementul flotei reprezintă activitatea de administrare a flotei de transport a unei companii. În componența flotei unei companii sau a unei organizații sunt incluse vehicule cu motor cum ar fi autovehicule, avioane, elicoptere, nave, camioane. Istoria acestei activități începe acum trei decenii, în anii 1980, când au apărut calculatoarele la bordul vehiculelor care erau conectate la sateliți sau la rețele terestre. În zilele de astăzi rețele mobile oferă conexiune la internet la prețuri rezonabile, având o calitate și o ergonomie crescută. Toți acești factori permit crearea aplicațiilor de management a vehiculelor în timp real, creând o legătură între vehicule și sisteme IT complexe.
Managementul flotei include o gama largă de funcții, cum ar fi administrarea aspectelor financiare a vehiculelor, mentenanță vehiculelor, urmărirea și diagnoza vehiculelor, gestionarea combustibilului, administrarea forței de muncă. Această activitate ajută companiile să reducă riscurile asociate investițiilor în vehicule, îmbunătățind productivitatea, eficiența și reducând costurile legate de personal.
Sistemele software de gestiune a flotei permit oamenilor să realizeze o serie de sarcini de management a uneia sau a mai multor aspecte ce țin de flota companiei. Aceste sarcini specifice includ toate operațiile de management, de la achiziția vehiculului până la înlăturarea lui din cadrul flotei. În funcție de capacitatea sistemului utilizat, se pot utiliza funcții de profilare a șoferului sau a vehiculului, profilarea expedițiilor, verificarea eficienței vehiculelor, urmărirea vehiculelor. De asemenea se pot returna informații de diagnosticare sau se poate realiza un control a vehiculului de la distanță. Putem spune că sistemele de management a flotei au ca scop îmbunătățirea calității și eficienții industriei prin identificarea și abordarea obstacolelor majore ce apar în cadrul operațiilor zilnice a unei întrepinderi.
Cea mai importantă componentă a sistemelor de gestiune reprezintă sistemul de urmărire în timp real a vehiculelor. Un sistem de urmărire combină utilizarea localizării automate a fiecărui vehicul în parte cu un sistem software care colectează aceste informații afișând o imagine completă a flotei. Localizarea vehiculului se bazează în cele mai multe cazuri pe tehnologia GPS, dar se mai pot folosi și tehnologii ca și GLONASS sau triangularea celulară. Odată ce locația vehiculului, direcția și viteză sunt determinate sistemul de urmărire se folosește de tehnologii de trasmitere wireless , de obicei GPRS sau 3G, pentru a trimite informațiile către un program software. In cazul in care conexiunea la rețea nu este disponibilă dispozitivul de urmărire va stoca informațiile in memoria internă si va trimite datele stocate când conexiunea va deveni din nou disponibilă.
Utilizatorii, cu ajutorul unui sistem software GIS, vor putea să vizualizeze locația fiecărui vehicul pe o hartă.
Dupa cum vedem mai sus, arhitectura de baza a unui sistem de urmărire se împarte in trei componente:
Dispozitivul GPS de urmărire care se plasează în interiorul vehicului și care înregistrează informații despre starea curentă a vehiculului pe care le trimite la intervale regulate la un server central. Informațiile înregistrate pot include poziția curentă, cantitatea de combustibil disponibilă, starea alarmelor antifurt, altitudinea, starea baterilor, starea motorului.
Serverul de urmărire care are responsabilitatea de a primi date de la componentă de urmărire, de a stoca datele primite și apoi de a deservi datele stocate către interfața grafică.
Interfața cu utilizatorul are rolul de a afișa informațiile stocate de către serverul central și de a configura serverul de urmărire și vehiculele conectate la acesta.
Activitatea de dragare
Dragarea este o activitate de excavație desfășurată, în mare parte, sub apă cu scopul adunării sedimentelor și depozitării lor în alte locații. Această tehnică este folosită foarte des pentru păstrarea canalelor navigabile sau pentru refacerea plajelor afectate de intemperii. Cele mai importante roluri pe care le îndeplinește procesul de dragare ar fi:
– păstrarea curată a canalelor de navigație.
– furnizarea materialelor de construcții.
– refacerea plajelor dezafectate.
– controlul inundațiilor prin menținerea fluxurilor de curgere a râurilor constante.
– excavarea minereurilor, metalelor prețioase.
– mentenanța canalelor de irigație.
Sedimentele extrase în procesul de dragare diferă de la proiect la proiect, dar cele mai comune tipuri de sedimente care se obțin sunt: pietre, argile, nisipuri, pietrișuri, soluri organice.
Figura 1.1 Procesul de dragare
Draga sau draglina este o nava folosită la excavarea materialului de pe fund. Este dotată cu un cadru de susținere, cu instalații de forță de săpat și ridicat material escavat. Dragele pot avea diverse instalații de săpare, cum ar fi cu bena, cu cupă, cu lingură iar ca mod de excavare pot fi drage cu pompă, drage cu refulanta și drage cu purtătoare.
Figura 1.2 Draga cu cupă
Obiective și specificația proiectului
Tema propriu-zisa
Formularea temei
Se cere dezvoltarea unui sistem informatic, care să permită monitorizarea și controlul unui număr nelimitat de vehicule mobile pe o arie geografică întinsă folosind tehnologia GSM/GPRS pentru comunicare și tehnologia GPS pentru localizare. Sistemul va trebuie să permită actulizarea locațiilor vehiculelor în timp real, stocarea locațiilor pentru o utilizare ulterioară, gestiunea flotei de vehicule și securizarea accesului la sistem.
Motivație
Spre deosebire de interprinderile mari care folosesc unele sisteme de gestiune și au lansate programe de monitorizare a vehiculelor majoritatea micilor operatori de flote folosesc metode manuale de gestiune și nu au nici un sistem de monitorizare. Sistemele de gestiune folosite de companii se rezumă la folosirea unui program de calcul tabelar sau folosirea unor produse scumpe care sunt mai greu de personalizat. Acest proiect vine cu scopul de a aduce o integrare între funcția de management (deși nu este implementată complet) și funcția de monitorizare.
Scurtă descriere
Sistemul va fi împărțit în două părți, server și client. Serverul se va ocupa de comunicarea cu dispozitivele instalate pe vehicule și va asigura achiziționarea și stocarea pozițiilor. Clientul, în schimb, va asigura configurarea acelor vehicule, gestiunea lor și vizualizarea lor pe o harta.
Serverul va asigura o comunicare securizată și consistentă cu vehiculele, din acest motiv va trebuit implementat un protocol de comunicare server-dispozitiv de monitorizare care să folosească un mod de autentificare și un mod de verificare a calității informației transmise. Sistemul de stocare a datelor care trebuie să permită o atomicitate consistentă, durabilitate și izolare a datelor, acest lucru ducând la alegerea unui sistem relațional că și Microsoft SQL Server.
Clientul se va putea instala pe un număr de n calculatoare, având cerințe minime de sistem. După procesul de autentificare aplicația client va oferi o hartă cu pozițiile curente ale vehiculelor și un meniu prin care se vor putea executa anumite operații de configurare și administrare. Adăugarea unui nou vehicul în sistem se va realiza în primul rând folosind panoul de administrare, selectând flota corespunzătoare și introducând datele specifice vehiculului iar apoi se va realiza configurarea folosind panoul de configurare. Administrarea utilizatorilor care au acces la sistem va fi făcută prin panoul de administrare de utilizatorii care au rol de administrator.
Studiu bibliografic
Descriere capitol
În acest capitol doresc să explic multitudinea tehnologiilor folosite la realizarea acestui proiect. Deoarece proiectul este la baza un sistem software voi începe cu descrierea tehnologiilor software de care m-am folosit iar pe la sfârșit voi continua cu descrierea tehnologiilor hardware pe care le-am utilizat.
Tehnologii software utilizate
3.2.1 Platforma Microsoft.Net
Microsoft .Net este o platformă software pentru dezvoltarea aplicațiilor care a revoluționat modul in care sunt create aplicațiile pentru sistemele de operare din familia Windows. Platforma pune laolaltã mai multe tehnologii (ASP, XML, OOP, SOAP,WDSL, UDDI) si limbaje de programare (VB, C++, C#, J#) asigurând totodatã atât portabilitatea codului compilat între diferite calculatoare cu sistem Windows, cât si reutilizarea codului în programe, indiferent de limbajul de programare utilizat.
Principalele sale caracteristici sunt :
-aplicațiile dezvoltate utilizând această platformă pot fi implementate intr-o varietate mare de limbaje.
-management automat al memoriei folosind mecanismul de gargabe collector.
– existența unei librării de clase cuprinzătoare care este accesibilă tuturor limbajelelor suportate de platforma .NET.
-interoperabilitate cu tehnologiile mai vechi, librăriile de tip COM putând fi foarte ușor importate in proiecte .NET.
-indepența de platformă si de procesor – există o serie de proiecte open-source care au creat posibilitatea de a rula aplicații .NET pe sisteme de operare bazate pe Unix sau MacOs.
-pot fi dezvoltate numeroare tipuri de aplicații, începând de la aplicațiile desktop, care
utilizează forme Windows, aplicații pentru dispozitive mobile, servicii Windows,
aplicații și servicii web.
Componentele principale ale platformei .NET sunt următoarele:
Common Language Runtime sau CLR este masină virtuală a platformei fiind responsabilă pentru incărcarea, localizarea si execuția programelor .NET. Componenta CLR se ocupă si de managementul memoriei, tratarea excepțiilor si de unele verificări de securitate.
Common Type System, pe scurt CTS, descriere toate tipurile de date si operațiile de bază, care se pot face cu aceste tipuri de date. Ajută la stabilirea regulilor comune prin care se crează obiecte asigurând compabilitate intre limbajele existente in .NET. Aici sunt implementate facilitățiile de boxing, unboxing, interfețe, delegări, tipuri referință, tipuri valoare.
Common Language Specification care definește un set de reguli pentru compilatoarele din cadrul platformei .NET asigurându-se că fiecare compilator va genera cod interoperabil cu toate celalalte limbaje.
Common Intermediate Language este limbajul de asamblare orientat obiect care este generat de compilatoarele platformei .NET in timpul procesul de compilare a unui program. Acest cod este transformat intr-un fișier de bytecode pentru a fi apoi procesat și executat de CLR.
Figura 3.1 Arhitectura platformei .NET
Limbajul de programare C#
Datorită familiarizării la orele de curs și laborator cu acest limbaj, faptului că limbajul C# este disponibil în platforma .NET și fiind unul dintre cele mai folosite limbaje la ora actuală am ales să folosesc acest limbaj în proiectul DredgerTracker.
C# este un limbaj de programare creat de către Anders Hejlsberg, un dezvoltator de la Microsoft care mai are în palmares crearea mediilor de dezvoltare Turbo Pascal și Delphi. Este un limbaj orientat-obiect care are sintaxa foarte asemănătoare cu cea a limbajului Java, făcând parte din familia limbajelor bazate pe C. Are o sintaxa simplă cu circa 80 de cuvinte cheie, și 12 tipuri de date predefinite. Se poate spune despre C# că este un hibrid, imprumutând multe din construcțiile sintactice de la alte limbaje. De exemplu în C# putem suprascrie operatori asemănător ca și în C++ sau putem să definim tipuri anonime, expresii lambda la fel ca și în Lisp sau Haskell.
Functionalitățile de bază ale limbajului sunt:
Nu sunt necesari pointeri ca si in C++.
Eliberarea automata a memoriei neutilizate, care este realizată de către garbage collector.
Suportă programare bazată pe atribute.
Suportă suprascrierea operatorilor.
Are construcții sintactice pentru definirea claselor, interfețelor, structurilor, enumerațiilor.
Librăria Windows Forms
Spațiul Forms, din cadrul librăriei de clase a platformei .NET, ne oferă toate funcționalitățile necesare pentru a construi interfețe grafice cu care interactioaneaza utilizatorii. Este de fapt o colecție de clase care utilizează Windows API pentru a afișa controalele grafice disponibile în sistemele de operare Windows.
Clasele din cadrul System.Windows.Forms se împart în următoarele tipuri:
Control: clasa de baza din care sunt derivate toate celelalte controale, expune metode pentru afișare și ascundere și are definite evenimente pentru interacțiunea cu mouseul.
Fereastră sau Form: Moștenește funcționalitățile de bază din clasa control și reprezintă o fereastră sau o casetă dialog.
Casete dialog de sistem: Reprezintă casetele dialog standard în Windows care sunt folosite pentru operații de baza cum ar fi: selectarea unui director, pentru a alege o culoare sau pentru a tipări un fișier. Oferă consistentă pentru toate aplicațiile.
Componente pentru afișarea și interacționarea cu informații provenite din bazele de date.
Controale standard : butoane, casete de text, casete de bifat.
Figura 3.2 Diagrama claselor care fac parte din spațiul Windows Forms
Librăria .Net Remoting
Reprezintă un API pentru comunicarea inter-proces, din cadrul platformei .NET, care face parte din seria tehnologiilor OLE, COM, DCOM. Se aseamănă cu tehnologiile CORBA și Java RMI, având o complexitate mărită dar având funcțiile de bază foarte simple. Principiul
sau de funcționare constă în trimiterea unui mesaj, de către un client, spre un server care trimite înapoi un răspuns.
Principalele scenarii în care librăria .NET Remoting este folosit sunt: cel în care se dorește separarea pe mai multe nivele a unei aplicații și în cel în care se dorește centralizarea funcțiilor de accesare a datelor pe unul sau mai multe server. Se obține astfel o mai ușoară operabilitate și mentenanță datorită faptului că schimbările legate de logică aplicației pot fi propagate mai repede și mai ușor pe un server decât pe fiecare client în parte. Deasemena se obține o securitate a datelor sporită datorită faptului că informațiile de autentificare nu sunt stocate pe mașină clientului.
Metoda de funcționare constă în crearea pe partea de client a unui obiect de tipul TransparentProxy care maschează toate metodele obiectului de pe partea de server, astfel se pot accesa toate metodele acestuia. Când o metodă este chemată, ea va fi convertită într-un mesaj care apoi va trece prin mai multe straturi de procesare. Mesajul va trece printr-un strat de serializare, care îl va transformă într-un format specific pentru comunicarea cu serveru și va fi trimis apoi unui canal de transport care va folosi un protocol de tip HTTP sau TCP pentru a trimite acest mesaj către server. Odată ajuns, mesajul va trece printr-un strat de formatare care va tranforma mesajul într-un obiect corespunzător și va execută metodă cerută iar rezultatul ei va fi trimis înapoi la client folosind același straturi de formatare și de transport.
Am ales această metodă de programare distribuită datorită necesității separării aplicației în mai multe straturi și a necesității folosirii pe mai multe stații a aplicației client și deasemena datorită ușurinței de utilizare și a procesului de învățare foarte rapid.
Figura 3.3 Arhitectura librăriei .NET Remoting
Librăria System.Net
Pentru a realiza conexiunile client-server din cadrul acestei aplicații am folosit namespace-ul System.Net, disponibil în cadrul platformei .NET. Această librărie oferă facilități pentru obținerea informațiilor despre rețea, interfața BSD în .NET, testarea conectivității, clienți și servere TCP. Sunt implementate majoritatea protocoalelor utilizate în rețele de calculatoare: IP,UDP, SMTP, TCP, HTTP etc.
La crearea serverului și a funcționalităților oferite de server am utilizat System.Net.Sockets, o colecție de clase care ne oferă socketuri TCP. Am instantiat un obiect TCPListener pentru a
ne atașa la un port pe calculatorul local iar apoi la detectarea apariției unei noi conexiuni am folosit TCPClient pentru a inițializa comunicarea cu clientul respectiv.
Figura 3.4 Arhitectura Client-Server
Bazele de date și sistemele de gestiune a bazelor de date
O bază de date reprezintă un ansamblu structurat de fișiere, care grupează datele, prelucrate în aplicații informatice, ale unei persoane, grup de persoane, interprinderi, instituții. Când vorbim despre o baza de date trebuie să avem în vedere două aspecte fundamentale , schemă și conținutul. Schema să reprezinte un ansamblu de instrumente pentru descrierea datelor, a relațiilor dintre acestea și a restricțiilor la care sunt supuse. Ansamblul informațiilor stocate în baza de date la un moment dat reprezintă conținutul. Corespunzător celor două aspecte limbajele de programare a bazelor de date se împart în limbaje de definire a datelor (Dată Definition Language) și limbaje de manipulare a datelor (Dată Manipulation Language). Limbajul cel mai utilizat la programarea bazelor de date se numește SQL și oferă atât funcționalități de declare a datelelor cât și funcționalități de interogare/manipulare.
Sistemele de gestiune a bazelor de date reprezintă un ansamblu de programe care oferă posibilitatea de a defini, de a crea, de actualiza și interoga o baza de date. Principalele funcții ale unui SGBD sunt:
-descrierea datelor.
-crearea și exploatarea datelor.
-accesul mai multor utilizatori în același timp la baza de date.
-controlul și verificarea integrității datelor.
-monitorizarea performanțelor.
-furnizarea unui set de comenzi și a unui limbaj prin care utilizatorii pot efectua operațiuni pe baza de date.
-securitatea datelor.
Organizarea datelor într-un SGBD se împarte pe trei nivele: fizic, conceptual și extern. Nivelul fizic reprezintă modul în care datele sunt stocate pe suportul de stocare. Nivelul conceptual reprezintă nivelul în care datele sunt privite prin prisma semanticii lor, a conținutului și prin prisma relațiilor care leagă datele. Nivelul extern este ultimul nivel în care
structura bazei de date se reprezintă utilizatorilor sub formă unor scheme externe sau diagrame, care asigura astfel creșterea securității și simplificarea interacțiunii utilizatorilor cu baza de date.
Figura 3.5 Arhitectura generala a unui SGDB
Microsoft SQL Server
Reprezintă un sistem complet de gestiune a bazelor de date, dezvoltat de către firma Microsoft. Că și majoritatea SGBD-urilor suportă limbajul standard ANSI SQL dar conține și un limbaj propriu numit T-SQL sau Transact-SQL.
Nucleul sistemului SQL Server este reprezentat de motorul de baze de date sau SQL Server Database Engine care se ocupă de stocarea, procesarea și securizarea datelor. Principalele sale caracteristici sunt:
Stocarea sigură a datelor.
Furnizarea rapidă a informațiilor din bazele de date.
Furnizarea unei consistențe in accesul la baza de date.
Controlul accesului la baza de date folosind metode de securitate.
Impunerea unor reguli stricte de menținere a integrității datelor.
În cadrul pachetului SQL server avem și unele unelte pentru administrarea și monitorizarea sistemului. SQL Server Management Studio este aplicația centrală prin care majoritatea sarcinilor de administrare a bazelor de date pot fi executate. SSMS furnizează o
singură interfață prin care toate serverele din cadrul unei companii pot fi dirijate. Câteva din sarcinile care pot fi îndeplinite cu ajutorul Management Studio sunt:
Setarea valorilor de configurare, cum ar fi cantitatea de memorie sau numărul de procesoare, locația fișierelor de log, limba implicită.
Administrarea utilizatorilor si a rolurilor acestora.
Crearea de procese care rulează in fundal prin SQL Server Agent.
Crearea de noi baze de date.
Listarea datelor din cadrul unei tabele.
Crearea tabelelor, procedurilor stocate si a indecși-lor.
Crearea, editarea si executarea scripturilor T-SQL
Figura 3.6 SQL Server Management Studio
O altă unealtă din cadrul sistemului SQL Server este SQL Server Profiler. Acesta ajută la capturarea tuturor comenzilor care vin spre un anumit server. Putem salva toate comenzile care sunt trimise către server sau putem utiliza filtre pentru a limita comenzile salvate doar la cele care ne interesează.
Alte componente din cadrul SQL Server sunt:
1.Replication – ajută la sincronizarea informațiilor intre două sau mai multe baze de date.
2.Full-Text Search – oferă funcționalități de căutare după unul sau mai multe cuvinte în cadrul câmpurilor de tip text.
3. SQL Server Reporting Services – pentru extragerea datelor și prelucrararea lor în rapoarte grafice, fiind suportate o varietate de formate (PDF, HTML, EXCEL).
3.2.7 Limbajul SQL
Datorită faptului că limbajele generale de programare (Pascal, C++, Java etc) nu dispun de existența unor comenzi de definire a datelor (Dată Definition Language), de manipulare a datelor (Dată Manipulation Language), producătorii SGBD-urilor au fost nevoiți să își inventeze propriile limbaje care să implementeze toate funcționalitățile necesare. Profunda incompabilitate între aceste limbaje a adus preocupări majore pentru elaborarea unor standarde care să armonizeze dialectele acestora. Limbajul SQL sau Structured Query Language a fost limbajul care s-a impus cel mai puternic dintre toate aceste limbaje.
Cele mai importante calități ale limbajului SQL sunt:
-portabilitatea intre diverse sisteme de operare.
-are sprijinul organizațiilor de standardize si al marilor firme producatoare de SGDB- uri: Microsoft, IBM si Oracle.
– este un limbaj înalt cu o sintaxă apropiată de limba engleză.
– majoritatea limbajelor de programare conțin librării care ușurează lucrul cu un server SQL.
– permite modificarea dinamică a datelor, chiar în timp ce unii utilizatori sunt conectați la sistem.
Limbajul SQL este un limbaj relațional complet, el se poate folosi pentru o gamă largă de operațiuni:
– definirea datelor.
– consultarea bazei de date.
– manipularea datelor.
– controlul accesului la baza de date și partajarea acesteia între mai mulți utilizatori.
– menținerea integrității bazei de date.
Comenzile de lucru cu baza de date in SQL, sunt:
Tipuri de baza in SQL sunt:
1.Numere:
– întregi: SMALLINT , INTEGER.
– reale: NUMERIC, DECIMAL, FLOAT, REAL.
2. Șiruri de caractere:
– de lungime fixă: CHARACTER (n) sau CHAR(n).
– de lungime variabilă: VARCHAR(n).
3. Date și ore calendaristice:
-data calendaristică: DATE.
-timp (oră, minut, secundă): TIME.
-dată-timp (an, lună, zi, oră, minut, secundă): TIMESTAMP.
3.2.8 Limbajul T-SQL
Transact SQL sau T-SQL este un limbaj proprietar Microsoft care este disponibil doar pe SQL Server. Este defapt o extindere a limbajului standard SQL, adăugând posibilitatea declarării de variabile, a tratării excepțiilor, a controlului tranzacțiilor.
Câteva din noutățile aduse limbajului SQL sunt:
Structuri de control if-else:
IF condiție
BEGIN
–Execută operație dacă condiția este adevarată
END
ELSE
BEGIN
–Execută operație daca condiția nu este adevarată
END
Utilizarea variabilelor
DECLARE @nume_variabile tip_variabila
SET @nume_variabila = valoare;
Blocuri TRY-CATCH de tratare a excepțiilor
BEGIN TRAN
BEGIN TRY
– execută intrucțiuni sql
– comite rezultate daca intrucțiunile s-au executat cu succes
COMMIT TRAN
END TRY
BEGIN CATCH
– in caz de eroare
ROLLBACK TRAN
END CATCH
Proceduri stocate (voi exemplifica aici folosind o procedura stocată in codul sursă a programului DredgerTrack pe care o folosesc la inserarea unei noi inregistrări in tabela Fleets).
CREATE PROCEDURE [dbo].[Fleets_Insert]
@Application_ID BIGINT,
@Fleet_GUID UNIQUEIDENTIFIER,
@Fleet_Description VARCHAR(255),
@Fleet_ID BIGINT OUT
AS
DECLARE @Application_Amount INT
SELECT @Application_Amount = COUNT(*)
FROM Applications
WHERE ID = @Application_ID;
DECLARE @Fleet_Amount INT
INSERT INTO Fleets
(Application_ID, GUID, Description)
VALUES (@Application_ID, @Fleet_GUID, @Fleet_Description);
SELECT @Fleet_ID = SCOPE_IDENTITY();
GO
Tehnologii hardware utilizate
Protocolul GPRS
GPRS este un serviciu de transmitere a datelor în rețele GSM care permite o compatibilitate totală cu rețeaua Internet. Standardul GPRS a fost inițial creat de Institutul European de Stardarde Telecomunicații că răspuns la apariția tehnologiilor de tipul packet-switched CDPD și i-mode.
Figura 3.7 Arhitectura GPRS
Această tehnologie este de tipul best-effort cu o lățime de bandă și lantențe variabile care depind de numărul de utilizatori conectați la serviciu spre deosebire de tehnologiile de comutatie sincronă care garantează o anumită calitate a serviciului permanent.
Nucleul de bază a sistemului GPRS este format dintr-o serie de protocoale care gestionează mobilitatea, menținerea sesiunii și transportul packetelor de tip IP în rețele GSM și WCDMA.
Elementele principale ale rețelei GPRS:
Unul dintre cele mai importante este Protocolul de tunelare GPRS (GTP) care asigură utilizatorilor posibilitatea de a se mută dintr-un loc în altul fiind conectați la același GPRS Support Node(GGSN). GTP permite utilizarea tunelarii pentru transmiterea prin magistrala GPRS între nodurile GSN a pachetelor diferitelor protocoale. Din punct de vedere a semnalizării GTP determină mecanisme de control și dirijare, ce permit protocolului SGSN să asigure pentru MS accesul în rețeaua GPRS. Semnalizarea servește pentru crearea, modificarea și distrugerea tunelurilor.Protocolol GTP se suporta doar de nodurile de deservire SGSN si de ecluzele GGSN . Un nod de deservire GGSN poate asigura serviciul pentru o multitudine de ecluze GGSN.
Antetul pachetului GTP se utilizeaza pentru toate tipurile de mesaje GTP și are o lungime fixa de 16 octeti.
Figura 3.8 Antetul pachetului GTP
Protocolul LLC (Logical Link Control) determină gestionarea canalului logic de comunicație și se utilizează la transmiterea datelor intre stația mobile si nodule i de deservire(SGSN). Protocolul LL asigură transmiterea datelor de la MS pană la SGSN și este destinat atât pentru transmiterea datelor cu confirmarea recepției, cât și pentru transmiterea datelor fără confirmare. Schimbul de informație intre obiectele unui nivel al protocolului LLC se realizează prin intermediul cadrelor, ce au următorul format:
Figura 3.9 Structura antetului LLC
Protocolul SNDCP are ca funcții de bază compresia si decompresia datelor utilizatorului, multiplicarea câtorva protocoale de pachet PDP.
GPS
Sistemul de poziționare globală este un sistem de navigare bazat pe sateliți care a fost dezvoltat de Departamentul Apărării din Statele Unite la începutul anilor 1970. Deși inițial a fost creat pentru a îndeplini scopuri militare, cu timpul a fost făcut disponibil și civililor.
GPS furnizează informații de temporizare și poziționare oriunde în lume, în orice condiții de mediu. Poate servi un număr nelimitat de utilizatori, fiind un serviciu pasiv, utilizatorii pot doar primi semnale, nu pot trimite.
Acest sistem este împărțit în 3 părți: segmentul spațial, segmentul de control și segmentul utilizatorilor. Segmentul spațial constă în 24 de sateliți, care sunt împărțiți în așa fel încât să poate fi acesați cel puțin 4 de pe orice punct al globului pământesc. Fiecare satelit transmite un semnal care e format următoarele componente: o frevența purtătoare ( 2 unde sinusoidale), două coduri digitale și un mesaj de navigație. Segmentul de control constă într-o rețea de stații care urmăresc și determina pozițiile sateliților, integritatea sistemelor, comportarea ceasurilor atomice. Segmentul utilizatorilor constă în receivere GPS folosite de părțile militare sau civile pentru a primi coordonate GPS care ajută la determinarea poziției curente de pe orice parte a globului.
Figura 3.10 Localizare folosind triangularea
Principiul de baza al funcționarii sistemului GPS e simplu. Dacă cunoaștem distanțele dintre un punct de pe globa față de 3 sateliți GPS și locația sateliților respectiv, atunci folosing o simplă triangulare putem află locația respectivă. Poziția și distanță sateliților se găsește folosind semnalul trimis pe fiecare satelit în parte. Receiverul GPS procesează semnalul achiziționat prin antena atașată iar rezultatul procesării constă în aflarea distanței până la satelit cu ajutorul codului digital și aflarea coordonatelor satelitului folosind mesajul de navigație.
3.3.3 Protocolul NMEA
Este protocolul de bază pentru returnarea datelor de poziționare în sistemul GPS fiind dezvoltat și controlat de Institutul de Electronica Maritima a Statelor Unite.
Cea mai comună versiune a standardului, NMEA 0183, este foarte simplă și permite unui expeditor( în cazul nostru receiver GPS) să trimită coordonate GPS, codate ca și caractere ASCII, mai multor receptori pasivi. Standardul definește o serie de reguli de prin care informațiile ca și poziția, timpul, statusul sistemului sunt formatate de expeditor și pot fi apoi decodate de un receptor compatibil (PC, Smartphone) care procesează datele mai departe.Voi exemplifica mai jos structura unui mesaj NMEA de tipul GLL, folosit pentru transmiterea poziției geografice:
Tabel 3.2
Tipul instrucțiunii trimise
Valoarea latitudinii
Nord sau Sud
Valoarea longitudinii
Est sau Vest
Timpul in format UTC
Indicator de status
Indicator FAA
Cod de control
Codul de control de la sfârșitul fiecărei instrucțiuni NMEA reprezintă suma tuturor operațiilor sau exclusiv(XOR) aplicate pe toți octeții care compun fraza de comandă, excluzând caracterul de inceput ‘$’.
Pentru a calcula acest cod de control, în limbajul C#, se foloseste urmatoarea metoda:
private static string getChecksum(string comanda)
{
int checksum= Convert.ToByte(comanda[sentence.IndexOf('$')+1]);
for (int i=comanda.IndexOf('$')+2 ; i<comanda.IndexOf('*') ; i++)
{
//sau exclusiv pe valoarea caracterului
checksum^=Convert.ToByte(sentence[i]);
}
return checksum.ToString("X2");
}
Analiză si proiectare
Descriere capitol
Înainte de a începe orice activitate, este necesar un proiect, iar în cazul de față proiectul trebuie să înceapă cu o analiza a componentelor hardware care sunt utilizate si să continue cu designul componentelor software.
Componentele de bază ale acestui sistem constau într-un dispozitiv, produs de firma AvMap, de urmărire a vehiculelor, un server pe care este instalat sistemul de operare Windows împreună cu Microsoft SQL Server și la care este atașat un modem GPRS și ultima componentă – un calculator personal pe care este instalat sistemul de operare Windows.
În cele ce urmează am să explic pe larg fiecare componentă importantă care face parte din sistemul de management a flotelor.
Componente hardware necesare
Dispozitivul de urmărire AvMap Blackstar
Acest dispozitiv este produs de către firma AvMap și este folosit la urmărirea în timp real a poziției și stării vehiculelor, la sistemele antifurt și la diverse sisteme de securitate. Pentru achiziționarea informațiilor de localizare folosește GPS iar pentru trimiterea acestor informații se folosește de GSM împreună cu GPRS.
Figura 4.1 Dispozitiv de urmărire fără carcasa de protecție
Figura 4.2 Antenă de recepție GPS
Dispozitivul are o acuratețe de aproximativ +/- 25m la determinarea poziției și +/- 0,1m/s la determinarea vitezei, în caz de întrerupere a conexiunii GPS repoziționarea durează aproximativ 15 sec. Codarea informațiilor se realizează cu ajutorul standartului NMEA 0183.
Pachetul Blackstar include dispozitivul propriu-zis, antena externă GPS, cablul de alimentare, antena GSM și un cablu serial pentru depanare. Dispozitivul este acoperit de o cutie de plastic care protejează împotriva intemperiilor și mărește durata de viață a dispozitivului.
Componentele principale ale sistemului BlackStar sunt:
– unitatea centrală
– modemul GSM
– receiverul GPS
– cititor de cartele SIM
– sursa de alimentare si bateria
– memorie EEPROM
Modemul GSM este programat cu ajutorul unitatii centrale prin comenzi AT. Astfel se pot primi, trimite mesaje SMS si realiza conexiuni GPRS. De exemplu pentru expedierea unui mesaj se trimit urmatoarele instructiuni:
AT+CMGF=1
OK
AT+CMGS="7789952010"
> Hello World
+CMGS: 44
OK
Figura 4.3 Dispozitivul văzut din exterior
Unitatea centrală reprezintă defapt un microcontroller pe 16 biți care rulează la o frecvență de aproximativ 20MHz,este alimentat cu o tensiune de 3V, poate funcționa la temperaturi între -30 C și +85 C. Microcontrolerul conține o memorie RAM de 6KB și o memorie flash de 128KB care este folosită la stocarea sistemului de operare. Pentru a putea comunica cu toate componentele externe (modem GSM, receiver GPS, alarme, butoane, leduri) acesta are 10 pini de intrare și 13 de ieșire. Principalele caracteristici ale unității centrale sunt: pastrarea ultimelor poziții valide, pastrarează poziția implicita, stochează fișiere jurnal, administrează alarmele, suportă reconfigurarea sistemului, suportă actualizarea sistemului de operare.
Configurarea acestui dispozitiv se realizează foarte ușor cu ajutorul unor mesaje SMS trimise de pe un telefon sau folosind sistemul DredgerTracker. În prima faza se trimite un mesaj pentru setarea informațiilor de autentificare(id,parolă), apoi urmează setarea parametrilor pentru accesul la servicul GPRS(user, gateway) iar ultimul pas constă trimiterea informațiilor de access la server principal(adresa ip, port).
Modemul GSM
Modemul GSM este un tip de modem care este folosit la obținerea accesului la internet prin rețelele mobile spre deosebire de modemurile conventionale care folosesc linia telefonică sau rețelele CATV. Apărut în anii 1990 modemul GSM este defapt un telefon mobil căruia i s-a dezmembrat display-ul și tastatura rămânând doar cu componenta radio și circuitul de control.
Figura 4.4 Modemul GSM
Acest dispozitiv se atașează la server prin portul serial și este folosit de către serverul central pentru obținerea conexiuni GSM prin care se realizează comunicarea cu vehiculele înregistrate. Modemul oferă posibilitatea trimiterii mesajelor SMS dar și folosirea conexiunii GPRS.
Serverul central
Este componenta cea mai importantă a sistemului care centralizează toate conexiunile vehiculelor și deasemenea conexiunile operatorilor. Serverul este reprezent de un calculator performant pe care este instalat sistemul de operare Windows, platforma .NET Framework și Microsoft SQL Server. Calculatorul trebuie să dispună de un port serial pentru a putea atașa modemul GSM și deasemenea de un hard disc cu un spațiu de stocare generos pentru a putea păstra toate datele generate de interacțiunea server-vehicule.
4.2.4 Stația de administrare
Această componentă poate fi reprezentată de unul sau mai multe PC-uri/ laptopuri pe care se va instala programul client. Necesită sistemul de operare Windows, platforma .NET și o conexiune la internet. Funcționalitatea stației de administrare este de a adaugă, modifica, configura vehiculele care interacționează cu serverul.
Arhitectura generală a sistemului
Având stabilite toate cerințele și componentele hardware putem trece la construirea arhitecturii generale a întregului sistem. Sistemul va constă într-un număr de vehicule care la intervale regulate de timp vor trimite serverului central poziția și starea curentă iar serverul central va înregistra aceste mesaje. Utilizatorii, folosind un PC care au instalat programul client, vor putea vizualiza pozitile clienților la momentual actual sau vor putea vizualiza
pozițiile stocate anterior. Deasemenea utilizatorii vor putea administra lista de vehicule și efectua operații pe acestea.
Figura 4.5 Arhitectura generală a sistemului
Arhitectura software
4.4.1 Arhitectura software a serverului
Serverul reprezintă componentă centrală a întregului sistem, majoritatea funcționalităților aplicației depinzând de acesta. Din această cauză va trebui avem o considerație crescută asupra structurii acestuia, având grijă să împărțim componenta de server în mai multe module care au sarcini specifice și care pot fi modificate ulterior fără a afecta celalate funcționalități. Arhitectura serverului este formată din: modulul de conexiune real-time care asigură comunicarea cu vehiculele înregistrate, modulul de admistrare a vehiculelor, modulul de administrare utilizatorilor și modulul de configurare a serverului.
Voi începe prin a construi arhitectura serverului real-time care asigură conexiunea cu vehiculele marine. Acesta va trebui să conțină în primul rând o interfață către modemul GSM prin care vor trece comenzile SMS sau GPRS, vom utiliza o librărie externă TelefixGSM care dispune de toate funcționalitățile necesare. Apoi vom adaugă o clasa numită ObjectListenerRTS care să se ocupe crearea și închiderea conexiunilor TCP/IP , o altă clasa ObjectSocketRTS care va reprezenta o mașină de stări cu toate etapele necesare pentru o comunicare securizată server-client. Ultimul lucru de care avem nevoie este de un decodificator al mesajelor provenite de la clienți, astfel vom crea o clasa numită DredgerStarParser.
Figura 4.6 Componentele serverului
Vom avea nevoie și de o clasa VehicleManagementServer care să conțină toate operațiile CRUD(CREATE, READ,UPDATE,DELETE) pentru obiectele din baza de date ce descriu informații despre vehicule. Această clasa se va ocupă de administrarea conexiunii cu serverul SQL, crearea tutoror comenzilor SQL necesare și executarea lor.Pentru a securiza
accesul la programul client (de administrare a vehiculelor) ne va trebui un sistem de autentificare, acest lucru va fi realizat de către clasa UserManagementServer. Această clasă va avea structura aseamanatoare cu cea a clasei VehicleManagementServer, doar că va execută operațiuni CRUD pe obiectele ce descriu utilizatorii și grupurile de utilizatori. Prin intermediul ei vom putea executa comenzi de autentificare, verificare de permisiuni, administrarea altor utilizatori.
Figura 4.7 Diagrama claselor care formează serverul
Arhitectura clientului
Programul client este necesar pentru administrarea vehiculelor și vizualizarea lor în timp real pe o harta, fără acesta întreg sistemul s-ar rezuma doar la stocarea într-o baza de date a unor poziții. Acesta va fi dezvoltat folosind componente Windows Forms din cadrul platformei .NET datorită compatibilității cu programul server și deasemenea datorită productivității mediului de dezvoltare. Vom avea nevoie de o componentă care să implementeze un sistem GIS și datorită complexității unui asemenea sistem vom folosi o librărie numită MapProducer care să implementeze această funcționalitate.
Interfața grafică va fi împărțită într-o fereastră principala din care vor fi executate toate acțiunile și în alte ferestre auxiliare care vor îndeplini diverse funcționalități.
Figura 4.8 Componentele programului client
Pentru motive de securitate fereastra principală MainFrame nu va fi afișată numai după ce autentificarea s-a realizat cu succes, iar apoi din interioul ferestei principale vor putea fi executate modulele de configurare și administrare.
Fereastra de configurare ComunicationConsole va fi folosit pentru trimiterea de mesaje de configurare către vehiculele conectate la sistem. Se va putea seta o parolă pentru fiecare vehicul în parte, parolă cu care vehiculul va fi recunoscut de sistem. Deasemenea se pot specifica parametrii de conectare GPRS și GSM.
Figura 4.9 Diagrama claselor care formează clientul
Fereastra AdministrationConsole va fi folosită la administrarea vehiculelor și a utilizatorilor. În funcție de nivelul de acces al utilizatorului administrarea se va limita la lista vehiculelor asignate sau la lista tuturor vehiculelor și a tuturor utilizatorilor (în cazul administratorilor).
Harta pe care vor fi poziționate vehiculele va fi găzduită de clasa ChildFrame. Prima dată va fi generată o imagine cu zona geografică, iar apoi folosind pozițiile stocate în baza de date vor fi afișate puncte cu locațiile vehiculelor.
Structura bazei de date
4.5.1 Descriere generală
În aplicația DredgerTracker sistemul de stocare se împarte în două părți, partea de stocare a informațiilor legate de utilizatori și partea de stocare a informațiilor legate de vehicule (dragline marine) pe care operează utilizatorii. Baza de date a fost construită ținând cont și de posibilitățile ulterioare în dezvoltarea aplicației, putând fi adăugate cu un efort relativ mic noi câmpuri care să poate fi gestionate și manipulate din codul aplicației.
Figura 4.10 Diagrama bazei de date UserManagement
4.5.2 Tabela Users
Tabela care deține informații esențiale despre utilizatori este tabela Users. Aici avem 10 coloane care descriu anumite carecteristici ale utilizatorului. Avem ca și cheie primară coloana ‘ID’ de tipul int care este folosită în toate celelalte tabele SQL din baza de date curentă pentru a referentia o anumită înregistrare din tabela Users. Deasemenea am adăugat câmpul Application_ID de tip int care este o cheie străină – face referire la tabela Application și care este utilizată pentru a stabili aplicația la care are access utilizatorul respectiv.
Pentru a stoca numele utilizatorului folosim coloana Login_Name, pentru parolă utilizatorului folosim coloana Password, pentru a stoca adresa de email a utilizatorului folosim coloana email și pentru a stoca adresa fizică folosim PostAdress. Ultimul câmp Access_Level de tip int se referă la rolul utilizatorului în cadrul aplicației.
Figura 4.11 Tabela Users
Tabela Settings
Este folosită pentru a stoca setările utilizatorilor care vor fi încărcate de programul client. Tabela este formate din 5 câmpuri. Câmpul ID de tip int este cheia primară, are valoare unică pentru fiecare înregistrare. Câmpul User_ID de tip int este o cheie străină și reprezintă id-ul utilizatorului pentru care se adresează setarea , SETTING_TYPE_ID de tip int stochează id-ul aplicației pentru care este disponibilă setarea.Câmpul Key_Text de tipul varchar reprezintă numele setării și câmpul Value_Text de tip varchar reprezintă valoarea atribuită setării respective.
Figura 4.12 Tabela Settings
4.5.4 Tabela Notifications
Acesta tabelă stochează mesajele primite de la administrator sau de la vehiculele asignate utilizatorului. În această tabela avem 8 coloane: Coloana ID de tip int care este cheia primară, User_Id de tip int care este o cheie străină și care este folosită pentru a referiri o anumită înregistrare din tabela Users, Event_Type_ID de tip int și este defapt o cheie străină care referentiază tabela Event_Type specificând tipul mesajului stocat, Delivery_Type_ID de tip int care este tot o cheie străină, făcând referire la tabela Delivery_Type, reprezintă modul prin care a fost recepționat mesajul, coloana IsUsed de tipul bit care specifică dacă mesajul a fost citit sau nu, coloana Address de tip varchar care stochează adresa mesajului și Text de tip varchar care reprezintă conținutul mesajului.
Figura 4.13 Tabela notifications
4.5.5 Tabela Applications
Această tabelă a fost creată pentru ca o singură baza de date să poată fi folosită de mai multe programe server și client în același timp. Este formată din 3 coloane: coloana ID de tip int care este cheia primară, coloana GUID de tip varchar și care reprezintă indentificatorul unic folosit pentru aplicație și Balance de tip money care reprezintă suma alocată aplicației.
Figura 4.14 Tabela Applications
Tabelele Setting_Types, Event_Types, Delivery_Types
Figura 4.15 Tabela Setting_Types
Figura 4.16 Tabela Event_Types
Figura 4.17 Tabela Delivery_Types
Aceste tabele sunt folosite pentru a împărți setările, evenimentele și tipurile de primire a mesajelor pentru fiecare utilizator în mai multe tipuri rezultăm o organizare mai bună și o flexibilitate la schimbare mai mare. Avem aici că și cheie prima coloana ID și că și cheie străină coloana Application_ID care reprezintă legătură spre o anumită aplicație. De asemenea avem câmpul Description de tipul varchar pentru a stoca detalii despre obiectul stocat.
4.5.7 Baza de date a vehiculelor
V-oi descrie mai jos tabelele care sunt folosite la stocarea informațiilor despre vehicule:
Figura 4.18 Diagrama bazei de date VehicleManagement
4.5.8 Tabela Vehicles
Această tabela este folosită pentru a stoca vehiculele care se pot conecta la serverul nostru. Ca și cheie primară avem coloana ID. Coloana Aplication_ID de tip bigint este o cheie străină și face referire spre aplicația în care este înregistrat vehiculul. Mai avem ca și chei străine coloana Channel_ID care face referire la canalul de comunicație utilizat de vehicul și coloana FleetID care reprezintă flota din care face parte vehiculul. Am adăugat și câmpul Description de tip varchar pentru a stoca o scurtă descriere despre vehiculul in cauză. Pentru stocarea informațiilor de autentificare și configurare specifice fiecărui vehicul avem coloanele Phone_Number, Service_Center, Password, GPRS_Login, GPRS_Password.
Figura 4.19 Tabela Vehicles
4.5.9 Tabela Positions
Pentru a stoca pozițiile primite prin mesaje de la vehicule folosim tabela Positions. Ca și cheie primară avem aici coloana ID de tip bigint iar că și chei externe avem coloana Vehicle_ID și coloana Channel_Id. Deasemenea pentru poziția efectivă folosim câmpurile Latitute,Longitude de tip float și Altitude,Speed de tip smallint.
Figura 4.20 Tabela Positions
4.5.10 Tabela Channels
În tabela Channels stocăm setările necesare pentru funcționarea modemului GSM instalat pe server și setările necesare pentru a primi și trimite mesaje prin GSM/GPRS. Coloanele COM_Serial_Line, COM_Port_Rate, COM_Byte_Size, COM_Parity, COM_StopBits, COM_FlowControl reprezintă parametri care sunt folosiți la accesarea modemului GSM prin portul serial de către server. Celelalte coloane WEB_Provider, WEB_Service_center, WEB_Phone_Number, WEB_Answer_Time sunt necesare pentru setarea serviciilor SMS și GPRS.
Figura 4.21 Tabela Channels
4.5.11 Tabela Incoming Messages
În tabela Incoming_Messages se găsesc toate mesaje care primite de la vehicule. Pe lângă conținutul mesajului, în această tabela se stochează toate informațiile legate de starea și configurația vehiculului, de starea alarmelor a bateriei și de parametri canalului de comunicație prin care acest mesaj a fost recepționat. Câmpul ID reprezintă cheia primară, iar ca și chei străine avem: Operation_Type_Id – face referință spre tabela Operation_Type și reprezintă tipul mesajului primit, Channel_ID – referință spre tabela Channels și este defapt canalului de comunicație prin care s-a primit mesajul și Vehicle_Id – face referire la vehiculul de la care a provenit mesajul.
Figura 4.22 Tabela IncomingMessages
4.5.12 Tabela Fleets
Pentru a se opera mai ușor asupra vehiculelor prezente în sistem le-am organizat în flote, fiecare vehicul având o singură flota de care aparține. Flotele sunt stocate în tabela Fleets care este compusă din 4 câmpuri, după cum se vede în figura de mai sus. Câmpul ID este cheie primară iar câmpul Aplication_ID este o cheie străină care face referință la tabela applications.
Figura 4.23 Tabela Fleets
4.5.13 Tabela SSAreas
Aici sunt definite zonele geografice de operare a vehiculelor, care sunt folosite de sistemul grafic pentru afișare în aplicația client. Cheia primară din cadrul acestei tabele este AreaName care reprezintă numele zonei. Deasemenea avem câmpul Description pentru a stoca descrierea zonei și câmpurile Color și Transparency care sunt folosite în cadrul interfeței grafice pentru a diferenția fiecare zona.
Tabela SSAreasShapes
Este folosită pentru a construi coordonatele geografice ale zonelor din tabela SSAreas. Câmpul ID reprezintă cheia prima, iar câmpul AreaName este folosit pentru a face referință la zona la care se adresează coordonatele. Câmpurile LLC_Longitude, LLC_Latitude, URC_Longitude, URC_Latitude stochează coordonate GPS, reprezentând defapt un segment ce delimitează zona curentă.
4.5.15 SSAreasVehicles
Pentru a plasa fiecare vehicul în zona corespunzătoare am creat tabela SSAreasVehicles. Câmpul AreaName este o cheie străină și face referință spre tabela SSAreas iar câmpul VehicleID, tot o cheie străină, face referire spre tabela Vehicles.
Figura 4.24 Relația dintre tabelele SSAreas, SSAreasVehicles, SSAreasShapes
Implementarea
Implementarea serverului
5.1.1 Serviciul DredgerServer
Serverul aplicației este pus in funcțiune de clasa DredgerServer din proiectul SvrImpl. Acestă clasă implementează interfața MarshallByRefObject facând posibil accessul la această clasă din orice punct al aplicației cu ajutorul funcțiilor de .NET remoting.
In constructorul clasei sunt instantiate cele trei componente majore ale serverului:
m_ VehicleServer care implementează interfață IVehicleManagementServerInterface – componenta de gestiune a vehiculelor înregistrate in sistem
m_VehicleServer = (IVehicleManagementServerInterface)new CMap.DredgerTrack.VehicleManagementServer.Server();
string VehicleServerConnectionString = C onfigurationSettings.AppSettings[Constants.VEHICLE_MANAGEMENT_CONNECTION_STRING];
m_VehicleServer.Initialize(VehicleServerConnectionString);
Parmetrul VehicleServerConnectionString, folosit în metoda de inițializare este stocat în fișierul de configurare a proiectului (app.config) și reprezintă parametrii de acess a bazei de date.
m_UserServer care implementează interfața IUserManagerServerInterface – componentă de gestiune a utilizatorilor
m_UserServer = (IUserManagementServerInterface)new CMap.DredgerTrack.UserManagementServer.Server();
string UserServerConnectionString = ConfigurationSettings.AppSettings[Constants.USER_MANAGEMENT_CONNECTION_STRING];
string UserServerSmtpServer = ConfigurationSettings.AppSettings[Constants.USER_MANAGEMENT_SMTP_SERVER];
string UserServerServerEmail = ConfigurationSettings.AppSettings[Constants.USER_MANAGEMENT_SERVER_EMAIL];
m_UserServer.Initialize(UserServerConnectionString, UserServerSmtpServer, UserServerServerEmail);
m_RealTimeManager care implementează interfața IRealTimeManager – componentă de gestiune a conexiunilor provenite de la dragline.
m_RealTimeManager = new RealTimeManager(m_RealTimeObjectPort);
De asemenea tot in funcția de constructor sunt atașate metodele de tratare a evenimentelor: RealTimeServer_OnMessagesReceivedEvent, RealTimeServer_OnCommandAcknowlegedEvent pentru recepționarea unor noi mesaje de la dispozitivele conectate, VehicleServer_VehicleManagementDataSetChangesEvent pentru notificare în cazul unor modificări a bazei de date și UserServer_UserManagementDataSetChangesEvent pentru procesarea comenzilor de la utilizatori.
m_UserServer.UserManagementDataSetChangesEvent += new UserManagementDataSetChangesHandler(UserServer_UserManagementDataSetChangesEvent);
m_VehicleServer.VehicleManagementNewMessagesEvent += new VehicleManagementNewMessagesHandler(VehicleServer_VehicleManagementNewMessagesEvent);
m_VehicleServer.VehicleManagementDataSetChangesEvent += new VehicleManagementDataSetChangesHandler(VehicleServer_VehicleManagementDataSetChangesEvent);
m_VehicleServer.ChannelStateChangedEvent += new ChannelStateChangedHandler(VehicleServer_ChannelStateChangedEvent);
m_RealTimeManager.OnMessagesReceived += new OnMessagesReceivedEvent(RealTimeServer_OnMessagesReceivedEvent);
m_RealTimeManager.OnCommandAcknowleged += new OnCommandAcknowlegedEvent(RealTimeServer_OnCommandAcknowlegedEvent);
m_RealTimeManager.OnCommandRejected += new OnCommandRejectedEvent(RealTimeServer_OnCommandRejectedEvent);
m_RealTimeManager.OnLogFileLoadingAborted += new OnLogFileLoadingAbortedEvent(RealTimeServer_OnLogFileLoadingAbortedEvent);
Tot în cadrul clasei DredgerServer avem metodele GoesDown și Dispose care gestionează acțiunea de oprirea serverului informând toți clienți connectați de acțiunea de shutdown și eliberând memoria ocupată de obiectele instanțiate în constructor.
5.1.2 Serverul de administrare a vehiculelor
Această clasa se ocupă de administrarea vehiculelor.Dispune de metode pentru adăugarea,ștergerea, modificarea vechiculelor, organizarea vehiculelor în flote, stocarea pozițiilor, stocarea mesajelor primite, administrarea zonelor de navigație, înregistrarea operațiilor în fisere log.
La începutul clasei găsim o serie de constante necesare pentru operațiile cu baza de date și pentru prelucrarea mesajelor de la vehicule, urmează apoi variabile private de tipul SqlDataAdapter,SqlConnection și SqlDataSet necesare pentru comenzile de lucru cu serverul SQL.
Metoda Initialize este folosită pentru inițializarea tuturor obiectelor folosite la conectarea cu serverul SQL și pentru inițializarea canalului de comunicare cu modemul GPRS. În primele linii de cod ne conectăm la serverul bazei de date și construim obiectele de tipul SqlCommand , specificând numele procedurii stocate și adăugând toți parametrii utilizați de această , pentru operațiile de tipul Select, Insert, Update, Delete, obiecte pe care le compunem într-un singur
obiect de tipul SqlDataAdapter. Facem acest lucru pentru fiecare tabela din baza de date VehicleManagement. V-oi prezenta acesta metodă pentru tabela Vehicles:
m_VclsAdapter = new SqlDataAdapter();
SqlCommand VclsSelectCmnd = new SqlCommand(Constants.VCLS_SELECT_COMMAND, m_Connection);
VclsSelectCmnd.CommandType = CommandType.StoredProcedure;
SqlCommand VclsInsertCmnd = new SqlCommand(Constants.VCLS_INSERT_COMMAND, m_Connection);
VclsInsertCmnd.CommandType = CommandType.StoredProcedure;
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_APPLICATION_ID, SqlDbType.BigInt, DATABASE_LENGTH_OF_ID, VehicleManagementConstants.DATASET_VCLS_APPLICATION_ID_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_CHANNEL_ID, SqlDbType.BigInt, DATABASE_LENGTH_OF_ID, VehicleManagementConstants.DATASET_VCLS_CHANNEL_ID_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_FLEET_ID, SqlDbType.BigInt, DATABASE_LENGTH_OF_ID, VehicleManagementConstants.DATASET_VCLS_FLEET_ID_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_GUID, SqlDbType.Char, DATABASE_LENGTH_OF_GUID, VehicleManagementConstants.DATASET_VCLS_GUID_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_TYPE, SqlDbType.SmallInt, DATABASE_LENGTH_OF_SMALLINT, VehicleManagementConstants.DATASET_VCLS_VEHICLE_TYPE_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_DESCRIPTION, SqlDbType.VarChar, DATABASE_LENGTH_OF_FULL_STRING, VehicleManagementConstants.DATASET_VCLS_DESCRIPTION_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_PHONE_NUMBER, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_PHONE_NUMBER_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_SERVICE_CENTER, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_SERVICE_CENTER_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_P
ASSWORD, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_PASSWORD_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_STATUS, SqlDbType.SmallInt, DATABASE_LENGTH_OF_SMALLINT, VehicleManagementConstants.DATASET_VCLS_STATUS_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_GPRS_GATEWAY, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_GPRS_GATEWAY_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_GPRS_LOGIN, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_GPRS_LOGIN_COLUMN);
VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_GPRS_PASSWORD, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_GPRS_PASSWORD_COLUMN);
SqlParameter VclsInsertParam1 = VclsInsertCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_ID, SqlDbType.BigInt, DATABASE_LENGTH_OF_ID, VehicleManagementConstants.DATASET_VCLS_ID_COLUMN);
VclsInsertParam1.Direction = ParameterDirection.Output;
SqlCommand VclsUpdateCmnd = new SqlCommand(Constants.VCLS_UPDATE_COMMAND, m_Connection);
VclsUpdateCmnd.CommandType = CommandType.StoredProcedure;
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_ID, SqlDbType.BigInt, DATABASE_LENGTH_OF_ID, VehicleManagementConstants.DATASET_VCLS_ID_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_CHANNEL_ID, SqlDbType.BigInt, DATABASE_LENGTH_OF_ID, VehicleManagementConstants.DATASET_VCLS_CHANNEL_ID_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_FLEET_ID, SqlDbType.BigInt, DATABASE_LENGTH_OF_ID, VehicleManagementConstants.DATASET_VCLS_FLEET_ID_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_GUID, SqlDbType.Char, DATABASE_LENGTH_OF_GUID, VehicleManagementConstants.DATASET_VCLS_GUID_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_TYPE, SqlDbType.SmallInt, DATABASE_LENGTH_OF_SMALLINT, VehicleManagementConstants.DATASET_VCLS_VEHICLE_TYPE_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_
DESCRIPTION, SqlDbType.VarChar, DATABASE_LENGTH_OF_FULL_STRING, VehicleManagementConstants.DATASET_VCLS_DESCRIPTION_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_PHONE_NUMBER, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_PHONE_NUMBER_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_SERVICE_CENTER, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_SERVICE_CENTER_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_PASSWORD, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_PASSWORD_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_STATUS, SqlDbType.SmallInt, DATABASE_LENGTH_OF_SMALLINT, VehicleManagementConstants.DATASET_VCLS_STATUS_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_GPRS_GATEWAY, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_GPRS_GATEWAY_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_GPRS_LOGIN, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_GPRS_LOGIN_COLUMN);
VclsUpdateCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_GPRS_PASSWORD, SqlDbType.VarChar, DATABASE_LENGTH_OF_LIMITED_STRING, VehicleManagementConstants.DATASET_VCLS_GPRS_PASSWORD_COLUMN);
SqlCommand VclsDeleteCmnd = new SqlCommand(Constants.VCLS_DELETE_COMMAND, m_Connection);
VclsDeleteCmnd.CommandType = CommandType.StoredProcedure;
VclsDeleteCmnd.Parameters.Add(Constants.STORED_PROC_PARAM_VEHICLE_ID, SqlDbType.BigInt, DATABASE_LENGTH_OF_ID, VehicleManagementConstants.DATASET_VCLS_ID_COLUMN);
m_VclsAdapter.SelectCommand = VclsSelectCmnd;
m_VclsAdapter.InsertCommand = VclsInsertCmnd;
m_VclsAdapter.UpdateCommand = VclsUpdateCmnd;
m_VclsAdapter.DeleteCommand = VclsDeleteCmnd;
Dupa ce terminăm operațiunea de creare a obiectelor SqlDataAdapter v-om inițializa un obiect de tipul DataSet în care v-om adîuga informațiile despre structura și conținutul
tabelelor existente , informații pe care le obținem rulând metoda Fill a fiecarui obiect SqlDataAdapter creat:
m_AppsAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_APPS_TABLE);
m_ChnsAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_CHNS_TABLE);
m_TypsAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_TYPS_TABLE);
m_AresAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_ARES_TABLE);
m_FltsAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_FLTS_TABLE);
m_VclsAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_VCLS_TABLE);
m_VinsAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_VINS_TABLE);
m_WptsAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_WPTS_TABLE);
m_PolpAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_POLP_TABLE);
m_PolvAdapter.Fill(m_DataSet, VehicleManagementConstants.DATASET_POLV_TABLE);
Următorul pas pe care îl facem este să creăm niște tabele temporare în care v-or stoca rezultatele generate de rularea procedurilor stocate:
m_OperCreateCacheTablesAdapter.Fill(m_DataSet);
m_DataSet.Tables[Constants.STORED_PROC_FIRST_RETURNED_TABLE].TableName = VehicleManagementConstants.DATASET_PSTS_TABLE;
m_DataSet.Tables[Constants.STORED_PROC_SECOND_RETURNED_TABLE].TableName = VehicleManagementConstants.DATASET_INCS_TABLE;
m_DataSet.Tables[Constants.STORED_PROC_THIRD_RETURNED_TABLE].TableName = VehicleManagementConstants.DATASET_OUTS_TABLE;
După ce această operație s-a terminat v-om adaugă informațiile despre cheile primare care aparțin tabelelor ,specificăm relațiile între tabele și v-om seta constrângerile specifice fiecărui tabel:
//adăugarea de chei primare
m_DataSet.Tables[VehicleManagementConstants.DATASET_APPS_TABLE].PrimaryKey = new DataColumn[] { m_DataSet.Tables[VehicleManagementConstants.DATASET_APPS_TABLE].Columns[VehicleManagementConstants.DATASET_APPS_ID_COLUMN] };
m_DataSet.Tables[VehicleManagementConstants.DATASET_CHNS_TABLE].PrimaryKey = new DataColumn[] { m_DataSet.Tables[VehicleManagementConstants.DATASET_CHNS_TABLE].Columns[VehicleManagementConstants.DATASET_CHNS_ID_COLUMN] };
m_DataSet.Tables[VehicleManagementConstants.DATASET_TYPS_TABLE].PrimaryKey = new DataColumn[] { m_DataSet.Tables[VehicleManagementConstants.DATASET_TYPS_TABLE].Columns[VehicleManagementConstants.DATASET_TYPS_ID_COLUMN] };
m_DataSet.Tables[VehicleManagementConstants.DATASET_ARES_TABLE].PrimaryKey = new DataColumn[] { m_DataSet.Tables[VehicleManagementConstants.DATASET_ARES_TABLE].Columns[VehicleManagementConstants.DATASET_ARES_ID_COLUMN] };
m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].PrimaryKey = new DataColumn[] { m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Columns[VehicleManagementConstants.DATASET_FLTS_ID_COLUMN] };
…//la fel pentru alte tabele
//setarea relațiilor intratabelare
m_DataSet.Relations.Add(new DataRelation(VehicleManagementConstants.APPLICATIONS_AREAS_RELATION,
m_DataSet.Tables[VehicleManagementConstants.DATASET_APPS_TABLE].Columns[VehicleManagementConstants.DATASET_APPS_ID_COLUMN],
m_DataSet.Tables[VehicleManagementConstants.DATASET_ARES_TABLE].Columns[VehicleManagementConstants.DATASET_ARES_APPLICATION_ID_COLUMN]));
m_DataSet.Relations.Add(new DataRelation(VehicleManagementConstants.APPLICATIONS_FLEETS_RELATION,
m_DataSet.Tables[VehicleManagementConstants.DATASET_APPS_TABLE].Columns[VehicleManagementConstants.DATASET_APPS_ID_COLUMN],
m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Columns[VehicleManagementConstants.DATASET_FLTS_APPLICATION_ID_COLUMN]));
….
//adăugarea constrângerilor
m_DataSet.Tables[VehicleManagementConstants.DATASET_APPS_TABLE].Constraints.Add(new UniqueConstraint(VehicleManagementConstants.APPLICATIONS_CONSTRAINT, new DataColumn[] {
m_DataSet.Tables[VehicleManagementConstants.DATASET_APPS_TABLE].Columns[VehicleManagementConstants.DATASET_APPS_GUID_COLUMN] }));
…
Ultimele lucruri pe care le v-om face în metoda Initialize este initializarea canalelor de comunicare GPRS folosing biblioteca TfxCHANELLPACKLib care asigură comunicarea
cu modemul GSM. Citim setările stocate în tabela Channels și ne construim o lista de obiecte Channels pe care o v-om trimite metodei StartTfxWebChannel.
În cadrul clasei VehicleManagementServer avem o serie de metode care efectuează operații de creare, de listare, de modificare și de ștergere pe obiecte din baza de date, având pentru fiecare tabel din baza de date cel puțin 4 de astfel de metode.Voi prezenta mai jos metodele care acționează pe tabela Fleets (care ajută la organizarea draglinelor în flote): ///Returnează informații despre o anumită flotă specificată prin FleetGUID
public bool Fleets_Get_Details(string ApplicationGUID, Guid FleetGUID, out string FleetDescription)
{
lock(this)
{
FleetDescription = null;
try
{
…. DataRow[] FleetRows = m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Select(VehicleManagementConstants.DATASET_FLTS_APPLICATION_ID_COLUMN + EQUALITY_STRING + ApplicationID + AND_PHRASE + VehicleManagementConstants.DATASET_FLTS_GUID_COLUMN + EQUALITY_STRING + LINE_DELIMITER + FleetGUID + LINE_DELIMITER);
if(FleetRows == null || FleetRows.Length != SINGLE_ROW_RESULT_LENGTH || FleetRows[SINGLE_ROW_INDEX] == null) return false;
DataRow FleetRow = FleetRows[SINGLE_ROW_INDEX];
// Retrive fleet details
FleetDescription = (string)FleetRow[VehicleManagementConstants.DATASET_FLTS_DESCRIPTION_COLUMN];
return true;
}
catch { return false; }
}
}
/// Returnează lista flotelor
public bool Fleets_Get_List(string ApplicationGUID, out Guid[] FleetGUIDs, out string[] FleetDescriptions)
{
lock(this)
{
FleetGUIDs = null; FleetDescriptions = null;
try
{
DataRow[] FleetRows = m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Select(Vehicl
eManagementConstants.DATASET_FLTS_APPLICATION_ID_COLUMN + EQUALITY_STRING + ApplicationID);
if(FleetRows == null || FleetRows.Length == 0) return true;
FleetGUIDs = new Guid[FleetRows.Length];
FleetDescriptions = new string[FleetRows.Length];
for(int i=0; i<FleetRows.Length; i++)
{
// Retrive fleet details
FleetGUIDs[i] = (Guid)FleetRows[i][VehicleManagementConstants.DATASET_FLTS_GUID_COLUMN];
FleetDescriptions[i] = (string)FleetRows[i][VehicleManagementConstants.DATASET_FLTS_DESCRIPTION_COLUMN];
}
return true;
}
catch { return false; }
}
}
//Crează o nouă flotă în baza de date
public bool Fleets_Insert(string ApplicationGUID, Guid FleetGUID, string FleetDescription)
{
….
// Insert fleet
DataRow FleetRow = m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].NewRow();
FleetRow[VehicleManagementConstants.DATASET_FLTS_ID_COLUMN] = INITIAL_ID;
FleetRow[VehicleManagementConstants.DATASET_FLTS_APPLICATION_ID_COLUMN] = ApplicationID;
FleetRow[VehicleManagementConstants.DATASET_FLTS_GUID_COLUMN] = FleetGUID;
FleetRow[VehicleManagementConstants.DATASET_FLTS_DESCRIPTION_COLUMN] = FleetDescription;
m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Rows.Add(FleetRow);
DataSet DataSetChanges = GetDataSetChanges();
m_FltsAdapter.Update(m_DataSet, VehicleManagementConstants.DATASET_FLTS_TABLE);
if(DataSetChanges != null)
{
DataRow ChangedFleetRow = DataSetChanges.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Rows[SINGLE_ROW_INDEX];
ChangedFleetRow[VehicleManagementConstants.DATASET_FLTS_ID_COLUMN] = (long)FleetRow[VehicleManagementConstants.DATASET_FLTS_ID_COLUMN];
FireDataSetChanges(DataSetChanges);
}
return true;
}
catch
{
m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].RejectChanges();
return false;
}
finally { DEBUG_CHECK(); }
}
}
//Modifică o anumită flotă specificată prin OldFleetGUID
public bool Fleets_Update(string ApplicationGUID, Guid OldFleetGUID, Guid NewFleetGUID, string FleetDescription)
{
lock(this)
{
try
{
DataRow[] FleetRows = m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Select(VehicleManagementConstants.DATASET_FLTS_APPLICATION_ID_COLUMN + EQUALITY_STRING + ApplicationID + AND_PHRASE + VehicleManagementConstants.DATASET_FLTS_GUID_COLUMN + EQUALITY_STRING + LINE_DELIMITER + OldFleetGUID + LINE_DELIMITER);
if(FleetRows == null || FleetRows.Length != SINGLE_ROW_RESULT_LENGTH || FleetRows[SINGLE_ROW_INDEX] == null) return false;
DataRow FleetRow = FleetRows[SINGLE_ROW_INDEX];
long FleetID = (long)FleetRow[VehicleManagementConstants.DATASET_FLTS_ID_COLUMN];
// Check whether there is already an fleet with such a GUID
if(OldFleetGUID != NewFleetGUID)
{
DataRow[] CheckFleetGUIDRows = m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Select(VehicleManagementConstants.DATASET_FLTS_APPLICATION_ID_COLUMN + EQUALITY_STRING + ApplicationID + AND_PHRASE +
VehicleManagementConstants.DATASET_FLTS_GUID_COLUMN + EQUALITY_STRING + LINE_DELIMITER + NewFleetGUID + LINE_DELIMITER);
if(CheckFleetGUIDRows != null && CheckFleetGUIDRows.Length > 0) return false;
}
// Update fleet
FleetRow[VehicleManagementConstants.DATASET_FLTS_GUID_COLUMN] = NewFleetGUID;
FleetRow[VehicleManagementConstants.DATASET_FLTS_DESCRIPTION_COLUMN] = FleetDescription;
DataSet DataSetChanges = GetDataSetChanges();
m_FltsAdapter.Update(m_DataSet, VehicleManagementConstants.DATASET_FLTS_TABLE);
FireDataSetChanges(DataSetChanges);
return true;
}
catch
{
m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].RejectChanges();
return false;
}
finally { DEBUG_CHECK(); }
}
}
//sterge o flota specificata prin FleetGuid
public bool Fleets_Delete(string ApplicationGUID, Guid FleetGUID)
{
lock(this)
{
try
{
….
DataRow[] FleetRows = m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].Select(VehicleManagementConstants.DATASET_FLTS_APPLICATION_ID_COLUMN + EQUALITY_STRING + ApplicationID + AND_PHRASE + VehicleManagementConstants.DATASET_FLTS_GUID_COLUMN + EQUALITY_STRING + LINE_DELIMITER + FleetGUID + LINE_DELIMITER);
if(FleetRows == null || FleetRows.Length != SINGLE_ROW_RESULT_LENGTH || FleetRows[SINGLE_ROW_INDEX] == null) return false;
DataRow FleetRow = FleetRows[SINGLE_ROW_INDEX];
long FleetID = (long)FleetRow[VehicleManagementConstants.DATASET_FLTS_ID_COLUMN];
// Use a special data adapter to delete child rows
m_OperFltsDeleteAdapter.SelectCommand.Parameters[Constants.STORED_PROC_PARAM_FLEET_ID].Value = FleetID;
DataSet AuxilaryDS = new DataSet();
m_OperFltsDeleteAdapter.Fill(AuxilaryDS);
// Kill all child items deleted by stored procedure
foreach(DataRow AuxilaryRow in AuxilaryDS.Tables[Constants.STORED_PROC_FIRST_RETURNED_TABLE].Rows)
{
DataRow VehicleInfoRow = m_DataSet.Tables[VehicleManagementConstants.DATASET_VINS_TABLE].Rows.Find((long)AuxilaryRow[VehicleManagementConstants.DATASET_VINS_ID_COLUMN]);
// Delete vehicle info
VehicleInfoRow.Delete();
}
foreach(DataRow AuxilaryRow in AuxilaryDS.Tables[Constants.STORED_PROC_SECOND_RETURNED_TABLE].Rows)
{
DataRow WaypointRow = m_DataSet.Tables[VehicleManagementConstants.DATASET_WPTS_TABLE].Rows.Find((long)AuxilaryRow[VehicleManagementConstants.DATASET_WPTS_ID_COLUMN]);
// Delete waypoints
WaypointRow.Delete();
}
foreach(DataRow AuxilaryRow in AuxilaryDS.Tables[Constants.STORED_PROC_THIRD_RETURNED_TABLE].Rows)
{
DataRow VehicleRow = m_DataSet.Tables[VehicleManagementConstants.DATASET_VCLS_TABLE].Rows.Find((long)AuxilaryRow[VehicleManagementConstants.DATASET_VCLS_ID_COLUMN]);
// Delete all child items in cache tables
foreach(DataRow TemporaryRow in VehicleRow.GetChildRows(VehicleManagementConstants.VEHICLES_POSITION_CACHE_RELATION))
{
TemporaryRow.Delete();
}
foreach(DataRow TemporaryRow in VehicleRow.GetChildRows(VehicleManagementConstants.VEHICLES_INCOMING_MESSAGE_CACHE_RELATION))
{
TemporaryRow.Delete();
}
foreach(DataRow TemporaryRow in VehicleRow.GetChildRows(VehicleManagementConstants.VEHICLES_OUTGOING_MESSAGE_CACHE_RELATION))
{
TemporaryRow.Delete();
}
// Delete vehicle
VehicleRow.Delete();
}
// Delete fleet
FleetRow.Delete();
DataSet DataSetChanges = GetDataSetChanges();
m_FltsAdapter.Update(m_DataSet, VehicleManagementConstants.DATASET_FLTS_TABLE);
m_DataSet.Tables[VehicleManagementConstants.DATASET_PSTS_TABLE].AcceptChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_INCS_TABLE].AcceptChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_OUTS_TABLE].AcceptChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_WPTS_TABLE].AcceptChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_VINS_TABLE].AcceptChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_VCLS_TABLE].AcceptChanges();
FireDataSetChanges(DataSetChanges);
return true;
}
catch
{
m_DataSet.Tables[VehicleManagementConstants.DATASET_FLTS_TABLE].RejectChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_VCLS_TABLE].RejectChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_VINS_TABLE].RejectChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_WPTS_TABLE].RejectChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_OUTS_TABLE].RejectChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_INCS_TABLE].RejectChanges();
m_DataSet.Tables[VehicleManagementConstants.DATASET_PSTS_TABLE].RejectChanges();
return false;
}
finally { DEBUG_CHECK(); }
}
}
Deasemenea în cadrul clasei VehicleManagementServer găsim metode care lucrează cu modemul GPRS, aceste metode se conțin textul ‘ARNI’ în numele lor. Ele ajută la trimiterea mesajelor de configurare, la setarea alarmelor, cereri de citire a logurile unui anumit dispozitiv, verificarea stării baterie, modificarea a firmware-ului. Voi exemplifica mai jos o asemenea metodă SendArniGPRSConfiguration care trimite un mesaj de configurare a accesului la internet unui anumit dispozitiv specificat.
public bool SendARNIGPRSConfiguration(string ApplicationGUID, string VehicleGUID, bool OnlyGetMethod,
string GPRSGateway, string GPRSLogin, string GPRSPassword)
{
lock(this)
{
try
{
long ApplicationID = 0, ChannelID = 0, VehicleID = 0, OperationTypeID = 0;
string VehiclePhoneNumber = string.Empty, VehicleServiceCenter = string.Empty;
string VehiclePassword = string.Empty, ChannelPhoneNumber = string.Empty;
TFXCHANNELPACKLib.ITfxWEBChannel IWebChannel = null;
if(!PrepareWebSending(ApplicationGUID, VehicleGUID, OnlyGetMethod ? OPERATION_TYPE_GET_COMMAND_CODE : OPERATION_TYPE_SET_COMMAND_CODE,
(int)TFXCHANNELPACKLib._WEBCommandType_.cpwct_ARNI_GPRS_CONFIGURATION_MESSAGE_TYPE, out ApplicationID,
out ChannelID, out VehicleID, out VehiclePhoneNumber, out VehicleServiceCenter,
out VehiclePassword, out OperationTypeID, out IWebChannel, out ChannelPhoneNumber)) throw new Exception();
// Send command through COM port
IWebChannel.SendARNIGPRSConfiguration(VehiclePhoneNumber, VehicleServiceCenter,
VehiclePassword, GPRSGateway, GPRSLogin, GPRSPassword, VehiclePhoneNumber,
OnlyGetMethod ? Constants.MASK_OFF_VALUE : Constants.MASK_ON_VALUE);
OutgoingMessage Message = DredgerStarParser.CreateGPRSConfigurationMessage(OnlyGetMethod,
VehiclePhoneNumber, GPRSGateway, GPRSLogin, GPRSPassword);
UpdateOutgoingMessage(Message, ApplicationID, ChannelID, OperationTypeID, VehicleID, VehicleServiceCenter, VehiclePassword);
if(!SaveApprovedOutgoingMessages(Message)) throw new Exception();
return true;
}
catch { return false; }
finally { DEBUG_CHECK(); }
}
}
5.1.3 Clasa UserManagementServer
Această clasa implementează o serie de metode care execută operații pe tabelele din baza de date UserManagement, se ocupă în mare parte de tot ce înseamnă administrarea datelor utilizatorilor și setararile aferente fiecărui utilizator, administrarea notificărilor prezente în sistem și trimiterea de emailuri.
Structura sa este foarte asemanatoare cu a clasei VehicleManagementServer, având definite o serie de proprietăți de tip SqlDataAdapter și o singură proprietate de tipul DataSet care sunt create și configurate în metoda Initialize() pentru a fi folosite ulterior.
5.1.4 Clasa RealTimeManager
Această clasă se ocupă de tot ce înseamnă administrarea tuturor conexiunilor TCP provenite de la dispozitivele configurate prin canalul de comunicare creat de modemul GPRS. Aici sunt folosite
La începutul clasei avem definite o serie de constante care vor fi folosite de metoda clasei la clasificarea stării unei conexiuni și la calculul poziției unui anumit dispozitiv. Urmează apoi o serie de proprietăți de tip delegate care descriu metodele care vor trata diferitele stări ale unei conexiuni cu un client: OnMessagesReceived, OnCommandRejected, OnCommandAcknowleged.
Aici avem și listele cu obiectele care au permisiunea de a se conecta la server reprezentate de obiectul de tip colectie _ObjectsInGPRS și deasemenea obiectele cu clienții care nu sunt înca autenticați la server reprezentate de lista _UnknowObjectSockets.
Serverul TCP propriu-zis este reprezentat de obiectul _ObjectListener de tipul ObjectListenerRTS care metoda ascultă la portul configurat dupa noi conexiuni și in cazul apariției unei noi conexiuni crează un nou obiect de tipul ObjectSocketRTS și managerul principal (obiectul de tip RealTimeManager) de acest lucru.
Clasa ObjectListenerRTS, metoda Run (apelata in constructorul clasei RealTimeManager):
protected override void Run()
{
// Cream obiectul de retea
_Listener = new TcpListener(IPAddress.Any, _PortNumber);
_Listener.Start();
// ascultam la infinit dupa noi clienti
while(true)
{
Thread.Sleep(SLEEP_INTERVAL);
//in caz ca aplicatia trebuie oprita iesim din ciclu
if(base.IsStopped()) break;
try
{
if(!_Listener.Pending()) continue;
//in cazul apariției unei noi conexiuni o adaugam in lista
TcpClient tcpClient = _Listener.AcceptTcpClient();
ObjectSocketRTS ObjectSocket = new ObjectSocketRTS(_Manager, tcpClient);
ObjectRTS Object = new ObjectRTS(ObjectSocket);
_Manager.NewObjectConnection(Object);
}
catch { break; }
}
// Ștergerea obiectelor utilizate
_Listener.Stop();
Dispose();
}
Clasa ObjectSocketRTS este folosită la reprezentarea conexiunii unui singur client și dispune de metode și evenimente pentru tratarea comenzilor și excepțiilor în comunicarea server-client. La începutul definiției găsim enumerația ObjectSocketState care care este folosită la descrierea stării conexiunii și enumerația ObjectSocketEvent care descrie evenimentele generate de temporizatoare. Urmează apoi o seria de constante care sunt folosite la citirea mesajelor de comandă, la generarea logurilor, și la configurarea temporizatoarelor . Ca și proprietăți ale clasei avem definită ca și referință spre managerul principal (RealTimeManager) proprietatea _Manager si proprietatea _Client care face referința la obiectul de tip TcpClient prin care este realizată conexiunea. Avem cinci temporizatoarele care sunt definite aici prin proprietați de tipul TimerRTS:
AuthenticationTimer reprezintă temporizatorul de autentificare adică timpul maxim în care serverul așteaptă sa primească credentialele.
_PingTimer reprezintă timpul în care serverul așteaptă mesajul de ping al clientului pentru a confirmă disponibilitatea.
_ReadyTime reprezintă timpul rămas până la trimitea următorului mesaj de confirmare a conexiunii.
_CommandTimer ajută la determinarea timpului când poate fi trimisă următoarea comandă spre client.
_AcknowledgeTimer reprezintă timpul în care client poate confirmă primirea unei comenzi.
În metoda Run din cadrul clasei ObjectSocketRTS avem un ciclu infinit care verifică starea temporizatoarelor și în cazul unei depășiri de timp sau a unei deconectări a clientului emite un eveniment specific cu ajutorul metodei OnEvent. După ce toate temporizatoarele au fost verificate se încearcă citirea pachetelor trimise de client și decodarea lor.
if(_AuthenticationTimer.Expired)
{ OnEvent(ObjectSocketEvent.AuthenticationTimerExpired);
continue; }
if(_PingTimer.Expired)
{ OnEvent(ObjectSocketEvent.PingTimerExpired); continue; }
……
int BytesReceived = _Stream.Read(tempBuffer, 0, tempBuffer.Length);
Tot în ObjectSocketRTS avem metoda OnEvent care implementează o masină de stări care functionează în 4 stări. În cazul primei stări numită ObjectSocketState.None nu se întâmplă nimic dar în cazul celei de-a două stare ObjectSocketState.Initialized se realizează verificarea temporizatoarelor, autentificarea clientului și depinzând de succesul autentificării se realizează trecerea la urmatoarea stare sau trecerea la starea anterioară ObjectSocketState.None și închiderea conexiunii cu clientul. În cea de-a treia stare ObjectSocketState.Waiting clientul poate trimite mesaje către server iar aceste mesaje sunt transformate în comenzi de către metodă PerformMessage(). Ultima stare se numește ObjectSocketState.Ready și este starea în care se pot trimite mesaje de comanda către client.
else if(ObjectEvent == ObjectSocketEvent.IncomingMessageFromObject)
{
// în cazul primirii unui nou mesaj se verifică dacă sunt mesaje de timp sau mesaj de comandă
if(_IncomingMessage.Length > PingAcknowledge.Length &&
_IncomingMessage.Substring(0, PingAcknowledge.Length) == PingAcknowledge)
{
if(_PingToken == int.Parse(_IncomingMessage.Substring(PingAcknowledge.Length)))
{
_PingTimer.Stop();
_ReadyTimer.Restart();
_State = ObjectSocketState.Ready;
}
}
else PerformMessage()
Metoda PerformMessage() se ocupă de descifrarea mesajelor primite de la client și apoi de administrarea lor. La începutul metodei verificăm tipul mesajului care poate fi mesaj de confirmare a execuției unei comenzi de la server sau poate fi un mesaj care conține logurile dispozitivului. În cazul în care întâlnim un mesaj de tip comandă îl v-om decoda cu ajutorul clasei statice DredgerStarParser care implementează metoda ParseIncomingMessage care se asigură că mesajul primit nu este corupt și că este o comandă validă. Deasemnea în cazul în care mesajul este defapt o comandă pentru administrarea fișierelor jurnal(log) v-om gestiona mesajul respectiv în funcție de antetul sau care specifică tipul operației. De exemplu dacă întâlnim la începul mesajului constanta LOG_FILE_PROCCESS_START v-om desfășura acțiunile de începere a întreg procesului de stocare a fișierului, dacă întâlnim LOG_FILE_BLOCK_START v-om stoca bucata primită de la client în fișier, dacă întâlnim LOG_FILE_PROCESS_FINISH v-om opri tot procesul de stocare, v-om salva fișierul și v-om elibera memoria de obiectele folosite.
Implementarea interfeței grafice de management a serverului
5.2.1 Descriere generală
Rolul acestei componente este de a administra și configura serverul și datele stocate de server. În cadrul proiectului DredgerTrackServer găsim clasele care compun interfață grafică: Configure_Form, DeleteForm, Export_Form, Import_Form, MainForm, RestorePositions, Scheduler, ShrinkDBForm, StorePositions. Fiecare din aceste clase au ca și clasa de bază clasa System.Windows.Form. si care reprezinta de fapt o fereastra in cadrul sistemului de operare Windows.
5.2.2 Clasa MainForm
Fereastra principală, care este afisată la pornire se găsește în clasa MainForm. Această clasa găzduiește toate referințele către celelate ferestre, pe care le afișează când utilizatorul face click pe butonul corespunzător. Contructorul clasei initializează toate componentele grafice prezentente în fereastră principală, atașează funcții de tratare a evenimentelor, specifică poziția și aspectul grafic pentru acestea.
Această clasă se ocupă și de păstrarea unei referințe cu serverul și de pornirea lui, acest lucu se întâmplă în cadrul metodei MainForm_Load. În primul rând se inițializează și configurează librăria de .NET Remoting, după aceea se caută obiectul de server care implementează interfață IDredgerServerInterface folosind metoda Activator.GetObject iar apoi, dupa ce obiectul a fost găsit se apelează metodele Ping.
try
{
RemotingConfiguration.Configure(Assembly.GetExecutingAssembly().Location + Constants.REMOTING_CONFIG_FILE_EXTENSION);
}
catch
{
MessageBox.Show(this, Constants.DREDGER_TRACK_SERVER_IS_ALREADY_STARTED, Constants.STARTUP_ERROR,
MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
this.Close(); return;
}
// preluarea metodelor .NET remoting
IDredgerServerInterface RemoteServer = null;
WellKnownClientTypeEntry[] RemotedTypes = RemotingConfiguration.GetRegisteredWellKnownClientTypes();
foreach (WellKnownClientTypeEntry RemotedType in RemotedTypes)
{
if (RemotedType.TypeName != typeof(IDredgerServerInterface).FullName) continue;
RemoteServer = (IDredgerServerInterface)Activator.GetObject(typeof(IDredgerServerInterface), RemotedType.ObjectUrl);
break;
}
((IUserManagementServerInterface)RemoteServer).Ping(Constants.APPLICATION_GUID);
((IVehicleManagementServerInterface)RemoteServer).Ping(Constants.APPLICATION_GUID);
Tot în clasa MainForm este declarată metoda de tratare a evenimentului de închidere a ferestrei, numita MainForm_Closed, în care se apelează metodele DredgerServer.m_Instance.GoesDown() si DredgerServer.m_Instance.Dispose()care informează clienții conectați de închiderea serverului. Deasemena în MainForm se definesc metodelele care inițializează celelalte ferestre din cadrul interfeței grafice, fiecare buton din interfață principală având atașat un handler de tratare a evenimentului de click care deschide fereastra corespunzătoare.
5.2.3 Clasa Configure_Form
Această clasa este folosită pentru a afișa fereastra de configurare a serverului. În cadrul ei se pot seta parametrii de comunicație, cum ar fi adresa IP, portul COM la care este conectat modemul GPRS, numărul centrului de mesagerie etc.
În metoda de constructor a acestei clase, ca și în cazul clasei MainForm, se inițializează toate elementele grafice. După ce se întâmplă acest lucru este chemată metodă Configure_Form_Load care, folosind obiectul de remoting inițiat anterior în clasa principală, încarcă setările stocate anterior și le afișează în căsuțele de text corespunzătoare: var modemsettings = CMap.DredgerTrack.SvrImpl.DredgerServer.m_Instance.m_VehicleServer.Configuration_get();
În cazul în care utilizatorul acționează butonul de salvare a setărilor, se apelează metoda appy_buttonClick. Această metodă rulează o seria de verificări pentru a valida conținutul introdus de utilizator iar apoi salvează setările în baza de date:
CMap.DredgerTrack.SvrImpl.DredgerServer.m_Instance.m_VehicleServer.Configuration_set(comLine, comRate, provider, serviceNumber, serverNumber);
5.2.4 Clasa DeleteForm
Această clasa afișează o fereastră care ne ajută la ștergerea anumitor poziții, preluate anterior de la vehicule și stocate în baza de date, care pot fi filtrate după o anumită dată. Pe butonul de ștergere avem atașată o metodă care va afișa un dialog de confirmare a acțiunii iar în caz afirmativ va începe procesul de ștergere a înregistrărilor din baza de date. Această operație se realizează într-un fir de proces separat pentru a nu bloca interfață grafică:
System.Threading.ThreadStart workThreadStart = new System.Threading.ThreadStart(ComputeResult);
workThread = new System.Threading.Thread(workThreadStart);
workThread.Start();
5.3 Implementarea programului client
5.3.1 Descriere generală
Programul client este utilizat pentru pentru vizualizarea și administrarea vehiculelor conectate la sistem. Aceasta a fost scris folosind Windows Forms din cadrul platormei .NET și este localizat în proiectul DredgerTrackClient. Voi descrie în subcapitolele următoare toate componentele importante care compun acest program.
Clasa LoginForm
Figura 5.1 Fereastra de autentificare
Această clasa este folosită pentru a afișa fereastra de autentificare care apare la deschiderea programului client și care limitează accesul la program. Fereastra este compusă din componente simple, un control de tip dropdown pentru introducerea numelui de utilizator, un câmp text pentru parolă și trei controale de tip button, unul pentru setarea parametrilor de conectare, unul pentru executarea acțiunii de autentificare și unul pentru anulare.
Clasa LoginForm conține metoda InitializeComponent() care are rolul de a inițializa toate componentele grafice și de a încarca lista de utilizatori. O altă metodă importantă este LoginButton_Click care este executată la click pe butonul de login și care va trimite o cerere către serverul de administrare a utilizatorilor pentru a valida credentialele:
if(((IUserManagementServerInterface)m_Owner.m_RemoteServer).Users_Check_User(
AdminConstants.APPLICATION_GUID, m_UserLoginName, UserPassword, out m_UserGUID, out m_UserRights))
5.3.3 Clasa MainFrame
Această clasa reprezintă un fel de recipient pentru toate ferestrele și componentele folosite în programul client, având definite variabile care dețin referințe către toate aceste componente. Cele mai importante referințe ar fi:
m_MapProducer de tip MapProducer care face legătura cu o librăria externă MapProducer folosită la desenarea hărții.
m_RemoteServer de tip IDredgerServerInterface care face referință către un server printr-un obiect distribuit în rețea.
m_AdministrationConsole de tip AdministrationConsole în care este reprezentată interfața de administrare.
m_ComunicationConsole de tip ComunicationConsole care este folosită pentru configurarea vehiculelor prin trimiterea de mesaje de configurare SMS.
m_ChildFrame de tip ChildFrame – o clasa care este folosită la găzduirea hărții generate de librăria MapProducer.
În cadrul clasei mai sunt definite o serie de controale grafice de tipul ToolBar, StatusBar, Label, TextBox, Panel, Button, MenuItem.
Prima metodă care este executată la pornirea programului este metoda IntializeComponent, această metodă are rolul de inițializa obiectele controalelor grafice, proprietățile lor și de a specifică pozițiile fiecăruia în parte generând aspectul ferestrei.
O alta metodă importantă este metoda MainFrame_Load care va fi executată la afișarea ferestrei (după ce s-a realizat autentificarea). Această va inițializa toate ferestrele auxiliare care vor putea fi deschise ulterior prin diverse evenimente, va inițializa librăria de afișare a hărților și fereastra de găzduire a lor, va porni conexiunea cu serverul principal (folosind metodă ConnectToRemoteServer) și va atașa metode de tratare a evenimentelor primite de la dispozitivele de intrare:
m_MapProducer.Initialize();
m_AdministrationConsole = new AdministrationConsole(this);
m_CommunicationConsole = new CommunicationConsole(this);
ChildFrame ChildFrame = new ChildFrame(this);
ChildFrame.Show();
m_IsConnectedToServer = ConnectToRemoteServer();
m_ListenerContainer.ChildFrameScaleCenterChangedEvent +=
new DredgerListenerContainer.ChildFrameScaleCenterChangedHandler(OnChildFrameScaleCenterChanged);
m_ListenerContainer.ChildFrameCenterUnderMouseChangedEvent +=
new DredgerListenerContainer.ChildFrameCenterUnderMouseChangedHandler(OnChildFrameCe
Metoda ConnectToRemoteServer realizează preluarea obiectului distribuit m_RemoteServer, care ne va ajută la comunicarea cu baza de date. Apoi vom prelua lista de
vehicule, utilizatori, setările utilizatorului curent și ultimele poziții cunoscute a vehiculelor înregistrare în sistem:
RemotingConfiguration.Configure(Assembly.GetExecutingAssembly().Location + MainFrameConstants.REMOTING_CONFIG_FILE_NAME);
WellKnownClientTypeEntry[] RemotedTypes = RemotingConfiguration.GetRegisteredWellKnownClientTypes();
//preluam toate obiectele distribuite din proiect
foreach(WellKnownClientTypeEntry RemotedType in RemotedTypes)
{
if(RemotedType.TypeName != typeof(IDredgerServerInterface).FullName) continue;
m_RemoteServer = (IDredgerServerInterface)Activator.GetObject(typeof(IDredgerServerInterface), RemotedType.ObjectUrl);
break;
}
bool IsConnected = false;
string ServerVersion = string.Empty;
try { ServerVersion = m_RemoteServer.GetServerVersion(); IsConnected = true; }
catch { IsConnected = false; }
string[] UserLoginNames = null;
if(IsConnected)
{
if(DredgerClientAbstractClass.VERSION != ServerVersion)
{
MessageBox.Show(null, MainFrameConstants.INCORRECT_SERVER_VERSION_TEXT,
MainFrameConstants.INCORRECT_SERVER_VERSION_CAPTION, MessageBoxButtons.OK,
MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
return false;
}
if(!((IUserManagementServerInterface)m_RemoteServer).Users_Get_List() ………………………………………………..
Figura 5.2 Aplicația client
Metoda statică Main realizează pornirea aplicației:
Application.ThreadException += new ThreadExceptionEventHandler(OnApplicationThreadException);
Application.EnableVisualStyles();
Application.DoEvents();
Application.Run(new MainFrame());
Concluzii
Realizări
În aceasta lucrare s-a dezvoltat un sistem de monitorizare a draglinelor marine folosind limbajul de programare C# si tehnologiile GPS/GSM. Acest sistem a fost testat folosind mai multe dispozitive de achiziție a poziției și a demonstrat că poate servi cu usurință un număr mare de vehicule și utilizatori. Deasemenea sistemul are o capacitate avansată de stocare a informațiilor, putând fi realizate operațiuni de mentenanță și arhivare a datelor.
În acest mod au fost îndeplinite următoarele obiective:
Studierea fezabilității unui astfel de sistem
Realizarea integrării hardware-software
Realizarea schemei bloc a întregului sistem
Realizarea unei arhitecturi software
Realizarea unui server realtime
Realizarea unei aplicații grafice de monitorizare
Realizarea unui protocol de comunicare server-dispozitiv care să îndeplinească următoarele caracteristici:
Autentificarea fiecărui dispozitiv
Securizarea comunicației
Notificarea executării comenzilor primite
Realizarea unui sistem de stocare a informațiilor primite
Direcții de dezvoltare
Acest sistem ar beneficia de un avantaj major dacă ar dispune de un modul de urmărire și control al procesului de dragare. Folosind o librărie grafică si instalând o multitudine de senzori de mișcare pe fiecare vehicul s-ar putea simula întregul procesul de dragare iar un operator ar putea controla aceste proces de la distanță.
O alta înbunatătire s-ar realiza prin instalarea unui dispozitiv de monitorizare mai performant care să foloseasca tehnologiile mobile de mare viteză prin care s-ar putea trimite un flux mai mare de informații (video, audio). Deasemenea folosind tehnologii web s-ar putea realiza o interfață care să poate fi accesată de o multitudine de medii (telefon, tableta, pc).
Bibliografie
[1] David S. Platt, „Introducing Microsoft .NET”,
[2] „Fleet Management Software”, http://en.wikipedia.org/wiki/Fleet_management_software
[3] Scott McLean, James Naftel, Kim Williams, „Microsoft .NET Remoting”
[4] „General Packet Radio Service Wikipedia”,
http://en.wikipedia.org/wiki/General_Packet_Radio_Service
[5] Andrew Krowczyk, „Professional .NET Network Programming ”,
[6] Jonathan Gennick, Ales Spetic, „Transact-SQL Cookbook ”
[7] Paul Nielsen, „Sql Server 2008 Bible“;
[8] Curs Microsoft, „Introducere in .Net Framework”;
Bibliografie
[1] David S. Platt, „Introducing Microsoft .NET”,
[2] „Fleet Management Software”, http://en.wikipedia.org/wiki/Fleet_management_software
[3] Scott McLean, James Naftel, Kim Williams, „Microsoft .NET Remoting”
[4] „General Packet Radio Service Wikipedia”,
http://en.wikipedia.org/wiki/General_Packet_Radio_Service
[5] Andrew Krowczyk, „Professional .NET Network Programming ”,
[6] Jonathan Gennick, Ales Spetic, „Transact-SQL Cookbook ”
[7] Paul Nielsen, „Sql Server 2008 Bible“;
[8] Curs Microsoft, „Introducere in .Net Framework”;
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Protocolul Nmea (ID: 123340)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
