openhab / openhab-addons

Add-ons for openHAB
https://www.openhab.org/
Eclipse Public License 2.0
1.9k stars 3.6k forks source link

[jellyfin] SDK Version 1.4.x no longer supports recent Jellyfin Server Versions (>10.8) #17674

Open pgfeller opened 4 weeks ago

pgfeller commented 4 weeks ago

With the changes introduced by with Jellyfin 10.9, Android-Devices are no longer properly supported (devices is no longer properly identified). With the update to 10.10 the binding does not work anymore:

2024-10-28 21:42:55.905 [ERROR] [.jellyfin.sdk.api.client.RawResponse] - Deserialization failed
kotlinx.serialization.SerializationException: org.jellyfin.sdk.model.api.GeneralCommandType does not contain element with name ',' at path $[0].Capabilities.SupportedCommands[1]

SDK 1.4.x is no longer mainteined; Server 10.10 requires SDK Version 1.6

Expected Behavior

I propose to migrate the binding to the latest SDK to be compatible with the latest Jellyfin Releases. Unfortunately it is liekly, that such an upgrade will break compatibility with earlier releases (<= 10.9); which might be problematic if a user does not want to update the media server.

However - as SDK 1.4.x is deprecated and older Jellyfin Server will no longer receive new features I favor this update despite the backward compatibility problem.

Current Behavior

With Jellyfin 10.9 the binding's function is limited for Android Clients; as sessions are not properly associated with devices (device id). With Server version 10.10 the binding does not work anymore.

Possible Solution

Migration to Jellyfin SDK 1.6.

Steps to Reproduce (for Bugs)

No special steps required to reproduce the problem. You'll see the problem if you try to operate the binding with Jellyfin Server 10.10.

Context

It is not possible to use Jellyfin Server Versions > 10.8 in a productive environment.

Your Environment

Jellyfin 10.10.0, openHAB 4.2.2, Release Build, Linux/6.8.0-45-generic (amd64 - Docker Container), Java Runtime 17.0.12

Links:

openhab-bot commented 4 weeks ago

This issue has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/jellyfin-problems-after-upgrade-to-10-9-no-longer-working-with-10-10/159494/1

lsiepel commented 4 weeks ago

Can’t it be configurable?

pgfeller commented 4 weeks ago

Most likely not without some rework of the binding; the SDK is included as dependency/library.

I an not too familiar with the build system, but I think those are declared in the pom. I'll have a look; but I do not think that both libraries can co-exist. Even if possible to isolate them somehow, I do not have the knowledge (yet) to do such a thing.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.openhab.addons.bundles</groupId>
    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
    <version>4.3.0-SNAPSHOT</version>
  </parent>
  <properties>
    <bnd.importpackage>
      !android.*,!com.android.*,!kotlin.internal.jdk7,!kotlin.internal.jdk8,!kotlin.reflect.*,!okhttp3.*,!okio.*
    </bnd.importpackage>
    <jellyfin.sdk>1.4.7</jellyfin.sdk>
  </properties>
  <artifactId>org.openhab.binding.jellyfin</artifactId>

  <name>openHAB Add-ons :: Bundles :: Jellyfin Binding</name>
  <dependencies>
    <dependency>
      <groupId>org.jellyfin.sdk</groupId>
      <artifactId>jellyfin-core-jvm</artifactId>
      <version>${jellyfin.sdk}</version>
    </dependency>
    <dependency>
      <groupId>org.jellyfin.sdk</groupId>
      <artifactId>jellyfin-api-jvm</artifactId>
      <version>${jellyfin.sdk}</version>
    </dependency>
    <dependency>
      <groupId>org.jellyfin.sdk</groupId>
      <artifactId>jellyfin-model-jvm</artifactId>
      <version>${jellyfin.sdk}</version>
    </dependency>
    <dependency>
      <groupId>io.ktor</groupId>
      <artifactId>ktor-client-core-jvm</artifactId>
      <version>1.6.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.ktor</groupId>
      <artifactId>ktor-client-cio-jvm</artifactId>
      <version>1.6.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.ktor</groupId>
      <artifactId>ktor-http-jvm</artifactId>
      <version>1.6.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.ktor</groupId>
      <artifactId>ktor-http-cio-jvm</artifactId>
      <version>1.6.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.ktor</groupId>
      <artifactId>ktor-network-jvm</artifactId>
      <version>1.6.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.ktor</groupId>
      <artifactId>ktor-utils-jvm</artifactId>
      <version>1.6.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.ktor</groupId>
      <artifactId>ktor-io-jvm</artifactId>
      <version>1.6.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.ktor</groupId>
      <artifactId>ktor-network-tls-jvm</artifactId>
      <version>1.6.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib</artifactId>
      <version>${kotlin.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlinx</groupId>
      <artifactId>kotlinx-coroutines-core-jvm</artifactId>
      <version>1.8.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlinx</groupId>
      <artifactId>kotlinx-serialization-core-jvm</artifactId>
      <version>1.6.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlinx</groupId>
      <artifactId>kotlinx-serialization-json-jvm</artifactId>
      <version>1.6.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.github.microutils</groupId>
      <artifactId>kotlin-logging-jvm</artifactId>
      <version>3.0.5</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

I'll create a branch and have a look and post what I find here. Then we can discuss what is the best option for the users. Of course a fork of the binding would be the worst option. It would be possible to bypass the SDK and use the REST API directly. Then we would be able to configure what we need and even detect the API version - but that would be a bigger refactoring. "Fortunately" the binding does only support a few channels - therefore might be an option ...

REST API available via /api-docs/swagger/index.html

image

In case yoy would like to have a look into it, docker might be a good option. Here my configuration as a jump start (as usual, the environment variables can be defined in the .env file, according to your needs):

services:
  jellyfin:
    container_name: ${COMPOSE_PROJECT_NAME}-jellyfin
    image: jellyfin/jellyfin:${VERSION_JELLYFIN} 
    deploy:
      resources:
        limits:
          cpus: "4"
          memory: 12GB
        reservations:
          cpus: "1"
          memory: 4GB
    restart: unless-stopped
    user: $USER_ID:$GROUP_ID
    network_mode: host
    group_add:
      - $GROUP_RENDERER
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro 

      - $MOUNT_SYSTEM/host/ssl:/config/ssl:ro
      - $MOUNT_SYSTEM/$COMPOSE_PROJECT_NAME/jellyfin/${VERSION_JELLYFIN}:/config:rw

      - $MOUNT_TRANSIENT/$COMPOSE_PROJECT_NAME/jellyfin/${VERSION_JELLYFIN}/log:/config/log:rw
      - $MOUNT_TRANSIENT/$COMPOSE_PROJECT_NAME/jellyfin/${VERSION_JELLYFIN}/cache:/cache:rw

      - $MEDIA:/media/public:rw
      - $MEDIA_PRIVATE:/media/private:rw
    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128
    environment:
      - HEALTHCHECK_URL=http://server:8096/health

For my personal use I'll create a POC with the new SDK to see if it works - as I would like to use 10.10 and upcomming versions (of course I use it in combination with the hue sync binding to automatically adjust ambient light if I watch a movie 🙂).

I'll ask in the forum if there is a high demand for legacy support - if there are no answers; or no request to support it I could help with the SDK migration. If we need legacy support I'm not sure yet if I'll do/help with the integration.

lsiepel commented 4 weeks ago

Dropping the SDK would be the best. But it would cost a little more time for you so, you have to decide. Upgrading to most recent SDK is the alternative option. I also don’t see a way to add both SDK versions.

pgfeller commented 3 weeks ago

I had a look into the issue - the SDK uses Kotlin. It should be/is possible to use the library in a java environment; but this touches an area which is new for me: I have to find out what are the compile time dependencies, and what is needed at runtime (and at a first glance it looks as there are conflicting versions already in the dependency tree of the SDK itself). It looks like jetbrains provides a runtime layer; but warns that not all libraries written in kotlin are "osgi" friendly - as i do not assume that there are additional dependencies this should not be an issue I hope ... but we'll see.

I did a downgrade to 10.8 - and discovered that the current jellyfin client for fire tv does not support 10.8 anymore - the phone client still does; but it's like a question of time until the support for other clients is droped as well.

➡️ Therefore I have now a personal usecase that does not work with eiter version - which means I'll try to solve this problem. I'm not sure yet about the approach. But first I'll now complete the work on the hue binding and then this will have priority for me. But as the clients start to drop support for deprecated server versions backward compatibility seems to have limited value and therefore independently of the approach I do not plan to include it in the changes.

Of course if the current maintainer of the binding has time he/she will probably find a solution sooner than I can - and it would not hurt my feelings if someone else solves the problem 😉. But it is next on my list.