getAttLog data from attendance device (Solution C1) with ZkLibrary PHP

717 Views Asked by At

I am currently developing a feature to retrieve attendance log data from the Solution C1 attendance machine using ZkLibrary. I am using LARAGON and have enabled the SOAP and SOCKET extensions in the php.ini file of LARAGON. This machine is a type that reads RFID cards. I have tried using the built-in PHP script example to download LogData from the SOAP SDK of the machine. However, I always fail to connect to the machine. The machine has an IP address of 192.168.XX.XX and port 4370.

Using ZkLibrary, I have successfully connected to the machine and retrieved 16,499 records out of a total of 20,704 records for today. However, I don't see any attendance data for the year 2023 among those 16,499 records. Interestingly, there are 12,000 records from the year 2000. I am confused about what might be causing this issue. When downloading using the desktop application, all the data for 2023 is present, around 4,000 records, but I am unable to find it. Even the data for 2022 is very limited. However, the machine has been in use since 2014. Here is an example of a SOAP request XMLRPC as mentioned in the SOAP manual guide:

**4.1.3.1 Get all information log**
**[Function]**
Read out the attendance record from attendance machines. 
**[XML protocols] 
Request Xml:**
<GetAttLog>
   <ArgComKey xsi:type="xsd:integer”>ComKey</ArgComKey>
   <Arg>
     <PIN xsi:type="xsd:integer”>Job Number</PIN>
   </Arg>
</GetAttLog>

**Response Xml:**
<GetAttLogResponse>
  <Row>
    <PIN>XXXXX</PIN>
    <DateTime >YYYY-MM-DD HH:MM:SS</DateTime>
    <Verified>X</Verified>
    <Status>X</Status>
    <WorkCode>XXXXX</WorkCode>
  </Row>
</GetAttLogResponse>
**[Parameters]** 
  ComKey: communications Password 
  PIN: User ID (Registration). 
**[Return value]** 
  If successful, return log information, or return Null. 
     Pin: User ID (Registration). 
     DateTime: Date Time. 
     Verified: Authentication method. 
     Status: Attendance status. 
     WorkCode: work code

I have tried the script to retrieve the attendance log from the SDK, as shown below:

 <html>
       <head><title>Contoh Koneksi Mesin Absensi Mengunakan SOAP Web Service</title></head>
       <body bgcolor="#caffcb">
       <H3>Download Log Data</H3>
       <
       $IP=$HTTP_GET_VARS["ip"];
       $Key=$HTTP_GET_VARS["key"];
       if($IP=="") $IP="192.168.XX.XX";
       if($Key=="") $Key="0";
       ?>

        <form action="tarik-data.php">
            IP Address: <input type="Text" name="ip" value="<?=$IP?>" size=15><BR>
            Comm Key: <input type="Text" name="key" size="5" value="<?=$Key?>"><BR><BR>

<input type="Submit" value="Download">
</form>
<BR>

<?
if($HTTP_GET_VARS["ip"]!=""){?>
    <table cellspacing="2" cellpadding="2" border="1">
    <tr align="center">
        <td><B>UserID</B></td>
        <td width="200"><B>Tanggal & Jam</B></td>
        <td><B>Verifikasi</B></td>
        <td><B>Status</B></td>
    </tr>
    <?
    $Connect = fsockopen($IP, "4370", $errno, $errstr, 1);
    if($Connect){
        $soap_request="<GetAttLog><ArgComKey xsi:type=\"xsd:integer\">".$Key."</ArgComKey><Arg><PIN xsi:type=\"xsd:integer\">All</PIN></Arg></GetAttLog>";
        $newLine="\r\n";
        fputs($Connect, "POST /iWsService HTTP/1.0".$newLine);
        fputs($Connect, "Content-Type: text/xml".$newLine);
        fputs($Connect, "Content-Length: ".strlen($soap_request).$newLine.$newLine);
        fputs($Connect, $soap_request.$newLine);
        $buffer="";
        while($Response=fgets($Connect, 1024)){
            $buffer=$buffer.$Response;
        }
    }else echo "Koneksi Gagal";
    
    include("parse.php");
    $buffer=Parse_Data($buffer,"<GetAttLogResponse>","</GetAttLogResponse>");
    $buffer=explode("\r\n",$buffer);
    for($a=0;$a<count($buffer);$a++){
        $data=Parse_Data($buffer[$a],"<Row>","</Row>");
        $PIN=Parse_Data($data,"<PIN>","</PIN>");
        $DateTime=Parse_Data($data,"<DateTime>","</DateTime>");
        $Verified=Parse_Data($data,"<Verified>","</Verified>");
        $Status=Parse_Data($data,"<Status>","</Status>");
    ?>
    <tr align="center">
            <td><?echo $PIN?></td>
            <td><?=$DateTime?></td>
            <td><?=$Verified?></td>
            <td><?=$Status?></td>
        </tr>
    <?}?>
    </table>
<?}?>

</body>
</html>

And I always get an error like this: Warning: fsockopen(): unable to connect to 192.168.xx.xx:4370 (A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.). Finally, I decided to use ZKLibrary and yes, I managed to retrieve 16,499 data as I mentioned earlier. However, there are many dates in those data that are not correct, as there are 12,000 records with the year 2000. Here is an example:enter image description here

Here is the script and file structure of ZkLibrary along with its example.php:enter image description here

Zklibrary.php:

<?php
error_reporting(0);

define('CMD_CONNECT', 1000);
define('CMD_EXIT', 1001);
define('CMD_ENABLEDEVICE', 1002);
define('CMD_DISABLEDEVICE', 1003);
define('CMD_RESTART', 1004);
define('CMD_POWEROFF', 1005);
define('CMD_SLEEP', 1006);
define('CMD_RESUME', 1007);
define('CMD_TEST_TEMP', 1011);
define('CMD_TESTVOICE', 1017);
define('CMD_VERSION', 1100);
define('CMD_CHANGE_SPEED', 1101);

define('CMD_ACK_OK', 2000);
define('CMD_ACK_ERROR', 2001);
define('CMD_ACK_DATA', 2002);
define('CMD_PREPARE_DATA', 1500);
define('CMD_DATA', 1501);

define('CMD_USER_WRQ', 8);
define('CMD_USERTEMP_RRQ', 9);
define('CMD_USERTEMP_WRQ', 10);
define('CMD_OPTIONS_RRQ', 11);
define('CMD_OPTIONS_WRQ', 12);
define('CMD_ATTLOG_RRQ', 13);
define('CMD_CLEAR_DATA', 14);
define('CMD_CLEAR_ATTLOG', 15);
define('CMD_DELETE_USER', 18);
define('CMD_DELETE_USERTEMP', 19);
define('CMD_CLEAR_ADMIN', 20);
define('CMD_ENABLE_CLOCK', 57);
define('CMD_STARTVERIFY', 60);
define('CMD_STARTENROLL', 61);
define('CMD_CANCELCAPTURE', 62);
define('CMD_STATE_RRQ', 64);
define('CMD_WRITE_LCD', 66);
define('CMD_CLEAR_LCD', 67);

define('CMD_GET_TIME', 201);
define('CMD_SET_TIME', 202);

define('USHRT_MAX', 65535);

define('LEVEL_USER', 0);          // 0000 0000
define('LEVEL_ENROLLER', 2);      // 0000 0010
define('LEVEL_MANAGER', 12);      // 0000 1100
define('LEVEL_SUPERMANAGER', 14); // 0000 1110 

class ZKLibrary
{
    public $ip = null;
    public $port = null;
    public $socket = null;
    public $session_id = 0;
    public $received_data = '';
    public $user_data = array();
    public $attendance_data = array();
    public $timeout_sec = 30;
    public $timeout_usec = 30000000;

    public function __construct($ip = null, $port = null)
    {
        if ($ip != null) {
            $this->ip = $ip;
        }
        if ($port != null) {
            $this->port = $port;
        }
        $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
        $this->setTimeout($this->timeout_sec, $this->timeout_usec);
    }
    
    //other public function
    ................
    ..............
    ..............
    ................
    ..............
    ..............
    ................
    ..............
    ..............
    
      public function getUserData()
    {
        $uid = 1;
        $command = CMD_USERTEMP_RRQ;
        $command_string = chr(5);
        $chksum = 0;
        $session_id = $this->session_id;
        $u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6/H2h7/H2h8', substr($this->received_data, 0, 8));
        $reply_id = hexdec($u['h8'] . $u['h7']);
        $buf = $this->createHeader($command, $chksum, $session_id, $reply_id, $command_string);
        socket_sendto($this->socket, $buf, strlen($buf), 0, $this->ip, $this->port);
        try {
            socket_recvfrom($this->socket, $this->received_data, 1024, 0, $this->ip, $this->port);
            $u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6', substr($this->received_data, 0, 8));
            $bytes = $this->getSizeUser();
            if ($bytes) {
                while ($bytes > 0) {
                    socket_recvfrom($this->socket, $received_data, 1032, 0, $this->ip, $this->port);
                    array_push($this->user_data, $received_data);
                    $bytes -= 1024;
                }
                $this->session_id =  hexdec($u['h6'] . $u['h5']);
                socket_recvfrom($this->socket, $received_data, 1024, 0, $this->ip, $this->port);
            }
            $users = array();
            $retdata = "";
            if (count($this->user_data) > 0) {
                for ($x = 0; $x < count($this->user_data); $x++) {
                    if ($x > 0) {
                        $this->user_data[$x] = substr($this->user_data[$x], 8);
                    }
                    if ($x > 0) {
                        $retdata .= substr($this->user_data[$x], 0);
                    } else {
                        $retdata .= substr($this->user_data[$x], 12);
                    }
                }
            }
            return $retdata;
        } catch (ErrorException $e) {
            return false;
        } catch (exception $e) {
            return false;
        }
    }
    
    
       public function getAttendance()
    {
        $command = CMD_ATTLOG_RRQ;
        $command_string = '';
        $chksum = 0;
        $session_id = $this->session_id;
        $u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6/H2h7/H2h8', substr($this->received_data, 0, 8));
        $reply_id = hexdec($u['h8'] . $u['h7']);
        $buf = $this->createHeader($command, $chksum, $session_id, $reply_id, $command_string);
        socket_sendto($this->socket, $buf, strlen($buf), 0, $this->ip, $this->port);
        try {
            socket_recvfrom($this->socket, $this->received_data, 1024, 0, $this->ip, $this->port);
            $bytes = $this->getSizeAttendance();
            if ($bytes) {
                while ($bytes > 0) {
                    socket_recvfrom($this->socket, $received_data, 1032, 0, $this->ip, $this->port);
                    array_push($this->attendance_data, $received_data);
                    $bytes -= 1024;
                }
                $this->session_id = hexdec($u['h6'] . $u['h5']);
                socket_recvfrom($this->socket, $received_data, 1024, 0, $this->ip, $this->port);
            }
            $attendance = array();
            if (count($this->attendance_data) > 0) {
                for ($x = 0; $x < count($this->attendance_data); $x++) {
                    if ($x > 0) {
                        $this->attendance_data[$x] = substr($this->attendance_data[$x], 8);
                    }
                }
                $attendance_data = implode('', $this->attendance_data);
                $attendance_data = substr($attendance_data, 10);
                echo var_dump($attendance_data);
                while (strlen($attendance_data) > 40) {
                    $u = unpack('H78', substr($attendance_data, 0, 39));
                    $u1 = hexdec(substr($u[1], 4, 2));
                    $u2 = hexdec(substr($u[1], 6, 2));
                    $uid = $u1 + ($u2 * 256);
                    $id = str_replace("\0", '', hex2bin(substr($u[1], 8, 16)));
                    $state = hexdec(substr($u[1], 56, 2));
                    $timestamp = $this->decodeTime(hexdec($this->reverseHex(substr($u[1], 58, 8))));
                    array_push($attendance, array($uid, $id, $state, $timestamp));
                    $attendance_data = substr($attendance_data, 40);
                }
            }
            return $attendance;
        } catch (exception $e) {
            return false;
        }
    }
      public function clearAttendance()
    {
        $command = CMD_CLEAR_ATTLOG;
        return $this->execCommand($command);
    }
}

TEST2.php:

<?php

require 'zklibrary.php';

$zk = new ZKLibrary('192.168.XX.XX', 4370);
$zk->connect();
$zk->disableDevice();

$users = $zk->getUser();
$log_kehadiran = $zk->getAttendance();
$absensi = $zk->getAbsensi();
//cek isi attendance isinya apa saja.
echo var_dump($users);
?>

<table width="100%" border="1" cellspacing="0" cellpadding="0" style="border-collapse:collapse;">
<thead>
  <tr>
    <td width="25">No</td>
    <td>UID</td>
    <td>ID</td>
    <td>Name</td>
    <td>Role</td>
    <td>Password</td>
  </tr>
</thead>
<tbody>
<?php
$no = 0;
foreach($log_kehadiran as $key => $uItem)
{
  $no++;
  ?>
    <tr>
        <td><?php echo $no; ?></td>
        <td><?php echo($uItem['uid']); ?></td>
        <td><?php echo($uItem['id']); ?></td>
        <td><?php echo($uItem['state']); ?></td>
        <td><?php echo($uItem['timestamp']); ?></td>
        <td><?php echo($uItem['type']); ?>&nbsp;</td>
    </tr>
  <?php
}
?>
</tbody>
</table>


<table width="100%" border="1" cellspacing="0" cellpadding="0" style="border-collapse:collapse;">
<thead>
  <tr>
    <td width="25">No</td>
    <td>UID</td>
    <td>ID</td>
    <td>State</td>
    <td>Date</td>
    <td>Time</td>
  </tr>
</thead>
<tbody>
<?php
$no = 0;

foreach($absensi as $key => $item)
{
  $no++;
  ?>
    <tr>
        <td><?php echo $no; ?></td>
        <td><?php echo($item['uid']); ?></td>
        <td><?php echo($item['id']); ?></td>
        <td><?php echo($item['state']); ?></td>
        <td><?php echo($item['date']); ?></td>
        <td><?php echo($item['time']); ?>&nbsp;</td>
    </tr>
  <?php
}

echo var_dump($absensi);
?>
</tbody>
</table>

<?php

$zk->enableDevice();
$zk->disconnect();

?>


                        
            

What should I do to retrieve the 4,000 attendance data from the machine using ZkLibrary? Or is there any other solution to get the attendance log from the machine? I kindly ask for your help, I'm really confused. I have searched for some tutorials, but none of them seem to work. :-(

1

There are 1 best solutions below

0
Muhammad Fahri On

Maybe you can use the ZK Soap PHP Library from ZK Soap PHP Library.

Can get Attendance Record with Date Range.

Just use:

// reference the ZK Soap PHP namespace
use Fahriztx\Zksoapphp\Fingerprint;

// initial
$machine = Fingerprint::connect('192.168.1.175', '80', '123456');

// get machine status
echo "Machine Status : ".$machine->getStatus(); // connect | disconnect

// get all log data
print_r($machine->getAttendance()); // return Array of Attendance Log

// get all log data with date
print_r($machine->getAttendance('all', '2022-05-01')); // return Array of Attendance Log

// get all log data with date range
print_r($machine->getAttendance('all', '2022-05-01', '2022-05-10')); // return Array of Attendance Log

// get specific pin log data
print_r($machine->getAttendance(1)); // return Array of Attendance Log
// OR Array
print_r($machine->getAttendance([1, 2])); // return Array of Attendance Log

No need to write a socket connection and XML payload.