Skip to content

Commit c59197e

Browse files
authored
Add more spotify sensors (#129215)
1 parent 03e3c88 commit c59197e

File tree

7 files changed

+714
-5
lines changed

7 files changed

+714
-5
lines changed

homeassistant/components/spotify/icons.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,41 @@
44
"spotify": {
55
"default": "mdi:spotify"
66
}
7+
},
8+
"sensor": {
9+
"song_tempo": {
10+
"default": "mdi:metronome"
11+
},
12+
"danceability": {
13+
"default": "mdi:dance-ballroom"
14+
},
15+
"energy": {
16+
"default": "mdi:lightning-bolt"
17+
},
18+
"mode": {
19+
"default": "mdi:music"
20+
},
21+
"speechiness": {
22+
"default": "mdi:speaker-message"
23+
},
24+
"acousticness": {
25+
"default": "mdi:guitar-acoustic"
26+
},
27+
"instrumentalness": {
28+
"default": "mdi:guitar-electric"
29+
},
30+
"valence": {
31+
"default": "mdi:emoticon-happy"
32+
},
33+
"liveness": {
34+
"default": "mdi:music-note"
35+
},
36+
"time_signature": {
37+
"default": "mdi:music-clef-treble"
38+
},
39+
"key": {
40+
"default": "mdi:music-clef-treble"
41+
}
742
}
843
}
944
}

homeassistant/components/spotify/sensor.py

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55

66
from spotifyaio.models import AudioFeatures
77

8-
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
8+
from homeassistant.components.sensor import (
9+
SensorDeviceClass,
10+
SensorEntity,
11+
SensorEntityDescription,
12+
)
13+
from homeassistant.const import PERCENTAGE
914
from homeassistant.core import HomeAssistant
1015
from homeassistant.helpers.entity_platform import AddEntitiesCallback
1116

@@ -17,7 +22,17 @@
1722
class SpotifyAudioFeaturesSensorEntityDescription(SensorEntityDescription):
1823
"""Describes Spotify sensor entity."""
1924

20-
value_fn: Callable[[AudioFeatures], float]
25+
value_fn: Callable[[AudioFeatures], float | str | None]
26+
27+
28+
def _get_key(audio_features: AudioFeatures) -> str | None:
29+
if audio_features.key is None:
30+
return None
31+
key_name = audio_features.key.name
32+
base = key_name[0]
33+
if len(key_name) > 1:
34+
base = f"{base}♯"
35+
return base
2136

2237

2338
AUDIO_FEATURE_SENSORS: tuple[SpotifyAudioFeaturesSensorEntityDescription, ...] = (
@@ -28,6 +43,86 @@ class SpotifyAudioFeaturesSensorEntityDescription(SensorEntityDescription):
2843
suggested_display_precision=0,
2944
value_fn=lambda audio_features: audio_features.tempo,
3045
),
46+
SpotifyAudioFeaturesSensorEntityDescription(
47+
key="danceability",
48+
translation_key="danceability",
49+
native_unit_of_measurement=PERCENTAGE,
50+
suggested_display_precision=0,
51+
value_fn=lambda audio_features: audio_features.danceability * 100,
52+
entity_registry_enabled_default=False,
53+
),
54+
SpotifyAudioFeaturesSensorEntityDescription(
55+
key="energy",
56+
translation_key="energy",
57+
native_unit_of_measurement=PERCENTAGE,
58+
suggested_display_precision=0,
59+
value_fn=lambda audio_features: audio_features.energy * 100,
60+
entity_registry_enabled_default=False,
61+
),
62+
SpotifyAudioFeaturesSensorEntityDescription(
63+
key="mode",
64+
translation_key="mode",
65+
device_class=SensorDeviceClass.ENUM,
66+
options=["major", "minor"],
67+
value_fn=lambda audio_features: audio_features.mode.name.lower(),
68+
entity_registry_enabled_default=False,
69+
),
70+
SpotifyAudioFeaturesSensorEntityDescription(
71+
key="speechiness",
72+
translation_key="speechiness",
73+
native_unit_of_measurement=PERCENTAGE,
74+
suggested_display_precision=0,
75+
value_fn=lambda audio_features: audio_features.speechiness * 100,
76+
entity_registry_enabled_default=False,
77+
),
78+
SpotifyAudioFeaturesSensorEntityDescription(
79+
key="acousticness",
80+
translation_key="acousticness",
81+
native_unit_of_measurement=PERCENTAGE,
82+
suggested_display_precision=0,
83+
value_fn=lambda audio_features: audio_features.acousticness * 100,
84+
entity_registry_enabled_default=False,
85+
),
86+
SpotifyAudioFeaturesSensorEntityDescription(
87+
key="instrumentalness",
88+
translation_key="instrumentalness",
89+
native_unit_of_measurement=PERCENTAGE,
90+
suggested_display_precision=0,
91+
value_fn=lambda audio_features: audio_features.instrumentalness * 100,
92+
entity_registry_enabled_default=False,
93+
),
94+
SpotifyAudioFeaturesSensorEntityDescription(
95+
key="liveness",
96+
translation_key="liveness",
97+
native_unit_of_measurement=PERCENTAGE,
98+
suggested_display_precision=0,
99+
value_fn=lambda audio_features: audio_features.liveness * 100,
100+
entity_registry_enabled_default=False,
101+
),
102+
SpotifyAudioFeaturesSensorEntityDescription(
103+
key="valence",
104+
translation_key="valence",
105+
native_unit_of_measurement=PERCENTAGE,
106+
suggested_display_precision=0,
107+
value_fn=lambda audio_features: audio_features.valence * 100,
108+
entity_registry_enabled_default=False,
109+
),
110+
SpotifyAudioFeaturesSensorEntityDescription(
111+
key="time_signature",
112+
translation_key="time_signature",
113+
device_class=SensorDeviceClass.ENUM,
114+
options=["3/4", "4/4", "5/4", "6/4", "7/4"],
115+
value_fn=lambda audio_features: f"{audio_features.time_signature}/4",
116+
entity_registry_enabled_default=False,
117+
),
118+
SpotifyAudioFeaturesSensorEntityDescription(
119+
key="key",
120+
translation_key="key",
121+
device_class=SensorDeviceClass.ENUM,
122+
options=["C", "C♯", "D", "D♯", "E", "F", "F♯", "G", "G♯", "A", "A♯", "B"],
123+
value_fn=_get_key,
124+
entity_registry_enabled_default=False,
125+
),
31126
)
32127

33128

@@ -63,7 +158,7 @@ def __init__(
63158
self.entity_description = entity_description
64159

65160
@property
66-
def native_value(self) -> float | None:
161+
def native_value(self) -> float | str | None:
67162
"""Return the state of the sensor."""
68163
if (audio_features := self.coordinator.data.audio_features) is None:
69164
return None

homeassistant/components/spotify/strings.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,40 @@
3535
"sensor": {
3636
"song_tempo": {
3737
"name": "Song tempo"
38+
},
39+
"danceability": {
40+
"name": "Song danceability"
41+
},
42+
"energy": {
43+
"name": "Song energy"
44+
},
45+
"mode": {
46+
"name": "Song mode",
47+
"state": {
48+
"minor": "Minor",
49+
"major": "Major"
50+
}
51+
},
52+
"speechiness": {
53+
"name": "Song speechiness"
54+
},
55+
"acousticness": {
56+
"name": "Song acousticness"
57+
},
58+
"instrumentalness": {
59+
"name": "Song instrumentalness"
60+
},
61+
"valence": {
62+
"name": "Song valence"
63+
},
64+
"liveness": {
65+
"name": "Song liveness"
66+
},
67+
"time_signature": {
68+
"name": "Song time signature"
69+
},
70+
"key": {
71+
"name": "Song key"
3872
}
3973
}
4074
}

tests/components/spotify/fixtures/audio_features.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"danceability": 0.696,
33
"energy": 0.905,
4-
"key": 2,
4+
"key": 3,
55
"loudness": -2.743,
66
"mode": 1,
77
"speechiness": 0.103,

tests/components/spotify/snapshots/test_diagnostics.ambr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
'danceability': 0.696,
2020
'energy': 0.905,
2121
'instrumentalness': 0.000905,
22-
'key': 2,
22+
'key': 3,
2323
'liveness': 0.302,
2424
'loudness': -2.743,
2525
'mode': 1,

0 commit comments

Comments
 (0)