kormax / apple-home-key-reader

Apple Home Key Reader Implementation
Apache License 2.0
557 stars 45 forks source link

Integration with HAP-python in Bridge Mode? #28

Closed cerahmed closed 5 months ago

cerahmed commented 5 months ago

Hi there and thanks for sharing this awesome guide.

Though I haven't tried the scipt yet (waiting for my ACR122U to arrive tomorrow), I was wondering about integrating the script into my existing project.

I use HAP-python bridge configuration to expose accessories to homekit as so Driver -> Bridge -> Accessory on my RPi in a django server to quickly generate homekit accessories to control GPIO, and I was wondering if this repo would work in bridge mode as opposed to a single accessory that the sample accessory.py shows.

Appreciate if anyone could provide some insight if tried.

Thanks again for the great work!

kormax commented 5 months ago

Frankly, I have no idea.

But there could be problems, as Apple mandates that lock accessories have to be connected directly, without any bridges or hubs in between. It's possible that it wouldn't let you do that at all, or there might be side effects, like no Home Key being generated, etc.

But you have to test to be sure, those are just my assumptions.

cerahmed commented 5 months ago

Thanks for the prompt response. I will try tomorrow and get back with my results.

BTW, I've ordered the ACR122U as it has next-day delivery (the reader seen in the README page of this repo). Any special configuration required for this reader compared to the PN532? Do I have to change the nfc:driver in configuration.json to anything else?

kormax commented 5 months ago

Hardware wise, it should be OK as ACR122U uses the same PN532 chip.

I don't remember if ECP works out of the box with the code already in this project, or if there are a couple of additional changes I need to add in order to enable it. But I'll assist if it's needed.

cerahmed commented 5 months ago

Ok so I just got the ACR122U, connected it to my mac, installed the drivers and tried tapping a few cards and viewing them in NFC Tools. All work good.

However, I don't seem to find the device under terminal ls dev/tty.*, although it appears under USB devices inside System Report -> USB. Is there anything I'm missing here?

kormax commented 5 months ago

Sorry, didn't read your question fully. The reader uses USB, it's not a serial device, so you can't see it via ls.

Instead, navigate to "Apple Icon" -> "System Information" -> "System Report", and find usb device there, copy the vendor and device id.

Use that info when configuring driver instead.

At first, try just "usb" in configuration

If that doesn't work, attempt "usb:{vid}:{pid}"

And don't forget to run with sudo, and remember that macOS might have problems with PCSC anyway.

cerahmed commented 5 months ago

Thanks for that. I tried usb which didn't work, then tried usb:vid:pid and still raises this error:

Exception: Could not connect to NFC device <util.bfclf.BroadcastFrameContactlessFrontend object at 0x101ec7c40> at tty:usb:0x072f:0x2200:

Before I move on to trying it on my RPi, will it work if I connect the ACR122U to the same UART adapter shown in the README? I happen to have one in hand if that helps.

kormax commented 5 months ago

Something is wrong with your config as it says tty: at the beginning.

Look at the table provided by nfc library developer, at the "Device Path", that's the value you have to put into configuration field.

https://nfcpy.readthedocs.io/en/latest/overview.html

cerahmed commented 5 months ago

Great reference. I modified my nfc config to the one mentioned in the doc page (which indeed matches my VID/PID shown in System Report):

"nfc": {
    "port": "usb:072f:2200", 
    "driver": "pn532",
    "broadcast": true
},

Still getting the same error (albeit with sudo permissions). Moving to trying it on RPi. Wondering how it worked in the README demo image 😃

cerahmed commented 5 months ago

The tty shown in the error is indeed coming from main.py line 47:

path=f"tty:{config['port']}:{config['driver']}",

Removing tty still shows the same error, however, with the seemingly correct device path:

Exception: Could not connect to NFC device <util.bfclf.BroadcastFrameContactlessFrontend object at 0x1061b7c40> at usb:072f:2200:pn532

kormax commented 5 months ago

I've recorded the video in a pre release version, where the code has been a bit different, yes. So there could be a couple of things that need changing to restore functionality.

In regards to tty: part being removed from code - that's the correct course of action.

Yes, try it from linux.

Just in case, I'm gonna get a new ACR122U in a few days, so I'll be able to help if we don't resolve the issue right now.

kormax commented 5 months ago

Oh, by the way, you have to remove "driver" part at the end from the code too. It too is breaking the config a little.

I've made those changes to reduce complexity during configuration, forgetting that it makes USB-based readers inoperable.

cerahmed commented 5 months ago

Yup removing the driver part made things progress but now I'm facing a new USB permission error:

usb1.USBErrorAccess: LIBUSB_ERROR_ACCESS [-3]

I'm looking around for a solution over python-libusb1 repo.

On a side note, connecting the reader to my pi doesn't seem to work for some reason, I'll try to debug my issues and will get back when I run out of luck.

kormax commented 5 months ago

Oh, now you've met those permission/macOS issues I've mentioned before.

Attempt running with sudo. If that doesn't help, use Linux.

cerahmed commented 5 months ago

Yup I tried sudo with no luck, Going back to rpi where I have reader not powering up when connected for some reason.

kormax commented 5 months ago

Meanwhile, I have a little hack you might want to try when connecting to a Mac. The issues you're encountering are caused by macOS controlling the PCSC device as there are kernel drivers for that in the system.

Another python usb library, called pyusb, has methods to kill the driver temporarily. You might want to try it out.

  1. Install python3 -m pip install pyusb
  2. Run the following code, either as a file, or in a REPL:
import usb.core

device = usb.core.find(
    idVendor=0x072f, idProduct=0x2200
)
print(f"{device=}")
device.detach_kernel_driver(0)
  1. If driver is stopped successfully, reader should do beepity-bloopity, and code should not crash.
  2. Attempt running this project with sudo.
cerahmed commented 5 months ago

Brillian! This made it work like a charm!

Now that I can expirement with it on mac, I'll move in to try to make it work on the RPi, then later explose ways to integrate it with my existing project. Namely, I'll try the following:

1) Use the lock in Bridge Mode. 2) Use a wiegand Mifare reader capable of reading the homekey payload. Not even sure if this can work; didn't read through the authentication process of this project. 3) Try with multiple locks per home.

I'll share my progress for anyone else interested, but for now I'll try to resolve the other error I got on my RPi.

kormax commented 5 months ago
  1. Does ECP work? (Your phone should present Home Key even without selecting it manually).
  2. Report your findings in regards to bridge mode back.
  3. Wiegand reader wouldn't work sadly, as Home Key has a specific protocol which has to be implemented in firmware, and It's quite computationally intensive.
  4. Multiple locks are supported by the spec.
cerahmed commented 5 months ago

0) It does, enabling express mode during the Lock setup made it work. Both on my iPhone and Apple Watch; both unlocked/locked the virtual lock successfully.

1) Sure will do once I get the reader to work with the RPi.

2) Uhh, that's unfortunate. All I need is the ability to have a reader outdoors, about 50+ meters away from where my RPi hub is located. I'm also thinking I can explore rpi-to-rpi communication over network but again not familiar whether the Homekey NFC protocol complexity would allow such a thing.

3) Awesome!

cerahmed commented 5 months ago

Oof, seems like dealing with ACR122 on Raspberry Pi is a pain, I keep encountering the same issue mentioned in nfcpy issues: here.

Probably better off using the PN532 with a UART adapter.

kormax commented 5 months ago

Maybe you could attempt the same hack as on macOS? Just add it to beginning of my code, perhaps it could help.

cerahmed commented 5 months ago

Sure I will try that now.

I moved on to trying the lock inside a bridge, happy to report that it works well!

You can even add the lock "dynamically" when the bridge is paired with no accessories, and the minute the lock is added you get a notification that the lock is added and it has a feature to setup: homekey! Awesome..

IMG_6221

cerahmed commented 5 months ago

Maybe you could attempt the same hack as on macOS? Just add it to beginning of my code, perhaps it could help.

Unfortunately it doesn't work, device.detach_kernel_driver(0) raises error usb.core.USBError: [Errno 2] Entity not found .. although device seems to initialize correctly with print() confirming that.

kormax commented 5 months ago

Maybe you could attempt the same hack as on macOS? Just add it to beginning of my code, perhaps it could help.

Unfortunately it doesn't work, device.detach_kernel_driver(0) raises error usb.core.USBError: [Errno 2] Entity not found .. although device seems to initialize correctly with print() confirming that.

:(

When my new ACR122U arrives, I'm going to take a look myself. The reader I've borrowed (the one on video), didn't have those problems as far as I remember.

cerahmed commented 5 months ago

So the pattern I've noticed is as follows:

1) On the first run of main.py after rebooting, it works great. I can read normal NFC cards without issues:

[2024-04-20 19:52:37,444] [    INFO] __init__          :151  using ACS ACR122U PN532v1.6 at usb:001:005
[2024-04-20 19:52:39,147] [    INFO] service           :126  Found non-ISODEP Tag with UID: E913717C
[2024-04-20 19:52:39,188] [    INFO] service           :130  Waiting for target to leave the field...
[2024-04-20 19:52:39,729] [    INFO] service           :130  Waiting for target to leave the field...
[2024-04-20 19:52:40,269] [    INFO] service           :130  Waiting for target to leave the field...
[2024-04-20 19:52:40,810] [    INFO] service           :130  Waiting for target to leave the field...

2) Only after tapping an Apple device that it disconnects/hangs and returns timeout errors:

[2024-04-20 19:53:25,407] [ WARNING] tt4               :510  ACS ACR122U on usb:001:005 does not support fsd 256
[2024-04-20 19:53:25,432] [ WARNING] tt4               :529  ACS ACR122U on usb:001:005 does not support fsc 256
[2024-04-20 19:53:25,432] [    INFO] service           :134  Got NFC tag Type4ATag MIU=249 FWT=0.038664
[2024-04-20 19:53:25,435] [    INFO] homekey           :533  SELECT CMD = ISO7816Command(cla=0x00; ins=0xa4; p1=0x04; p2=0x00; lc=0x07(7); data=a0000008580101; le=0x00)
[2024-04-20 19:53:25,467] [    INFO] homekey           :539  SELECT RES = ISO7816Response(sw1=0x90; sw2=0x00; data=5c0402000100(6))
**seemingly some private info**
[2024-04-20 19:53:26,494] [ WARNING] tt4               :112  ISO-DEP timeout error (#1)
[2024-04-20 19:53:27,496] [   ERROR] threads           :20   Unhandled exception in runner homekey. Continuing in 5 seconds
usb1.USBErrorTimeout: LIBUSB_ERROR_TIMEOUT [-7]

3) Disonnecting and reconnecting the reader, then rerunning the app makes it go back to step 1.

kormax commented 5 months ago

I might have a clue why that happens.

There might be problems with USB init and deinit logic in nfcpy, which does not release device properly, so it stops working on next attempts unless it's power cycled.

When I encounter any issues during communication, I delete connection object and create a new one, which could make the issue even worse.

https://github.com/kormax/apple-home-key-reader/blob/5c39b9cc3d5d71e2a0947bbd751c6efd38077fa9/service.py#L178

Wrap 176-186 in try block, with. finally part doing .close() call on clf.

cerahmed commented 5 months ago

There might be problems with USB init and deinit logic in nfcpy, which does not release device properly, so it stops working on next attempts unless it's power cycled.

That's what I was suspecting but didn't dig into nfcpy code.

Wrap 176-186 in try block, with. finally part doing .close() call on clf.

Tried modifying def run to the following, but still gets the same error right after tapping my Apple Watch/iPhone, and ctrl+c doesn't seem to release the reader, still requires power cycling:

    def run(self):
        if self.repository.get_reader_private_key() in (None, b""):
            raise Exception("Device is not configured via HAP. NFC inactive")

        log.exception("Connecting to the NFC reader...")

        try:
            self.clf.device = None
            self.clf.open(self.clf.path)
            if self.clf.device is None:
                raise Exception(
                    f"Could not connect to NFC device {self.clf} at {self.clf.path}"
                )

            while self._run_flag:
                self._read_homekey()    

        finally:
            self.clf.close()
kormax commented 5 months ago

That code snippet looks correct. Try self.clf.chip.transport.close() or self.clf.transport.close() instead of self.clf.close()

Yeah, the need to power cycle is 100% related to improper release of usb, I've encountered that issue in many of my private projects.

cerahmed commented 5 months ago

I will try that in a while, but wondering why the code fails when tapping apple devices but not with normal NFC's. Could've something to do with this project?

kormax commented 5 months ago

If you tell me what the last successful command before the communication error is, It might give me more context. My guess It could be "DESELECT C4".

The difference is that for non-home key tags we don't do anything, so there's nothing to crash at, as there's basically no additional communication.

cerahmed commented 5 months ago

Sure, here's the entire log of error, I just replaced some data with *** cause I'm not really sure what's the private parts :D If any of them are necessary to debug, please let me know:

[2024-04-20 20:21:31,064] [    INFO] __init__          :151  using ACS ACR122U PN532v1.6 at usb:001:011
[2024-04-20 20:21:37,443] [ WARNING] tt4               :510  ACS ACR122U on usb:001:011 does not support fsd 256
[2024-04-20 20:21:37,467] [ WARNING] tt4               :529  ACS ACR122U on usb:001:011 does not support fsc 256
[2024-04-20 20:21:37,468] [    INFO] service           :134  Got NFC tag Type4ATag MIU=249 FWT=0.038664
[2024-04-20 20:21:37,469] [    INFO] homekey           :533  SELECT CMD = ISO7816Command(cla=0x00; ins=0xa4; p1=0x04; p2=0x00; lc=0x07(7); data=*****************; le=0x00)
[2024-04-20 20:21:37,502] [    INFO] homekey           :539  SELECT RES = ISO7816Response(sw1=0x90; sw2=0x00; data==***************(6))
[2024-04-20 20:21:37,503] [    INFO] homekey           :712  reader_identifier=***************
[2024-04-20 20:21:37,503] [    INFO] homekey           :725  Choosing preferred version b'\x02\x00'
[2024-04-20 20:21:37,505] [    INFO] homekey           :573  Reader public key: x=*************** y==***************
[2024-04-20 20:21:37,505] [    INFO] homekey           :579  protocol_version=0200
[2024-04-20 20:21:37,506] [    INFO] homekey           :172  AUTH0 CMD = ISO7816Command(cla=0x80; ins=0x80; p1=0x01; p2=0x01; lc=0x6b(107); data==***************)
[2024-04-20 20:21:38,524] [ WARNING] tt4               :112  ISO-DEP timeout error (#1)
[2024-04-20 20:21:40,527] [   ERROR] threads           :20   Unhandled exception in runner homekey. Continuing in 5 seconds
Traceback (most recent call last):
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/clf/transport.py", line 314, in read
    frame = self.usb_dev.bulkRead(ep_addr, 300, 1000)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/usb1/__init__.py", line 1412, in bulkRead
    transferred = self._bulkTransfer(endpoint, data, length, timeout)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/usb1/__init__.py", line 1358, in _bulkTransfer
    mayRaiseUSBError(libusb1.libusb_bulk_transfer(
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/usb1/__init__.py", line 127, in mayRaiseUSBError
    __raiseUSBError(value)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/usb1/__init__.py", line 119, in raiseUSBError
    raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
usb1.USBErrorTimeout: LIBUSB_ERROR_TIMEOUT [-7]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/util/threads.py", line 18, in function_
    target(*args, **kwargs)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/service.py", line 186, in run
    self._read_homekey()
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/service.py", line 138, in _read_homekey
    result_flow, new_issuers_state, endpoint = read_homekey(
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/homekey.py", line 737, in read_homekey
    result_flow, issuer, endpoint = perform_authentication_flow(
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/homekey.py", line 581, in perform_authentication_flow
    endpoint_ephemeral_public_key, endpoint, secure = fast_auth(
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/homekey.py", line 173, in fast_auth
    response = tag.transceive(command)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/util/iso7816.py", line 199, in transceive
    self._implementation.transceive(
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/tag/tt4.py", line 437, in transceive
    data = self._dep.exchange(data, timeout)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/tag/tt4.py", line 95, in exchange
    data = self.clf.exchange(data, timeout)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/clf/__init__.py", line 1055, in exchange
    rcvd_data = exchange(self.target, send_data, timeout)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/clf/pn53x.py", line 634, in send_cmd_recv_rsp
    txm, rxm, txa = self.chipset.read_register(*reg)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/clf/pn53x.py", line 310, in read_register
    data = self._read_register(data)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/clf/pn532.py", line 142, in _read_register
    return self.command(0x06, data, timeout=0.25)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/clf/acr122.py", line 232, in command
    frame = self.ccid_xfr_block(frame, timeout)
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/clf/acr122.py", line 210, in ccid_xfr_block
    frame = self.transport.read(int(3 * 1000))
  File "/home/pi/Desktop/python/homekey/apple-home-key-reader/venv/lib/python3.9/site-packages/nfc/clf/transport.py", line 316, in read
    raise IOError(errno.ETIMEDOUT, os.strerror(errno.ETIMEDOUT))
TimeoutError: [Errno 110] Connection timed out
kormax commented 5 months ago

Seems like something with USB library implementation on linux, if on macOS you didn't have those problems.

When my reader comes, I'll be able to take a deeper look myself in order to solve this issue.

cerahmed commented 5 months ago

Yeah that was on my RPi not on my Mac. Great, till then I'll queitly try stuff out. Will be back with interesting results only :D

kormax commented 5 months ago

My ACR122U (A9) arrived.

It was a bit different from the one I had previously, as It was not able to communicate using the same code I had, and it hanged on long commands.

I've resolved the issue by re-writing the USB implementation used by nfcpy, and the hangs/timeouts were resolved by limiting max USB packet size I've sent, as the device reports just 64 and it hanged on 65+, so I had to split the payloads in chunks and send them separately.

(For reference, Internet says that libusb should chunk packets itself depending on supported USB packet size. In actuality, this is not the case, or there's something wrong with it, as performing chunking manually fixes the issue.)

Now, it seems to be working great for me. I'm going to create a new branch for you to test in about 8+ Hours, when I wake up.

(BTW), I would be glad if you can send me info about your ACR122U as it's displayed in "system info", I'm also going to add some logs that show maxPacketSize and some other Info, would be glad If you can send me the values. This I need in order to find out more about what the differences between those samples are.

kormax commented 5 months ago

@cerahmed

I've pushed discussed changes to develop branch, you can try them out:

To try new code out, you can either do git checkout develop in the existing folder, or git clone git@github.com:kormax/apple-home-key-reader.git@develop.

cerahmed commented 5 months ago

Hey Kormax,

Now, it seems to be working great for me.

That's good to hear! I'll pull the branch and test it out on my mac & RPi and will let you know how it goes.

I would be glad if you can send me info about your ACR122U as it's displayed in "system info"

Screenshot 2024-04-23 at 7 26 21 PM

I'm also going to add some logs that show maxPacketSize and some other Info

Will share them when I'm done testing in a while.

Cheers!

cerahmed commented 5 months ago

So testing now with my RPi, I did the following:

1) Cloned the repo, checked out develop 2) Created a new venv, installed requirements.txt 3) Modified the path in configuration.json to usb:072f:2200. 4) Ran python main.py, resulted in the following error:

Or enter this code in your HomeKit app on your iOS device: 176-74-051
[2024-04-23 20:01:40,629] [   ERROR] acr122            :234  insufficient data for decoding chip response
[2024-04-23 20:01:40,629] [   ERROR] threads           :17   Unhandled exception in runner homekey. Continuing in 5 seconds
Traceback (most recent call last):
  File "/home/pi/Desktop/python/homekey/util/threads.py", line 15, in function_
    target(*args, **kwargs)
  File "/home/pi/Desktop/python/homekey/service.py", line 178, in run
    self.clf.open(self.clf.path)
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/__init__.py", line 149, in open
    self.device = device.connect(path)
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/device.py", line 95, in connect
    raise error
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/device.py", line 89, in connect
    device = driver.init(transport.USB(bus, dev))
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/acr122.py", line 61, in init
    device = Device(Chipset(transport))
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/acr122.py", line 71, in __init__
    super(Device, self).__init__(chipset, logger=log)
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/pn532.py", line 190, in __init__
    super(Device, self).__init__(chipset, logger)
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/pn53x.py", line 478, in __init__
    chipset_communication = self.chipset.diagnose('line')
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/pn53x.py", line 269, in diagnose
    return self.command(0x00, data, timeout=1.0) == data
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/acr122.py", line 235, in command
    raise IOError(errno.EIO, os.strerror(errno.EIO))
OSError: [Errno 5] Input/output error
[2024-04-23 20:01:45,638] [   ERROR] service           :175  Connecting to the NFC reader...
NoneType: None
[2024-04-23 20:01:45,638] [    INFO] __init__          :148  searching for reader on path usb:072f:2200
[2024-04-23 20:01:45,782] [   ERROR] acr122            :218  RDR_to_PC_DataBlock length mismatch
[2024-04-23 20:01:45,783] [   ERROR] threads           :17   Unhandled exception in runner homekey. Continuing in 5 seconds
Traceback (most recent call last):
  File "/home/pi/Desktop/python/homekey/util/threads.py", line 15, in function_
    target(*args, **kwargs)
  File "/home/pi/Desktop/python/homekey/service.py", line 178, in run
    self.clf.open(self.clf.path)
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/__init__.py", line 149, in open
    self.device = device.connect(path)
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/device.py", line 95, in connect
    raise error
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/device.py", line 89, in connect
    device = driver.init(transport.USB(bus, dev))
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/acr122.py", line 61, in init
    device = Device(Chipset(transport))
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/acr122.py", line 153, in __init__
    reader_version = self.ccid_xfr_block(bytearray.fromhex("FF00480000"))
  File "/home/pi/Desktop/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/acr122.py", line 219, in ccid_xfr_block
    raise IOError(errno.EIO, os.strerror(errno.EIO))
OSError: [Errno 5] Input/output error
^C[2024-04-23 20:01:47,298] [    INFO] main              :76   SIGNAL 15
kormax commented 5 months ago

Seems like there's a power issue happening indeed.

I've been testing on a linux VM before - It worked fine. Now with my RPI -I'm also getting

insufficient data for decoding chip response

The responses get cut-out and/or are different from the ones I get on my machine.

Don't have a powered hub to test the theory sadly.

cerahmed commented 5 months ago

That's wierd, I'll see if I have a powered hub to test with and will let you know. Meanwhile, I'm trying it on my Mac and I got a stubborn No Backend available error (which I got last time I was testing, but didn't seem persistent).

To use the QR Code feature, use 'pip install HAP-python[QRCode]'
Enter this code in your HomeKit app on your iOS device: 869-82-096
[2024-04-23 20:59:10,162] [   ERROR] threads           :17   Unhandled exception in runner homekey. Continuing in 5 seconds
Traceback (most recent call last):
  File "/python/homekey/util/threads.py", line 15, in function_
    target(*args, **kwargs)
  File "/python/homekey/service.py", line 178, in run
    self.clf.open(self.clf.path)
  File "/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/__init__.py", line 149, in open
    self.device = device.connect(path)
  File "/python/homekey/venv/lib/python3.9/site-packages/nfc/clf/device.py", line 68, in connect
    found = transport.USB.find(path)
  File "/python/homekey/util/bfclf.py", line 132, in find
    devices = usb.core.find(
  File "/python/homekey/venv/lib/python3.9/site-packages/usb/core.py", line 1309, in find
    raise NoBackendError('No backend available')
usb.core.NoBackendError: No backend available

Though I do have libusb1 installed:

Package                    Version
-------------------------- -------
async-timeout              4.0.3
cbor2                      5.4.6
cffi                       1.16.0
chacha20poly1305-reuseable 0.12.0
cryptography               41.0.7
h11                        0.14.0
HAP-python                 4.9.1
ifaddr                     0.2.0
libusb1                    3.1.0 <---
ndeflib                    0.3.3
nfcpy                      1.0.4
orjson                     3.10.1
packaging                  24.0
pip                        24.0
pkg-about                  1.1.5
pycparser                  2.22
pyDes                      2.0.1
pyserial                   3.5
pyusb                      1.2.1
setuptools                 69.2.0
tomli                      2.0.1
wheel                      0.43.0
zeroconf                   0.132.2

I can't recall when/why it occured before, but I tried everything I can to get rid of it with no luck. Searching online now for solutions.

kormax commented 5 months ago

Try doing "brew install libusb". You have to have brew installed for that.

cerahmed commented 5 months ago

Seems like there's a power issue happening indeed.

Just tested with my powered hub, still throws the same error.

cerahmed commented 5 months ago

Try doing "brew install libusb". You have to have brew installed for that.

Yeah I already have it installed, did reinstall it and tried again. Same error. I'll try to remember how I got rid of it.

kormax commented 5 months ago

Frankly, I have no Idea what to try out next. I think It would be wise to check that my changes didn't break anything on macOS for you, and base next steps or conclusions on that.

The libusb issue seems to be a config issue on macOS. Perhaps some ARM64/INTEL binaries conflict. Could happen if your python is arm and brew is intel, or vice versa, or if for some reasons the environment variables were not exported properly into zsh. Setting backend path manually could also be an option.

cerahmed commented 5 months ago

The libusb issue seems to be a config issue on macOS. Perhaps some ARM64/INTEL binaries conflict. Could happen if your python is arm and brew is intel, or vice versa, or if for some reasons the environment variables were not exported properly into zsh.

Indeed, that is part of the issue. Following the solution here seemed to make some progress when running main.py non-sudo (gives the expected permission denied error), however does nothing when running with sudo. Will keep looking for a solution.

On the positive side, I'm receiving my PN532 tomorrow. I spent a good amount of time reading through your research on Apple's ECP and stuff, really awesome work and I might have some questions once I get my PN532.

cerahmed commented 5 months ago

Got it to work again with Mac by running ln -s /opt/homebrew/lib ~/lib while in sudo su. Works without any modification except the path in the configuratino file .. perfect. Will move on to the Pi after a quick break.

Meanwhile, I'd love to hear your thoughts on my use case:

My Home Control Pi is about 100 meters (320ft) away from my main door, where I'd like to have the NFC reader. I'm sure that the UART wiring has cable length limitations, so I'm thinking to use reader -> rpi#1 -> (network) -> pi#2 -> lock communication. Would that work theoritically? If not, any thoughts on how to handle the situation.

kormax commented 5 months ago

I think it could be possible to wire the PN532 module via RS485 directly to your device.

I see connection as follows:

RPI <-> USB RS485 <-> RS485 to UART <-> PN532

Power has to be supplied in addition to two RS485 wires.

kormax commented 5 months ago

The person on this website (use Google Translate) seems to have wired via USB directly, but used Ethernet cables.

kormax commented 5 months ago

Alternatively, you can use two RPIs, but It'll require software modification:

The PI connected to the reader will have to expose its serial port via network - perhaps via an http server

And PI running the lock software will have to connect to that server and transfer data. But that will also require modifying the implementation here.

HomeKey protocol does not have any timing constraints that I know of, so this is entirely possible, but you'll have to roll your own implementation for serial server and client.

cerahmed commented 5 months ago

Good hints, I'll read through and take my time reasoning them. Thanks a bunch again!

cerahmed commented 5 months ago

Closing this issue as completed. Will move further discussion to the Discussions section. Answer to OP: Yes; it does work in bridge mode. Thanks a lot for your outstanding help and support!