maxileith / homebridge-appletv-enhanced

Homebridge plugin that exposes Apple TVs with features that should be native to Apple HomeKit.
MIT License
186 stars 3 forks source link

32-bit: Error on first run - installation failing "ffi.h: No such file or directory" #236

Closed codemavn closed 8 months ago

codemavn commented 8 months ago

Analysis

Thanks for the great plugin. I'm having an issue on first run in home bridge. Steps I took:

During startup, the plugin is throwing a fatal error, ffi.h: No such file or directory (on one of the pip installs, I think).

my setup:

From a touch of research, I think I could run:

apt-get install libffi libffi-dev

in the container, but not sure if that's going to get toasted the next time I pull a home bridge version.

Alternatively, I may just be doing something wrong or missing something somewhere

Expected Behavior

the plugin completes install and then discovers Apple TVs

Steps To Reproduce

Logs

[2/7/2024, 12:29:27 AM] [Apple TV Enhanced] Launched child bridge with PID 4468
[2/7/2024, 12:29:28 AM] Registering platform 'homebridge-appletv-enhanced.AppleTVEnhanced'
[2/7/2024, 12:29:28 AM] [Apple TV Enhanced] Loaded homebridge-appletv-enhanced v1.2.1 child bridge successfully
[2/7/2024, 12:29:28 AM] [Apple TV Enhanced] [I] Platform: Finished initializing platform: Apple TV Enhanced
[2/7/2024, 12:29:28 AM] [Apple TV Enhanced] [I] Python check: Starting python check.
[2/7/2024, 12:29:28 AM] [Apple TV Enhanced] [I] Python check: plugin dir exists.
[2/7/2024, 12:29:28 AM] Homebridge v1.7.0 (HAP v0.11.1) (Apple TV Enhanced) is running on port 31700.
[2/7/2024, 12:29:28 AM] [Apple TV Enhanced] [I] Python check: Python 3.10.12 is installed and supported by the plugin.
[2/7/2024, 12:29:28 AM] [Apple TV Enhanced] [I] Python check: Virtual environment already exists.
[2/7/2024, 12:29:28 AM] [Apple TV Enhanced] [I] Python check: Venv is using current system python version (3.10.12).
[2/7/2024, 12:29:29 AM] [Apple TV Enhanced] [I] Python check: Venv pip version: 24.0
[2/7/2024, 12:29:29 AM] [Apple TV Enhanced] [I] Python check: Checking if there is an update for venv pip ...
[2/7/2024, 12:29:29 AM] [Apple TV Enhanced] [I] Python check: Venv pip is up-to-date
[2/7/2024, 12:29:31 AM] [Apple TV Enhanced] [W] Python check: Python requirements are not satisfied. Installing them now ...
[2/7/2024, 12:29:33 AM] [Apple TV Enhanced] [I] Python check: Collecting aiohttp==3.9.3 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 1))
[2/7/2024, 12:29:33 AM] [Apple TV Enhanced] [I] Python check: Using cached aiohttp-3.9.3.tar.gz (7.5 MB)
[2/7/2024, 12:29:34 AM] [Apple TV Enhanced] [I] Python check: Installing build dependencies: started
[2/7/2024, 12:29:39 AM] [Apple TV Enhanced] [I] Python check: Installing build dependencies: finished with status 'done'
[2/7/2024, 12:29:39 AM] [Apple TV Enhanced] [I] Python check: Getting requirements to build wheel: started
[2/7/2024, 12:29:40 AM] [Apple TV Enhanced] [I] Python check: Getting requirements to build wheel: finished with status 'done'
[2/7/2024, 12:29:40 AM] [Apple TV Enhanced] [I] Python check: Installing backend dependencies: started
[2/7/2024, 12:29:43 AM] [Apple TV Enhanced] [I] Python check: Installing backend dependencies: finished with status 'done'
[2/7/2024, 12:29:43 AM] [Apple TV Enhanced] [I] Python check: Preparing metadata (pyproject.toml): started
[2/7/2024, 12:29:44 AM] [Apple TV Enhanced] [I] Python check: Preparing metadata (pyproject.toml): finished with status 'done'
[2/7/2024, 12:29:44 AM] [Apple TV Enhanced] [I] Python check: Collecting aiosignal==1.3.1 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 2))
[2/7/2024, 12:29:44 AM] [Apple TV Enhanced] [I] Python check: Downloading aiosignal-1.3.1-py3-none-any.whl (7.6 kB)
[2/7/2024, 12:29:44 AM] [Apple TV Enhanced] [I] Python check: Collecting annotated-types==0.6.0 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 3))
[2/7/2024, 12:29:44 AM] [Apple TV Enhanced] [I] Python check: Downloading annotated_types-0.6.0-py3-none-any.whl.metadata (12 kB)
[2/7/2024, 12:29:45 AM] [Apple TV Enhanced] [I] Python check: Collecting async-timeout==4.0.3 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 4))
[2/7/2024, 12:29:45 AM] [Apple TV Enhanced] [I] Python check: Downloading async_timeout-4.0.3-py3-none-any.whl.metadata (4.2 kB)
[2/7/2024, 12:29:45 AM] [Apple TV Enhanced] [I] Python check: Collecting attrs==23.2.0 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 5))
[2/7/2024, 12:29:45 AM] [Apple TV Enhanced] [I] Python check: Downloading attrs-23.2.0-py3-none-any.whl.metadata (9.5 kB)
[2/7/2024, 12:29:46 AM] [Apple TV Enhanced] [I] Python check: Collecting certifi==2024.2.2 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 6))
[2/7/2024, 12:29:46 AM] [Apple TV Enhanced] [I] Python check: Downloading certifi-2024.2.2-py3-none-any.whl.metadata (2.2 kB)
[2/7/2024, 12:29:46 AM] [Apple TV Enhanced] [I] Python check: Collecting cffi==1.16.0 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 7))
[2/7/2024, 12:29:46 AM] [Apple TV Enhanced] [I] Python check: Downloading cffi-1.16.0.tar.gz (512 kB)
[2/7/2024, 12:29:47 AM] [Apple TV Enhanced] [I] Python check: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 512.9/512.9 kB 3.9 MB/s eta 0:00:00
[2/7/2024, 12:29:47 AM] [Apple TV Enhanced] [I] Python check: Installing build dependencies: started
[2/7/2024, 12:29:51 AM] [Apple TV Enhanced] [I] Python check: Installing build dependencies: finished with status 'done'
[2/7/2024, 12:29:51 AM] [Apple TV Enhanced] [I] Python check: Getting requirements to build wheel: started
[2/7/2024, 12:29:52 AM] [Apple TV Enhanced] [I] Python check: Getting requirements to build wheel: finished with status 'done'
[2/7/2024, 12:29:52 AM] [Apple TV Enhanced] [I] Python check: Installing backend dependencies: started
[2/7/2024, 12:29:54 AM] [Apple TV Enhanced] [I] Python check: Installing backend dependencies: finished with status 'done'
[2/7/2024, 12:29:54 AM] [Apple TV Enhanced] [I] Python check: Preparing metadata (pyproject.toml): started
[2/7/2024, 12:29:55 AM] [Apple TV Enhanced] [I] Python check: Preparing metadata (pyproject.toml): finished with status 'done'
[2/7/2024, 12:29:56 AM] [Apple TV Enhanced] [I] Python check: Collecting chacha20poly1305-reuseable==0.12.1 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 8))
[2/7/2024, 12:29:56 AM] [Apple TV Enhanced] [I] Python check: Downloading chacha20poly1305_reuseable-0.12.1.tar.gz (11 kB)
[2/7/2024, 12:29:56 AM] [Apple TV Enhanced] [I] Python check: Installing build dependencies: started
[2/7/2024, 12:30:12 AM] [Apple TV Enhanced] [I] Python check: Installing build dependencies: finished with status 'done'
[2/7/2024, 12:30:12 AM] [Apple TV Enhanced] [I] Python check: Getting requirements to build wheel: started
[2/7/2024, 12:30:12 AM] [Apple TV Enhanced] [I] Python check: Getting requirements to build wheel: finished with status 'done'
[2/7/2024, 12:30:12 AM] [Apple TV Enhanced] [I] Python check: Preparing metadata (pyproject.toml): started
[2/7/2024, 12:30:13 AM] [Apple TV Enhanced] [I] Python check: Preparing metadata (pyproject.toml): finished with status 'done'
[2/7/2024, 12:30:14 AM] [Apple TV Enhanced] [I] Python check: Collecting charset-normalizer==3.3.2 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 9))
[2/7/2024, 12:30:14 AM] [Apple TV Enhanced] [I] Python check: Downloading charset_normalizer-3.3.2-py3-none-any.whl.metadata (33 kB)
[2/7/2024, 12:30:15 AM] [Apple TV Enhanced] [I] Python check: Collecting cryptography==42.0.2 (from -r /homebridge/node_modules/homebridge-appletv-enhanced/requirements.txt (line 10))
[2/7/2024, 12:30:15 AM] [Apple TV Enhanced] [I] Python check: Downloading cryptography-42.0.2.tar.gz (672 kB)
[2/7/2024, 12:30:15 AM] [Apple TV Enhanced] [I] Python check: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 672.8/672.8 kB 2.4 MB/s eta 0:00:00
[2/7/2024, 12:30:15 AM] [Apple TV Enhanced] [I] Python check: Installing build dependencies: started
[2/7/2024, 12:30:30 AM] [Apple TV Enhanced] [I] Python check: Installing build dependencies: finished with status 'error'
[2/7/2024, 12:30:30 AM] [Apple TV Enhanced] [E] Python check:   error: subprocess-exited-with-error

  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 1
  ╰─> [99 lines of output]
      Collecting setuptools>=61.0.0
        Using cached setuptools-69.0.3-py3-none-any.whl.metadata (6.3 kB)
      Collecting wheel
        Using cached wheel-0.42.0-py3-none-any.whl.metadata (2.2 kB)
      Collecting cffi>=1.12
        Using cached cffi-1.16.0.tar.gz (512 kB)
        Installing build dependencies: started
        Installing build dependencies: finished with status 'done'
        Getting requirements to build wheel: started
        Getting requirements to build wheel: finished with status 'done'
        Installing backend dependencies: started
        Installing backend dependencies: finished with status 'done'
        Preparing metadata (pyproject.toml): started
        Preparing metadata (pyproject.toml): finished with status 'done'
      Collecting setuptools-rust>=1.7.0
        Downloading setuptools_rust-1.8.1-py3-none-any.whl.metadata (9.4 kB)
      Collecting pycparser (from cffi>=1.12)
        Downloading pycparser-2.21-py2.py3-none-any.whl (118 kB)
           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 118.7/118.7 kB 2.1 MB/s eta 0:00:00
      Collecting semantic-version<3,>=2.8.2 (from setuptools-rust>=1.7.0)
        Downloading semantic_version-2.10.0-py2.py3-none-any.whl (15 kB)
      Collecting tomli>=1.2.1 (from setuptools-rust>=1.7.0)
        Downloading tomli-2.0.1-py3-none-any.whl (12 kB)
      Using cached setuptools-69.0.3-py3-none-any.whl (819 kB)
      Using cached wheel-0.42.0-py3-none-any.whl (65 kB)
      Downloading setuptools_rust-1.8.1-py3-none-any.whl (26 kB)
      Building wheels for collected packages: cffi
        Building wheel for cffi (pyproject.toml): started
        Building wheel for cffi (pyproject.toml): finished with status 'error'
        error: subprocess-exited-with-error

        × Building wheel for cffi (pyproject.toml) did not run successfully.
        │ exit code: 1
        ╰─> [59 lines of output]
            Package libffi was not found in the pkg-config search path.
            Perhaps you should add the directory containing `libffi.pc'
            to the PKG_CONFIG_PATH environment variable
            No package 'libffi' found
            Package libffi was not found in the pkg-config search path.
            Perhaps you should add the directory containing `libffi.pc'
            to the PKG_CONFIG_PATH environment variable
            No package 'libffi' found
            Package libffi was not found in the pkg-config search path.
            Perhaps you should add the directory containing `libffi.pc'
            to the PKG_CONFIG_PATH environment variable
            No package 'libffi' found
            Package libffi was not found in the pkg-config search path.
            Perhaps you should add the directory containing `libffi.pc'
            to the PKG_CONFIG_PATH environment variable
            No package 'libffi' found
            Package libffi was not found in the pkg-config search path.
            Perhaps you should add the directory containing `libffi.pc'
            to the PKG_CONFIG_PATH environment variable
            No package 'libffi' found
            running bdist_wheel
            running build
            running build_py
            creating build
            creating build/lib.linux-armv7l-cpython-310
            creating build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/commontypes.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/cparser.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/setuptools_ext.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/_imp_emulation.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/pkgconfig.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/__init__.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/model.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/verifier.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/recompiler.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/ffiplatform.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/error.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/vengine_cpy.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/_shimmed_dist_utils.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/backend_ctypes.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/vengine_gen.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/lock.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/cffi_opcode.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/api.py -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/_cffi_include.h -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/parse_c_type.h -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/_embedding.h -> build/lib.linux-armv7l-cpython-310/cffi
            copying src/cffi/_cffi_errors.h -> build/lib.linux-armv7l-cpython-310/cffi
            running build_ext
            building '_cffi_backend' extension
            creating build/temp.linux-armv7l-cpython-310
            creating build/temp.linux-armv7l-cpython-310/src
            creating build/temp.linux-armv7l-cpython-310/src/c
            arm-linux-gnueabihf-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -DFFI_BUILDING=1 -DUSE__THREAD -DHAVE_SYNC_SYNCHRONIZE -I/usr/include/ffi -I/usr/include/libffi -I/var/lib/homebridge/appletv-enhanced/.venv/include -I/usr/include/python3.10 -c src/c/_cffi_backend.c -o build/temp.linux-armv7l-cpython-310/src/c/_cffi_backend.o
            src/c/_cffi_backend.c:15:10: fatal error: ffi.h: No such file or directory
               15 | #include <ffi.h>
                  |          ^~~~~~~
            compilation terminated.
            error: command '/usr/bin/arm-linux-gnueabihf-gcc' failed with exit code 1
            [end of output]

        note: This error originates from a subprocess, and is likely not a problem with pip.
        ERROR: Failed building wheel for cffi
      Failed to build cffi
      ERROR: Could not build wheels for cffi, which is required to install pyproject.toml-based projects
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.

[2/7/2024, 12:30:30 AM] [Apple TV Enhanced] [E] Python check: error: subprocess-exited-with-error

× pip subprocess to install build dependencies did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

[2/7/2024, 12:30:31 AM] [Apple TV Enhanced] [I] Python check: Finished

Configuration

{
    "name": "Apple TV Enhanced",
    "mediaTypes": [
        "music",
        "tv",
        "video"
    ],
    "deviceStates": [
        "paused",
        "playing"
    ],
    "deviceStateDelay": 0,
    "remoteKeysAsSwitch": [
        "pause",
        "play"
    ],
    "avadaKedavraAppAmount": 15,
    "disableVolumeControlRemote": false,
    "setTopBox": false,
    "discover": {
        "multicast": true
    },
    "forceVenvRecreate": false,
    "logLevel": 3,
    "deviceSpecificOverrides": [
        {
            "overrideMediaTypes": false,
            "overrideDeviceStates": false,
            "overrideDeviceStateDelay": false,
            "deviceStateDelay": 0,
            "overrideRemoteKeysAsSwitch": false,
            "overrideAvadaKedavraAppAmount": false,
            "avadaKedavraAppAmount": 15,
            "overrideCustomInputURIs": false,
            "overrideDisableVolumeControlRemote": false,
            "disableVolumeControlRemote": false,
            "overrideSetTopBox": false,
            "setTopBox": false
        }
    ],
    "platform": "AppleTVEnhanced",
    "_bridge": {
        "username": "0E:53:8A:61:1F:9A",
        "port": 31700
    }
}

Environment

Additional Context

No response

maxileith commented 8 months ago

From a touch of research, I think I could run:

apt-get install libffi libffi-dev

in the container, but not sure if that's going to get toasted the next time I pull a home bridge version.

I think your research is correct. Try installing the two packages and restart the plugin. Then let me know if it worked out for you. If that solves the problem, we should open an issue in the repo of the docker image and add these two packages by default.

codemavn commented 8 months ago

Okay. Thanks heaps for that. The apt-get did resolve the issue (slightly diff to line above, see below), but there were a few more missing. Namely rust and open ssl. To resolve:

apt-get update apt-get install libffi8 libffi-dev pip install --upgrade pip apt-get install cargo apt-get install libssl-dev

note using rustc and rustup didn't do the trick, you have to use the cargo installe.

I think we should get this added to the docker container.

Now pardon me because it's been a minute since I was a techie so my docker memory eludes me, but I'm thinking an alternative could be to drop a shell script in the container config directory and getting compose to execute it. Don't know for sure if that's doable, though.

In any case, thanks for the great plugin. once I've overcome the above it's an outstanding implementation.

maxileith commented 8 months ago

Thanks for the steps to fix. I will try to reproduce the scenario and will open an issue once I could successfully reproduce it on an ARM based system.

CardenB commented 8 months ago

Just ran into this issue with my Hoobs box. Installing the aforementioned system packages with aptitude helped- except for cargo. I could not install cargo with a recent enough version via apt.

Rustup installation instructions (as instructed by cryptography python package) did not work.

I had to . /var/lib/hoobs/appletvenhancedbridge/appletv-enhanced/.venv/bin/activate and then run

curl https://sh.rustup.rs -sSf | sh
export PATH=$PATH:~/.cargo/bin

Afterward, I ran pip install -r /usr/local/share/.cache/yarn/v6/npm-homebridge-appletv-enhanced-1.2.1-a803532ba99cf7090d2d7ff60c54e5895a7b879d-integrity/node_modules/homebridge-appletv-enhanced/requirements.txt

It stuck on cryptography for a while (30-60 minutes) but it worked this way. Not sure how to adjust to make this work programmatically.

codemavn commented 8 months ago

@maxileith great. Let me know how you come along with that. Do you want me to close the issue or will you keep it open until you validate and find a universal solution?

@CardenB wow, >half an hour? interested to know the hardware in hoobs. I thought it took awhile on mine, but even then it was only about 5-7mins for the whole kit and kaboodle. in any case, glad you got it sorted.

maxileith commented 8 months ago

@maxileith great. Let me know how you come along with that. Do you want me to close the issue or will you keep it open until you validate and find a universal solution?

Keep it open for now.

maxileith commented 8 months ago

@codemavn Do you use a 32-bit installation?

CardenB commented 8 months ago

FWIW I was installing on a 32 bit machine with 32 bit user space.

I saw many issues indicating that a 64 bit rust install was searched and that caused some confusion in the build process, but I wasn’t able to confirm this issue for myself.

What fixed was making sure the PATH referenced my recent rust install. For some reason I couldn’t get pip to read this path via the Apple TV plugin install, even when I had it added to the venv activate. I had to do it from the same shell session.

maxileith commented 8 months ago

Okay, I have installed the plugin without any issues on a 64-bit arm system (with and without docker). Without any issues. Maybe I will try to do that with a 32-bit installation as well just to verify everything.

However, since even Raspberry's are 64-bit these days, I don't think we should bother the homebridge team with adding unwanted dependencies to homebridge.

What do you guys think about just adding 64-bit as a requirement to the plugins README?

CardenB commented 8 months ago

Personally I think making platforms not supported more clear with a reason for each is ideal. For example, somewhere near the top of the readme:

CAUTION, a few exceptional platforms are UNSUPPORTED:

  • 32 bit systems
    • Issues indicate that python packages required for this plugin have difficulties with 32 bit systems and cannot be installed automatically. This includes 32 bit systems in a 64 bit userspace.
  • HOOBS
    • HOOBS is a 32 bit architecture and suffers from the above limitations.
    • HOOBS has a different plugin system that prevents managing Apple TVs.

I think people are more likely to see this than the current "HOOBS not supported" towards the end of the README.

I wouldn't worry about validating on a 32 bit system. Very few platforms have this restriction and you're not really in control of how things are packaged anyway. It could easily be changed in the future, and clearly is not protected against 32 bit architectures.

CardenB commented 8 months ago

You could also add a link to another section for the platforms you have tested against, since the homebridge verification doesn't currently protect against this.

codemavn commented 8 months ago

@maxileith, apologies for the late reply. both my pi and the docker container are 32-bit: $ uname -m armv7l

codemavn commented 8 months ago

I agree that we shouldn't worry about bothering the home bridge team. I think a message as per @CardenB posted above works fine, and perhaps with a link to this issue for workaround options.

maxileith commented 8 months ago

Personally I think making platforms not supported more clear with a reason for each is ideal. For example, somewhere near the top of the readme:

CAUTION, a few exceptional platforms are UNSUPPORTED:

  • 32 bit systems

    • Issues indicate that python packages required for this plugin have difficulties with 32 bit systems and cannot be installed automatically. This includes 32 bit systems in a 64 bit userspace.
  • HOOBS

    • HOOBS is a 32 bit architecture and suffers from the above limitations.
    • HOOBS has a different plugin system that prevents managing Apple TVs.

I think people are more likely to see this than the current "HOOBS not supported" towards the end of the README.

I wouldn't worry about validating on a 32 bit system. Very few platforms have this restriction and you're not really in control of how things are packaged anyway. It could easily be changed in the future, and clearly is not protected against 32 bit architectures.

I have added a disclaimer similar to your suggestion to the README :)