[
  {
    "path": "CHANGELOG.md",
    "content": ""
  },
  {
    "path": "README.md",
    "content": "# ZKTeco - Laravel Library #\n\n[![Issues](https://img.shields.io/github/issues/raihanafroz/zkteco?style=flat-square)](https://github.com/raihanafroz/zkteco/issues)\n[![Forks](https://img.shields.io/github/forks/raihanafroz/zkteco?style=flat-square)](https://github.com/raihanafroz/zkteco/network/members)\n[![Stars](https://img.shields.io/github/stars/raihanafroz/zkteco?style=flat-square)](https://github.com/raihanafroz/zkteco/stargazers)\n[![Total Downloads](https://img.shields.io/packagist/dt/rats/zkteco?style=flat-square)](https://packagist.org/packages/rats/zkteco)\n[![License](https://poser.pugx.org/rats/zkteco/license.svg)](https://packagist.org/packages/rats/zkteco)\n\n\nThe `rats/zkteco` package provides easy to use functions to ZKTeco Device activities.\n\n__Requires:__  **Laravel** >= **6.0**\n\n__License:__ MIT or later\n\n## Installation:\nYou can install the package via composer:\n\n``` bash\ncomposer require rats/zkteco\n```\nThe package will automatically register itself.\n\nYou have to enable your php socket if it is not enable. \n\n\n## Usage\n\n1. Create a object of ZKTeco class.\n\n```php\n    use Rats\\Zkteco\\Lib\\ZKTeco;\n\n//  1 s't parameter is string $ip Device IP Address\n//  2 nd  parameter is integer $port Default: 4370\n  \n    $zk = new ZKTeco('192.168.1.201');\n    \n//  or you can use with port\n//    $zk = new ZKTeco('192.168.1.201', 8080);\n    \n```\n\n2. Call ZKTeco methods\n\n* __Connect__ \n```php\n//    connect\n//    this return bool\n    $zk->connect();   \n```\n\n* __Disconnect__ \n```php\n//    disconnect\n//    this return bool\n\n    $zk->disconnect();   \n```\n\n* __Enable Device__ \n```php\n//    enable\n//    this return bool/mixed\n\n    $zk->enableDevice();   \n```\n> **NOTE**: You have to call after read/write any info of Device.\n\n* __Disable Device__ \n```php\n//    disable \n//    this return bool/mixed\n\n    $zk->disableDevice(); \n```\n> **NOTE**: You have to call before read/write any info of Device. \n\n\n* __Device Version__ \n```php\n//    get device version \n//    this return bool/mixed\n\n    $zk->version(); \n```\n\n\n* __Device Os Version__ \n```php\n//    get device os version \n//    this return bool/mixed\n\n    $zk->osVersion(); \n```\n\n* __Power Off__ \n```php\n//    turn off the device \n//    this return bool/mixed\n\n    $zk->shutdown(); \n```\n\n* __Restart__ \n```php\n//    restart the device \n//    this return bool/mixed\n\n    $zk->restart(); \n```\n\n* __Sleep__ \n```php\n//    sleep the device \n//    this return bool/mixed\n\n    $zk->sleep(); \n```\n\n* __Resume__ \n```php\n//    resume the device from sleep \n//    this return bool/mixed\n\n    $zk->resume(); \n```\n\n* __Voice Test__ \n```php\n//    voice test of the device \"Thank you\" \n//    this return bool/mixed\n\n    $zk->testVoice(); \n```\n\n* __Platform__ \n```php\n//    get platform \n//    this return bool/mixed\n\n    $zk->platform(); \n```\n\n* __Firmware Version__ \n```php\n//    get firmware version\n//    this return bool/mixed\n\n    $zk->fmVersion(); \n```\n\n* __Work Code__ \n```php\n//    get work code\n//    this return bool/mixed\n\n    $zk->workCode(); \n```\n\n* __SSR__ \n```php\n//    get SSR\n//    this return bool/mixed\n\n    $zk->ssr(); \n```\n\n* __Pin Width__ \n```php\n//    get  Pin Width\n//    this return bool/mixed\n\n    $zk->pinWidth(); \n```\n\n* __Serial Number__ \n```php\n//    get device serial number\n//    this return bool/mixed\n\n    $zk->serialNumber(); \n```\n\n* __Device Name__ \n```php\n//    get device name\n//    this return bool/mixed\n\n    $zk->deviceName(); \n```\n\n* __Get Device Time__ \n```php\n//    get device time\n\n//    return bool/mixed bool|mixed Format: \"Y-m-d H:i:s\"\n\n    $zk->getTime(); \n```\n\n* __Set Device Time__ \n```php\n//    set device time\n//    parameter string $t Format: \"Y-m-d H:i:s\"\n//    return bool/mixed\n\n    $zk->setTime(); \n```\n\n* __Get Users__ \n```php\n//    get User\n//    this return array[]\n\n    $zk->getUser(); \n```\n\n* __Set Users__ \n```php\n//    set user\n\n//    1 s't parameter int $uid Unique ID (max 65535)\n//    2 nd parameter int|string $userid ID in DB (same like $uid, max length = 9, only numbers - depends device setting)\n//    3 rd parameter string $name (max length = 24)\n//    4 th parameter int|string $password (max length = 8, only numbers - depends device setting)\n//    5 th parameter int $role Default Util::LEVEL_USER\n//    6 th parameter int $cardno Default 0 (max length = 10, only numbers\n\n//    return bool|mixed\n\n    $zk->setUser(); \n```\n\n* __Clear All Admin__ \n```php\n//    remove all admin\n//    return bool|mixed\n\n    $zk->clearAdmin(); \n```\n\n* __Clear All Users__ \n```php\n//    remove all users\n//    return bool|mixed\n\n    $zk->clearAdmin(); \n```\n\n* __Remove A User__ \n```php\n//    remove a user by $uid\n//    parameter integer $uid\n//    return bool|mixed\n\n    $zk->removeUser(); \n```\n\n* __Get Attendance Log__ \n```php\n//    get attendance log\n\n//    return array[]\n\n//    like as 0 => array:5 [▼\n//              \"uid\" => 1      /* serial number of the attendance */\n//              \"id\" => \"1\"     /* user id of the application */\n//              \"state\" => 1    /* the authentication type, 1 for Fingerprint, 4 for RF Card etc */\n//              \"timestamp\" => \"2020-05-27 21:21:06\" /* time of attendance */\n//              \"type\" => 255   /* attendance type, like check-in, check-out, overtime-in, overtime-out, break-in & break-out etc. if attendance type is none of them, it gives  255. */\n//              ]\n\n    $zk->getAttendance(); \n```\n\n* __Clear Attendance Log__ \n```php\n//    clear attendance log\n\n//    return bool/mixed\n\n    $zk->clearAttendance(); \n```\n\n\n\n\n\n\n\n# end\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"rats/zkteco\",\n    \"description\": \"ZKTeco Laravel Library\",\n    \"type\": \"library\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Raihan Afroz\",\n            \"email\": \"raihanafroz9@gmail.com\"\n        }\n    ],\n    \"autoload\": {\n      \"psr-4\":{\n          \"Rats\\\\Zkteco\\\\\": \"src\"\n      }\n    },\n    \"minimum-stability\": \"dev\",\n    \"require\": {}\n}\n"
  },
  {
    "path": "src/Lib/Helper/Attendance.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Attendance\n{\n    /**\n     * @param ZKTeco $self\n     * @return array [uid, id, state, timestamp]\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_ATT_LOG_RRQ;\n        $command_string = '';\n\n        $session = $self->_command($command, $command_string, Util::COMMAND_TYPE_DATA);\n        if ($session === false) {\n            return [];\n        }\n\n        $attData = Util::recData($self);\n\n        $attendance = [];\n        if (!empty($attData)) {\n            $attData = substr($attData, 10);\n\n            while (strlen($attData) > 40) {\n                $u = unpack('H78', substr($attData, 0, 39));\n\n                $u1 = hexdec(substr($u[1], 4, 2));\n                $u2 = hexdec(substr($u[1], 6, 2));\n                $uid = $u1 + ($u2 * 256);\n                $id = hex2bin(substr($u[1], 8, 18));\n                $id = str_replace(chr(0), '', $id);\n                $state = hexdec(substr($u[1], 56, 2));\n                $timestamp = Util::decodeTime(hexdec(Util::reverseHex(substr($u[1], 58, 8))));\n                $type = hexdec(Util::reverseHex(substr($u[1], 66, 2 )));\n\t\t\t\t\n                $attendance[] = [\n                    'uid' => $uid,\n                    'id' => $id,\n                    'state' => $state,\n                    'timestamp' => $timestamp,\n                    'type' => $type\n                ];\n\n                $attData = substr($attData, 40);\n            }\n\n        }\n\n        return $attendance;\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function clear(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_CLEAR_ATT_LOG;\n        $command_string = '';\n\n        return $self->_command($command, $command_string);\n    }\n}\n"
  },
  {
    "path": "src/Lib/Helper/Connect.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\Helper\\Util;\nuse Rats\\Zkteco\\Lib\\ZKTeco;\nuse ErrorException;\nuse Exception;\n\nclass Connect\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool\n     */\n    static public function connect(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_CONNECT;\n        $command_string = '';\n        $chksum = 0;\n        $session_id = 0;\n        $reply_id = -1 + Util::USHRT_MAX;\n\n        $buf = Util::createHeader($command, $chksum, $session_id, $reply_id, $command_string);\n\n        socket_sendto($self->_zkclient, $buf, strlen($buf), 0, $self->_ip, $self->_port);\n\n        try {\n            @socket_recvfrom($self->_zkclient, $self->_data_recv, 1024, 0, $self->_ip, $self->_port);\n            if (strlen($self->_data_recv) > 0) {\n                $u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6', substr($self->_data_recv, 0, 8));\n\n                $session = hexdec($u['h6'] . $u['h5']);\n                if (empty($session)) {\n                    return false;\n                }\n\n                $self->_session_id = $session;\n                return Util::checkValid($self->_data_recv);\n            } else {\n                return false;\n            }\n        } catch (ErrorException $e) {\n            return false;\n        } catch (Exception $e) {\n            return false;\n        }\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @return bool\n     */\n    static public function disconnect(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_EXIT;\n        $command_string = '';\n        $chksum = 0;\n        $session_id = $self->_session_id;\n\n        $u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6/H2h7/H2h8', substr($self->_data_recv, 0, 8));\n        $reply_id = hexdec($u['h8'] . $u['h7']);\n\n        $buf = Util::createHeader($command, $chksum, $session_id, $reply_id, $command_string);\n\n\n        socket_sendto($self->_zkclient, $buf, strlen($buf), 0, $self->_ip, $self->_port);\n        try {\n            @socket_recvfrom($self->_zkclient, $self->_data_recv, 1024, 0, $self->_ip, $self->_port);\n\n            $self->_session_id = 0;\n            return Util::checkValid($self->_data_recv);\n        } catch (ErrorException $e) {\n            return false;\n        } catch (Exception $e) {\n            return false;\n        }\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/Device.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Device\n{\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed\n   */\n  static public function name(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_DEVICE;\n    $command_string = '~DeviceName';\n\n    return $self->_command($command, $command_string);\n  }\n\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed\n   */\n  static public function enable(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_ENABLE_DEVICE;\n    $command_string = '';\n\n    return $self->_command($command, $command_string);\n  }\n\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed\n   */\n  static public function disable(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_DISABLE_DEVICE;\n    $command_string = chr(0) . chr(0);\n\n    return $self->_command($command, $command_string);\n  }\n\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed *** this will turn off the device\n   */\n  public static function powerOff(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_POWEROFF;\n    $command_string = chr(0) . chr(0);\n    return $self->_command($command, $command_string);\n  }\n\n\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed *** this will restart the device\n   */\n  public static function restart(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_RESTART;\n    $command_string = chr(0) . chr(0);\n    return $self->_command($command, $command_string);\n  }\n\n\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed *** this will sleep the device\n   */\n  public static function sleep(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_SLEEP;\n    $command_string = chr(0) . chr(0);\n    return $self->_command($command, $command_string);\n  }\n\n\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed *** this will resume the device from sleep\n   */\n  public static function resume(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_RESUME;\n    $command_string = chr(0) . chr(0);\n    return $self->_command($command, $command_string);\n  }\n\n\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed *** this will play voice \"Thank you\"\n   */\n  public static function testVoice(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_TESTVOICE;\n    $command_string = chr(0) . chr(0);\n    return $self->_command($command, $command_string);\n  }\n\n\n  /**\n   * @param ZKTeco $self\n   * @return bool|mixed *** this will clear the LCD screen\n   */\n  public static function clearLCD(ZKTeco $self)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_CLEAR_LCD;\n    return $self->_command($command, '');\n  }\n\n\n  /**\n   * @param ZKTeco $self\n   * @param $rank *** Line number of text\n   * @param $text *** Text which will display in the LCD screen\n   * @return bool|mixed *** this will write text into the LCD\n   */\n  public static function writeLCD(ZKTeco $self, $rank, $text)\n  {\n    $self->_section = __METHOD__;\n\n    $command = Util::CMD_WRITE_LCD;\n    $byte1 = chr((int)($rank % 256));\n    $byte2 = chr((int)($rank >> 8));\n    $byte3 = chr(0);\n    $command_string = $byte1.$byte2.$byte3.' '.$text;\n    return $self->_command($command, $command_string);\n  }\n}"
  },
  {
    "path": "src/Lib/Helper/Face.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Face\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function on(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DEVICE;\n        $command_string = 'FaceFunOn';\n\n        return $self->_command($command, $command_string);\n    }\n}\n\n"
  },
  {
    "path": "src/Lib/Helper/Fingerprint.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Fingerprint\n{\n    /**\n     * TODO: Can get data, but don't know how to parse the data. Need more documentation about it...\n     *\n     * @param ZKTeco $self\n     * @param integer $uid Unique Employee ID in ZK device\n     * @return array Binary fingerprint data array (where key is finger ID (0-9))\n     */\n    static public function get(ZKTeco $self, $uid)\n    {\n        $self->_section = __METHOD__;\n\n        $data = [];\n        //fingers of the hands\n        for ($i = 0; $i <= 9; $i++) {\n          $finger = new Fingerprint();\n            $tmp = $finger->_getFinger($self, $uid, $i);\n            if ($tmp['size'] > 0) {\n                $data[$i] = $tmp['tpl'];\n            }\n            unset($tmp);\n        }\n        return $data;\n    }\n\n\n    /**\n     * @param ZKTeco $self\n     * @param integer $uid Unique Employee ID in ZK device\n     * @param integer $finger Finger ID (0-9)\n     * @return array\n     */\n    private function _getFinger(ZKTeco $self, $uid, $finger)\n    {\n        $command = Util::CMD_USER_TEMP_RRQ;\n        $byte1 = chr((int)($uid % 256));\n        $byte2 = chr((int)($uid >> 8));\n        $command_string = $byte1 . $byte2 . chr($finger);\n\n        $ret = [\n            'size' => 0,\n            'tpl' => ''\n        ];\n\n        $session = $self->_command($command, $command_string, Util::COMMAND_TYPE_DATA);\n        if ($session === false) {\n            return $ret;\n        }\n\n        $data = Util::recData($self, 10, false);\n\n        if (!empty($data)) {\n            $templateSize = strlen($data);\n            $prefix = chr($templateSize % 256) . chr(round($templateSize / 256)) . $byte1 . $byte2 . chr($finger) . chr(1);\n            $data = $prefix . $data;\n            if (strlen($templateSize) > 0) {\n                $ret['size'] = $templateSize;\n                $ret['tpl'] = $data;\n            }\n        }\n\n        return $ret;\n    }\n\n    /**\n     * TODO: Still can not set fingerprint. Need more documentation about it...\n     *\n     * @param ZKTeco $self\n     * @param int $uid Unique Employee ID in ZK device\n     * @param array $data Binary fingerprint data array (where key is finger ID (0-9) same like returned array from 'get' method)\n     * @return int Count of added fingerprints\n     */\n    static public function set(ZKTeco $self, $uid, array $data)\n    {\n        $self->_section = __METHOD__;\n\n\n        $count = 0;\n        foreach ($data as $finger => $item) {\n            $allowSet = true;\n            $fingerPrint = new Fingerprint();\n            if ($fingerPrint->_checkFinger($self, $uid, $finger) === true) {\n                $allowSet = $fingerPrint->_removeFinger($self, $uid, $finger);\n            }\n            if ($allowSet === true && $fingerPrint->_setFinger($self, $item) === true) {\n                $count++;\n            }\n        }\n\n        return $count;\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @param string $data Binary fingerprint data item\n     * @return bool|mixed\n     */\n    private function _setFinger(ZKTeco $self, $data)\n    {\n        $command = Util::CMD_USER_TEMP_WRQ;\n        $command_string = $data;\n\n        return $self->_command($command, $command_string);\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @param int $uid Unique Employee ID in ZK device\n     * @param array $data Fingers ID array (0-9)\n     * @return int Count of deleted fingerprints\n     */\n    static public function remove(ZKTeco $self, $uid, array $data)\n    {\n        $self->_section = __METHOD__;\n\n        $count = 0;\n        foreach ($data as $finger) {\n          $fingerPrint = new Fingerprint();\n            if ($fingerPrint->_checkFinger($self, $uid, $finger) === true) {\n                if ($fingerPrint->_removeFinger($self, $uid, $finger) === true) {\n                    $count++;\n                }\n            }\n        }\n\n        return $count;\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @param int $uid Unique Employee ID in ZK device\n     * @param int $finger Finger ID (0-9)\n     * @return bool\n     */\n    private function _removeFinger(ZKTeco $self, $uid, $finger)\n    {\n        $command = Util::CMD_DELETE_USER_TEMP;\n        $byte1 = chr((int)($uid % 256));\n        $byte2 = chr((int)($uid >> 8));\n        $command_string = ($byte1 . $byte2) . chr($finger);\n\n        $self->_command($command, $command_string);\n        $fingerPrint = new Fingerprint();\n        return !($fingerPrint->_checkFinger($self, $uid, $finger));\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @param int $uid Unique Employee ID in ZK device\n     * @param int $finger Finger ID (0-9)\n     * @return bool Returned true if exist\n     */\n    private function _checkFinger(ZKTeco $self, $uid, $finger)\n    {\n      $fingerPrint = new Fingerprint();\n        $res = $fingerPrint->_getFinger($self, $uid, $finger);\n        return (bool)($res['size'] > 0);\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/Os.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Os\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DEVICE;\n        $command_string = '~OS';\n\n        return $self->_command($command, $command_string);\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/Pin.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Pin\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function width(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DEVICE;\n        $command_string = '~PIN2Width';\n\n        return $self->_command($command, $command_string);\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/Platform.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Platform\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DEVICE;\n        $command_string = '~Platform';\n\n        return $self->_command($command, $command_string);\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function getVersion(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DEVICE;\n        $command_string = '~ZKFPVersion';\n\n        return $self->_command($command, $command_string);\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/SerialNumber.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass SerialNumber\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DEVICE;\n        $command_string = '~SerialNumber';\n\n        return $self->_command($command, $command_string);\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/Ssr.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Ssr\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DEVICE;\n        $command_string = '~SSR';\n\n        return $self->_command($command, $command_string);\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/Time.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Time\n{\n    /**\n     * @param ZKTeco $self\n     * @param string $t Format: \"Y-m-d H:i:s\"\n     * @return bool|mixed\n     */\n    static public function set(ZKTeco $self, $t)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_SET_TIME;\n        $command_string = pack('I', Util::encodeTime($t));\n\n        return $self->_command($command, $command_string);\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_GET_TIME;\n        $command_string = '';\n\n        $ret = $self->_command($command, $command_string);\n\n        if ($ret) {\n            return Util::decodeTime(hexdec(Util::reverseHex(bin2hex($ret))));\n        } else {\n            return false;\n        }\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/User.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass User\n{\n    /**\n     * @param ZKTeco $self\n     * @param int $uid Unique ID (max 65535)\n     * @param int|string $userid (max length = 9, only numbers - depends device setting)\n     * @param string $name (max length = 24)\n     * @param int|string $password (max length = 8, only numbers - depends device setting)\n     * @param int $role Default Util::LEVEL_USER\n     * @param int $cardno Default 0 (max length = 10, only numbers)\n     * @return bool|mixed\n     */\n    static public function set(ZKTeco $self, $uid, $userid, $name, $password, $role = Util::LEVEL_USER, $cardno = 0)\n    {\n        $self->_section = __METHOD__;\n\n        if (\n            (int)$uid === 0 ||\n            (int)$uid > Util::USHRT_MAX ||\n            strlen($userid) > 9 ||\n            strlen($name) > 24 ||\n            strlen($password) > 8 ||\n            strlen($cardno) > 10\n        ) {\n            return false;\n        }\n\n        $command = Util::CMD_SET_USER;\n        $byte1 = chr((int)($uid % 256));\n        $byte2 = chr((int)($uid >> 8));\n        $cardno = hex2bin(Util::reverseHex(dechex($cardno)));\n\n        $command_string = implode('', [\n            $byte1,\n            $byte2,\n            chr($role),\n            str_pad($password, 8, chr(0)),\n            str_pad($name, 24, chr(0)),\n            str_pad($cardno, 4, chr(0)),\n            str_pad(chr(1), 9, chr(0)),\n            str_pad($userid, 9, chr(0)),\n            str_repeat(chr(0), 15)\n        ]);\n//        die($command_string);\n        return $self->_command($command, $command_string);\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @return array [userid, name, cardno, uid, role, password]\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_USER_TEMP_RRQ;\n        $command_string = chr(Util::FCT_USER);\n\n        $session = $self->_command($command, $command_string, Util::COMMAND_TYPE_DATA);\n        if ($session === false) {\n            return [];\n        }\n\n        $userData = Util::recData($self);\n\n        $users = [];\n        if (!empty($userData)) {\n            $userData = substr($userData, 11);\n\n            while (strlen($userData) > 72) {\n                $u = unpack('H144', substr($userData, 0, 72));\n\n                $u1 = hexdec(substr($u[1], 2, 2));\n                $u2 = hexdec(substr($u[1], 4, 2));\n                $uid = $u1 + ($u2 * 256);\n                $cardno = hexdec(substr($u[1], 78, 2) . substr($u[1], 76, 2) . substr($u[1], 74, 2) . substr($u[1], 72, 2)) . ' ';\n                $role = hexdec(substr($u[1], 6, 2)) . ' ';\n                $password = hex2bin(substr($u[1], 8, 16)) . ' ';\n                $name = hex2bin(substr($u[1], 24, 74)) . ' ';\n                $userid = hex2bin(substr($u[1], 98, 72)) . ' ';\n\n                //Clean up some messy characters from the user name\n                $password = explode(chr(0), $password, 2);\n                $password = $password[0];\n                $userid = explode(chr(0), $userid, 2);\n                $userid = $userid[0];\n                $name = explode(chr(0), $name, 3);\n                $name = utf8_encode($name[0]);\n                $cardno = str_pad($cardno, 11, '0', STR_PAD_LEFT);\n\n                if ($name == '') {\n                    $name = $userid;\n                }\n\n                $users[$userid] = [\n                    'uid' => $uid,\n                    'userid' => $userid,\n                    'name' => $name,\n                    'role' => intval($role),\n                    'password' => $password,\n                    'cardno' => $cardno,\n                ];\n\n                $userData = substr($userData, 72);\n            }\n        }\n\n        return $users;\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function clear(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_CLEAR_DATA;\n        $command_string = '';\n\n        return $self->_command($command, $command_string);\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function clearAdmin(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_CLEAR_ADMIN;\n        $command_string = '';\n\n        return $self->_command($command, $command_string);\n    }\n\n    /**\n     * @param ZKTeco $self\n     * @param integer $uid\n     * @return bool|mixed\n     */\n    static public function remove(ZKTeco $self, $uid)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DELETE_USER;\n        $byte1 = chr((int)($uid % 256));\n        $byte2 = chr((int)($uid >> 8));\n        $command_string = ($byte1 . $byte2);\n\n        return $self->_command($command, $command_string);\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/Util.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Util\n{\n  const USHRT_MAX = 65535;\n\n  const CMD_CONNECT = 1000; # Connections requests\n  const CMD_EXIT = 1001; # Disconnection requests\n  const CMD_ENABLE_DEVICE = 1002; # Ensure the machine to be at the normal work condition\n  const CMD_DISABLE_DEVICE = 1003; # Make the machine to be at the shut-down condition, generally demonstrates ‘in the work ...’on LCD\n\n  const CMD_RESTART = 1004; # Restart the machine\n  const CMD_POWEROFF = 1005; # Turn Off the machine\n  const CMD_SLEEP = 1006; # Sleep the machine\n  const CMD_RESUME = 1007; # Resume the machine from Sleep\n  const CMD_TEST_TEMP = 1011;\n  const CMD_TESTVOICE = 1017; # Voice test to the device\n  const CMD_CHANGE_SPEED = 1101;\n\n\n  const CMD_WRITE_LCD = 66; # Write in LCD\n  const CMD_CLEAR_LCD = 67; # Clear LCD\n\n  const CMD_ACK_OK = 2000; # Return value for order perform successfully\n  const CMD_ACK_ERROR = 2001; # Return value for order perform failed\n  const CMD_ACK_DATA = 2002; # Return data\n  const CMD_ACK_UNAUTH = 2005; # Connection unauthorized\n\n  const CMD_PREPARE_DATA = 1500; # Prepares to transmit the data\n  const CMD_DATA = 1501; # Transmit a data packet\n  const CMD_FREE_DATA = 1502; # Clear machines open buffer\n\n  const CMD_USER_TEMP_RRQ = 9; # Read some fingerprint template or some kind of data entirely\n  const CMD_ATT_LOG_RRQ = 13; # Read all attendance record\n  const CMD_CLEAR_DATA = 14; # Clear Data\n  const CMD_CLEAR_ATT_LOG = 15; # Clear attendance records\n\n  const CMD_GET_TIME = 201; # Obtain the machine time\n  const CMD_SET_TIME = 202; # Set machines time\n\n  const CMD_VERSION = 1100; # Obtain the firmware edition\n  const CMD_DEVICE = 11; # Read in the machine some configuration parameter\n\n  const CMD_SET_USER = 8; # Upload the user information (from PC to terminal).\n  const CMD_USER_TEMP_WRQ = 10; # Upload some fingerprint template\n  const CMD_DELETE_USER = 18; # Delete some user\n  const CMD_DELETE_USER_TEMP = 19; # Delete some fingerprint template\n  const CMD_CLEAR_ADMIN = 20; # Cancel the manager\n\n  const LEVEL_USER = 0; # User level as User\n  const LEVEL_ADMIN = 14; # User level as Admin\n\n  const FCT_ATTLOG = 1;\n  const FCT_WORKCODE = 8;\n  const FCT_FINGERTMP = 2;\n  const FCT_OPLOG = 4;\n  const FCT_USER = 5;\n  const FCT_SMS = 6;\n  const FCT_UDATA = 7;\n\n  const COMMAND_TYPE_GENERAL = 'general';\n  const COMMAND_TYPE_DATA = 'data';\n\n  const ATT_STATE_FINGERPRINT = 1;\n  const ATT_STATE_PASSWORD = 0;\n  const ATT_STATE_CARD = 2;\n\n  const ATT_TYPE_CHECK_IN = 0;\n  const ATT_TYPE_CHECK_OUT = 1;\n  const ATT_TYPE_OVERTIME_IN = 4;\n  const ATT_TYPE_OVERTIME_OUT = 5;\n\n  /**\n   * Encode a timestamp send at the timeclock\n   * copied from zkemsdk.c - EncodeTime\n   *\n   * @param string $t Format: \"Y-m-d H:i:s\"\n   * @return int\n   */\n  static public function encodeTime($t)\n  {\n    $timestamp = strtotime($t);\n    $t = (object)[\n      'year' => (int)date('Y', $timestamp),\n      'month' => (int)date('m', $timestamp),\n      'day' => (int)date('d', $timestamp),\n      'hour' => (int)date('H', $timestamp),\n      'minute' => (int)date('i', $timestamp),\n      'second' => (int)date('s', $timestamp),\n    ];\n\n    $d = (($t->year % 100) * 12 * 31 + (($t->month - 1) * 31) + $t->day - 1) *\n      (24 * 60 * 60) + ($t->hour * 60 + $t->minute) * 60 + $t->second;\n\n    return $d;\n  }\n\n  /**\n   * Decode a timestamp retrieved from the timeclock\n   * copied from zkemsdk.c - DecodeTime\n   *\n   * @param int|string $t\n   * @return false|string Format: \"Y-m-d H:i:s\"\n   */\n  static public function decodeTime($t)\n  {\n    $second = $t % 60;\n    $t = $t / 60;\n\n    $minute = $t % 60;\n    $t = $t / 60;\n\n    $hour = $t % 24;\n    $t = $t / 24;\n\n    $day = $t % 31 + 1;\n    $t = $t / 31;\n\n    $month = $t % 12 + 1;\n    $t = $t / 12;\n\n    $year = floor($t + 2000);\n\n    $d = date('Y-m-d H:i:s', strtotime(\n      $year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $minute . ':' . $second\n    ));\n\n    return $d;\n  }\n\n  /**\n   * @param string $hex\n   * @return string\n   */\n  static public function reverseHex($hex)\n  {\n    $tmp = '';\n\n    for ($i = strlen($hex); $i >= 0; $i--) {\n      $tmp .= substr($hex, $i, 2);\n      $i--;\n    }\n\n    return $tmp;\n  }\n\n  /**\n   * Checks a returned packet to see if it returned self::CMD_PREPARE_DATA,\n   * indicating that data packets are to be sent\n   * Returns the amount of bytes that are going to be sent\n   *\n   * @param ZKTeco $self\n   * @return bool|number\n   */\n  static public function getSize(ZKTeco $self)\n  {\n    $u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6/H2h7/H2h8', substr($self->_data_recv, 0, 8));\n    $command = hexdec($u['h2'] . $u['h1']);\n\n    if ($command == self::CMD_PREPARE_DATA) {\n      $u = unpack('H2h1/H2h2/H2h3/H2h4', substr($self->_data_recv, 8, 4));\n      $size = hexdec($u['h4'] . $u['h3'] . $u['h2'] . $u['h1']);\n      return $size;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * This function calculates the chksum of the packet to be sent to the\n   * time clock\n   * Copied from zkemsdk.c\n   *\n   * @inheritdoc\n   */\n  static public function createChkSum($p)\n  {\n    $l = count($p);\n    $chksum = 0;\n    $i = $l;\n    $j = 1;\n    while ($i > 1) {\n      $u = unpack('S', pack('C2', $p['c' . $j], $p['c' . ($j + 1)]));\n\n      $chksum += $u[1];\n\n      if ($chksum > self::USHRT_MAX) {\n        $chksum -= self::USHRT_MAX;\n      }\n      $i -= 2;\n      $j += 2;\n    }\n\n    if ($i) {\n      $chksum = $chksum + $p['c' . strval(count($p))];\n    }\n\n    while ($chksum > self::USHRT_MAX) {\n      $chksum -= self::USHRT_MAX;\n    }\n\n    if ($chksum > 0) {\n      $chksum = -($chksum);\n    } else {\n      $chksum = abs($chksum);\n    }\n\n    $chksum -= 1;\n    while ($chksum < 0) {\n      $chksum += self::USHRT_MAX;\n    }\n\n    return pack('S', $chksum);\n  }\n\n  /**\n   * This function puts a the parts that make up a packet together and\n   * packs them into a byte string\n   *\n   * @inheritdoc\n   */\n  static public function createHeader($command, $chksum, $session_id, $reply_id, $command_string)\n  {\n    $buf = pack('SSSS', $command, $chksum, $session_id, $reply_id) . $command_string;\n\n    $buf = unpack('C' . (8 + strlen($command_string)) . 'c', $buf);\n\n    $u = unpack('S', self::createChkSum($buf));\n\n    if (is_array($u)) {\n      $u = reset($u);\n    }\n    $chksum = $u;\n\n    $reply_id += 1;\n\n    if ($reply_id >= self::USHRT_MAX) {\n      $reply_id -= self::USHRT_MAX;\n    }\n\n    $buf = pack('SSSS', $command, $chksum, $session_id, $reply_id);\n\n    return $buf . $command_string;\n\n  }\n\n  /**\n   * Checks a returned packet to see if it returned Util::CMD_ACK_OK,\n   * indicating success\n   *\n   * @inheritdoc\n   */\n  static public function checkValid($reply)\n  {\n    $u = unpack('H2h1/H2h2', substr($reply, 0, 8));\n\n    $command = hexdec($u['h2'] . $u['h1']);\n    /** TODO: Some device can return 'Connection unauthorized' then should check also */\n    if ($command == self::CMD_ACK_OK || $command == self::CMD_ACK_UNAUTH) {\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * Get User Role string\n   * @param integer $role\n   * @return string\n   */\n  static public function getUserRole($role)\n  {\n    switch ($role) {\n      case self::LEVEL_USER:\n        $ret = 'User';\n        break;\n      case self::LEVEL_ADMIN:\n        $ret = 'Admin';\n        break;\n      default:\n        $ret = 'Unknown';\n    }\n\n    return $ret;\n  }\n\n  /**\n   * Get Attendance State string\n   * @param integer $state\n   * @return string\n   */\n  static public function getAttState($state)\n  {\n    switch ($state) {\n      case self::ATT_STATE_FINGERPRINT:\n        $ret = 'Fingerprint';\n        break;\n      case self::ATT_STATE_PASSWORD:\n        $ret = 'Password';\n        break;\n      case self::ATT_STATE_CARD:\n        $ret = 'Card';\n        break;\n      default:\n        $ret = 'Unknown';\n    }\n\n    return $ret;\n  }\n\n  /**\n   * Get Attendance Type string\n   * @param integer $type\n   * @return string\n   */\n  static public function getAttType($type)\n  {\n    switch ($type) {\n      case self::ATT_TYPE_CHECK_IN:\n        $ret = 'Check-in';\n        break;\n      case self::ATT_TYPE_CHECK_OUT:\n        $ret = 'Check-out';\n        break;\n      case self::ATT_TYPE_OVERTIME_IN:\n        $ret = 'Overtime-in';\n        break;\n      case self::ATT_TYPE_OVERTIME_OUT:\n        $ret = 'Overtime-out';\n        break;\n      default:\n        $ret = 'Undefined';\n    }\n\n    return $ret;\n  }\n\n  /**\n   * Receive data from device\n   * @param ZKTeco $self\n   * @param int $maxErrors\n   * @param bool $first if 'true' don't remove first 4 bytes for first row\n   * @return string\n   */\n  static public function recData(ZKTeco $self, $maxErrors = 10, $first = true)\n  {\n    $data = '';\n    $bytes = self::getSize($self);\n\n    if ($bytes) {\n      $received = 0;\n      $errors = 0;\n\n      while ($bytes > $received) {\n        $ret = @socket_recvfrom($self->_zkclient, $dataRec, 1032, 0, $self->_ip, $self->_port);\n\n        if ($ret === false) {\n          if ($errors < $maxErrors) {\n            //try again if false\n            $errors++;\n            sleep(1);\n            continue;\n          } else {\n            //return empty if has maximum count of errors\n            self::logReceived($self, $received, $bytes);\n            unset($data);\n            return '';\n          }\n        }\n\n        if ($first === false) {\n          //The first 4 bytes don't seem to be related to the user\n          $dataRec = substr($dataRec, 8);\n        }\n\n        $data .= $dataRec;\n        $received += strlen($dataRec);\n\n        unset($dataRec);\n        $first = false;\n      }\n\n      //flush socket\n      @socket_recvfrom($self->_zkclient, $dataRec, 1024, 0, $self->_ip, $self->_port);\n      unset($dataRec);\n    }\n\n    return $data;\n  }\n\n  /**\n   * @param ZKTeco $self\n   * @param int $received\n   * @param int $bytes\n   */\n  static private function logReceived(ZKTeco $self, $received, $bytes)\n  {\n    self::logger($self, 'Received: ' . $received . ' of ' . $bytes . ' bytes');\n  }\n\n  /**\n   * Write log\n   * @param ZKTeco $self\n   * @param string $str\n   */\n  static private function logger(ZKTeco $self, $str)\n  {\n    if (defined('ZK_LIB_LOG')) {\n      //use constant if defined\n      $log = ZK_LIB_LOG;\n    } else {\n      $dir = dirname(dirname(__FILE__));\n      $log = $dir . '/logs/error.log';\n    }\n\n    $row = '<' . $self->_ip . '> [' . date('d.m.Y H:i:s') . '] ';\n    $row .= (empty($self->_section) ? '' : '(' . $self->_section . ') ');\n    $row .= $str;\n    $row .= PHP_EOL;\n\n    file_put_contents($log, $row, FILE_APPEND);\n  }\n}\n"
  },
  {
    "path": "src/Lib/Helper/Version.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;;\n\nuse Rats\\Zkteco\\Lib\\Helper\\Util;\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass Version\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_VERSION;\n        $command_string = '';\n\n        return $self->_command($command, $command_string);\n    }\n}"
  },
  {
    "path": "src/Lib/Helper/WorkCode.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib\\Helper;\n\nuse Rats\\Zkteco\\Lib\\ZKTeco;\n\nclass WorkCode\n{\n    /**\n     * @param ZKTeco $self\n     * @return bool|mixed\n     */\n    static public function get(ZKTeco $self)\n    {\n        $self->_section = __METHOD__;\n\n        $command = Util::CMD_DEVICE;\n        $command_string = 'WorkCode';\n\n        return $self->_command($command, $command_string);\n    }\n}\n"
  },
  {
    "path": "src/Lib/ZKTeco.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Lib;\n\nuse ErrorException;\nuse Exception;\nuse Rats\\Zkteco\\Lib\\Helper\\Attendance;\nuse Rats\\Zkteco\\Lib\\Helper\\Device;\nuse Rats\\Zkteco\\Lib\\Helper\\Face;\nuse Rats\\Zkteco\\Lib\\Helper\\Fingerprint;\nuse Rats\\Zkteco\\Lib\\Helper\\Os;\nuse Rats\\Zkteco\\Lib\\Helper\\Pin;\nuse Rats\\Zkteco\\Lib\\Helper\\Platform;\nuse Rats\\Zkteco\\Lib\\Helper\\SerialNumber;\nuse Rats\\Zkteco\\Lib\\Helper\\Ssr;\nuse Rats\\Zkteco\\Lib\\Helper\\Time;\nuse Rats\\Zkteco\\Lib\\Helper\\User;\nuse Rats\\Zkteco\\Lib\\Helper\\Util;\nuse Rats\\Zkteco\\Lib\\Helper\\Connect;\nuse Rats\\Zkteco\\Lib\\Helper\\Version;\nuse Rats\\Zkteco\\Lib\\Helper\\WorkCode;\n\n\nclass ZKTeco{\n  public $_ip;\n  public $_port;\n  public $_zkclient;\n\n  public $_data_recv = '';\n  public $_session_id = 0;\n  public $_section = '';\n\n  /**\n   * ZKLib constructor.\n   * @param string $ip Device IP\n   * @param integer $port Default: 4370\n   */\n  public function __construct($ip, $port = 4370)\n  {\n    $this->_ip = $ip;\n    $this->_port = $port;\n\n    $this->_zkclient = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);\n\n    $timeout = array('sec' => 60, 'usec' => 500000);\n    socket_set_option($this->_zkclient, SOL_SOCKET, SO_RCVTIMEO, $timeout);\n\n  }\n\n  /**\n   * Create and send command to device\n   *\n   * @param string $command\n   * @param string $command_string\n   * @param string $type\n   * @return bool|mixed\n   */\n  public function _command($command, $command_string, $type = Util::COMMAND_TYPE_GENERAL)\n  {\n    $chksum = 0;\n    $session_id = $this->_session_id;\n\n    $u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6/H2h7/H2h8', substr($this->_data_recv, 0, 8));\n    $reply_id = hexdec($u['h8'] . $u['h7']);\n\n    $buf = Util::createHeader($command, $chksum, $session_id, $reply_id, $command_string);\n\n    socket_sendto($this->_zkclient, $buf, strlen($buf), 0, $this->_ip, $this->_port);\n\n    try {\n      @socket_recvfrom($this->_zkclient, $this->_data_recv, 1024, 0, $this->_ip, $this->_port);\n\n      $u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6', substr($this->_data_recv, 0, 8));\n\n      $ret = false;\n      $session = hexdec($u['h6'] . $u['h5']);\n\n      if ($type === Util::COMMAND_TYPE_GENERAL && $session_id === $session) {\n        $ret = substr($this->_data_recv, 8);\n      } else if ($type === Util::COMMAND_TYPE_DATA && !empty($session)) {\n        $ret = $session;\n      }\n\n      return $ret;\n    } catch (ErrorException $e) {\n      return false;\n    } catch (Exception $e) {\n      return false;\n    }\n  }\n\n  /**\n   * Connect to device\n   *\n   * @return bool\n   */\n  public function connect()\n  {\n    return Connect::connect($this);\n  }\n\n  /**\n   * Disconnect from device\n   *\n   * @return bool\n   */\n  public function disconnect()\n  {\n    return Connect::disconnect($this);\n  }\n\n  /**\n   * Get device version\n   *\n   * @return bool|mixed\n   */\n  public function version()\n  {\n    return Version::get($this);\n  }\n\n  /**\n   * Get OS version\n   *\n   * @return bool|mixed\n   */\n  public function osVersion()\n  {\n    return Os::get($this);\n  }\n\n  /**\n   * Get platform\n   *\n   * @return bool|mixed\n   */\n  public function platform()\n  {\n    return Platform::get($this);\n  }\n\n  /**\n   * Get firmware version\n   *\n   * @return bool|mixed\n   */\n  public function fmVersion()\n  {\n    return Platform::getVersion($this);\n  }\n\n  /**\n   * Get work code\n   *\n   * @return bool|mixed\n   */\n  public function workCode()\n  {\n    return WorkCode::get($this);\n  }\n\n  /**\n   * Get SSR\n   *\n   * @return bool|mixed\n   */\n  public function ssr()\n  {\n    return Ssr::get($this);\n  }\n\n  /**\n   * Get pin width\n   *\n   * @return bool|mixed\n   */\n  public function pinWidth()\n  {\n    return Pin::width($this);\n  }\n\n  /**\n   * @return bool|mixed\n   */\n  public function faceFunctionOn()\n  {\n    return Face::on($this);\n  }\n\n  /**\n   * Get device serial number\n   *\n   * @return bool|mixed\n   */\n  public function serialNumber()\n  {\n    return SerialNumber::get($this);\n  }\n\n  /**\n   * Get device name\n   *\n   * @return bool|mixed\n   */\n  public function deviceName()\n  {\n    return Device::name($this);\n  }\n\n  /**\n   * Disable device\n   *\n   * @return bool|mixed\n   */\n  public function disableDevice()\n  {\n    return Device::disable($this);\n  }\n\n  /**\n   * Enable device\n   *\n   * @return bool|mixed\n   */\n  public function enableDevice()\n  {\n    return Device::enable($this);\n  }\n\n  /**\n   * Get users data\n   *\n   * @return array [userid, name, cardno, uid, role, password]\n   */\n  public function getUser()\n  {\n    return User::get($this);\n  }\n\n  /**\n   * Set user data\n   *\n   * @param int $uid Unique ID (max 65535)\n   * @param int|string $userid ID in DB (same like $uid, max length = 9, only numbers - depends device setting)\n   * @param string $name (max length = 24)\n   * @param int|string $password (max length = 8, only numbers - depends device setting)\n   * @param int $role Default Util::LEVEL_USER\n   * @param int $cardno Default 0 (max length = 10, only numbers)\n   * @return bool|mixed\n   */\n  public function setUser($uid, $userid, $name, $password, $role = Util::LEVEL_USER, $cardno = 0)\n  {\n    return User::set($this, $uid, $userid, $name, $password, $role, $cardno);\n  }\n\n\n\n  /**\n   * Remove All users\n   *\n   * @return bool|mixed\n   */\n  public function clearUsers()\n  {\n    return User::clear($this);\n  }\n\n  /**\n   * Remove admin\n   *\n   * @return bool|mixed\n   */\n  public function clearAdmin()\n  {\n    return User::clearAdmin($this);\n  }\n\n  /**\n   * Remove user by UID\n   *\n   * @param integer $uid\n   * @return bool|mixed\n   */\n  public function removeUser($uid)\n  {\n    return User::remove($this, $uid);\n  }\n\n\n\n  /**\n   * Get fingerprint data array by UID\n   * TODO: Can get data, but don't know how to parse the data. Need more documentation about it...\n   *\n   * @param integer $uid Unique ID (max 65535)\n   * @return array Binary fingerprint data array (where key is finger ID (0-9))\n   */\n  public function getFingerprint($uid)\n  {\n    return Fingerprint::get($this, $uid);\n  }\n\n  /**\n   * Set fingerprint data array\n   * TODO: Still can not set fingerprint. Need more documentation about it...\n   *\n   * @param integer $uid Unique ID (max 65535)\n   * @param array $data Binary fingerprint data array (where key is finger ID (0-9) same like returned array from 'getFingerprint' method)\n   * @return int Count of added fingerprints\n   */\n  public function setFingerprint($uid, array $data)\n  {\n    return Fingerprint::set($this, $uid, $data);\n  }\n\n  /**\n   * Remove fingerprint by UID and fingers ID array\n   *\n   * @param integer $uid Unique ID (max 65535)\n   * @param array $data Fingers ID array (0-9)\n   * @return int Count of deleted fingerprints\n   */\n  public function removeFingerprint($uid, array $data)\n  {\n    return Fingerprint::remove($this, $uid, $data);\n  }\n\n\n  /**\n   * Get attendance log\n   *\n   * @return array [uid, id, state, timestamp]\n   */\n  public function getAttendance()\n  {\n    return Attendance::get($this);\n  }\n\n  /**\n   * Clear attendance log\n   *\n   * @return bool|mixed\n   */\n  public function clearAttendance()\n  {\n    return Attendance::clear($this);\n  }\n\n  /**\n   * Set device time\n   *\n   * @param string $t Format: \"Y-m-d H:i:s\"\n   * @return bool|mixed\n   */\n  public function setTime($t)\n  {\n    return Time::set($this, $t);\n  }\n\n  /**\n   * Get device time\n   *\n   * @return bool|mixed Format: \"Y-m-d H:i:s\"\n   */\n  public function getTime()\n  {\n    return Time::get($this);\n  }\n\n\n  /**\n   * turn off the device\n   *\n   * @return bool|mixed\n   */\n  public function shutdown()\n  {\n    return Device::powerOff($this);\n  }\n\n  /**\n   * restart the device\n   *\n   * @return bool|mixed\n   */\n  public function restart()\n  {\n    return Device::restart($this);\n  }\n\n\n  /**\n   * make sleep mood the device\n   *\n   * @return bool|mixed\n   */\n  public function sleep()\n  {\n    return Device::sleep($this);\n  }\n\n\n  /**\n   * resume the device from sleep\n   *\n   * @return bool|mixed\n   */\n  public function resume()\n  {\n    return Device::resume($this);\n  }\n\n\n  /**\n   * voice test Sound will \"Thank you\"\n   *\n   * @return bool|mixed\n   */\n  public function testVoice()\n  {\n    return Device::testVoice($this);\n  }\n\n\n  public function clearLCD()\n  {\n    return Device::clearLCD($this);\n  }\n\n\n  public function writeLCD()\n  {\n    return Device::writeLCD($this, 2, \"RAIHAN Afroz Topu\");\n  }\n}"
  },
  {
    "path": "src/Providers/ZktecoServiceProvider.php",
    "content": "<?php\n\nnamespace Rats\\Zkteco\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\n\nclass ZktecoServiceProvider extends ServiceProvider {\n\n  public function boot(){\n//    dd(\"Zkteco is running\");\n  }\n\n  public function register(){\n\n  }\n}"
  }
]