D. Prameswara
D. Prameswara Tukang ketik yang sedang belajar pemrograman #linux #android #vue #node.js

Cara membaca data absensi dari mesin absensi dengan Lazarus+Freepascal di Linux

Alhamdulillah, musim hujan banyak berkah, Insya Alloh.
Pada kesempatan ini saya mencoba berbagi pengalaman tentang cara membaca data dari mesin absensi di lingkungan Linux dengan menggunakan aplikasi yang dibuat dengan Lazarus+Freepascal, semoga bermanfaat.

Suatu waktu, saya mendapat tugas untuk membuat aplikasi untuk membaca data abensi dari suatu mesin absensi (lebih tepatnya submodule) via network. Tugas ini kelihatannya simple, tetapi ternyata menjadi sangat sulit karena aplikasi itu harus berjalan di Linux Ubuntu dan sayangnya SDK dari mesin absensi tersebut ternyata hanya tersedia untuk Wi***** saja . Hadeehhh.

Syukurlah, masih ada 1 jalan meskipun unofficial, yaitu dengan menggunakan fitur WebService+SOAP yang dimiliki oleh mesin absensi tersebut. Saya tidak akan menjelaskan secara detail apakah itu WebService dan SOAP (karena memang saya tidak memiliki cukup ilmunya :D ). Intinya, dengan fitur tersebut, kita bisa melakukan koneksi ke mesin absensi, kemudian mengirimkan XML command dengan format tertentu untuk mendapatkan respon berupa data absensi dan lain-lain. 

Sekali lagi, untuk kasus saya, fitur tersebut tidak di support secara official, jadi TIDAK ADA dokumentasi lengkap bagaimana format XML  SOAP tersebut. Beruntunglah anda yang memilikinya secara lengkap. Selain itu, tidak semua mesin absensi memiliki fitur tersebut, jadi silakan anda cek manual mesin absensi anda terlebih dahulu.

OK, selanjutnya kita akan mencoba membuat aplikasi kecil yang akan melakukan koneksi dan merequest data absensi ke mesin absensi. Aplikasi ini akan kita buat dengan menggunakan Lazarus dan Freepascal. Versi yang saya gunakan sekarang adalah Lazarus 1.0.14 dan FPC 2.6.2.

Pertama, untuk melakukan koneksi ke mesin absensi, saya menggunakan komponen bernama lNet. Komponen tersebut dapat di download di sini. Silahkan anda download, kemudian install komponent tersebut. Setelah anda berhasil install component tersebut, maka akan muncul tab baru bernama lNet di component Lazarus.


Kemudian, buatlah project baru dengan nama yang anda sukai. Secara otomatis akan dibuatkan 1 form bernama form1 dengan nama unit unit1. Kemudian tambahkan komponent label, edittext, spinedit, memo dan LTCPComponent pada form1 tersebut, seperti gambar di bawah ini.


Edit1 : akan digunakan untuk input hostname dari mesin absensi
Spinedit1 : akan digunakan untuk input port webservice mesin absensi, default 80
Edit2 : akan digunakan untuk input password dari mesin absensi. Jangan lupa, karena Edit2 untuk input password, maka tentukan nilai property PasswordChar nya, misalkan dengan *


Memo1 : akan digunakan untuk menuliskan command XML SOAP.
Memo2 : akan digunakan untuk menampikan respond dari mesin absensi.
LTCPComponent1 :  komponent inti untuk melakukan koneksi ke mesin absensi dan untuk mengirimkan command serta menerima respon dari mesin absensi.

Sebelum mulai coding, anda harus mengetahui bagaimana bentuk format XML command yang akan dikirim ke mesin absensi. Di bawah ini adalah bentuk string command untuk mendapatkan data absensi pegawai.
POST /iWsService HTTP/1.0
Content-Type: text/xml
Content-Length: 128

<GetAttLog>
<ArgComKey xsi:type="xsd:integer">0</ArgComKey>
<Arg>
<PIN xsi:type="xsd:integer">All</PIN>
</Arg>
</GetAttLog>
Secara umum, format XML command tersebut terdiri atas header dan body. Header selalu sama untuk semua command (kecuali pada bagian Content-Length). Pada contoh di atas, maka headernya adalah :
POST /iWsService HTTP/1.0
Content-Type: text/xml
Content-Length: 128
dan body nya adalah :
<GetAttLog>
<ArgComKey xsi:type="xsd:integer">0</ArgComKey>
<Arg>
<PIN xsi:type="xsd:integer">All</PIN>
</Arg>
</GetAttLog>
Nilai dari Content-Length adalah panjang dari string command body. Pada contoh di atas adalah 128 karakter. Nilai ini tentu bisa berubah-ubah sesuai dengan jenis command yang diberikan.

<GetAttLog> adalah root node XML yang nama node nya menentukan jenis commandnya. GetAttLog (mungkin kependekan dari Get Attendance Log), sesuai dengan namanya, command ini untuk meminta data kehadiran/absensi yang tersimpan di dalam mesin absensi.

<ArgComKey xsi:type="xsd:integer">0</ArgComKey> , ArgComKey artinya node ini berisi password dari mesin absensi yang tipenya interger. Nilainya dalam hal ini adalah 0 (secara default, password WebService dari mesin absensi biasanya adalah 0). Ganti nilai 0 sesuai dengan password dari mesin absensi.

 <PIN xsi:type="xsd:integer">All</PIN> adalah argument/parameter dari command GetAttLog. PIN artinya adalah data absensi dari pegawai dengan PIN berapakah yang ingin diambil ? Jika nilainya All, maka artinya ambil semua data absensi yang ada. Jika misalnya disini dengan 166, maka hanya data absensi dari pegawai dengan ID 166 yang akan diambil.



OK, setelah anda mengetahui garis besar struktur XML command tersebut, maka salah satu cara mengimplementasikannya adalah dengan membuat XML command tersebut menjadi konstanta. Silahkan buat constanta seperti contoh di bawah ini pada form1.

interface

uses
  Classes, SysUtils, FileUtil, lNetComponents, Forms, Controls, Graphics,
  Dialogs, StdCtrls, Spin, lNet;

const

  COMMAND_HEADER =
    'POST /iWsService HTTP/1.0'+LineEnding+
    'Content-Type: text/xml'+LineEnding+
    'Content-Length: %d '+LineEnding+LineEnding; // 2 line end ini harus ada !!!

type




Maksud dari Content-Length: %d adalah, nilai dari Content-Length kelak akan diganti/isi sesuai dengan panjang karanter body. Nah, untuk body nya, tidak saya buatkan konstantanya, melainkan saya tuliskan langsung ke dalam Memo1. Silahkan anda isi property Lines dari Memo1 dengan string di bawah ini.

<GetAttLog>
<ArgComKey xsi:type="xsd:integer">%s</ArgComKey>
<Arg>
<PIN xsi:type="xsd:integer">All</PIN>
</Arg>
</GetAttLog>


%s di atas maksudnya adalah, nilai password dari mesin absensi kelak akan diganti dengan suatu nilai, dalam hal ini akan diisi sesuai dengan nilai yang diinput ke dalam Memo2.



Selanjutnya, tambahkan events ke dalam LTCPComponent1, yaitu pada OnConnect, OnDisconnect, OnError dan OnReceive.



Di bawah ini adalah masing-masing kodenya.

procedure TForm1.LTCPComponent1Connect(aSocket: TLSocket);
begin
  Memo2.Append('Connected');
end;

procedure TForm1.LTCPComponent1Disconnect(aSocket: TLSocket);
begin
  Memo2.Append('Disconneted');
end;

procedure TForm1.LTCPComponent1Error(const msg: string; aSocket: TLSocket);
begin
  Memo2.Append('Error --> '+msg);
end;

procedure TForm1.LTCPComponent1Receive(aSocket: TLSocket);
var
  lStr: String;
begin
  lStr :='';
  if (aSocket.GetMessage(lStr)>0) then
  begin
    Memo2.Text:=Memo2.Text+lStr;
  end;
end;

Intinya, akan muncul pesan di dalam memo2 pada saat connect, disconnect dan error. Sedangkan pada OnReceive, maka perlu cek terlebih dahulu apakah ada data yang dikirim atau tidak. Jika ada, maka tambahkan data string itu ke dalam Memo2.

Sekarang kita tambahkan event OnClick pada button1 (connect). Pada saat tombol tersebut ditekan, maka lakukan koneksi ke dalam mesin absensi dengan nilai host dan port sesuai dengan yang diinput pada edit1 dan spinedit1.

procedure TForm1.Button1Click(Sender: TObject);
begin
  if not LTCPComponent1.Connect(Edit1.Text,SpinEdit1.Value) then
     ShowMessage('Connection Fail');
end;

Terakhir, tambahkan event OnClick pada button2 (Send). Pada saat tombol tersebut ditekan, kirimkan command ke dalam mesin absensi.

procedure TForm1.Button2Click(Sender: TObject);
var
  lCmd: String;
begin
  Memo2.Clear;
  // isi password sesuai dengan yang diinput pada edit2
  lCmd :=
    Format(Memo1.Text,[Edit2.Text]);
  

  //Isi Content-Length sesuai dengan panjang body
  lCmd :=
    Format(COMMAND_HEADER,[Length(lCmd)])+
    lCmd;




  // kirimkan commend ke mesin
  LTCPComponent1.SendMessage(lCmd);
end;


Yang dilakukan kode di atas adalah, pertama nilai %s dari <ArgComKey xsi:type="xsd:integer">%s</ArgComKey> diganti dengan nilai yang diinput ke dalam Edit2 (password) dengan mengunakan prosedut format. Kemudian, nilai dari Content-Length: %d pada header diganti dengan panjang karakter body yang telah diisi dengan password. String tersebut kemudian dikirim ke mesin dengan menggunakan prosedur SendMessage dari LTCPComponent.

OK, coding selesai. Mudah-mudahan tidak terlalu mbulet ya. Sekarang saatnya build dan run aplikasi untuk melihat hasilnya. Jika semuanya berhasil dicompile tanpa masalah, maka hasilnya seperti di bawah ini.



Yups. Selamat untuk anda yang sudah berhasil. Jika belum, jangan patah semangat, silahkan coba terus.

Aplikasi kecil ini sebenarnya masih setengah jalan. Iya setengah jalan. Setelah anda berhasil melakukan koneksi, mengirim command dan menerima hasilnya, maka langkah selanjutnya adalah tentu saja parsing. String XML respond tersebut tentu harus diparsing terlebih dahulu untuk mendapatkan nilai-nilai nya. Nah, bagian tersebut adalah PR untuk anda :D . Saya yakin anda bisa bahkan mungkin sudah memiliki library sendiri untuk memparsing XML tersebut.






Source code lengkap dari aplikasi ini dapat anda download di sini. Atau versi dengan sedikit modifikasi di sini.



Tambahan :
Di bawah ini adalah beberapa XML command yang saya ketahui dari hasil browsing.

UNTUK BACA DATA ATTLOG
=============================================================
<GetAttLog>
<ArgComKey xsi:type="xsd:integer">
ComKey</ArgComKey>
<Arg>
<PIN xsi:type="xsd:integer">ID pegawai</PIN>
</Arg>
</GetAttLog>

UNTUK CLEAR ATTLOG DATA, HATI-HATI !!!
==============================================================
<ClearData>
<ArgComKey xsi:type="xsd:integer">
ComKey</ArgComKey>
<Arg><Value xsi:type="xsd:integer">3</Value></Arg>
</ClearData>


UNTUK MENAMPILKAN DATA PEGAWAI
============================================================== 
<GetUserInfo> 
<ArgComKey Xsi:type="xsd:integer">ComKey</ ArgComKey> 
<Arg> 
<PIN Xsi:type="xsd:integer">ID Pegawai</ PIN> 
</Arg> 
</GetUserInfo>


MENAMPILKAN SEMUA DATA PEGAWAI
==============================================================
<GetAllUserInfo>
<ArgComKey xsi:type="xsd:integer">ComKey</ArgComKey>
</GetAllUserInfo>

RESTART MESIN ABSENSI
==============================================================
<Restart>
<ArgComKey xsi:type="xsd:integer">ComKey</ArgComKey>
</Restart>


MEMBACA TEMPLATE FINGER PRINT
===============================================================
<GetUserTemplate>

<ArgComKey xsi:type="xsd:integer">ComKey</ArgComKey>
<Arg>
<PIN xsi:type="xsd:integer">ID Pegawai</PIN>
<FingerID xsi:type="xsd:integer">No Finger</FingerID>
</Arg>
</GetUserTemplate>



D. Prameswara
D. Prameswara Tukang ketik yang sedang belajar pemrograman #linux #android #vue #node.js
Load comments