{"id":20390604,"url":"https://github.com/gotthardp/python-mercuryapi","last_synced_at":"2025-04-06T10:14:33.134Z","repository":{"id":10111236,"uuid":"61789525","full_name":"gotthardp/python-mercuryapi","owner":"gotthardp","description":"Python wrapper for the ThingMagic Mercury API","archived":false,"fork":false,"pushed_at":"2024-03-11T22:13:32.000Z","size":120,"stargazers_count":118,"open_issues_count":31,"forks_count":62,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-04-24T09:19:09.151Z","etag":null,"topics":["python","rfid","thingmagic"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gotthardp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-23T08:42:29.000Z","updated_at":"2024-04-16T09:23:45.000Z","dependencies_parsed_at":"2024-01-23T22:06:52.578Z","dependency_job_id":"c0862b92-6176-41c9-85eb-0b18c294b6a1","html_url":"https://github.com/gotthardp/python-mercuryapi","commit_stats":{"total_commits":127,"total_committers":12,"mean_commits":"10.583333333333334","dds":0.4251968503937008,"last_synced_commit":"325efef87b207ac95866848c538f830c54bf9c0b"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gotthardp%2Fpython-mercuryapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gotthardp%2Fpython-mercuryapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gotthardp%2Fpython-mercuryapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gotthardp%2Fpython-mercuryapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gotthardp","download_url":"https://codeload.github.com/gotthardp/python-mercuryapi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247464226,"owners_count":20942970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","rfid","thingmagic"],"created_at":"2024-11-15T03:25:56.114Z","updated_at":"2025-04-06T10:14:33.101Z","avatar_url":"https://github.com/gotthardp.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Python wrapper for the ThingMagic Mercury API\n\nThe [ThingMagic Mercury API](https://www.jadaktech.com/products/thingmagic-rfid/thingmagic-mercury-api) is used to discover,\nprovision and control ThingMagic RFID readers.\n\nReading RFID tags is as simple as this:\n\n```python\nimport mercury\nreader = mercury.Reader(\"tmr:///dev/ttyUSB0\")\n\nreader.set_region(\"EU3\")\nreader.set_read_plan([1], \"GEN2\")\nprint(reader.read())\n```\n\n## Installation\nOn Windows, use the pre-compiled binary installer.\n\nOn Linux:\n * Check prerequisites using `apt-get install unzip patch xsltproc gcc libreadline-dev`,\n * Then build and install using `pip install python-mercuryapi`.\n\nNote: The build process will (temporarily) require upto 500MB of free space in `/tmp`.\nIf your `/tmp` is smaller, use e.g. `pip install python-mercuryapi -b $HOME/tmp` to redirect.\n\nAlternatively, you can follow the **Build Instructions** below and install the software manually.\n\n## Usage\nImport the module `mercury` and create an `mercury.Reader` object.\n```python\nimport mercury\n```\n\n### Reader Object\nRepresents a connection to the reader.\n\n#### mercury.Reader(*uri*, *baudrate=115200*, *antenna*, *protocol*)\nObject constructor. Connects to the reader:\n * *uri* identifies the device communication channel:\n   * `\"tmr:///com2\"` is a typical format to connect to a serial based module on Windows COM2\n   * `\"tmr:///dev/ttyUSB0\"` is a typical format to connect to a USB device named ttyUSB0 on a Unix system\n   * `\"llrp://192.198.1.100\"` is a typical format to connect to an Ethernet device (works on Linux only)\n * *baudrate* defines the desired communication speed of the serial port.\n   Supported values include 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600 and 115200 (default).\n   This parameter is not allowed for network-connected readers.\n * *antenna* number and *protocol* for operations not using the read-plan (see bellow)\n\nFor example:\n```python\nreader = mercury.Reader(\"tmr:///dev/ttyUSB0\", baudrate=9600)\n```\nor\n```python\nreader = mercury.Reader(\"tmr://192.168.1.101\")\n```\n\n#### reader.set_read_plan(*antennas*, *protocol*, *epc_target=None*, *bank=[]*, *read_power=default*)\nSpecifies the antennas and protocol to use for a search:\n * *antennas* list define which antennas (or virtual antenna numbers) to use in the search\n * *protocol* defines the protocol to search on. Supported values are:\n   * `\"GEN2\"`, UPC GEN2\n   * `\"ISO180006B\"`, ISO 180006B\n   * `\"UCODE\"`, ISO 180006B UCODE\n   * `\"IPX64\"`, IPX (64kbps link rate)\n   * `\"IPX256\"`, IPX (256kbps link rate)\n   * `\"ATA\"`\n * *epc_target* defines tags to be addressed (see Filtering)\n * *bank* defines the memory banks to read. Supported values are:\n   * `\"reserved\"`\n   * `\"epc\"`\n   * `\"tid\"`\n   * `\"user\"`\n * *read_power* defines the transmit power, in centidBm, for read operations. If not given,\n   a reader specific default value is used.\n\nFor example:\n```python\nreader.set_read_plan([1], \"GEN2\")\n```\nor\n```python\nreader.set_read_plan([1], \"GEN2\", bank=[\"user\"], read_power=1900)\n```\n\n#### Target filtering\n\nThe *epc_target* may be:\n * *None* to address all tags\n * Single hexa-string, e.g. `b'E2002047381502180820C296'` to address a tag\n   with specific data (non-protocol-specific)\n * List of hexa-strings to address multiple Gen2 tags with given EPC\n * List of Gen2 Select filters (or even a single Gen2 filter) to address a given\n   tag population (see below).\n\nThe Gen2 Select filter is a Dict with arguments:\n * *reserved*, *epc*, *tid*, or *user* that defines the mask as a hexa-string.\n   This also determines the memory bank in which to compare the mask.\n * *invert* flag to match tags **not** matching the mask (by default *false*)\n * *bit* indicating the location (in bits) at which to begin comparing the mask\n   (by default 32 for the *epc* bank and 0 otherwise)\n * *len* indicating length (in bits) of the mask (by default, the entire\n   hexa-string given will be matched)\n * *action* defines the filter action on the matching and not-matching tags\n   (by default, *on\u0026off* for the first filter in the list and *on\u0026nop* otherwise)\n\n  Action   | Tag Matching | Tag Not-Matching\n ----------|--------------|------------------\n *on\u0026off*  | Assert SL    | Deassert SL\n *on\u0026nop*  | Assert SL    | Do nothing\n *nop\u0026off* | Do nothing   | Deassert SL\n *neg\u0026nop* | Negate SL    | Do nothing\n *off\u0026on*  | Deassert SL  | Assert SL\n *off\u0026nop* | Deassert SL  | Do nothing\n *nop\u0026on*  | Do nothing   | Assert SL\n *nop\u0026neg* | Do nothing   | Negate SL\n\nThe tuples are processed sequentially and depending on the action the\nselection (SL) of matching and not-matching tags is either *asserted*,\n*deasserted* or *negated*. The read/write operation is applied to the\ntags that remain asserted after processing the entire filter.\n\nTo select one tag or another, use *on\u0026off*, followed by a sequence of *on\u0026nop*.\nFor example:\n```python\n[b'E2002047381502180820C296', b'0000000000000000C0002403']\n```\nis equivalent to\n```python\n[{'epc':b'E2002047381502180820C296', 'action':'on\u0026off'}, {'epc':b'0000000000000000C0002403', 'action':'on\u0026nop'}]\n```\n\nPlease note that the assertion is a state of the (physical) tag that\ndisappears after some time. Therefore, the result of one operation\nmay affect another!\n\n#### reader.read(*timeout=500*)\nPerforms a synchronous read, and then returns a list of *TagReadData* objects resulting from the search.\nIf no tags were found then the list will be empty.\n * *timeout* sets the reading time\n\nFor example:\n```python\nprint(reader.read())\n[EPC(b'E2002047381502180820C296'), EPC(b'0000000000000000C0002403')]\n```\n\nTo get a list (or a set) of EPC codes you can use the map function:\n```python\nepcs = map(lambda t: t.epc, reader.read())\nprint(list(epcs))\n[b'E2002047381502180820C296', b'0000000000000000C0002403']\nprint(set(epcs))\n{b'E2002047381502180820C296', b'0000000000000000C0002403'}\n```\n\n#### reader.write(*epc_code*, *epc_target=None*)\nPerforms a synchronous write. Returns *True* upon success, or *False* if no tag\nwas found. Upon failure an exception is raised.\n\nFor example:\n```python\nold_epc = b'E2002047381502180820C296'\nnew_epc = b'E20020470000000000000012'\n\nreader = Reader('llrp://192.168.0.2')\nreader.set_read_plan([1], \"GEN2\")\n\nif reader.write(epc_code=new_epc, epc_target=old_epc):\n    print('Rewrited \"{}\" with \"{}\"'.format(old_epc, new_epc))\nelse:\n    print('No tag found')\n```\n\n#### reader.enable_stats(*callback*)\nProvide reader stats during asynchronous tag reads.\n\nThe function must be called before `reader.start_reading()`.\n\nFor example:\n```python\ndef stats_received(stats):\n    print({\"temp\" : stats.temperature})\n    print({\"antenna\" : stats.antenna})\n    print({\"protocol\" : stats.protocol})\n    print({\"frequency\" : stats.frequency})\n\nreader.enable_stats(stats_received)\n```\n\n### reader.enable_exception_handler(*callback*)\nProvide reader exception handling\nThe function must be called before `reader.start_reading()`.\n\nFor example:\n```python\ndef exeception_handle(e):\n    print(e)\n\nreader.enable_exception_handler(exeception_handle)\n```\n\n#### reader.start_reading(*callback*, *on_time=250*, *off_time=0*)\nStarts asynchronous reading. It returns immediately and begins a sequence of\nreads or a continuous read. The results are passed to the *callback*.\nThe reads are repeated until the `reader.stop_reading()` method is called\n * *callback(TagReadData)* will be invoked for every tag detected\n * *on_time* sets the duration, in milliseconds, for the reader to be actively querying\n * *off_time* duration, in milliseconds, for the reader to be quiet while querying\n\nFor example:\n```python\nreader.start_reading(lambda tag: print(tag.epc))\nb'E2002047381502180820C296'\nb'0000000000000000C0002403'\n```\n\n#### reader.stop_reading()\nStops the asynchronous reading started by `reader.start_reading()`.\n\nFor example:\n```python\nreader.stop_reading()\n```\n\n#### reader.read_tag_mem(*bank*, *address*, *count*, *epc_target=None*)\nReads bytes from the memory bank of a tag. Returns a *bytearray* or None if no\ntag was found. Upon failure an exception is raised.\n\nThe read-plan is not used. Use the *antenna* and *protocol* parameters in the\nReader constuctor.\n\nFor example:\n```python\nreader = mercury.Reader(\"tmr:///dev/ttyUSB0\", baudrate=9600, protocol=\"GEN2\")\nprint(reader.read_tag_mem(1, 0x08, 8))\nbytearray(b'\\x00\\x00\\x00\\x16\\x12\\x00\\x00\\x61')\n```\n\n#### reader.write_tag_mem(*bank*, *address*, *data*, *epc_target=None*)\nWrites bytes to the memory bank of a tag. Returns *True* upon success, or\n*False* if no tag was found. Upon failure an exception is raised.\n\nThe read-plan is not used. Use the *antenna* and *protocol* parameters in the\nReader constuctor.\n\nFor example:\n```python\nreader.write_tag_mem(1, 0x08, bytearray(b'\\x00\\x00\\x00\\x16\\x12\\x00\\x00\\x61'))\n```\n\n#### reader.gpi_get(*pin*)\nReturns value of a GPIO *pin*, or *None* is the pin is not configured as input (see `get_gpio_inputs`).\n\nFor example:\n```python\nprint(reader.get_gpio_inputs())\n[1]\nprint(reader.gpi_get(1))\nTrue\n```\n\n#### reader.gpo_set(*pin*, *value*)\nSets value of a GPIO *pin* configured as output (see `get_gpio_outputs`).\n\nFor example:\n```python\nprint(reader.get_gpio_outputs())\n[1]\nreader.gpo_set(1, False)\n```\n\n#### reader.get_model()\nReturns a model identifier for the connected reader hardware.\n\nFor example:\n```python\nprint(reader.get_model())\nM6e Nano\n```\n\n#### reader.get_software_version()\nReturns the software version of the reader hardware\nFor example:\n```python\nprint(reader.get_software_version())\n01.09.02.02-20.19.09.23-BL14.12.08.00\n```\n01.09.02.02 is the current firmware version\n\n\n#### reader.get_serial()\nReturns a serial number of the reader, the same number printed on the barcode label.\n\n#### reader.set_region(*region*)\nControls the Region of Operation for the connected device:\n * *region* represents the regulatory region that the device will operate in. Supported values are:\n    * `\"NA\"`, North America/FCC\n    * `\"NA2\"`, Reduced FCC region\n    * `\"NA3\"`, 5MHZ FCC band\n    * `\"EU\"`, European Union/ETSI EN 302 208\n    * `\"EU2\"`, European Union/ETSI EN 300 220\n    * `\"EU3\"`, European Union/ETSI Revised EN 302 208\n    * `\"EU4\"`, 4 channels (916.3MHz, 917.5MHz, 918.7MHz)\n    * `\"IS\"`, Israel\n    * `\"IN\"`, India\n    * `\"JP\"`, Japan\n    * `\"JP2\"`, Japan 24dBm with 13 channels\n    * `\"JP3\"`, Japan 24dBm with 6 channels\n    * `\"KR\"`, Korea MIC\n    * `\"KR2\"`, Korea KCC\n    * `\"PRC\"`, China\n    * `\"PRC2\", China 840MHZ\n    * `\"AU\"`, Australia/AIDA LIPD Variation 2011\n    * `\"NZ\"`, New Zealand\n\nFor example:\n```python\nreader.set_region(\"EU3\")\n```\n\n#### reader.get_supported_regions()\nLists supported regions for the connected device.\n\nFor example:\n```python\nprint(reader.get_supported_regions())\n['NA2', 'IN', 'JP', 'PRC', 'EU3', 'KR2', 'AU', 'NZ']\n```\n\n#### reader.get_hop_table()\nGets the frequencies for the reader to use, in kHz.\n\n#### reader.set_hop_table(*list*)\nSets the frequencies for the reader to use, in kHz.\n\n#### reader.get_hop_time()\nGets the frequency hop time, in milliseconds.\n\n#### reader.set_hop_time(*num*)\nSets the frequency hop time, in milliseconds.\n\n#### reader.get_antennas()\nLists available antennas.\n\nFor example:\n```python\nprint(reader.get_antennas())\n[1, 2]\n```\n\n#### reader.get_connected_ports()\nReturns numbers of the antenna ports where the reader has detected antennas.\n\nFor example:\n```python\nprint(reader.get_connected_ports())\n[1]\n```\n\n#### reader.get_power_range()\nLists supported radio power range, in centidBm.\n\nFor example:\n```python\nprint(reader.get_power_range())\n(0, 3000)\n```\n\n#### reader.get_read_powers()\nLists configured read powers for each antenna. [(antenna, power)].\nThe list does not include antennas with default power setting, so the list may be empty.\n\nFor example:\n```python\nprint(reader.get_read_powers())\n[(1, 1800), (2, 3000)]\n```\n\n#### reader.get_write_powers()\nLists configured write powers for each antenna. [(antenna, power)].\n\n#### reader.set_read_powers(*powers*)\nSet the read power for each listed antenna and return the real setted values.\nSetted values may differ from those passed due to reader rounding.\n * *powers* list of 2-tuples that include:\n    * which antenna (or virtual antenna numbers) is going to be setted\n    * required power, in centidBm, for the antenna, overriding the value from\n      set_read_plan or reader specific default.\n      The value must be within the allowed power range.\n\nFor example:\n```python\nsetted_powers = reader.set_read_powers([(1, 1533), (2, 1912)])\nprint(setted_powers)\n[(1, 1525), (2, 1900)]\n```\n\n#### reader.set_write_powers(*powers*)\nSet the write power for each listed antenna and return the real setted values.\n\n#### reader.get_gpio_inputs()\nGet numbers of the GPIO pins available as input pins on the device.\n\nFor example:\n```python\nprint(reader.get_gpio_inputs())\n[1, 2]\n```\n\n#### reader.set_gpio_inputs(*list*)\nSet numbers of the GPIO pins available as input pins on the device.\n\nFor example:\n```python\nreader.set_gpio_inputs([1, 2])\n```\n\n#### reader.get_gpio_outputs()\nGet numbers of the GPIO pins available as output pins on the device.\n\n#### reader.set_gpio_outputs(*list*)\nSet numbers of the GPIO pins available as output pins on the device.\n\nOn some devices this parameter is not writeable. Thus, instead of calling\n`set_gpio_outputs` with the a set you may need to call `set_gpio_inputs`\nwith the pin omitted.\n\n#### reader.get_gen2_blf()\nReturns the current Gen2 BLF setting.\n\nFor example:\n```python\nprint(reader.get_gen2_blf())\n250\n```\n\n#### reader.set_gen2_blf(*blf*)\nSets the Gen2 BLF. Supported values include:\n * 250 (250KHz)\n * 320 (320KHz)\n * 640 (640KHz)\n\nNot all values may be supported by a particular reader. If successful the\ninput value will be returned. For example:\n```python\nprint(reader.set_gen2_blf(640))\n640\n```\n\n#### reader.get_gen2_tari()\nReturns the current Gen2 Tari setting.\n\nFor example:\n```python\nprint(reader.get_gen2_tari())\n0\n```\n\n#### reader.set_gen2_tari(*tari*)\nSets the Gen2 Tari. Supported values include:\n * 0 (25 us)\n * 1 (12.5 us)\n * 2 (6.25 us)\n\nIf successful the input value will be returned. For example:\n```python\nprint(reader.set_gen2_tari(1))\n1\n```\n\n#### reader.get_gen2_tagencoding()\nReturns the current Gen2 TagEncoding setting.\n\nFor example:\n```python\nprint(reader.get_gen2_tagencoding())\n0\n```\n\n#### reader.set_gen2_tagencoding(*tagencoding*)\nSets the Gen2 TagEncoding. Supported values include:\n * 0 (FM0)\n * 1 (M = 2)\n * 2 (M = 4)\n * 3 (M = 8)\n\nIf successful the input value will be returned. For example:\n```python\nprint(reader.set_gen2_tagencoding(2))\n2\n```\n\n#### reader.get_gen2_session()\nReturns the current Gen2 Session setting.\n\nFor example:\n```python\nprint(reader.get_gen2_session())\n0\n```\n\n#### reader.set_gen2_session(*session*)\nSets the Gen2 Session. Supported values include:\n * 0 (S0)\n * 1 (S1)\n * 2 (S2)\n * 3 (S3)\n\nIf successful the input value will be returned. For example:\n```python\nprint(reader.set_gen2_session(2))\n2\n```\n\n#### reader.get_gen2_target()\nReturns the current Gen2 Target setting.\n\nFor example:\n```python\nprint(reader.get_gen2_target())\n0\n```\n\n#### reader.set_gen2_target(*target*)\nSets the Gen2 Target. Supported values include:\n * 0 (A)\n * 1 (B)\n * 2 (AB)\n * 3 (BA)\n\nIf successful the input value will be returned. For example:\n```python\nprint(reader.set_gen2_target(2))\n2\n```\n\n#### reader.get_gen2_q()\nReturns the current Gen2 Q setting as a tuple containing the current Q type,\nand initial Q value.\n\nFor example:\n```python\nprint(reader.get_gen2_q())\n(0, 16)\n```\n\n#### reader.set_gen2_q(*qtype*, *initialq*)\nSets the Gen2 Q.\n * *qtype* defines Dynamic vs Static Q value where:\n   * 0 (Dynamic)\n   * 1 (Static)\n * *initialq* defines 2^*initialq* time slots to be used initially for tag communication.\n\nIf Dynamic Q is used then the input *initialq* value is ignored as the reader\nwill choose this on its own. It is then likely for *initialq* on a get to be different than the value used on a set.\n\nIf successful the input value will be returned. For example:\n```python\nprint(reader.set_gen2_q(0, 4))\n(0, 4)\nprint(reader.get_gen2_q())\n(0, 64)\n```\nor\n```python\nprint(reader.set_gen2_q(1, 4))\n(1, 4)\nprint(reader.get_gen2_q())\n(1, 4)\n```\n\n#### reader.get_temperature()\nReturns the chip temperature in degrees of Celsius.\n\n### TagReadData Object\nRepresents a read of an RFID tag:\n * *epc* corresponds to the Electronic Product Code\n * *phase* of the tag response\n * *antenna* indicates where the tag was read\n * *read_count* indicates how many times was the tag read during interrogation\n * *rssi* is the strength of the signal recieved from the tag\n * *frequency* the tag was read with\n * *timestamp* of the read, in floating-point seconds\n   for [datetime.fromtimestamp](https://docs.python.org/3/library/datetime.html#datetime.datetime.fromtimestamp)\n * *epc_mem_data* contains the EPC bank data bytes\n * *tid_mem_data* contains the TID bank data bytes\n * *user_mem_data* contains the User bank data bytes\n * *reserved_mem_data* contains the Reserved bank data bytes\n\n```python\nprint(tag.epc)\nb'E2000087071401930700D206'\nprint(tag.antenna)\n2\nprint(tag.read_count)\n2\nprint(tag.rssi)\n-65\nprint(datetime.fromtimestamp(tag.timestamp))\n2018-07-29 09:17:13.812189\nprint(tag.user_mem_data)\nbytearray(b'\\x00\\x00\\x00...')\n```\n\nPlease note that the bank data bytes need to be requested via the *bank* parameter\nof the reader.*set_read_plan* function. Data not requested will not be read.\n\nThe friendly string representation (`str`) of the tag data is its EPC.\n\n```python\nprint(tag)\nb'E2000087071401930700D206'\n```\n\nHowever, to avoid ambiguity, the string representation (`repr`) includes\na prefix.\n\n```python\nprint(repr(tag))\nEPC(b'E2000087071401930700D206')\n```\n\n\n## Build Instructions\n\n### Windows\nUse the Windows installer for the\n[latest release](https://github.com/gotthardp/python-mercuryapi/releases) and Python 3.6.\n\nTo build an installer for other Python releases you need to:\n * Download the latest [Mercury API](https://www.jadaktech.com/products/thingmagic-rfid/thingmagic-mercury-api), e.g.\n   [mercuryapi-AHAB-1.35.2.72-1.zip](https://www.jadaktech.com/documents-downloads/thingmagic-mercury-api-firmware-v1-35-2).\n * Go to mercuryapi-1.35.2.72\\c\\src\\api\\ltkc_win32 and run `gencode.bat`\n * Open mercuryapi-1.35.2.72\\c\\src\\api\\ltkc_win32\\inc\\stdint_win32.h and comment (or delete)\n   the block of `typedef` for `int_fast8_t` through `uint_fast64_t` (8 lines)\n * Download the [latest pthreads-win32](https://sourceforge.net/projects/pthreads4w/files/pthreads-w32-2-9-1-release.zip/download)\n   binaries (both .dll and .lib) for your architecture and put them into\n   mercuryapi-1.35.2.72\\c\\src\\pthreads-win32\\x86 or \\x64\n * Obtain [Microsoft Visual Studio 2017](https://visualstudio.microsoft.com/downloads/), including the Python extensions, Visual Studio Desktop development with C++ and the individual component MSVC v142 - VS 2019 C++ x64/x86 build tools \n * Open the Solution and review the\n   [setup-win.py](https://github.com/gotthardp/python-mercuryapi/blob/master/setup-win.py)\n   * Verify the `mercuryapi` directory\n   * Set `library_dirs` and `data_files` to the pthreads-win32 you downloaded and update to `x64` if required\n   * Set Script Arguments to `bdist_wininst -p win32` (default) or `bdist_wininst -p amd64`\n * Start setup-win.py (without debugging)\n * To build with python \u003e 3.8 use `python setup-win.py build install` or `python setup-win.py build -p win-amd64 install`\n\nIf you get the \"ImportError: DLL load failed\", make sure you have the\n[Microsoft Visual C++ 2010 Redistributable Package](https://www.microsoft.com/en-us/download/details.aspx?id=26999)\ninstalled. Since python 3.8 adding the egg install directory with its dependencies via [add_dll_directory](https://docs.python.org/3/library/os.html#os.add_dll_directory) might be required.\n\n\n### Linux\nFirst, make sure you have the required packages\n```bash\nyum install unzip patch libxslt gcc readline-devel python-devel python-setuptools\n```\nor\n```bash\napt-get install unzip patch xsltproc gcc libreadline-dev python-dev python-setuptools\n```\n\nBoth Python 2.x and Python 3.x are supported. To use the Python 3.x you may need to\ninstall the `python3-dev[evel]` instead of the `python-dev[evel]` packages.\n\nBuild the module simply by running\n```bash\ngit clone https://github.com/gotthardp/python-mercuryapi.git\ncd python-mercuryapi\nmake\n```\nThis will download and build the [Mercury API SDK](https://www.jadaktech.com/products/thingmagic-rfid/thingmagic-mercury-api)\nand then it will build the Python module itself.\n\nThe `make` command will automatically determine which Python version is installed. If both\n2.x and 3.x are installed, the 3.x takes precedence. To build and install 2.x you need to\nexplicitly specify the Python interpreter to use:\n```bash\nsudo make PYTHON=python\n```\n\nThen, install the module by running\n```bash\nsudo make install\n```\nwhich is a shortcut to running\n```bash\nsudo python setup.py build install\n```\n\nIf you are getting a \"Module not found\" error, please double check that you built and\ninstalled the module using the same Python version (2 or 3) you now use to run your script.\n(Or simply build and install it twice: once with python2 and once with python3.)\n\nTo access ports like `/dev/ttyUSB0` as a non-root user you may need to add this\nuser to the `dialout` group:\n```bash\nsudo usermod -a -G dialout $USER\n```\n\n### MacOS X (Darwin)\nTo build on Mac\n * Copy `mercuryapi_osx.patch` to `mercuryapi.patch` (and overwrite the target)\n * Run `make`\n\nOr simply do `python setup.py build install`\n\n\n## Copyright and Licensing\n\nThe python-mercuryapi is distributed under the terms of the MIT License.\nSee the [LICENSE](LICENSE).\n\nCopyright (c) 2016-2020 Petr Gotthard\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgotthardp%2Fpython-mercuryapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgotthardp%2Fpython-mercuryapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgotthardp%2Fpython-mercuryapi/lists"}