Commit ·
5f89e0d
1
Parent(s): be4ed94
v0.2.4: Fix microphone volume control - Use daemon HTTP API (/api/volume/microphone/set) instead of ReSpeaker DSP parameters - This matches the official implementation using amixer commands
Browse files- pyproject.toml +1 -1
- reachy_mini_ha_voice/__init__.py +1 -1
- reachy_mini_ha_voice/reachy_controller.py +45 -40
pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
| 4 |
|
| 5 |
[project]
|
| 6 |
name = "reachy_mini_ha_voice"
|
| 7 |
-
version = "0.2.
|
| 8 |
description = "Home Assistant Voice Assistant for Reachy Mini"
|
| 9 |
readme = "README.md"
|
| 10 |
requires-python = ">=3.10"
|
|
|
|
| 4 |
|
| 5 |
[project]
|
| 6 |
name = "reachy_mini_ha_voice"
|
| 7 |
+
version = "0.2.4"
|
| 8 |
description = "Home Assistant Voice Assistant for Reachy Mini"
|
| 9 |
readme = "README.md"
|
| 10 |
requires-python = ">=3.10"
|
reachy_mini_ha_voice/__init__.py
CHANGED
|
@@ -11,7 +11,7 @@ Key features:
|
|
| 11 |
- Reachy Mini motion control integration
|
| 12 |
"""
|
| 13 |
|
| 14 |
-
__version__ = "0.2.
|
| 15 |
__author__ = "Desmond Dong"
|
| 16 |
|
| 17 |
# Don't import main module here to avoid runpy warning
|
|
|
|
| 11 |
- Reachy Mini motion control integration
|
| 12 |
"""
|
| 13 |
|
| 14 |
+
__version__ = "0.2.4"
|
| 15 |
__author__ = "Desmond Dong"
|
| 16 |
|
| 17 |
# Don't import main module here to avoid runpy warning
|
reachy_mini_ha_voice/reachy_controller.py
CHANGED
|
@@ -137,32 +137,34 @@ class ReachyController:
|
|
| 137 |
logger.error(f"Error setting speaker volume: {e}")
|
| 138 |
|
| 139 |
def get_microphone_volume(self) -> float:
|
| 140 |
-
"""Get microphone volume (0-100) using
|
| 141 |
-
|
| 142 |
-
if respeaker is None:
|
| 143 |
return getattr(self, '_microphone_volume', 50.0)
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
|
|
|
|
|
|
|
|
|
| 161 |
return getattr(self, '_microphone_volume', 50.0)
|
| 162 |
|
| 163 |
def set_microphone_volume(self, volume: float) -> None:
|
| 164 |
"""
|
| 165 |
-
Set microphone volume (0-100) using
|
| 166 |
|
| 167 |
Args:
|
| 168 |
volume: Volume level 0-100
|
|
@@ -170,27 +172,30 @@ class ReachyController:
|
|
| 170 |
volume = max(0.0, min(100.0, volume))
|
| 171 |
self._microphone_volume = volume
|
| 172 |
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
logger.warning("Cannot set microphone volume: ReSpeaker not available")
|
| 176 |
return
|
| 177 |
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
|
| 195 |
# ========== Phase 2: Motor Control ==========
|
| 196 |
|
|
|
|
| 137 |
logger.error(f"Error setting speaker volume: {e}")
|
| 138 |
|
| 139 |
def get_microphone_volume(self) -> float:
|
| 140 |
+
"""Get microphone volume (0-100) using daemon HTTP API."""
|
| 141 |
+
if not self.is_available:
|
|
|
|
| 142 |
return getattr(self, '_microphone_volume', 50.0)
|
| 143 |
+
|
| 144 |
+
try:
|
| 145 |
+
# Get WLAN IP from cached daemon status
|
| 146 |
+
status = self._get_cached_status()
|
| 147 |
+
if status is None:
|
| 148 |
+
return getattr(self, '_microphone_volume', 50.0)
|
| 149 |
+
wlan_ip = status.get('wlan_ip', 'localhost')
|
| 150 |
+
|
| 151 |
+
# Call the daemon API to get microphone volume
|
| 152 |
+
response = requests.get(
|
| 153 |
+
f"http://{wlan_ip}:8000/api/volume/microphone/current",
|
| 154 |
+
timeout=2
|
| 155 |
+
)
|
| 156 |
+
if response.status_code == 200:
|
| 157 |
+
data = response.json()
|
| 158 |
+
self._microphone_volume = float(data.get('volume', 50))
|
| 159 |
+
return self._microphone_volume
|
| 160 |
+
except Exception as e:
|
| 161 |
+
logger.debug(f"Could not get microphone volume from API: {e}")
|
| 162 |
+
|
| 163 |
return getattr(self, '_microphone_volume', 50.0)
|
| 164 |
|
| 165 |
def set_microphone_volume(self, volume: float) -> None:
|
| 166 |
"""
|
| 167 |
+
Set microphone volume (0-100) using daemon HTTP API.
|
| 168 |
|
| 169 |
Args:
|
| 170 |
volume: Volume level 0-100
|
|
|
|
| 172 |
volume = max(0.0, min(100.0, volume))
|
| 173 |
self._microphone_volume = volume
|
| 174 |
|
| 175 |
+
if not self.is_available:
|
| 176 |
+
logger.warning("Cannot set microphone volume: robot not available")
|
|
|
|
| 177 |
return
|
| 178 |
|
| 179 |
+
try:
|
| 180 |
+
# Get WLAN IP from cached daemon status
|
| 181 |
+
status = self._get_cached_status()
|
| 182 |
+
if status is None:
|
| 183 |
+
logger.error("Cannot get daemon status for microphone volume control")
|
| 184 |
+
return
|
| 185 |
+
wlan_ip = status.get('wlan_ip', 'localhost')
|
| 186 |
+
|
| 187 |
+
# Call the daemon API to set microphone volume
|
| 188 |
+
response = requests.post(
|
| 189 |
+
f"http://{wlan_ip}:8000/api/volume/microphone/set",
|
| 190 |
+
json={"volume": int(volume)},
|
| 191 |
+
timeout=5
|
| 192 |
+
)
|
| 193 |
+
if response.status_code == 200:
|
| 194 |
+
logger.info(f"Microphone volume set to {volume}%")
|
| 195 |
+
else:
|
| 196 |
+
logger.error(f"Failed to set microphone volume: {response.status_code} {response.text}")
|
| 197 |
+
except Exception as e:
|
| 198 |
+
logger.error(f"Error setting microphone volume: {e}")
|
| 199 |
|
| 200 |
# ========== Phase 2: Motor Control ==========
|
| 201 |
|