Strona 1 z 1

[Pascal][Synapse] Prosty klient sieciowy w Lazarus

: niedziela 18 lis 2018, 22:32
autor: tasza
#slowanawiatr
♬ ☘ Moja muzyka do kodowania ♬ ♬ ♬ ☘
♫ ♩ ♪ Marillion ⚡ ☘ ⚡ Grendel / B'Sides Themselves ♪ ♩ ♫
https://youtu.be/Rxp5KJOHqmI


Post niejako z dedykacją i mocno na fali miniaturki okładki przyszłej EdW 1/2019. Temat oprogramowania sieci w Lazarus / Free Pascal wykluł się z korespondencji, ale te kilka zdań tutaj właśnie padnie, może komuś jeszcze to przydatnym będzie.

Komponentów do obsługi sieci stworzono dla Lazarusa masę całą, niech za punkt wejścia w temat posłuży link

:arrow: http://wiki.lazarus.freepascal.org/Networking

W gąszczu owym o zagubienie łatwo ponieważ proponowane są i komponenty wizualne, współpracujące z formą na ekranie (INet), jest też wiele zestawów komponentów niemych czy tylko skromnych aczkolwiek pracowitych klas do działań w tle. Warto choćby pobieżnie poznać różne warianty, na początek proponuję dość sympatyczną w użyciu "bibliotekę" Synapse. To właściwie bardziej zestaw unit-ów przeznaczonych do włączenia w projekt i tak właśnie jej użyjemy. Stronka Wiki Synapse jest pod adresem:

:arrow: http://wiki.freepascal.org/Synapse

Niezbędne pliki znajdziemy w archiwum synapse40.zip dostępnym pod adresem:

:arrow: http://www.ararat.cz/synapse/doku.php/download

Odnośnie instalacji - nie jestem do końca przekonana czy to mądre czy nie, ale ja wszelkie takie pakiety luzem, nawet jeżeli nie podlegają formalnej rejestracji na paletkach IDE, wrzucam sobie do foldera /components, potem ewentualnie wskazuje kompilatorowi dokładną lokalizację. Idąc tą droga usieciowienie naszego projektu sprowadza się do prostej konfiguracji - wykonujemy:
Project → Project options → Compiler options → Paths
tam w rzeczonym polu edycyjnym 'other unit files' wstawiamy

Kod: Zaznacz cały

$(LazarusDir)/components/synapse/source/lib

i to zasadniczo kończy sprawę. Od tej chwili w sekcji uses możemy dodać moduł blcksock niosący implementację klasy TTCPBlockSocket, która służy do synchronicznej (blokującej) komunikacji TCP/IP.

I teraz ważne - ta klasa idealnie nadaje się do zwinnej, treściwej komunikacji typu request-response, gdzie nasz program jest stroną inicjującą przepływ informacji (klientem), a odpowiedź z reguły nadchodzi w sensownie krótkim czasie i oczekiwanie na nią przy zawłaszczonym sterowaniu jest zasadne.

Kliniczny przykład tego typu komunikacji, który akurat (ciągle i nieustająco) mam pod ręką to melanż SCPI+Rigol+Meratronik, zatem dwa proste demka proponuje do wglądu, jako pierwsze - odpytywanie dżenderuśnego oscyloskopu o bieżący przebieg w buforze ekranowym:

:arrow: https://github.com/bienata/lazarus/tree/master/rigview
:arrow: https://github.com/bienata/lazarus/blob ... w/main.pas

Zrzutki ekranu takowe, filmiku jakoś wtedy nie nagrałam, ale może nadrobię.

rigview-2.png
rigview-1.png


Fragment kodu:

Kod: Zaznacz cały

sock := TTCPBlockSocket.Create;
sock.Connect('192.168.1.100' (* IP *), '5555' (* port *));
if sock.LastError <> 0 then
  begin
    showmessage('RIP');
    exit;
  end;
sock.SendString(':waveform:source CHANNEL1'#13#10 );
sock.SendString(':waveform:mode NORMAL'#13#10 );
sock.SendString(':waveform:form ASCII'#13#10 );
sock.SendString(':waveform:data?'#13#10 );
repeat
  buffer := sock.RecvPacket(500);
  rx :=  rx + buffer;
until buffer = '';


gdzie sock - to zmienna lokalne procedurki. Ma to pewne konsekwencje, a mianowicie - połączenie sieciowe zostanie zamknięte z chwilą zwrócenia sterowania do warstwy wyżej - po prostu wszelkie close() na sieciowym API wołane są w destruktorze klasy. Jeżeli chcemy połączenie utrzymywać przez dłuższy czas - automatycznie należy zadbać o trwałość zmiennej zapewniającej obsługę linku. I przykład tego mamy dla odmiany poniżej - to odpytywanie neonowego Meratronika o dane pomiarowe,

:arrow: https://github.com/bienata/lazarus/tree ... -scpi-demo
:arrow: https://github.com/bienata/lazarus/blob ... o/main.pas

Filmiki są - na multimetrze - generator podaje sygnał o ułamkowej częstotliwości, przebieg ładnie biegnie w górę i w dół przecinając zero co jakiś czas.

https://youtu.be/RDZSnIlVMgg

Na desktopie - cała komunikacja - proszę zwrócić uwagę na to, co wypisuje konektor SCPI na konsoli ssh od Raspberry (okienko tekstowe po lewo), w szczególności co dzieje się przy zamykaniu okna aplikacji klienckiej.

https://youtu.be/D62P8AC2dC8

No i dla kompletności mój najnowszy firmware SCPI do Meratronik V543 - z tego punktu widzenia - cześć serwerowa:

:arrow: https://github.com/bienata/piv543scpi/b ... /v543lxi.c

Stara wersja opisana na bienacie nie wytrzymała starcia z VISA+LabVIEW, musiałam się bardziej ustandaryzować, że tak oględnie napiszę.

Wracając na chwilę do decyzji - czy zestawiać połączenie co jakiś czas, czy utrzymywać stale, to nie jest oczywisty wybór. Cykliczne nawiązywanie połączenia jest w sumie kosztowną operacją (a jeszcze z SSL to już w ogóle), ale nie musimy potem tego połączenia pilnować, w szczególności tego czy rurka dalej jest drożna. Dla trwałych połączeń pojawiają się natomiast techniki typu pakiety keep-alive i inne sztuki podtrzymujące komunikację na poziomie technicznym, gdy akurat nie ma ruchu 'biznesowego'. Tak więc coś za coś. No i jeżeli pracujemy z fabrycznym urządzeniem, a nie domową samoróbką - pewnie będziemy musieli się dostosować do realiów implementacji drugiej strony....

W podsumowaniu - do prostych tekstowych dialogów typu wydawanie poleceń czy odpytywanie o status - Synapse jest godne polecenia i pisze się z jego wykorzystaniem całkiem sprawnie.

ps.
w obu demkach przemycam drobne info, jak wykorzystać komponent TChart, w szczególności jego karmienie danymi na raz / na raty i skalowania osi, ale to inna historia...

Re: [Pascal][Synapse] Prosty klient sieciowy w Lazarus

: czwartek 29 lis 2018, 22:01
autor: tasza

Re: [Pascal][Synapse] Prosty klient sieciowy w Lazarus

: piątek 30 lis 2018, 23:07
autor: gaweł
Dzięki za książkę kucharską, chodzi mi po głowie pewna koncepcja, ale to wymaga trochę czasu.