├── .DS_Store ├── .gitignore ├── LICENSE ├── LICENSE.txt ├── MANIFEST ├── README.md ├── README.txt ├── setup.py ├── zklib ├── .DS_Store ├── __init__.py ├── zkAtt.py ├── zkAttdev.py ├── zkattendance.py ├── zkconnect.py ├── zkconst.py ├── zkdevice.py ├── zkextendfmt.py ├── zkextendoplog.py ├── zkface.py ├── zkfreedata.py ├── zklib.py ├── zkos.py ├── zkpin.py ├── zkplatform.py ├── zkprepare.py ├── zkrefreshdata ├── zkrefreshdata.py ├── zkrestart.py ├── zkserialnumber.py ├── zkssr.py ├── zktime.py ├── zkuser.py ├── zkversion.py └── zkworkcode.py └── zktest.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dnaextrim/python_zklib/9cbc866b64bf4581aed6419f1d63ed5d001abf24/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | 47 | # Translations 48 | *.mo 49 | *.pot 50 | 51 | # Django stuff: 52 | *.log 53 | 54 | # Sphinx documentation 55 | docs/_build/ 56 | 57 | # PyBuilder 58 | target/ 59 | 60 | # macOS file type 61 | .DS_Store 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | README.txt 3 | setup.py 4 | zklib/__init__.py 5 | zklib/zkattendance.py 6 | zklib/zkconnect.py 7 | zklib/zkconst.py 8 | zklib/zkdevice.py 9 | zklib/zkextendfmt.py 10 | zklib/zkextendoplog.py 11 | zklib/zkface.py 12 | zklib/zklib.py 13 | zklib/zkos.py 14 | zklib/zkpin.py 15 | zklib/zkplatform.py 16 | zklib/zkserialnumber.py 17 | zklib/zkssr.py 18 | zklib/zktime.py 19 | zklib/zkuser.py 20 | zklib/zkversion.py 21 | zklib/zkworkcode.py 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python ZKLib # 2 | 3 | ZK fingerprint Attendance Machine Library for python with a connection to the network using the UDP protocol and port 4370 4 | 5 | [![](http://i.imgur.com/2tqfhMO.png?1)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=DCSTC5GTWLBAN&lc=ID&item_name=donywahyuisp¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted) 6 | 7 | ## NOW ## 8 | > This library is now beginning to be redeveloped and will come with complete documentation 9 | 10 | ## Getting started 11 | 12 | Login as admin to attendance machine and set the ip address for example (to 192.168.0.201) and connect the machine with ethernet to your network. 13 | 14 | Connect to the machine 15 | 16 | ```python 17 | import sys 18 | import zklib 19 | import time 20 | import zkconst 21 | 22 | zk = zklib.ZKLib("192.168.0.201", 4370) 23 | ret = zk.connect() 24 | print "connection:", ret 25 | ``` 26 | 27 | If result was 28 | ``` 29 | connection True 30 | ``` 31 | Then you are connected. 32 | 33 | More examples on how to use the Library available in the 34 | zktest.py file 35 | 36 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | # Python ZKLib # 2 | 3 | ZK fingerprint Attendance Machine Library for python with a connection to the network using the UDP protocol and port 4370 4 | 5 | ## Getting started 6 | 7 | Login as admin to attendance machine and set the ip address for example (to 192.168.0.201) and connect the machine with ethernet to your network. 8 | ```bash 9 | pip install zklib 10 | ``` 11 | Connect to the machine 12 | 13 | ```python 14 | import sys 15 | import zklib 16 | import time 17 | import zkconst 18 | 19 | zk = zklib.ZKLib("192.168.0.201", 4370) 20 | ret = zk.connect() 21 | print "connection:", ret 22 | ``` 23 | 24 | If result was 25 | ``` 26 | connection True 27 | ``` 28 | Then you are connected. 29 | 30 | More examples on how to use the Library available in the 31 | zktest.py file 32 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | # Application name: 5 | name="zklib", 6 | # Version number (initial): 7 | version="0.1.1", 8 | # Application author details: 9 | url="https://github.com/AlSayedGamal/python_zklib", 10 | author="AlSayed Gamal", 11 | author_email="mail.gamal@gmail.com", 12 | packages=["zklib"], 13 | license="LICENSE.txt", 14 | description="Zk Attendance Machine lib", 15 | long_description=open("README.txt").read(), 16 | 17 | ) 18 | -------------------------------------------------------------------------------- /zklib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dnaextrim/python_zklib/9cbc866b64bf4581aed6419f1d63ed5d001abf24/zklib/.DS_Store -------------------------------------------------------------------------------- /zklib/__init__.py: -------------------------------------------------------------------------------- 1 | import zkattendance 2 | import zkconst 3 | import zkdevice 4 | import zkconnect 5 | import zkextendfmt 6 | import zkextendoplog 7 | import zkface 8 | import zklib 9 | import zkos 10 | import zkpin 11 | import zkpin 12 | import zkplatform 13 | import zkserialnumber 14 | import zkssr 15 | import zktime 16 | import zkuser 17 | import zkversion 18 | import zkworkcode 19 | import zkprepare 20 | import zkrefreshdata 21 | import zkfreedata 22 | import zkrestart 23 | import zkAtt 24 | -------------------------------------------------------------------------------- /zklib/zkAtt.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | import sys 4 | 5 | from zkconst import * 6 | 7 | 8 | def acmOK(self): 9 | """send CMD_ACK_OK""" 10 | """ try cmd_ack_data""" 11 | command = CMD_ACK_DATA 12 | command_string = '' 13 | chksum = 0 14 | session_id = 0 15 | reply_id = -1 + USHRT_MAX 16 | 17 | buf = self.createHeader(command, chksum, session_id, 18 | reply_id, command_string) 19 | 20 | self.zkclient.sendto(buf, self.address) 21 | 22 | try: 23 | self.data_recv, addr = self.zkclient.recvfrom(1024) 24 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 25 | 26 | return self.checkValid(self.data_recv) 27 | except: 28 | return False 29 | 30 | 31 | def reverseHex(hexstr): 32 | tmp = '' 33 | for i in reversed(xrange(len(hexstr) / 2)): 34 | tmp += hexstr[i * 2:(i * 2) + 2] 35 | 36 | return tmp 37 | 38 | 39 | def zkAtt(self): 40 | 41 | command = CMD_ATTLOG_RRQ 42 | comand_string = '' 43 | chksum = 0 44 | session_id = self.session_id 45 | reply_id = unpack('4H', self.data_recv[:8])[3] 46 | 47 | buf = self.createHeader(command, chksum, session_id, 48 | reply_id, comand_string) 49 | self.zkclient.sendto(buf, self.address) 50 | 51 | size = None 52 | attendance = [] 53 | self.data_recv, addr = self.zkclient.recvfrom(1024) 54 | # print unpack('24s1s4s11s',self.data_recv.ljust(40)[:40]) 55 | # print "unpack HcHc :7", unpack('HcHc',self.data_recv[:7]) 56 | # print "unpack HHHH :8", unpack('HHHH',self.data_recv[:8]) 57 | # print "unpack HHHH :8 [1]", unpack('4H',self.data_recv[:8])[0] 58 | print "size", sys.getsizeof(self.data_recv) 59 | print "size", len(self.data_recv) 60 | lensi = len(self.data_recv) / 2 61 | fstri = str(lensi) + "H" 62 | print "unpack 4I ", unpack(fstri, self.data_recv) 63 | # print "unpack 8H", unpack('8H', self.data_recv) 64 | # print "unpack I 8:12 [0]", unpack ('I', self.data_recv[8:12])[0] 65 | 66 | attendance = [] 67 | self.data_recv, addr = self.zkclient.recvfrom(1024) 68 | 69 | if unpack('4H', self.data_recv[:8])[0] == CMD_PREPARE_DATA: 70 | print "received CMD_PREPARE_DATA" 71 | size = unpack('I', self.data_recv[8:12])[0] 72 | 73 | wa = unpack('II', self.data_recv[:8])[0] 74 | print "received ", wa 75 | print 'Receiving %s %s' % (size, "bytes") 76 | try: 77 | 78 | data_recv, addr = self.zkclient.recvfrom(size) 79 | print "size of data_recv", sys.getsizeof(data_recv) 80 | self.attendancedata.append(data_recv) 81 | acmOK(self) 82 | print unpack('24s1s4s11s', self.data_recv.ljust(40)[:40]) 83 | 84 | except: 85 | 86 | print "socket timeout 1 - no more data to receive" 87 | 88 | while unpack('4H', self.data_recv[:8])[0] != 2000 or unpack('4H', self.data_recv[:8])[0] == 1501: 89 | 90 | try: 91 | 92 | data_recv, addr = self.zkclient.recvfrom(size) 93 | acmOK(self) 94 | print unpack('24s1s4s11s', self.data_recv.ljust(40)[:40]) 95 | 96 | except: 97 | 98 | print "socket timeout 2 - no more data to receive" 99 | self.attendancedata.append(data_recv) 100 | acmOK(self) 101 | break 102 | # print "length of reiceived data packet", len(data_recv) 103 | # print "unpack 126H", unpack('126H', data_recv) 104 | 105 | data_recv, addr = self.zkclient.recvfrom(1024) 106 | 107 | self.attendancedata.append(data_recv) 108 | 109 | if unpack('4H', self.data_recv[:8])[0] == CMD_PREPARE_DATA: 110 | 111 | print "received CMD_PREPARE_DATA" 112 | size = unpack('I', self.data_recv[8:12])[0] 113 | print 'Receiving %s %s' % (size, "bytes") 114 | 115 | elif unpack('4H', data_recv[:8])[0] == 1501: 116 | print "receiving Data packet" 117 | 118 | elif unpack('4H', self.data_recv[:8])[0] == 2000: 119 | print "received CMD_ACK_OK" 120 | try: 121 | 122 | self.data_recv, addr = self.zkclient.recvfrom(size) 123 | acmOK(self) 124 | # print len(self.data_recv) 125 | except: 126 | print "socket timeout 3 - no more data to receive" 127 | 128 | #self.data_recv, addr = self.zkclient.recvfrom(1024) 129 | # print "length of reiceived data packet", len(self.data_recv) 130 | print "length", len(self.data_recv) 131 | lens = len(self.data_recv) / 2 132 | fstr = str(lens) + "H" 133 | 134 | print unpack(fstr, self.data_recv) 135 | if unpack('4H', self.data_recv[:8])[0] == 2000: 136 | print "received CMD_ACK_OK" 137 | try: 138 | 139 | self.data_recv, addr = self.zkclient.recvfrom(4096) 140 | # print len(self.data_recv) 141 | except: 142 | print "socket timeout 4 - no more data to receive" 143 | print "length of att data", len(self.attendancedata) 144 | #data_recv = self.zkclient.recvfrom(8) 145 | 146 | for x in xrange(len(self.attendancedata)): 147 | 148 | # print self.attendancedata[x][8:] 149 | #self.attendancedata[x] = self.attendancedata[x][8:] 150 | # print self.attendancedata[x][0:] 151 | self.attendancedata[x] = self.attendancedata[x][0:] 152 | 153 | self.data_recv, addr = self.zkclient.recvfrom(1024) 154 | 155 | if unpack('4H', self.data_recv)[0] == 2000: 156 | print "received CMD_ACK_OK" 157 | try: 158 | 159 | self.data_recv, addr = self.zkclient.recvfrom(1024) 160 | 161 | except: 162 | print "socket timeout - no more data to receive" 163 | 164 | for x in xrange(len(self.attendancedata)): 165 | 166 | self.attendancedata[x] = self.attendancedata[x][0:] 167 | 168 | attendancedata = self.attendancedata 169 | 170 | attendancedata = self.attendancedata 171 | 172 | attendancedata = ''.join(self.attendancedata) 173 | 174 | attendancedata = attendancedata[14:] 175 | #attendancedata = attendancedata[14:] 176 | 177 | print "len attendancedata", len(attendancedata) 178 | 179 | while len(attendancedata): 180 | 181 | #uidm = unpack('24s1s4s11s',attendancedata.ljust(40)[:40]) 182 | 183 | #uidt = unpack('38s',attendancedata[:38]) 184 | 185 | #uidmn = unpack('16s',attendancedata[:16])[0] 186 | 187 | pls = unpack('c', attendancedata[29:30]) # [3] 188 | 189 | #statev = unpack('=2c',attendancedata[21:23]) 190 | #datem = unpack('ii',attendancedata[:8])[1] 191 | 192 | uid, state, timestamp, space = unpack( 193 | '24s1s4s11s', attendancedata.ljust(40)[:40]) 194 | print "%s, %s, %s, %s" % (uid, 1, ord(space[0]), decode_time(int(reverseHex(timestamp.encode('hex')), 16))) 195 | # print "%s, %s, %s, %s" % (uid, ord(pls[0]), ord(space[0]), decode_time( int( reverseHex( timestamp.encode('hex') ), 16 ) ) ) 196 | # print "%s, %s, %s, %s" % (uid, state, space, timestamp) 197 | #attendance.append( ( uid, ord(pls[0]), decode_time( int( reverseHex( timestamp.encode('hex') ), 16 ) ) ) ) 198 | attendance.append((uid, ord(pls[0]), decode_time( 199 | int(reverseHex(timestamp.encode('hex')), 16)))) 200 | attendancedata = attendancedata[40:] 201 | 202 | while len(attendancedata): 203 | 204 | pls = unpack('c', attendancedata[29:30]) # [3] 205 | 206 | uid, state, timestamp, space = unpack( 207 | '24s1s4s11s', attendancedata.ljust(40)[:40]) 208 | # print "%s, %s, %s, %s" % (uid, ord(pls[0]), ord(space[0]), 209 | # decode_time( int( reverseHex( timestamp.encode('hex') ), 16 ) 210 | # ) ) 211 | 212 | attendance.append((uid, ord(pls[0]), decode_time( 213 | int(reverseHex(timestamp.encode('hex')), 16)))) 214 | attendancedata = attendancedata[40:] 215 | 216 | return attendance 217 | 218 | 219 | def zkclearattendance(self): 220 | """Start a connection with the time clock""" 221 | command = CMD_CLEAR_ATTLOG 222 | command_string = '' 223 | chksum = 0 224 | session_id = self.session_id 225 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 226 | 227 | buf = self.createHeader(command, chksum, session_id, 228 | reply_id, command_string) 229 | self.zkclient.sendto(buf, self.address) 230 | # print buf.encode("hex") 231 | try: 232 | self.data_recv, addr = self.zkclient.recvfrom(1024) 233 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 234 | return self.data_recv[8:] 235 | except: 236 | return False 237 | -------------------------------------------------------------------------------- /zklib/zkAttdev.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | import sys 4 | 5 | from zkconst import * 6 | 7 | 8 | 9 | def reverseHex(hexstr): 10 | tmp = '' 11 | for i in reversed( xrange( len(hexstr)/2 ) ): 12 | tmp += hexstr[i*2:(i*2)+2] 13 | 14 | return tmp 15 | 16 | 17 | def zkAtt(self): 18 | 19 | print "testing" 20 | file = open("binw", "w") 21 | 22 | command = CMD_ATTLOG_RRQ 23 | comand_string = '' 24 | chksum = 0 25 | session_id = self.session_id 26 | reply_id = unpack('4H',self.data_recv[:8])[3] 27 | 28 | buf = self.createHeader(command,chksum,session_id, reply_id, comand_string) 29 | self.zkclient.sendto(buf,self.address) 30 | #file.write(self.data_recv[0:]) 31 | #print "reply_id", reply_id 32 | 33 | attendance = [] 34 | self.data_recv, addr = self.zkclient.recvfrom(1024) 35 | #print "unpack HcHc :7", unpack('HcHc',self.data_recv[:7]) 36 | #print "unpack HHHH :8", unpack('HHHH',self.data_recv[:8]) 37 | #print "unpack HHHH :8 [1]", unpack('4H',self.data_recv[:8])[0] 38 | #print "length", len(self.data_recv) 39 | #print "unpack 4I ", unpack ('4I', self.data_recv) 40 | #print "unpack 8H", unpack('8H', self.data_recv) 41 | #print "unpack I 8:12 [0]", unpack ('I', self.data_recv[8:12])[0] 42 | 43 | if unpack('4H',self.data_recv[:8])[0] == CMD_PREPARE_DATA: 44 | print "received CMD_PREPARE_DATA" 45 | 46 | while unpack('4H', self.data_recv[:8])[0] != 2000: 47 | 48 | data_recv, addr = self.zkclient.recvfrom(1024) 49 | #print "length of reiceived data packet", len(data_recv) 50 | #print "unpack 126H", unpack('126H', data_recv) 51 | self.attendancedata.append(data_recv) 52 | file.write(data_recv) 53 | if unpack('4H', data_recv[:8])[0] == 1501: 54 | print "receiving Data packet" 55 | #print "trying to unpack data", unpack('i', data_recv[:8])[1] 56 | 57 | self.data_recv, addr = self.zkclient.recvfrom(1024) 58 | #print "length of reiceived data packet", len(self.data_recv) 59 | #print unpack('4H', self.data_recv) 60 | if unpack('4H', self.data_recv)[0] == 2000: 61 | print "received CMD_ACK_OK" 62 | try: 63 | 64 | self.data_recv, addr = self.zkclient.recvfrom(1024) 65 | #print len(self.data_recv) 66 | except: 67 | print "socket timeout - no more data to receive" 68 | #print "length of att data", len(self.attendancedata) 69 | 70 | for x in xrange(len(self.attendancedata)): 71 | #print self.attendancedata[x][8:] 72 | #self.attendancedata[x] = self.attendancedata[x][8:] 73 | #print self.attendancedata[x][0:] 74 | self.attendancedata[x] = self.attendancedata[x][0:] 75 | 76 | 77 | attendancedata = self.attendancedata 78 | 79 | 80 | 81 | attendancedata = ''.join( self.attendancedata) 82 | 83 | attendancedata = attendancedata[14:] 84 | 85 | while len(attendancedata): 86 | 87 | #print "length att", len(attendancedata) 88 | uidm = unpack('24s1s4s11s',attendancedata.ljust(40)[:40]) 89 | #print "length att40", len(attendancedata[:38]) 90 | uidt = unpack('38s',attendancedata[:38]) 91 | #print "uidt", uidt 92 | #print "sizeof", sys.getsizeof(attendancedata[:40]) 93 | #try unpacking the state bits in reverse order 94 | #try unpacking using different endianness 95 | #timestamp = int.from_bytes(ba_object[:4], byteorder='big') 96 | #print "LENNY", len(attendancedata[30:]) 97 | uidmn = unpack('16s',attendancedata[:16])[0] 98 | pls = unpack('c',attendancedata[29:30])#[3] 99 | #print "pls wo ord", pls 100 | #statem = unpack('=5c',attendancedata[:10])[3] 101 | statev = unpack('=2c',attendancedata[21:23]) 102 | datem = unpack('ii',attendancedata[:8])[1] 103 | #print "uidm", uidm 104 | #print "uidmn", uidmn 105 | #print "pls w ord", ord(pls[0]) 106 | #print "statem", ord(statem) 107 | #print "statev", ord(statev[0]) 108 | #print "statev", statev[0] 109 | #print "datem",datem 110 | 111 | 112 | 113 | uid, state, timestamp, space = unpack( '24s1s4s11s', attendancedata.ljust(40)[:40] ) 114 | print "%s, %s, %s, %s" % (uid, ord(pls[0]), ord(space[0]), decode_time( int( reverseHex( timestamp.encode('hex') ), 16 ) ) ) 115 | #print "%s, %s, %s, %s" % (uid, state, space, timestamp) 116 | attendance.append( ( uid, ord(pls[0]), decode_time( int( reverseHex( timestamp.encode('hex') ), 16 ) ) ) ) 117 | attendancedata = attendancedata[40:] 118 | 119 | return attendance 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | def zkclearattendance(self): 128 | """Start a connection with the time clock""" 129 | command = CMD_CLEAR_ATTLOG 130 | command_string = '' 131 | chksum = 0 132 | session_id = self.session_id 133 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 134 | 135 | buf = self.createHeader(command, chksum, session_id, 136 | reply_id, command_string) 137 | self.zkclient.sendto(buf, self.address) 138 | #print buf.encode("hex") 139 | try: 140 | self.data_recv, addr = self.zkclient.recvfrom(1024) 141 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 142 | return self.data_recv[8:] 143 | except: 144 | return False -------------------------------------------------------------------------------- /zklib/zkattendance.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | import pprint 7 | pp = pprint.PrettyPrinter(indent=4) 8 | 9 | def getSizeAttendance(self): 10 | """Checks a returned packet to see if it returned CMD_PREPARE_DATA, 11 | indicating that data packets are to be sent 12 | 13 | Returns the amount of bytes that are going to be sent""" 14 | command = unpack('HHHH', self.data_recv[:8])[0] 15 | #file = open("binw", "w") 16 | #file.write(command) 17 | if command == CMD_PREPARE_DATA: 18 | print command 19 | size = unpack('I', self.data_recv[8:12])[0] 20 | print "size:" 21 | pp.pprint(size) 22 | return size 23 | else: 24 | return False 25 | 26 | 27 | def reverseHex(hexstr): 28 | tmp = '' 29 | for i in reversed( xrange( len(hexstr)/2 ) ): 30 | tmp += hexstr[i*2:(i*2)+2] 31 | 32 | return tmp 33 | 34 | def zkgetattendance(self): 35 | """Start a connection with the time clock""" 36 | command = CMD_ATTLOG_RRQ 37 | command_string = '' 38 | chksum = 0 39 | session_id = self.session_id 40 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 41 | 42 | buf = self.createHeader(command, chksum, session_id, 43 | reply_id, command_string) 44 | self.zkclient.sendto(buf, self.address) 45 | try: 46 | self.data_recv, addr = self.zkclient.recvfrom(1024) 47 | 48 | if getSizeAttendance(self): 49 | bytes = getSizeAttendance(self) 50 | while bytes > 0: 51 | data_recv, addr = self.zkclient.recvfrom(1032) 52 | self.attendancedata.append(data_recv) 53 | bytes -= 1024 54 | 55 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 56 | data_recv = self.zkclient.recvfrom(8) 57 | 58 | attendance = [] 59 | if len(self.attendancedata) > 0: 60 | # The first 4 bytes don't seem to be related to the user 61 | for x in xrange(len(self.attendancedata)): 62 | if x > 0: 63 | self.attendancedata[x] = self.attendancedata[x][8:] 64 | 65 | attendancedata = ''.join( self.attendancedata ) 66 | 67 | attendancedata = attendancedata[14:] 68 | while len(attendancedata): 69 | 70 | uid, state, timestamp, space = unpack( '24s1s4s11s', attendancedata.ljust(40)[:40] ) 71 | 72 | 73 | # Clean up some messy characters from the user name 74 | #uid = unicode(uid.strip('\x00|\x01\x10x'), errors='ignore') 75 | uid = uid.split('\x00', 1)[0] 76 | #print "%s, %s, %s" % (uid, state, decode_time( int( reverseHex( timestamp.encode('hex') ), 16 ) ) ) 77 | 78 | attendance.append( ( uid, int( state.encode('hex'), 16 ), decode_time( int( reverseHex( timestamp.encode('hex') ), 16 ) ) ) ) 79 | 80 | attendancedata = attendancedata[40:] 81 | 82 | return attendance 83 | except: 84 | return False 85 | 86 | 87 | def zkclearattendance(self): 88 | """Start a connection with the time clock""" 89 | command = CMD_CLEAR_ATTLOG 90 | command_string = '' 91 | chksum = 0 92 | session_id = self.session_id 93 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 94 | 95 | buf = self.createHeader(command, chksum, session_id, 96 | reply_id, command_string) 97 | self.zkclient.sendto(buf, self.address) 98 | #print buf.encode("hex") 99 | try: 100 | self.data_recv, addr = self.zkclient.recvfrom(1024) 101 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 102 | return self.data_recv[8:] 103 | except: 104 | return False 105 | -------------------------------------------------------------------------------- /zklib/zkconnect.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkconnect(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_CONNECT 9 | command_string = '' 10 | chksum = 0 11 | session_id = 0 12 | reply_id = -1 + USHRT_MAX 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | 17 | self.zkclient.sendto(buf, self.address) 18 | 19 | try: 20 | self.data_recv, addr = self.zkclient.recvfrom(1024) 21 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 22 | 23 | return self.checkValid( self.data_recv ) 24 | except: 25 | return False 26 | 27 | 28 | def zkdisconnect(self): 29 | """Disconnect from the clock""" 30 | command = CMD_EXIT 31 | command_string = '' 32 | chksum = 0 33 | session_id = self.session_id 34 | 35 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 36 | 37 | buf = self.createHeader(command, chksum, session_id, 38 | reply_id, command_string) 39 | 40 | self.zkclient.sendto(buf, self.address) 41 | 42 | self.data_recv, addr = self.zkclient.recvfrom(1024) 43 | return self.checkValid( self.data_recv ) 44 | 45 | -------------------------------------------------------------------------------- /zklib/zkconst.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, date 2 | 3 | USHRT_MAX = 65535 4 | 5 | 6 | CMD_CONNECT = 1000 7 | CMD_EXIT = 1001 8 | CMD_ENABLEDEVICE = 1002 9 | CMD_DISABLEDEVICE = 1003 10 | CMD_RESTART = 1004 11 | CMD_POWEROFF = 1005 12 | 13 | CMD_ACK_OK = 2000 14 | CMD_ACK_ERROR = 2001 15 | CMD_ACK_DATA = 2002 16 | 17 | CMD_PREPARE_DATA = 1500 18 | CMD_DATA = 1501 19 | 20 | CMD_USERTEMP_RRQ = 9 21 | CMD_ATTLOG_RRQ = 13 22 | CMD_CLEAR_DATA = 14 23 | CMD_CLEAR_ATTLOG = 15 24 | 25 | CMD_WRITE_LCD = 66 26 | 27 | CMD_GET_TIME = 201 28 | CMD_SET_TIME = 202 29 | 30 | CMD_VERSION = 1100 31 | CMD_DEVICE = 11 32 | 33 | CMD_STARTENROLL = 61 34 | CMD_CLEAR_ADMIN = 20 35 | CMD_SET_USER = 8 36 | CMD_PREPARE_DATA = 1500 37 | CMD_REFRESHOPTION = 1014 38 | CMD_FREE_DATA = 1502 39 | CMD_RESTART = 1004 40 | CMD_REFRESHDATA = 1013 41 | 42 | LEVEL_USER = 0 43 | LEVEL_ADMIN = 14 44 | 45 | def encode_time(t): 46 | """Encode a timestamp send at the timeclock 47 | 48 | copied from zkemsdk.c - EncodeTime""" 49 | d = ( (t.year % 100) * 12 * 31 + ((t.month - 1) * 31) + t.day - 1) *\ 50 | (24 * 60 * 60) + (t.hour * 60 + t.minute) * 60 + t.second 51 | 52 | return d 53 | 54 | 55 | def decode_time(t): 56 | """Decode a timestamp retrieved from the timeclock 57 | 58 | copied from zkemsdk.c - DecodeTime""" 59 | second = t % 60 60 | t = t / 60 61 | 62 | minute = t % 60 63 | t = t / 60 64 | 65 | hour = t % 24 66 | t = t / 24 67 | 68 | day = t % 31+1 69 | t = t / 31 70 | 71 | month = t % 12+1 72 | t = t / 12 73 | 74 | year = t + 2000 75 | 76 | d = datetime(year, month, day, hour, minute, second) 77 | 78 | return d 79 | 80 | -------------------------------------------------------------------------------- /zklib/zkdevice.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkdevicename(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_DEVICE 9 | command_string = '~DeviceName' 10 | chksum = 0 11 | session_id = self.session_id 12 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | self.zkclient.sendto(buf, self.address) 17 | #print buf.encode("hex") 18 | try: 19 | self.data_recv, addr = self.zkclient.recvfrom(1024) 20 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 21 | return self.data_recv[8:] 22 | except: 23 | return False 24 | 25 | def zkpoweroff(self): 26 | """Start a connection with the time clock""" 27 | command = CMD_POWEROFF 28 | command_string = '' 29 | chksum = 0 30 | session_id = self.session_id 31 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 32 | 33 | buf = self.createHeader(command, chksum, session_id, 34 | reply_id, command_string) 35 | self.zkclient.sendto(buf, self.address) 36 | #print buf.encode("hex") 37 | try: 38 | self.data_recv, addr = self.zkclient.recvfrom(1024) 39 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 40 | return self.data_recv[8:] 41 | except: 42 | return False 43 | 44 | def zkrestart(self): 45 | """Start a connection with the time clock""" 46 | command = CMD_RESTART 47 | command_string = '' 48 | chksum = 0 49 | session_id = self.session_id 50 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 51 | 52 | buf = self.createHeader(command, chksum, session_id, 53 | reply_id, command_string) 54 | self.zkclient.sendto(buf, self.address) 55 | #print buf.encode("hex") 56 | try: 57 | self.data_recv, addr = self.zkclient.recvfrom(1024) 58 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 59 | return self.data_recv[8:] 60 | except: 61 | return False 62 | 63 | def zkenabledevice(self): 64 | """Start a connection with the time clock""" 65 | command = CMD_ENABLEDEVICE 66 | command_string = '' 67 | chksum = 0 68 | session_id = self.session_id 69 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 70 | 71 | buf = self.createHeader(command, chksum, session_id, 72 | reply_id, command_string) 73 | self.zkclient.sendto(buf, self.address) 74 | #print buf.encode("hex") 75 | try: 76 | self.data_recv, addr = self.zkclient.recvfrom(1024) 77 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 78 | return self.data_recv[8:] 79 | except: 80 | return False 81 | 82 | def zkdisabledevice(self): 83 | """Start a connection with the time clock""" 84 | command = CMD_DISABLEDEVICE 85 | command_string = '\x00\x00' 86 | chksum = 0 87 | session_id = self.session_id 88 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 89 | 90 | buf = self.createHeader(command, chksum, session_id, 91 | reply_id, command_string) 92 | self.zkclient.sendto(buf, self.address) 93 | #print buf.encode("hex") 94 | try: 95 | self.data_recv, addr = self.zkclient.recvfrom(1024) 96 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 97 | return self.data_recv[8:] 98 | except: 99 | return False 100 | -------------------------------------------------------------------------------- /zklib/zkextendfmt.py: -------------------------------------------------------------------------------- 1 | def zkextendfmt(self): 2 | try: 3 | test = self.exttrynumber 4 | except: 5 | self.exttrynumber = 1 6 | 7 | data_seq=[ self.data_recv.encode("hex")[4:6], self.data_recv.encode("hex")[6:8] ] 8 | print data_seq 9 | if self.exttrynumber == 1: 10 | plus1 = 0 11 | plus2 = 0 12 | else: 13 | plus1 = -1 14 | plus2 = +1 15 | 16 | 17 | desc = ": +"+hex( int('99', 16)+plus1 ).lstrip('0x')+", +"+hex(int('b1', 16)+plus2).lstrip("0x") 18 | self.data_seq1 = hex( int( data_seq[0], 16 ) + int( '99', 16 ) + plus1 ).lstrip("0x") 19 | self.data_seq2 = hex( int( data_seq[1], 16 ) + int( 'b1', 16 ) + plus2 ).lstrip("0x") 20 | 21 | if len(self.data_seq1) >= 3: 22 | #self.data_seq2 = hex( int( self.data_seq2, 16 ) + int( self.data_seq1[:1], 16) ).lstrip("0x") 23 | self.data_seq1 = self.data_seq1[-2:] 24 | 25 | if len(self.data_seq2) >= 3: 26 | #self.data_seq1 = hex( int( self.data_seq1, 16 ) + int( self.data_seq2[:1], 16) ).lstrip("0x") 27 | self.data_seq2 = self.data_seq2[-2:] 28 | 29 | 30 | if len(self.data_seq1) <= 1: 31 | self.data_seq1 = "0"+self.data_seq1 32 | 33 | if len(self.data_seq2) <= 1: 34 | self.data_seq2 = "0"+self.data_seq2 35 | 36 | 37 | counter = hex( self.counter ).lstrip("0x") 38 | if len(counter): 39 | counter = "0" + counter 40 | print self.data_seq1+" "+self.data_seq2+desc 41 | data = "0b00"+self.data_seq1+self.data_seq2+self.id_com+counter+"007e457874656e64466d7400" 42 | self.zkclient.sendto(data.decode("hex"), self.address) 43 | print data 44 | try: 45 | self.data_recv, addr = self.zkclient.recvfrom(1024) 46 | except: 47 | if self.exttrynumber == 1: 48 | self.exttrynumber = 2 49 | tmp = zkextendfmt(self) 50 | if len(tmp) < 1: 51 | self.exttrynumber = 1 52 | 53 | self.id_com = self.data_recv.encode("hex")[8:12] 54 | self.counter = self.counter+1 55 | print self.data_recv.encode("hex") 56 | return self.data_recv[8:] 57 | -------------------------------------------------------------------------------- /zklib/zkextendoplog.py: -------------------------------------------------------------------------------- 1 | def zkextendoplog(self, index=0): 2 | try: 3 | test = self.extlogtrynumber 4 | except: 5 | self.extlogtrynumber = 1 6 | 7 | data_seq=[ self.data_recv.encode("hex")[4:6], self.data_recv.encode("hex")[6:8] ] 8 | print data_seq 9 | 10 | if index==0: 11 | self.data_seq1 = hex( int( data_seq[0], 16 ) + int( '104', 16 ) ).lstrip("0x") 12 | self.data_seq2 = hex( int( data_seq[1], 16 ) + int( '19', 16 ) ).lstrip("0x") 13 | desc = ": +104, +19" 14 | header="0b00" 15 | elif index==1: 16 | self.data_seq1 = hex( abs( int( data_seq[0], 16 ) - int( '2c', 16 ) ) ).lstrip("0x") 17 | self.data_seq2 = hex( abs( int( data_seq[1], 16 ) - int( '2', 16 ) ) ).lstrip("0x") 18 | desc = ": -2c, -2" 19 | header="d107" 20 | elif index>=2: 21 | self.data_seq1 = hex( abs( int( data_seq[0], 16 ) - int( '2c', 16 ) ) ).lstrip("0x") 22 | self.data_seq2 = hex( abs( int( data_seq[1], 16 ) - int( '2', 16 ) ) ).lstrip("0x") 23 | desc = ": -2c, -2" 24 | header="ffff" 25 | 26 | 27 | print self.data_seq1+" "+self.data_seq2 28 | if len(self.data_seq1) >= 3: 29 | self.data_seq2 = hex( int( self.data_seq2, 16 ) + int( self.data_seq1[:1], 16) ).lstrip("0x") 30 | self.data_seq1 = self.data_seq1[-2:] 31 | 32 | if len(self.data_seq2) >= 3: 33 | self.data_seq1 = hex( int( self.data_seq1, 16 ) + int( self.data_seq2[:1], 16) ).lstrip("0x") 34 | self.data_seq2 = self.data_seq2[-2:] 35 | 36 | if len(self.data_seq1) <= 1: 37 | self.data_seq1 = "0"+self.data_seq1 38 | 39 | if len(self.data_seq2) <= 1: 40 | self.data_seq2 = "0"+self.data_seq2 41 | 42 | 43 | counter = hex( self.counter ).lstrip("0x") 44 | if len(counter): 45 | counter = "0" + counter 46 | 47 | print self.data_seq1+" "+self.data_seq2+desc 48 | data = header+self.data_seq1+self.data_seq2+self.id_com+counter+"00457874656e644f504c6f6700" 49 | self.zkclient.sendto(data.decode("hex"), self.address) 50 | print data 51 | try: 52 | self.data_recv, addr = self.zkclient.recvfrom(1024) 53 | except: 54 | bingung=1 55 | if self.extlogtrynumber == 1: 56 | self.extlogtrynumber = 2 57 | zkextendoplog(self) 58 | 59 | self.id_com = self.data_recv.encode("hex")[8:12] 60 | self.counter = self.counter+1 61 | print self.data_recv.encode("hex") 62 | return self.data_recv[8:] 63 | -------------------------------------------------------------------------------- /zklib/zkface.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkfaceon(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_DEVICE 9 | command_string = 'FaceFunOn' 10 | chksum = 0 11 | session_id = self.session_id 12 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | self.zkclient.sendto(buf, self.address) 17 | #print buf.encode("hex") 18 | try: 19 | self.data_recv, addr = self.zkclient.recvfrom(1024) 20 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 21 | return self.data_recv[8:] 22 | except: 23 | return False 24 | 25 | -------------------------------------------------------------------------------- /zklib/zkfreedata.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | 7 | def zkfreedata(self): 8 | """Tell device to free data for transmisison""" 9 | command = CMD_FREE_DATA 10 | command_string = '' 11 | chksum = 0 12 | session_id = self.session_id 13 | 14 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 15 | 16 | buf = self.createHeader(command,chksum, session_id,reply_id, command_string) 17 | self.zkclient.sendto(buf,self.address) 18 | 19 | try: 20 | self.data_recv, addr = self.zkclient.recvfrom(1024) 21 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 22 | return self.data_recv[8:] 23 | except: 24 | return False -------------------------------------------------------------------------------- /zklib/zklib.py: -------------------------------------------------------------------------------- 1 | from socket import * 2 | 3 | import sys 4 | import select 5 | import errno 6 | import time 7 | 8 | from struct import pack, unpack 9 | from datetime import datetime, date 10 | 11 | from zkconnect import * 12 | from zkversion import * 13 | from zkos import * 14 | from zkextendfmt import * 15 | from zkextendoplog import * 16 | from zkplatform import * 17 | from zkworkcode import * 18 | from zkssr import * 19 | from zkpin import * 20 | from zkface import * 21 | from zkserialnumber import * 22 | from zkdevice import * 23 | from zkuser import * 24 | from zkattendance import * 25 | from zktime import * 26 | from zkprepare import * 27 | from zkrefreshdata import * 28 | from zkfreedata import * 29 | from zkrestart import * 30 | from zkAtt import * 31 | 32 | class ZKLib: 33 | 34 | def __init__(self, ip, port): 35 | self.address = (ip, port) 36 | self.zkclient = socket(AF_INET, SOCK_DGRAM) 37 | self.zkclient.settimeout(3) 38 | self.session_id = 0 39 | self.userdata = [] 40 | self.attendancedata = [] 41 | 42 | 43 | def createChkSum(self, p): 44 | """This function calculates the chksum of the packet to be sent to the 45 | time clock 46 | 47 | Copied from zkemsdk.c""" 48 | l = len(p) 49 | chksum = 0 50 | while l > 1: 51 | chksum += unpack('H', pack('BB', p[0], p[1]))[0] 52 | 53 | p = p[2:] 54 | if chksum > USHRT_MAX: 55 | chksum -= USHRT_MAX 56 | l -= 2 57 | 58 | 59 | if l: 60 | chksum = chksum + p[-1] 61 | 62 | while chksum > USHRT_MAX: 63 | chksum -= USHRT_MAX 64 | 65 | chksum = ~chksum 66 | 67 | while chksum < 0: 68 | chksum += USHRT_MAX 69 | 70 | return pack('H', chksum) 71 | 72 | 73 | def createHeader(self, command, chksum, session_id, reply_id, 74 | command_string): 75 | """This function puts a the parts that make up a packet together and 76 | packs them into a byte string""" 77 | buf = pack('HHHH', command, chksum, 78 | session_id, reply_id) + command_string 79 | 80 | buf = unpack('8B'+'%sB' % len(command_string), buf) 81 | 82 | chksum = unpack('H', self.createChkSum(buf))[0] 83 | #print unpack('H', self.createChkSum(buf)) 84 | reply_id += 1 85 | if reply_id >= USHRT_MAX: 86 | reply_id -= USHRT_MAX 87 | 88 | buf = pack('HHHH', command, chksum, session_id, reply_id) 89 | return buf + command_string 90 | 91 | 92 | def checkValid(self, reply): 93 | """Checks a returned packet to see if it returned CMD_ACK_OK, 94 | indicating success""" 95 | command = unpack('HHHH', reply[:8])[0] 96 | 97 | if command == CMD_ACK_OK: 98 | print "CMD_ACK_OK" 99 | return True 100 | else: 101 | return False 102 | 103 | def connect(self): 104 | return zkconnect(self) 105 | 106 | def disconnect(self): 107 | return zkdisconnect(self) 108 | 109 | def version(self): 110 | return zkversion(self) 111 | 112 | def osversion(self): 113 | return zkos(self) 114 | 115 | def extendFormat(self): 116 | return zkextendfmt(self) 117 | 118 | def extendOPLog(self, index=0): 119 | return zkextendoplog(self, index) 120 | 121 | def platform(self): 122 | return zkplatform(self) 123 | 124 | def fmVersion(self): 125 | return zkplatformVersion(self) 126 | 127 | def workCode(self): 128 | return zkworkcode(self) 129 | 130 | def ssr(self): 131 | return zkssr(self) 132 | 133 | def pinWidth(self): 134 | return zkpinwidth(self) 135 | 136 | def faceFunctionOn(self): 137 | return zkfaceon(self) 138 | 139 | def serialNumber(self): 140 | return zkserialnumber(self) 141 | 142 | def deviceName(self): 143 | return zkdevicename(self) 144 | 145 | def enableDevice(self): 146 | return zkenabledevice(self) 147 | 148 | def disableDevice(self): 149 | return zkdisabledevice(self) 150 | 151 | def restartDevice(self): 152 | return zkrestart(self) 153 | 154 | def poweroffDevice(self): 155 | return zkpoweroff(self) 156 | 157 | def getUser(self): 158 | return zkgetuser(self) 159 | 160 | def setUser(self, uid, userid, name, password, role): 161 | return zksetuser(self, uid, userid, name, password, role) 162 | 163 | def clearUser(self): 164 | return zkclearuser(self) 165 | 166 | def clearAdmin(self): 167 | return zkclearadmin(self) 168 | 169 | def enrollUser(self, uid): 170 | return zkenrolluser(self, uid) 171 | 172 | def getAttendance(self): 173 | return zkgetattendance(self) 174 | 175 | def clearAttendance(self): 176 | return zkclearattendance(self) 177 | 178 | def setTime(self, t): 179 | return zksettime(self, t) 180 | 181 | def getTime(self): 182 | return zkgettime(self) 183 | 184 | def prepareData(self): 185 | return zkprepare(self) 186 | 187 | def refreshData(self): 188 | return zkrefreshdata(self) 189 | 190 | def freeData(self): 191 | return zkfreedata(self) 192 | 193 | def reboot(self): 194 | return zkrestart(self) 195 | 196 | def testatt(self): 197 | return zkAtt(self) -------------------------------------------------------------------------------- /zklib/zkos.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkos(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_DEVICE 9 | command_string = '~OS' 10 | chksum = 0 11 | session_id = self.session_id 12 | 13 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 14 | 15 | buf = self.createHeader(command, chksum, session_id, 16 | reply_id, command_string) 17 | self.zkclient.sendto(buf, self.address) 18 | 19 | try: 20 | self.data_recv, addr = self.zkclient.recvfrom(1024) 21 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 22 | return self.data_recv[8:] 23 | except: 24 | return False 25 | -------------------------------------------------------------------------------- /zklib/zkpin.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkpinwidth(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_DEVICE 9 | command_string = '~PIN2Width' 10 | chksum = 0 11 | session_id = self.session_id 12 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | self.zkclient.sendto(buf, self.address) 17 | #print buf.encode("hex") 18 | try: 19 | self.data_recv, addr = self.zkclient.recvfrom(1024) 20 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 21 | return self.data_recv[8:] 22 | except: 23 | return False 24 | 25 | -------------------------------------------------------------------------------- /zklib/zkplatform.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkplatform(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_DEVICE 9 | command_string = '~Platform' 10 | chksum = 0 11 | session_id = self.session_id 12 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | self.zkclient.sendto(buf, self.address) 17 | #print buf.encode("hex") 18 | try: 19 | self.data_recv, addr = self.zkclient.recvfrom(1024) 20 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 21 | return self.data_recv[8:] 22 | except: 23 | return False 24 | 25 | 26 | def zkplatformVersion(self): 27 | """Start a connection with the time clock""" 28 | command = CMD_DEVICE 29 | command_string = '~ZKFPVersion' 30 | chksum = 0 31 | session_id = self.session_id 32 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 33 | 34 | buf = self.createHeader(command, chksum, session_id, 35 | reply_id, command_string) 36 | self.zkclient.sendto(buf, self.address) 37 | #print buf.encode("hex") 38 | try: 39 | self.data_recv, addr = self.zkclient.recvfrom(1024) 40 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 41 | return self.data_recv[8:] 42 | except: 43 | return False 44 | -------------------------------------------------------------------------------- /zklib/zkprepare.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | 7 | def zkprepare(self): 8 | """Tell device to prepare for data transmisison""" 9 | command = CMD_PREPARE_DATA 10 | command_string = '' 11 | chksum = 0 12 | session_id = self.session_id 13 | 14 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 15 | 16 | buf = self.createHeader(command,chksum, session_id,reply_id, command_string) 17 | self.zkclient.sendto(buf,self.address) 18 | 19 | try: 20 | self.data_recv, addr = self.zkclient.recvfrom(1024) 21 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 22 | return self.data_recv[8:] 23 | except: 24 | return False -------------------------------------------------------------------------------- /zklib/zkrefreshdata: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | 7 | def zkrefreshdata(self): 8 | """Tell device to prepare for data transmisison""" 9 | command = CMD_REFRESHDATA 10 | command_string = '' 11 | chksum = 0 12 | session_id = self.session_id 13 | 14 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 15 | 16 | buf = self.createHeader(command,chksum, session_id,reply_id, command_string) 17 | self.zkclient.sendto(buf,self.address) 18 | 19 | try: 20 | self.data_recv, addr = self.zkclient.recvfrom(1024) 21 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 22 | return self.data_recv[8:] 23 | except: 24 | return False -------------------------------------------------------------------------------- /zklib/zkrefreshdata.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | 7 | def zkrefreshdata(self): 8 | """Tell device to refresh data for transmisison""" 9 | command = CMD_REFRESHDATA 10 | command_string = '' 11 | chksum = 0 12 | session_id = self.session_id 13 | 14 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 15 | 16 | buf = self.createHeader(command,chksum, session_id,reply_id, command_string) 17 | self.zkclient.sendto(buf,self.address) 18 | 19 | try: 20 | self.data_recv, addr = self.zkclient.recvfrom(1024) 21 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 22 | return self.data_recv[8:] 23 | except: 24 | return False -------------------------------------------------------------------------------- /zklib/zkrestart.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | 7 | def zkrestart(self): 8 | """Tell device to reboot""" 9 | command = CMD_RESTART 10 | command_string = '' 11 | chksum = 0 12 | session_id = self.session_id 13 | 14 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 15 | 16 | buf = self.createHeader(command,chksum, session_id,reply_id, command_string) 17 | self.zkclient.sendto(buf,self.address) 18 | 19 | try: 20 | self.data_recv, addr = self.zkclient.recvfrom(1024) 21 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 22 | return self.data_recv[8:] 23 | except: 24 | return False -------------------------------------------------------------------------------- /zklib/zkserialnumber.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkserialnumber(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_DEVICE 9 | command_string = '~SerialNumber' 10 | chksum = 0 11 | session_id = self.session_id 12 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | self.zkclient.sendto(buf, self.address) 17 | #print buf.encode("hex") 18 | try: 19 | self.data_recv, addr = self.zkclient.recvfrom(1024) 20 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 21 | return self.data_recv[8:] 22 | except: 23 | return False 24 | 25 | -------------------------------------------------------------------------------- /zklib/zkssr.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkssr(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_DEVICE 9 | command_string = '~SSR' 10 | chksum = 0 11 | session_id = self.session_id 12 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | self.zkclient.sendto(buf, self.address) 17 | #print buf.encode("hex") 18 | try: 19 | self.data_recv, addr = self.zkclient.recvfrom(1024) 20 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 21 | return self.data_recv[8:] 22 | except: 23 | return False 24 | 25 | -------------------------------------------------------------------------------- /zklib/zktime.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def reverseHex(hexstr): 7 | tmp = '' 8 | for i in reversed( xrange( len(hexstr)/2 ) ): 9 | tmp += hexstr[i*2:(i*2)+2] 10 | 11 | return tmp 12 | 13 | def zksettime(self, t): 14 | """Start a connection with the time clock""" 15 | command = CMD_SET_TIME 16 | command_string = pack('I',encode_time(t)) 17 | chksum = 0 18 | session_id = self.session_id 19 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 20 | 21 | buf = self.createHeader(command, chksum, session_id, 22 | reply_id, command_string) 23 | self.zkclient.sendto(buf, self.address) 24 | #print buf.encode("hex") 25 | try: 26 | self.data_recv, addr = self.zkclient.recvfrom(1024) 27 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 28 | return self.data_recv[8:] 29 | except: 30 | return False 31 | 32 | 33 | def zkgettime(self): 34 | """Start a connection with the time clock""" 35 | command = CMD_GET_TIME 36 | command_string = '' 37 | chksum = 0 38 | session_id = self.session_id 39 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 40 | 41 | buf = self.createHeader(command, chksum, session_id, 42 | reply_id, command_string) 43 | self.zkclient.sendto(buf, self.address) 44 | #print buf.encode("hex") 45 | try: 46 | self.data_recv, addr = self.zkclient.recvfrom(1024) 47 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 48 | return decode_time( int( reverseHex( self.data_recv[8:].encode("hex") ), 16 ) ) 49 | except: 50 | return False 51 | -------------------------------------------------------------------------------- /zklib/zkuser.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def getSizeUser(self): 7 | """Checks a returned packet to see if it returned CMD_PREPARE_DATA, 8 | indicating that data packets are to be sent 9 | 10 | Returns the amount of bytes that are going to be sent""" 11 | command = unpack('HHHH', self.data_recv[:8])[0] 12 | if command == CMD_PREPARE_DATA: 13 | size = unpack('I', self.data_recv[8:12])[0] 14 | return size 15 | else: 16 | return False 17 | 18 | 19 | def zksetuser(self, uid, userid, name, password, role): 20 | """Start a connection with the time clock""" 21 | command = CMD_SET_USER 22 | command_string = pack('sxs8s28ss7sx8s16s', chr( uid ), chr(role), password, name, chr(1), '', userid, '' ) 23 | chksum = 0 24 | session_id = self.session_id 25 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 26 | 27 | buf = self.createHeader(command, chksum, session_id, 28 | reply_id, command_string) 29 | self.zkclient.sendto(buf, self.address) 30 | #print buf.encode("hex") 31 | try: 32 | self.data_recv, addr = self.zkclient.recvfrom(1024) 33 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 34 | return self.data_recv[8:] 35 | except: 36 | return False 37 | 38 | 39 | def zkgetuser(self): 40 | """Start a connection with the time clock""" 41 | command = CMD_USERTEMP_RRQ 42 | command_string = '\x05' 43 | chksum = 0 44 | session_id = self.session_id 45 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 46 | 47 | buf = self.createHeader(command, chksum, session_id, 48 | reply_id, command_string) 49 | self.zkclient.sendto(buf, self.address) 50 | #print buf.encode("hex") 51 | try: 52 | self.data_recv, addr = self.zkclient.recvfrom(1024) 53 | 54 | 55 | if getSizeUser(self): 56 | bytes = getSizeUser(self) 57 | 58 | while bytes > 0: 59 | data_recv, addr = self.zkclient.recvfrom(1032) 60 | self.userdata.append(data_recv) 61 | bytes -= 1024 62 | 63 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 64 | data_recv = self.zkclient.recvfrom(8) 65 | 66 | users = {} 67 | if len(self.userdata) > 0: 68 | # The first 4 bytes don't seem to be related to the user 69 | for x in xrange(len(self.userdata)): 70 | if x > 0: 71 | self.userdata[x] = self.userdata[x][8:] 72 | 73 | userdata = ''.join( self.userdata ) 74 | 75 | userdata = userdata[11:] 76 | 77 | while len(userdata) > 72: 78 | 79 | uid, role, password, name, userid = unpack( '2s2s8s28sx31s', userdata.ljust(72)[:72] ) 80 | 81 | uid = int( uid.encode("hex"), 16) 82 | # Clean up some messy characters from the user name 83 | password = password.split('\x00', 1)[0] 84 | password = unicode(password.strip('\x00|\x01\x10x'), errors='ignore') 85 | 86 | #uid = uid.split('\x00', 1)[0] 87 | userid = unicode(userid.strip('\x00|\x01\x10x'), errors='ignore') 88 | 89 | name = name.split('\x00', 1)[0] 90 | 91 | if name.strip() == "": 92 | name = uid 93 | 94 | users[uid] = (userid, name, int( role.encode("hex"), 16 ), password) 95 | 96 | #print("%d, %s, %s, %s, %s" % (uid, userid, name, int( role.encode("hex"), 16 ), password)) 97 | userdata = userdata[72:] 98 | 99 | return users 100 | except: 101 | return False 102 | 103 | 104 | def zkclearuser(self): 105 | """Start a connection with the time clock""" 106 | command = CMD_CLEAR_DATA 107 | command_string = '' 108 | chksum = 0 109 | session_id = self.session_id 110 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 111 | 112 | buf = self.createHeader(command, chksum, session_id, 113 | reply_id, command_string) 114 | self.zkclient.sendto(buf, self.address) 115 | #print buf.encode("hex") 116 | try: 117 | self.data_recv, addr = self.zkclient.recvfrom(1024) 118 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 119 | return self.data_recv[8:] 120 | except: 121 | return False 122 | 123 | 124 | def zkclearadmin(self): 125 | """Start a connection with the time clock""" 126 | command = CMD_CLEAR_ADMIN 127 | command_string = '' 128 | chksum = 0 129 | session_id = self.session_id 130 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 131 | 132 | buf = self.createHeader(command, chksum, session_id, 133 | reply_id, command_string) 134 | self.zkclient.sendto(buf, self.address) 135 | #print buf.encode("hex") 136 | try: 137 | self.data_recv, addr = self.zkclient.recvfrom(1024) 138 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 139 | return self.data_recv[8:] 140 | except: 141 | return False 142 | 143 | def zkenrolluser(self, uid): 144 | '''Start Remote Fingerprint Enrollment''' 145 | 146 | command = CMD_STARTENROLL 147 | command_string = pack('2s', uid) 148 | chksum = 0 149 | session_id = self.session_id 150 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 151 | 152 | buf = self.createHeader(command, chksum, session_id, 153 | reply_id, command_string) 154 | self.zkclient.sendto(buf, self.address) 155 | 156 | try: 157 | self.data_recv, addr = self.zkclient.recvfrom(1024) 158 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 159 | return self.data_recv[8:] 160 | except: 161 | print "failed", self.data_recv 162 | return False -------------------------------------------------------------------------------- /zklib/zkversion.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkversion(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_VERSION 9 | command_string = '' 10 | chksum = 0 11 | session_id = self.session_id 12 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | self.zkclient.sendto(buf, self.address) 17 | #print buf.encode("hex") 18 | try: 19 | self.data_recv, addr = self.zkclient.recvfrom(1024) 20 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 21 | return self.data_recv[8:] 22 | except: 23 | return False 24 | 25 | -------------------------------------------------------------------------------- /zklib/zkworkcode.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from datetime import datetime, date 3 | 4 | from zkconst import * 5 | 6 | def zkworkcode(self): 7 | """Start a connection with the time clock""" 8 | command = CMD_DEVICE 9 | command_string = 'WorkCode' 10 | chksum = 0 11 | session_id = self.session_id 12 | reply_id = unpack('HHHH', self.data_recv[:8])[3] 13 | 14 | buf = self.createHeader(command, chksum, session_id, 15 | reply_id, command_string) 16 | self.zkclient.sendto(buf, self.address) 17 | #print buf.encode("hex") 18 | try: 19 | self.data_recv, addr = self.zkclient.recvfrom(1024) 20 | self.session_id = unpack('HHHH', self.data_recv[:8])[2] 21 | return self.data_recv[8:] 22 | except: 23 | return False 24 | -------------------------------------------------------------------------------- /zktest.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append("zklib") 3 | 4 | from zklib import zklib 5 | import time 6 | import zkconst 7 | 8 | zk = zklib.ZKLib("192.168.1.201", 4370) 9 | 10 | ret = zk.connect() 11 | print "connection:", ret 12 | 13 | if ret == True: 14 | print "Disable Device", zk.disableDevice() 15 | 16 | print "ZK Version:", zk.version() 17 | print "OS Version:", zk.osversion() 18 | """ 19 | print "Extend Format:", zk.extendFormat() 20 | print "Extend OP Log:", zk.extendOPLog() 21 | """ 22 | 23 | print "Platform:", zk.platform() 24 | print "Platform Version:", zk.fmVersion() 25 | print "Work Code:", zk.workCode() 26 | print "Work Code:", zk.workCode() 27 | print "SSR:", zk.ssr() 28 | print "Pin Width:", zk.pinWidth() 29 | print "Face Function On:", zk.faceFunctionOn() 30 | print "Serial Number:", zk.serialNumber() 31 | print "Device Name:", zk.deviceName() 32 | 33 | data_user = zk.getUser() 34 | print "Get User:" 35 | if data_user: 36 | for uid in data_user: 37 | 38 | if data_user[uid][2] == 14: 39 | level = 'Admin' 40 | else: 41 | level = 'User' 42 | print "[UID %d]: ID: %s, Name: %s, Level: %s, Password: %s" % ( uid, data_user[uid][0], data_user[uid][1], level, data_user[uid][3] ) 43 | 44 | #zk.setUser(uid=61, userid='41', name='Dony Wahyu Isp', password='123456', role=zkconst.LEVEL_ADMIN) 45 | 46 | attendance = zk.getAttendance() 47 | print "Get Attendance:" 48 | 49 | if ( attendance ): 50 | for lattendance in attendance: 51 | print lattendance[1] 52 | if lattendance[1] == 15: 53 | state = 'Check In' 54 | elif lattendance[1] == 0: 55 | state = 'Check Out' 56 | else: 57 | state = 'Undefined' 58 | 59 | print "date %s, Jam %s: %s, Status: %s" % ( lattendance[2].date(), lattendance[2].time(), lattendance[0], state ) 60 | 61 | # print "Clear Attendance:", zk.clearAttendance() 62 | 63 | zk.setUser(67, '67', 'Shubhamoy Chakrabarty', '', 0) 64 | zk.enrollUser('67') 65 | print "Get Time:", zk.getTime() 66 | print "Enable Device", zk.enableDevice() 67 | print "Disconnect:", zk.disconnect() 68 | --------------------------------------------------------------------------------