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:
Here is the script and file structure of ZkLibrary along with its example.php:
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']); ?> </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']); ?> </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. :-(
Maybe you can use the ZK Soap PHP Library from ZK Soap PHP Library.
Can get Attendance Record with Date Range.
Just use:
No need to write a socket connection and XML payload.