{ "info": { "author": "Vinicius Schettino", "author_email": "vinicius.schettino@ice.ufjf.br", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# SDK for Henry Argos Biometric Fingerprint\n\nHenry Argos SDK is a helper project to handle communication with [Henry Argos](http://www.henry.com.br/controle-de-acesso/argos) access control fingerprint/card reader. All communication happens through TCP/IP sockets, where the reader is the server and this SDK plays the client role.\n\n## Compability\nThe protocol should be compatible with other [Henry products](https://www.henry.com.br/controle-de-acesso), but many features were tailored down to Argos use, since this is the main goal of the project. Given it time, the goal is to remain compatible and feature balanced with other products as well. All development, use and automated testing were conducted using Argos firmware versions **1.0.1.3b** and **1.0.0.24**.\n\n## Basic install\n\nYou can install it from pip like:\n```bash\npip install ArgosSDK\n```\nIt has the following dependencies:\n1. Python 3.6+\n1. [Daiquiri](https://daiquiri.readthedocs.io/) for logging\n1. [Parse](https://pypi.org/project/parse/) for handling package parsing.\n\n## Basic usage\nIn the basic usage you only need to import the SDK and the exceptions for error handling:\n\n```python\nfrom argos import SDK, exceptions\nfrom datetime import datetime, timedelta\nimport daiquiri, logging\n\ndaiquiri.setup(level=logging.INFO)\nlogger = daiquiri.getLogger()\n\nip = \"192.168.0.200\"\nfingerprints = [\n \"021474747414\",\n \"021474747414\"\n]\nnow = datetime.today()\nd = now - timedelta(days=1)\ntry:\n with SDK(ip) as s:\n s.set_timestamp(timestamp=now)\n s.get_timestamp()\n s.get_cards(count=14, start_index=0)\n s.get_quantity(typec=SDK.QT_CARDS)\n s.send_cards(card_number=\"TEST\")\n s.capture_fingerprint(card_number=\"47854785\", timeout=30)\n s.get_fingerprints(card_number=\"47854785\")\n s.send_fingerprints(\"47854785\", fingerprints)\n s.delete_fingerprints(card_number=\"47854785\")\n s.send_cards(card_number=\"47854785\", mode=SDK.SEND_DELETE)\n s.get_events(start_date=d)\nexcept (\n exceptions.ConnectTimeout,\n exceptions.SendCommandTimeout,\n exceptions.TooManyCardsRequested,\n exceptions.GenericErrorResponse,\n) as e:\n logger.warning(e)\n```\n\nBesides the IP, you can also specify the following parameters to the SDK:\n\n1. `port` (default 3000)\n1. `timeout`, meaning the default time the socket should hang while expecting a response. Valid to the connection procedure. (default 3s)\n1. `max_tries` specifies how many times the command should be resend before it gives up. (default 5 times)\n1. `sleep_between_tries` meaning how much the SDK should wait before sending again the command. (default .5s)\n\n\n## Commands\n\n# Command send configuration\nEvery command can receive the following ``**connection_params``:\n\n1. `timeout` overrides the SDK configuration on how much the socket should hang while expecting a response.\n1. `tries` overrides the SDK configuration on how many times the command should be resend before it gives up.\n\n# Command response\nCommands always return a `Response` object. If you want to access the returned data, you can simply use it as a dict:\n\n```python\nwith SDK(ip) as s:\n response = s.set_timestamp(timestamp=now)\n print(response) # print the response dict repr()\n print(response.data) # the actual dict with the response data\n print(response['payload']) # the payload of the response, already parsed\n\n```\n\nIf the return code is **greater than 10**, it means something went wrong. A `GenericErrorResponse` or one of its children will be raised containing more information.\n\n## Command list\n\n### SDK.get_timestamp([\\*\\*conection_params])\nGet the current timestamp setted on the equipment.\n\n**Expects**: None\n\n**Returns**: datetime object\n\n### SDK.set_timestamp([timestamp], [\\*\\*conection_params])\nSet the current timestamp setted on the equipment.\n\n**Expects**: Datime object. If none, `datetime.now()` will be used instead.\n\n**Returns**: No payload.\n\n### SDK.get_cards(count, start_index, [\\*\\*conection_params])\nRetrieve the cards registered, between `[start_index, start_index+count]`.\nThe protocol here limitates the response into 30 cards. If you try to get more than\nthat, a `TooManyCardsRequested` will be raised.\n\n**Expects**:\n1. `count`: how many cards\n1. `start_index`: from index. These parameters work like SQL's [LIMIT and OFFSET](http://www.sqltutorial.org/sql-limit/)\n\n**Returns**: payload containing `count` cards on a list\n\n### SDK.get_quantity([type, \\*\\*conection_params])\nGet the count of a given entry type.\n\n\n**Expects**: Type. The options are:\n\n1. SDK.QT_USERS = \"U\"\n1. SDK.QT_CARDS = \"C\"\n1. SDK.QT_FINGERPRINTS = \"D\"\n1. SDK.QT_MAX_FINGERPRINTS = \"TD\"\n\n**Returns**: a String containing a numeric value.\n\n### SDK.send_cards([card_number, [master], [verify_fingerprint], [send_mode]\\*\\*conection_params])\nGet the current timestamp setted on the equipment.\n\n**Expects**:\n1. `card_number` MAX 20\n1. `master` the card type, being:\n - SDK.NORMAL_MODE ('1') without master access (default)\n - SDK.MASTER_MODE ('6') master access\n1. `verify_fingerprint` whether the fingerprint is required to validate access (default True)\n1. `send_mode` the way the command should be send, being:\n - SEND_INSERT = \"I\" (default)\n - SEND_UPDATE = \"A\"\n - SEND_DELETE = \"E\" (complete wipe out, be careful)\n\n**Returns**: No payload\n\n### SDK.capture_fingerprints(card_number, [\\*\\*conection_params])\nAsk to the reader to collect a new fingerprint. The user will have about 15 seconds to put his finger on the reader. The system will ask the user to put the finger twice to confirm and save it into memory.\n\n**Expects**:\n1. `card_number` MAX 20 (must be registered already)\n\n**Returns**: No payload\n\n### SDK.get_fingerprints(card_number, [\\*\\*conection_params])\nGet all fingerprints of a card from the equipment.\n\n**Expects**:\n1. `card_number` MAX 20 (must be registered already)\n\n**Returns**: List of hex strings representing the fingerprint.\n\n### SDK.send_fingerprints(card_number, fingerprints[\\*\\*conection_params])\nSend a list of fingerprints to the reader.\n\n**Expects**:\n1. `card_number` MAX 20 (must be registered already)\n1. `fingerprints` a list of fingerprints as hex strings.\n\n**Returns**: No payload\n\n### SDK.delete_fingerprints(card_number, [\\*\\*conection_params])\nClear fingerprints of a card.\n\n**Expects**:\n1. `card_number` MAX 20 (must be registered already)\n\n**Returns**: No payload\n\n### SDK.get_events(start_date, [end_date], [\\*\\*conection_params])\nGet the current timestamp setted on the equipment.\n\n**Expects**:\n1. `start_date` datetime object\n1. `end_date` datetime object, `default datetime.now()`\n\n**Returns**: A list of events.\n\n## Basic package protocol information\nUsually the protocol follows this format:\n```python\n{START:1}{PAYLOAD_SIZE:2}{MESSAGE:8|10}{PAYLOAD:??}{CHECKSUM:1}{END:1}\n```\n\n1. `START`: Initial byte - 0x02\n1. `PAYLOAD_SIZE`: 2 bytes where the most significant byte is most right. **Like 421 = A5 01 (not 01 A5)** \n1. `MESSAGE`: that can be 8 byte like \"00+RH+00\" or 10 byte like \"00+ECAR+00\". The first two bytes indicate the version, and the last two bytes whether there was an error.\n1. `CHECKSUM`: resut of a **bitwise xor** of each byte from `PAYLOAD_SIZE` to the end of the `PAYLOAD`.\n1. `END`: End byte - 0x03\n\n## Create your own command\n\nYou can extend this project creating your own command and sending it to the SDK. It would be something like this:\n\n\n```python\nfrom argos import SDK, Command, Response\n\nclass AnotherResponse(Response):\n response_mapping = {\"payload\": (12, 29, False)}\n\n def parse_payload(self, bytes):\n string = bytes.decode()\n return self.dosomething(string)\n\nclass AnotherCommand(Command):\n response = AnotherResponse\n\n def payload(self):\n return \"01+??+00\"\n\nwith SDK(ip) as s:\n response = s.send_command(AnotherCommand(params), timeout=30)\n print(response['payload'])\n```\n## #ToDo stuff\n1. Use checksum byte in order to verify package integrity. Today it only verifies the start/end bytes.\n1. Send more than one card at time.\n\n## Building and testing\n\nYou can use docker to build and run the test suit, like:\n```bash\ndocker build . -t argos-sdk\ndocker run -eEQUIPMENT_IP=x.x.x.x -it argos-sdk\n# build and upload it to PyPi\ndocker run -eTWINE_PASSWORD=pass -eTWINE_USERNAME=user -eARGOS_SDK_VERSION=3.0 argos-sdk sh ./build_script\n```\n## About this Project\n\nThis project came from a demand at [Universidade Federal de Juiz de Fora (UFJF)](https://www2.ufjf.br/ufjf/), more specifically the Departamento de Energia Eletrica (DENE) at [Faculdade de Engenharia](http://www.ufjf.br/engenharia/). We needed a better system to access control of our labs and classrooms, so we decided to ship this communication layer as a opensource project.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://gitlab.com/engenharia-ufjf/biometria/argos-sdk", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "ArgosSDK", "package_url": "https://pypi.org/project/ArgosSDK/", "platform": "", "project_url": "https://pypi.org/project/ArgosSDK/", "project_urls": { "Homepage": "https://gitlab.com/engenharia-ufjf/biometria/argos-sdk" }, "release_url": "https://pypi.org/project/ArgosSDK/0.5.2/", "requires_dist": [ "daiquiri", "parse" ], "requires_python": ">=3.6", "summary": "A SDK to handle Henry Argos Fingerprint/Card readers", "version": "0.5.2" }, "last_serial": 5820303, "releases": { "0.1b0": [ { "comment_text": "", "digests": { "md5": "6a108c80eea1690db10493a6b408aa64", "sha256": "13c44a3c668097f2363f93336e866d08ceaa4f99597725a68af432b2eabc89ac" }, "downloads": -1, "filename": "ArgosSDK-0.1b0-py3-none-any.whl", "has_sig": false, "md5_digest": "6a108c80eea1690db10493a6b408aa64", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8152, "upload_time": "2019-09-10T13:17:33", "url": "https://files.pythonhosted.org/packages/85/96/13054d1f1db025e67518bfb523336a5c050dcfc835aa2a2838ffe59ebd52/ArgosSDK-0.1b0-py3-none-any.whl" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "67e9c5baf663e721ea31a84c3495e3f8", "sha256": "45fe2cb2395c1c31c386504fd16632781d0418dde51fe1d0bbe02afc02619a10" }, "downloads": -1, "filename": "ArgosSDK-0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "67e9c5baf663e721ea31a84c3495e3f8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11315, "upload_time": "2019-09-10T15:40:13", "url": "https://files.pythonhosted.org/packages/bd/c7/81e48155652e91bf34995ca4af3ae74386c0fb9dfbfb2050d552fd5bade6/ArgosSDK-0.2-py3-none-any.whl" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "8ce1c0e1dcf414ce73b1dc57a61cb9e5", "sha256": "659073f34da2ef70307f86ad30740dc32ccde21ea7071e0b1c62a065810c0ccb" }, "downloads": -1, "filename": "ArgosSDK-0.2.2-py3-none-any.whl", "has_sig": false, "md5_digest": "8ce1c0e1dcf414ce73b1dc57a61cb9e5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11335, "upload_time": "2019-09-10T18:28:13", "url": "https://files.pythonhosted.org/packages/2f/53/f38bdc1e05ab1de761e43a359ae432c7e0bcf5d1f230d8637269ae8492ec/ArgosSDK-0.2.2-py3-none-any.whl" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "8922e930d3f0974b5fcf8c228dfb9c72", "sha256": "cc188b74d46041407785438561adfdf72c6cb7800221cfda1240660e6750025c" }, "downloads": -1, "filename": "ArgosSDK-0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "8922e930d3f0974b5fcf8c228dfb9c72", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11124, "upload_time": "2019-09-10T18:30:31", "url": "https://files.pythonhosted.org/packages/a1/4b/3d11eee9be589c5f4745d525e5395e6fea2eb952cfef93e5541ec0dd77ed/ArgosSDK-0.3-py3-none-any.whl" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "318418967a7a765bacfdf452fc86b300", "sha256": "9f65bcc5fd12648513930feabf83582f560213d4d6be27746f9501985dd83d3c" }, "downloads": -1, "filename": "ArgosSDK-0.4-py3-none-any.whl", "has_sig": false, "md5_digest": "318418967a7a765bacfdf452fc86b300", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11123, "upload_time": "2019-09-11T17:49:47", "url": "https://files.pythonhosted.org/packages/6b/c0/e3c7387ae59ad9c91148e917ce9c22e47bf92ca6d5f8377cbfc7f07e0f01/ArgosSDK-0.4-py3-none-any.whl" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "878a4ae88c3c2992cf49ffe60872b74b", "sha256": "7ec7bf43927d91bd0b1f131fc772567368f9068e0eaa687813daf56cd7501a4a" }, "downloads": -1, "filename": "ArgosSDK-0.4.1-py3-none-any.whl", "has_sig": false, "md5_digest": "878a4ae88c3c2992cf49ffe60872b74b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11201, "upload_time": "2019-09-11T19:13:53", "url": "https://files.pythonhosted.org/packages/1e/aa/b04529b9522d3c4e1e90e86f9e178b7c4c986b1b884efbb645dde90ff371/ArgosSDK-0.4.1-py3-none-any.whl" } ], "0.4b3": [ { "comment_text": "", "digests": { "md5": "53a0b78ad34333abf131a7ca64d05be9", "sha256": "6a67c0d2217a5d3d0d70e3b0767df9ad2c006d4ffea760496d165d1a86219b67" }, "downloads": -1, "filename": "ArgosSDK-0.4b3-py3-none-any.whl", "has_sig": false, "md5_digest": "53a0b78ad34333abf131a7ca64d05be9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11144, "upload_time": "2019-09-11T17:26:34", "url": "https://files.pythonhosted.org/packages/dc/20/56116dc6904a13d231824252e510a7f5e519101b5a03abacd92737d4972a/ArgosSDK-0.4b3-py3-none-any.whl" } ], "0.4b4": [ { "comment_text": "", "digests": { "md5": "502cc47005e134b5c4e5ea5d65c22ef8", "sha256": "c735ae09aeb99b2d575c2e11050c4f2d715592797389926e4f8efc95feddc5f2" }, "downloads": -1, "filename": "ArgosSDK-0.4b4-py3-none-any.whl", "has_sig": false, "md5_digest": "502cc47005e134b5c4e5ea5d65c22ef8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11143, "upload_time": "2019-09-11T17:29:04", "url": "https://files.pythonhosted.org/packages/94/df/fb16ee7dd0097b0c9daeee03c68bb6025ba684cfdd87a6dc271b173660d5/ArgosSDK-0.4b4-py3-none-any.whl" } ], "0.4b5": [ { "comment_text": "", "digests": { "md5": "3f4e87eb1011ca8b3fc42ad4ddd0cc6a", "sha256": "53ffb57548cee9d0faa357db842960e4f35e79200941fc1ab8893430613071ac" }, "downloads": -1, "filename": "ArgosSDK-0.4b5-py3-none-any.whl", "has_sig": false, "md5_digest": "3f4e87eb1011ca8b3fc42ad4ddd0cc6a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11143, "upload_time": "2019-09-11T17:40:30", "url": "https://files.pythonhosted.org/packages/a0/87/c606121f9f01b48f4647acaf8954f0ed97badaebffc32bfa56d37287d2aa/ArgosSDK-0.4b5-py3-none-any.whl" } ], "0.5.2": [ { "comment_text": "", "digests": { "md5": "86954200689c048a52191c50136a086b", "sha256": "18e70f063c6269ea97d3b0fbe2dbbccdd038575a6ae80e25b38b3a86faeea2cc" }, "downloads": -1, "filename": "ArgosSDK-0.5.2-py3-none-any.whl", "has_sig": false, "md5_digest": "86954200689c048a52191c50136a086b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11275, "upload_time": "2019-09-12T13:02:24", "url": "https://files.pythonhosted.org/packages/bb/57/e0dbb249076c7c2e3322bc492684e0be40a1e21b9de78c7a54e323722c45/ArgosSDK-0.5.2-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "86954200689c048a52191c50136a086b", "sha256": "18e70f063c6269ea97d3b0fbe2dbbccdd038575a6ae80e25b38b3a86faeea2cc" }, "downloads": -1, "filename": "ArgosSDK-0.5.2-py3-none-any.whl", "has_sig": false, "md5_digest": "86954200689c048a52191c50136a086b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 11275, "upload_time": "2019-09-12T13:02:24", "url": "https://files.pythonhosted.org/packages/bb/57/e0dbb249076c7c2e3322bc492684e0be40a1e21b9de78c7a54e323722c45/ArgosSDK-0.5.2-py3-none-any.whl" } ] }