about summary refs log tree commit diff
path: root/pkgs/servers/home-assistant
diff options
context:
space:
mode:
authorMartin Weinelt <hexa@darmstadt.ccc.de>2021-12-11 20:59:08 +0100
committerMartin Weinelt <hexa@darmstadt.ccc.de>2021-12-12 20:25:50 +0100
commitfd19df269d61b897dc42cbbe9495cfa1bdd6fe09 (patch)
tree8133e33b58e4c19dd461c7a1f3c1797cbe7b07cd /pkgs/servers/home-assistant
parentc9e0271369f228d66f574997e77bfd13910e229e (diff)
home-assistant: 2021.11.4 -> 2021.12.0
Diffstat (limited to 'pkgs/servers/home-assistant')
-rw-r--r--pkgs/servers/home-assistant/component-packages.nix22
-rw-r--r--pkgs/servers/home-assistant/default.nix161
-rw-r--r--pkgs/servers/home-assistant/frontend.nix4
-rw-r--r--pkgs/servers/home-assistant/patches/ffmpeg-path.patch84
-rw-r--r--pkgs/servers/home-assistant/patches/tests-ignore-OSErrors-in-hass-fixture.patch (renamed from pkgs/servers/home-assistant/0001-tests-ignore-OSErrors-in-hass-fixture.patch)0
-rw-r--r--pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch13
-rwxr-xr-xpkgs/servers/home-assistant/update.sh2
7 files changed, 246 insertions, 40 deletions
diff --git a/pkgs/servers/home-assistant/component-packages.nix b/pkgs/servers/home-assistant/component-packages.nix
index 5fccf5816d8c3..e76db52e982eb 100644
--- a/pkgs/servers/home-assistant/component-packages.nix
+++ b/pkgs/servers/home-assistant/component-packages.nix
@@ -2,7 +2,7 @@
 # Do not edit!
 
 {
-  version = "2021.11.5";
+  version = "2021.12.0";
   components = {
     "abode" = ps: with ps; [ abodepy ];
     "accuweather" = ps: with ps; [ accuweather ];
@@ -77,6 +77,7 @@
     "azure_event_hub" = ps: with ps; [ azure-eventhub ];
     "azure_service_bus" = ps: with ps; [ azure-servicebus ];
     "baidu" = ps: with ps; [ ]; # missing inputs: baidu-aip
+    "balboa" = ps: with ps; [ pybalboa ];
     "bayesian" = ps: with ps; [ ];
     "bbb_gpio" = ps: with ps; [ ]; # missing inputs: Adafruit_BBIO
     "bbox" = ps: with ps; [ ]; # missing inputs: pybbox
@@ -112,6 +113,7 @@
     "bt_home_hub_5" = ps: with ps; [ ]; # missing inputs: bthomehub5-devicelist
     "bt_smarthub" = ps: with ps; [ ]; # missing inputs: btsmarthub_devicelist
     "buienradar" = ps: with ps; [ buienradar ];
+    "button" = ps: with ps; [ ];
     "caldav" = ps: with ps; [ caldav ];
     "calendar" = ps: with ps; [ aiohttp-cors ];
     "camera" = ps: with ps; [ pyturbojpeg aiohttp-cors ];
@@ -166,7 +168,7 @@
     "default_config" = ps: with ps; [ pynacl pyturbojpeg aiodiscover aiohttp-cors async-upnp-client emoji hass-nabucasa home-assistant-frontend ifaddr pillow pyserial pyudev scapy sqlalchemy zeroconf ];
     "delijn" = ps: with ps; [ pydelijn ];
     "deluge" = ps: with ps; [ deluge-client ];
-    "demo" = ps: with ps; [ aiohttp-cors ];
+    "demo" = ps: with ps; [ aiohttp-cors sqlalchemy ];
     "denon" = ps: with ps; [ ];
     "denonavr" = ps: with ps; [ denonavr ];
     "derivative" = ps: with ps; [ ];
@@ -175,6 +177,7 @@
     "device_sun_light_trigger" = ps: with ps; [ aiohttp-cors pillow ];
     "device_tracker" = ps: with ps; [ ];
     "devolo_home_control" = ps: with ps; [ aiohttp-cors devolo-home-control-api ifaddr zeroconf ];
+    "devolo_home_network" = ps: with ps; [ devolo-plc-api ];
     "dexcom" = ps: with ps; [ pydexcom ];
     "dhcp" = ps: with ps; [ aiodiscover scapy ];
     "dht" = ps: with ps; [ ]; # missing inputs: adafruit-circuitpython-dht
@@ -204,7 +207,6 @@
     "dwd_weather_warnings" = ps: with ps; [ dwdwfsapi ];
     "dweet" = ps: with ps; [ ]; # missing inputs: dweepy
     "dynalite" = ps: with ps; [ ]; # missing inputs: dynalite_devices
-    "dyson" = ps: with ps; [ aiohttp-cors ifaddr libpurecool zeroconf ];
     "eafm" = ps: with ps; [ aioeafm ];
     "ebox" = ps: with ps; [ ]; # missing inputs: pyebox
     "ebusd" = ps: with ps; [ ]; # missing inputs: ebusdpy
@@ -246,6 +248,7 @@
     "etherscan" = ps: with ps; [ ]; # missing inputs: python-etherscan-api
     "eufy" = ps: with ps; [ ]; # missing inputs: lakeside
     "everlights" = ps: with ps; [ pyeverlights ];
+    "evil_genius_labs" = ps: with ps; [ pyevilgenius ];
     "evohome" = ps: with ps; [ evohome-async ];
     "ezviz" = ps: with ps; [ ha-ffmpeg pyezviz ];
     "faa_delays" = ps: with ps; [ faadelays ];
@@ -411,7 +414,6 @@
     "intent_script" = ps: with ps; [ ];
     "intesishome" = ps: with ps; [ pyintesishome ];
     "ios" = ps: with ps; [ aiohttp-cors ifaddr zeroconf ];
-    "iota" = ps: with ps; [ ]; # missing inputs: pyota
     "iotawatt" = ps: with ps; [ iotawattpy ];
     "iperf3" = ps: with ps; [ ]; # missing inputs: iperf3
     "ipma" = ps: with ps; [ pyipma ];
@@ -424,6 +426,7 @@
     "itach" = ps: with ps; [ ]; # missing inputs: pyitachip2ir
     "itunes" = ps: with ps; [ ];
     "izone" = ps: with ps; [ python-izone ];
+    "jellyfin" = ps: with ps; [ jellyfin-apiclient-python ];
     "jewish_calendar" = ps: with ps; [ hdate ];
     "joaoapps_join" = ps: with ps; [ ]; # missing inputs: python-join-api
     "juicenet" = ps: with ps; [ python-juicenet ];
@@ -476,7 +479,6 @@
     "london_air" = ps: with ps; [ ];
     "london_underground" = ps: with ps; [ ]; # missing inputs: london-tube-status
     "lookin" = ps: with ps; [ aiolookin ];
-    "loopenergy" = ps: with ps; [ ]; # missing inputs: pyloopenergy
     "lovelace" = ps: with ps; [ ];
     "luci" = ps: with ps; [ openwrt-luci-rpc ];
     "luftdaten" = ps: with ps; [ luftdaten ];
@@ -519,7 +521,7 @@
     "microsoft_face_identify" = ps: with ps; [ pyturbojpeg aiohttp-cors ];
     "miflora" = ps: with ps; [ bluepy ]; # missing inputs: miflora
     "mikrotik" = ps: with ps; [ librouteros ];
-    "mill" = ps: with ps; [ millheater ];
+    "mill" = ps: with ps; [ mill-local millheater ];
     "min_max" = ps: with ps; [ ];
     "minecraft_server" = ps: with ps; [ aiodns getmac mcstatus ];
     "minio" = ps: with ps; [ minio ];
@@ -547,7 +549,6 @@
     "mutesync" = ps: with ps; [ mutesync ];
     "mvglive" = ps: with ps; [ PyMVGLive ];
     "my" = ps: with ps; [ aiohttp-cors home-assistant-frontend pillow sqlalchemy ];
-    "mychevy" = ps: with ps; [ ]; # missing inputs: mychevy
     "mycroft" = ps: with ps; [ ]; # missing inputs: mycroftapi
     "myq" = ps: with ps; [ pymyq ];
     "mysensors" = ps: with ps; [ aiohttp-cors paho-mqtt pymysensors ];
@@ -695,6 +696,7 @@
     "random" = ps: with ps; [ ];
     "raspihats" = ps: with ps; [ smbus-cffi ]; # missing inputs: raspihats
     "raspyrfm" = ps: with ps; [ ]; # missing inputs: raspyrfm-client
+    "rdw" = ps: with ps; [ vehicle ];
     "recollect_waste" = ps: with ps; [ aiorecollect ];
     "recorder" = ps: with ps; [ sqlalchemy ];
     "recswitch" = ps: with ps; [ ]; # missing inputs: pyrecswitch
@@ -709,6 +711,7 @@
     "rest_command" = ps: with ps; [ ];
     "rflink" = ps: with ps; [ rflink ];
     "rfxtrx" = ps: with ps; [ pyrfxtrx ];
+    "ridwell" = ps: with ps; [ aioridwell ];
     "ring" = ps: with ps; [ ha-ffmpeg ring-doorbell ];
     "ripple" = ps: with ps; [ ]; # missing inputs: python-ripple-api
     "risco" = ps: with ps; [ pyrisco ];
@@ -852,6 +855,7 @@
     "tado" = ps: with ps; [ python-tado ];
     "tag" = ps: with ps; [ ];
     "tahoma" = ps: with ps; [ tahoma-api ];
+    "tailscale" = ps: with ps; [ tailscale ];
     "tank_utility" = ps: with ps; [ ]; # missing inputs: tank_utility
     "tankerkoenig" = ps: with ps; [ pytankerkoenig ];
     "tapsaff" = ps: with ps; [ ]; # missing inputs: tapsaff
@@ -867,6 +871,7 @@
     "temper" = ps: with ps; [ ]; # missing inputs: temperusb
     "template" = ps: with ps; [ ];
     "tensorflow" = ps: with ps; [ numpy pillow pycocotools tensorflow ]; # missing inputs: tf-models-official
+    "tesla_wall_connector" = ps: with ps; [ tesla-wall-connector ];
     "tfiac" = ps: with ps; [ ]; # missing inputs: pytfiac
     "thermoworks_smoke" = ps: with ps; [ stringcase ]; # missing inputs: thermoworks_smoke
     "thethingsnetwork" = ps: with ps; [ ];
@@ -883,6 +888,7 @@
     "tod" = ps: with ps; [ ];
     "todoist" = ps: with ps; [ todoist ];
     "tof" = ps: with ps; [ ]; # missing inputs: RPi.GPIO VL53L1X2
+    "tolo" = ps: with ps; [ tololib ];
     "tomato" = ps: with ps; [ ];
     "toon" = ps: with ps; [ pyturbojpeg aiohttp-cors hass-nabucasa toonapi ];
     "torque" = ps: with ps; [ aiohttp-cors ];
@@ -995,7 +1001,7 @@
     "yamaha_musiccast" = ps: with ps; [ aiohttp-cors aiomusiccast async-upnp-client ifaddr zeroconf ];
     "yandex_transport" = ps: with ps; [ aioymaps ];
     "yandextts" = ps: with ps; [ ];
-    "yeelight" = ps: with ps; [ aiohttp-cors async-upnp-client ifaddr yeelight ];
+    "yeelight" = ps: with ps; [ aiohttp-cors async-upnp-client ifaddr yeelight zeroconf ];
     "yeelightsunflower" = ps: with ps; [ ]; # missing inputs: yeelightsunflower
     "yi" = ps: with ps; [ aioftp ha-ffmpeg ];
     "youless" = ps: with ps; [ youless-api ];
diff --git a/pkgs/servers/home-assistant/default.nix b/pkgs/servers/home-assistant/default.nix
index 9d6618452e6af..f3beafdf388cf 100644
--- a/pkgs/servers/home-assistant/default.nix
+++ b/pkgs/servers/home-assistant/default.nix
@@ -1,7 +1,10 @@
 { stdenv
 , lib
 , fetchFromGitHub
+, fetchpatch
 , python3
+, substituteAll
+, ffmpeg
 , inetutils
 , nixosTests
 
@@ -21,10 +24,6 @@
 
 let
   defaultOverrides = [
-    # Remove with Home Assistant 2021.12
-    (mkOverride "aiohue" "2.6.3" "sha256-zpwkDKPrE5TFZQO0A1ifTQ7n+TRFpXi3jai3h5plyGM=")
-    (mkOverride "PyChromecast" "9.4.0" "sha256-Y8PLrjxZHml7BmklEJ/VXGqkRyneAy+QVA5rusPeBHQ=")
-
     # aiounify 29 breaks integration tests
     (self: super: {
       aiounifi = super.aiounifi.overridePythonAttrs (oldAttrs: rec {
@@ -42,6 +41,87 @@ let
     (mkOverride "python-slugify" "4.0.1" "69a517766e00c1268e5bbfc0d010a0a8508de0b18d30ad5a1ff357f8ae724270")
 
     (self: super: {
+      httpcore = super.httpcore.overridePythonAttrs (oldAttrs: rec {
+        version = "0.14.3";
+        src = fetchFromGitHub {
+          owner = "encode";
+          repo = "httpcore";
+          rev = version;
+          sha256 = "sha256-jPsbMhY1lWKBXlh6hsX6DGKXi/g7VQSU00tF6H7qkOo=";
+        };
+        propagatedBuildInputs = oldAttrs.propagatedBuildInputs ++ [ python3.pkgs.certifi ];
+        doCheck = false;
+      });
+    })
+
+    (self: super: {
+      httpx = super.httpx.overridePythonAttrs (oldAttrs: rec {
+        version = "0.21.1";
+        src = fetchFromGitHub {
+          owner = "encode";
+          repo = "httpx";
+          rev = version;
+          sha256 = "sha256-ayhLP+1hPWAx2ds227CKp5cebVkD5B2Z59L+3dzdINc=";
+        };
+        doCheck = false;
+      });
+    })
+
+    (self: super: {
+      pytest-httpx = super.pytest-httpx.overridePythonAttrs (oldAttrs: rec {
+        version = "0.15.0";
+        src = fetchFromGitHub {
+          owner = "Colin-bin";
+          repo = "pytest_httpx";
+          rev = "v${version}";
+          sha256 = "08dxvjkxlnam3r0yp17495d1vksyawzzkpykacjql1gi6hqlfrwg";
+        };
+      });
+    })
+
+    (self: super: {
+      respx = super.respx.overridePythonAttrs (oldAttrs: rec {
+        version = "0.19.0";
+        src = fetchFromGitHub {
+          owner = "lundberg";
+          repo = "respx";
+          rev = version;
+          sha256 = "sha256-xiAt42kc1+rro99KMwzYKi3XC+wxYVqOY11tM+M/uV8=";
+        };
+      });
+    })
+
+    (self: super: {
+      envoy-reader = super.envoy-reader.overridePythonAttrs (oldAttrs: rec {
+        patches = [
+          # Support for later httpx, https://github.com/jesserizzo/envoy_reader/pull/82
+          (fetchpatch {
+            name = "support-later-httpx.patch";
+            url = "https://github.com/jesserizzo/envoy_reader/commit/6019a89419fe9c830ba839be7d39ec54725268b0.patch";
+            sha256 = "17vsrx13rskvh8swvjisb2dk6x1jdbjcm8ikkpidia35pa24h272";
+          })
+        ];
+      });
+    })
+
+    (self: super: {
+      sanic = super.sanic.overridePythonAttrs (oldAttrs: rec {
+        version = "21.9.3";
+        src = fetchFromGitHub {
+          owner = "sanic-org";
+          repo = "sanic";
+          rev = "v${version}";
+          sha256 = "0m18jdw1mvf7jhpnrxhm96p24pxvv0h9m71a8c7sqqkwnnpa3p5i";
+        };
+        disabledTests = oldAttrs.disabledTests ++ [
+          "test_redirect"
+          "test_chained_redirect"
+          "test_unix_connection"
+        ];
+      });
+    })
+
+    (self: super: {
       huawei-lte-api = super.huawei-lte-api.overridePythonAttrs (oldAttrs: rec {
         version = "1.4.18";
         src = fetchFromGitHub {
@@ -82,17 +162,7 @@ let
       });
     })
 
-    (self: super: {
-      nettigo-air-monitor = super.nettigo-air-monitor.overridePythonAttrs (oldAttrs: rec {
-        version = "1.1.1";
-        src = fetchFromGitHub {
-          owner = "bieniu";
-          repo = "nettigo-air-monitor";
-          rev = version;
-          sha256 = "sha256-OIB1d6XtstUr5P0q/dmyJS7+UbtkFQIiuSnzwcdP1mE=";
-        };
-      });
-    })
+    (mkOverride "jinja2" "3.0.3" "1mvwr02s86zck5wsmd9wjxxb9iaqr17hdi5xza9vkwv8rmrv46v1")
 
     # Pinned due to API changes in pyruckus>0.12
     (self: super: {
@@ -123,6 +193,32 @@ let
     # Pinned due to API changes in 0.1.0
     (mkOverride "poolsense" "0.0.8" "09y4fq0gdvgkfsykpxnvmfv92dpbknnq5v82spz43ak6hjnhgcyp")
 
+    # Pinned due to API changes in 0.4.0
+    (self: super: {
+      vilfo-api-client = super.vilfo-api-client.overridePythonAttrs (oldAttrs: rec {
+        version = "0.3.3";
+        src = fetchFromGitHub {
+          owner = "ManneW";
+          repo = "vilfo-api-client-python";
+          rev = "v$version}";
+          sha256 = "1gy5gpsg99rcm1cc3m30232za00r9i46sp74zpd12p3vzz1wyyqf";
+        };
+      });
+    })
+
+    # Pinned due to API changes ~1.0
+    (self: super: {
+      vultr = super.vultr.overridePythonAttrs (oldAttrs: rec {
+        version = "0.1.2";
+        src = fetchFromGitHub {
+          owner = "spry-group";
+          repo = "python-vultr";
+          rev = "v${version}";
+          sha256 = "1qjvvr2v9gfnwskdl0ayazpcmiyw9zlgnijnhgq9mcri5gq9jw5h";
+        };
+      });
+    })
+
     # home-assistant-frontend does not exist in python3.pkgs
     (self: super: {
       home-assistant-frontend = self.callPackage ./frontend.nix { };
@@ -156,7 +252,7 @@ let
   extraBuildInputs = extraPackages py.pkgs;
 
   # Don't forget to run parse-requirements.py after updating
-  hassVersion = "2021.11.5";
+  hassVersion = "2021.12.0";
 
 in with py.pkgs; buildPythonApplication rec {
   pname = "homeassistant";
@@ -173,20 +269,25 @@ in with py.pkgs; buildPythonApplication rec {
     owner = "home-assistant";
     repo = "core";
     rev = version;
-    sha256 = "sha256-5MxArJLzOg9dU4Q2c6BDjvEzR2u7UVumNZjwE84+br8=";
+    hash = "sha256:00hi709pb06c4ki0zb42my6g9cifrp2pn04ygrn5i7q7sr6min71";
   };
 
   # leave this in, so users don't have to constantly update their downstream patch handling
   patches = [
-    ./0001-tests-ignore-OSErrors-in-hass-fixture.patch
+    (substituteAll {
+      src = ./patches/ffmpeg-path.patch;
+      ffmpeg = "${lib.getBin ffmpeg}/bin/ffmpeg";
+    })
+    ./patches/tests-ignore-OSErrors-in-hass-fixture.patch
   ];
 
   postPatch = ''
     substituteInPlace setup.py \
-      --replace "async_timeout==3.0.1" "async_timeout" \
-      --replace "awesomeversion==21.10.1" "awesomeversion" \
-      --replace "aiohttp==3.7.4.post0" "aiohttp" \
+      --replace "aiohttp==3.8.1" "aiohttp" \
+      --replace "async_timeout==4.0.0" "async_timeout" \
       --replace "bcrypt==3.1.7" "bcrypt" \
+      --replace "cryptography==35.0.0" "cryptography" \
+      --replace "httpx==0.21.0" "httpx" \
       --replace "pip>=8.0.3,<20.3" "pip" \
       --replace "pyyaml==6.0" "pyyaml" \
       --replace "yarl==1.6.3" "yarl"
@@ -198,6 +299,7 @@ in with py.pkgs; buildPythonApplication rec {
     aiohttp
     astral
     async-timeout
+    atomicwrites
     attrs
     awesomeversion
     bcrypt
@@ -347,7 +449,6 @@ in with py.pkgs; buildPythonApplication rec {
     "dte_energy_bridge"
     "duckdns"
     "dunehd"
-    "dyson"
     "eafm"
     "ecobee"
     "econet"
@@ -406,7 +507,8 @@ in with py.pkgs; buildPythonApplication rec {
     "geonetnz_quakes"
     "geonetnz_volcano"
     "gios"
-    "glances"
+    # updated to incompatible version and overriding is annoying because of async_timeout<4 pin
+    # "glances"
     "goalzero"
     "gogogate2"
     "google"
@@ -686,8 +788,6 @@ in with py.pkgs; buildPythonApplication rec {
     "telegram"
     "tellduslive"
     "template"
-    # disable tesla comonent tests while typer is incompatible with click>=8.0
-    # "tesla"
     "threshold"
     "tibber"
     "tile"
@@ -726,7 +826,8 @@ in with py.pkgs; buildPythonApplication rec {
     "uvc"
     "vacuum"
     "velbus"
-    "venstar"
+    # disabled, because it includes onewire component tests, for which we lack p1wire dependency
+    # "venstar"
     "vera"
     "verisure"
     "version"
@@ -736,8 +837,7 @@ in with py.pkgs; buildPythonApplication rec {
     "vlc_telnet"
     "voicerss"
     "volumio"
-    # disabled, becaused AttributeError: <class 'vultr.vultr.Vultr'> does not have the attribute 'server_list'
-    # "vultr"
+    "vultr"
     "wake_on_lan"
     "wallbox"
     "water_heater"
@@ -756,7 +856,8 @@ in with py.pkgs; buildPythonApplication rec {
     "xbox"
     "xiaomi"
     "xiaomi_aqara"
-    "xiaomi_miio"
+    # disabled, because we require cryptography>=35.0 for the miio package
+    # "xiaomi_miio"
     "yamaha"
     "yandex_transport"
     "yandextts"
@@ -873,6 +974,8 @@ in with py.pkgs; buildPythonApplication rec {
   preCheck = ''
     export HOME="$TEMPDIR"
 
+    patch -p1 < ${./patches/tests-mock-source-ip.patch}
+
     # the tests require the existance of a media dir
     mkdir /build/media
 
diff --git a/pkgs/servers/home-assistant/frontend.nix b/pkgs/servers/home-assistant/frontend.nix
index bf614a11e027d..ae8b2f0fb5d0f 100644
--- a/pkgs/servers/home-assistant/frontend.nix
+++ b/pkgs/servers/home-assistant/frontend.nix
@@ -4,11 +4,11 @@ buildPythonPackage rec {
   # the frontend version corresponding to a specific home-assistant version can be found here
   # https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/frontend/manifest.json
   pname = "home-assistant-frontend";
-  version = "20211109.0";
+  version = "20211211.0";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "sha256-DXL+D58kS8q4we6/r6iRuXA/d9NOoYUp9A3vsHQ0KVg=";
+    sha256 = "sha256-+rUrNCWf7CBzTPGuK7m88c1ouApelGla/L3SBwxYqdQ=";
   };
 
   # there is nothing to strip in this package
diff --git a/pkgs/servers/home-assistant/patches/ffmpeg-path.patch b/pkgs/servers/home-assistant/patches/ffmpeg-path.patch
new file mode 100644
index 0000000000000..a72674ff7a5fe
--- /dev/null
+++ b/pkgs/servers/home-assistant/patches/ffmpeg-path.patch
@@ -0,0 +1,84 @@
+diff --git a/homeassistant/components/ffmpeg/__init__.py b/homeassistant/components/ffmpeg/__init__.py
+index 74c826f47d..91f359da2a 100644
+--- a/homeassistant/components/ffmpeg/__init__.py
++++ b/homeassistant/components/ffmpeg/__init__.py
+@@ -40,7 +40,7 @@ CONF_FFMPEG_BIN = "ffmpeg_bin"
+ CONF_EXTRA_ARGUMENTS = "extra_arguments"
+ CONF_OUTPUT = "output"
+ 
+-DEFAULT_BINARY = "ffmpeg"
++DEFAULT_BINARY = "@ffmpeg@"
+ 
+ CONFIG_SCHEMA = vol.Schema(
+     {
+diff --git a/tests/components/ffmpeg/test_init.py b/tests/components/ffmpeg/test_init.py
+index e1730ffdab..e9cd7934fd 100644
+--- a/tests/components/ffmpeg/test_init.py
++++ b/tests/components/ffmpeg/test_init.py
+@@ -87,7 +87,7 @@ class TestFFmpegSetup:
+         with assert_setup_component(1):
+             setup_component(self.hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
+ 
+-        assert self.hass.data[ffmpeg.DATA_FFMPEG].binary == "ffmpeg"
++        assert self.hass.data[ffmpeg.DATA_FFMPEG].binary == "@ffmpeg@"
+ 
+     def test_setup_component_test_service(self):
+         """Set up ffmpeg component test services."""
+diff --git a/tests/components/ffmpeg/test_sensor.py b/tests/components/ffmpeg/test_sensor.py
+index a6c9c1f441..f13091da1a 100644
+--- a/tests/components/ffmpeg/test_sensor.py
++++ b/tests/components/ffmpeg/test_sensor.py
+@@ -27,7 +27,7 @@ class TestFFmpegNoiseSetup:
+             setup_component(self.hass, "binary_sensor", self.config)
+         self.hass.block_till_done()
+ 
+-        assert self.hass.data["ffmpeg"].binary == "ffmpeg"
++        assert self.hass.data["ffmpeg"].binary == "@ffmpeg@"
+         assert self.hass.states.get("binary_sensor.ffmpeg_noise") is not None
+ 
+     @patch("haffmpeg.sensor.SensorNoise.open_sensor", return_value=mock_coro())
+@@ -37,7 +37,7 @@ class TestFFmpegNoiseSetup:
+             setup_component(self.hass, "binary_sensor", self.config)
+         self.hass.block_till_done()
+ 
+-        assert self.hass.data["ffmpeg"].binary == "ffmpeg"
++        assert self.hass.data["ffmpeg"].binary == "@ffmpeg@"
+         assert self.hass.states.get("binary_sensor.ffmpeg_noise") is not None
+ 
+         self.hass.start()
+@@ -53,7 +53,7 @@ class TestFFmpegNoiseSetup:
+             setup_component(self.hass, "binary_sensor", self.config)
+         self.hass.block_till_done()
+ 
+-        assert self.hass.data["ffmpeg"].binary == "ffmpeg"
++        assert self.hass.data["ffmpeg"].binary == "@ffmpeg@"
+         assert self.hass.states.get("binary_sensor.ffmpeg_noise") is not None
+ 
+         self.hass.start()
+@@ -89,7 +89,7 @@ class TestFFmpegMotionSetup:
+             setup_component(self.hass, "binary_sensor", self.config)
+         self.hass.block_till_done()
+ 
+-        assert self.hass.data["ffmpeg"].binary == "ffmpeg"
++        assert self.hass.data["ffmpeg"].binary == "@ffmpeg@"
+         assert self.hass.states.get("binary_sensor.ffmpeg_motion") is not None
+ 
+     @patch("haffmpeg.sensor.SensorMotion.open_sensor", return_value=mock_coro())
+@@ -99,7 +99,7 @@ class TestFFmpegMotionSetup:
+             setup_component(self.hass, "binary_sensor", self.config)
+         self.hass.block_till_done()
+ 
+-        assert self.hass.data["ffmpeg"].binary == "ffmpeg"
++        assert self.hass.data["ffmpeg"].binary == "@ffmpeg@"
+         assert self.hass.states.get("binary_sensor.ffmpeg_motion") is not None
+ 
+         self.hass.start()
+@@ -115,7 +115,7 @@ class TestFFmpegMotionSetup:
+             setup_component(self.hass, "binary_sensor", self.config)
+         self.hass.block_till_done()
+ 
+-        assert self.hass.data["ffmpeg"].binary == "ffmpeg"
++        assert self.hass.data["ffmpeg"].binary == "@ffmpeg@"
+         assert self.hass.states.get("binary_sensor.ffmpeg_motion") is not None
+ 
+         self.hass.start()
diff --git a/pkgs/servers/home-assistant/0001-tests-ignore-OSErrors-in-hass-fixture.patch b/pkgs/servers/home-assistant/patches/tests-ignore-OSErrors-in-hass-fixture.patch
index add0ea1d5521f..add0ea1d5521f 100644
--- a/pkgs/servers/home-assistant/0001-tests-ignore-OSErrors-in-hass-fixture.patch
+++ b/pkgs/servers/home-assistant/patches/tests-ignore-OSErrors-in-hass-fixture.patch
diff --git a/pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch b/pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch
new file mode 100644
index 0000000000000..4094d08ee7ff8
--- /dev/null
+++ b/pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch
@@ -0,0 +1,13 @@
+diff --git a/homeassistant/components/network/__init__.py b/homeassistant/components/network/__init__.py
+index 7cc864727d..69333a5454 100644
+--- a/homeassistant/components/network/__init__.py
++++ b/homeassistant/components/network/__init__.py
+@@ -26,7 +26,7 @@ async def async_get_source_ip(
+ ) -> str:
+     """Get the source ip for a target ip."""
+     adapters = await async_get_adapters(hass)
+-    all_ipv4s = []
++    all_ipv4s = ["127.0.0.1"]
+     for adapter in adapters:
+         if adapter["enabled"] and (ipv4s := adapter["ipv4"]):
+             all_ipv4s.extend([ipv4["address"] for ipv4 in ipv4s])
diff --git a/pkgs/servers/home-assistant/update.sh b/pkgs/servers/home-assistant/update.sh
index 8a47daf51c55c..05f2e93dfe464 100755
--- a/pkgs/servers/home-assistant/update.sh
+++ b/pkgs/servers/home-assistant/update.sh
@@ -6,7 +6,7 @@ set -eux
 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
 cd "$DIR"
 
-CURRENT_VERSION=$(nix eval --raw '(with import ../../.. {}; home-assistant.version)')
+CURRENT_VERSION=$(nix-instantiate ../../.. --eval --strict -A home-assistant.version | tr -d '"')
 TARGET_VERSION=$(curl https://api.github.com/repos/home-assistant/core/releases/latest | jq -r '.name')
 MANIFEST=$(curl https://raw.githubusercontent.com/home-assistant/core/${TARGET_VERSION}/homeassistant/components/frontend/manifest.json)
 FRONTEND_VERSION=$(echo $MANIFEST | jq -r '.requirements[] | select(startswith("home-assistant-frontend")) | sub(".*==(?<vers>.*)"; .vers)')