Desmond-Dong commited on
Commit
a88f884
·
1 Parent(s): cd59e9e

v0.2.17: Remove head_joints/passive_joints, move error_message to diagnostic

Browse files

- Remove Phase 13-14 entities (head_joints, passive_joints)
- Remove get_head_joints_json() and get_passive_joints_json() from reachy_controller
- Move error_message from Phase 1 to Phase 6 (Diagnostic)
- Add entity_category=2 (diagnostic) to all Phase 6 entities

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.16"
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.17"
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.16"
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.17"
15
  __author__ = "Desmond Dong"
16
 
17
  # Don't import main module here to avoid runpy warning
reachy_mini_ha_voice/entity_registry.py CHANGED
@@ -25,7 +25,6 @@ ENTITY_KEYS: Dict[str, int] = {
25
  # Phase 1: Basic status and volume
26
  "daemon_state": 100,
27
  "backend_ready": 101,
28
- "error_message": 102,
29
  "speaker_volume": 103,
30
  # Phase 2: Motor control
31
  "motors_enabled": 200,
@@ -53,6 +52,7 @@ ENTITY_KEYS: Dict[str, int] = {
53
  "wireless_version": 603,
54
  "simulation_mode": 604,
55
  "wlan_ip": 605,
 
56
  # Phase 7: IMU sensors
57
  "imu_accel_x": 700,
58
  "imu_accel_y": 701,
@@ -79,10 +79,6 @@ ENTITY_KEYS: Dict[str, int] = {
79
  "agc_max_gain": 1201,
80
  "noise_suppression": 1202,
81
  "echo_cancellation_converged": 1203,
82
- # Phase 13: Robot joints (single JSON sensor)
83
- "head_joints": 1300,
84
- # Phase 14: Passive joints for 3D visualization
85
- "passive_joints": 1400,
86
  }
87
 
88
 
@@ -148,7 +144,7 @@ class EntityRegistry:
148
  self._setup_phase10_entities(entities)
149
  # Phase 11 (LED control) disabled - LEDs are inside the robot and not visible
150
  self._setup_phase12_entities(entities)
151
- self._setup_phase13_entities(entities)
152
 
153
  _LOGGER.info("All entities registered: %d total", len(entities))
154
 
@@ -175,15 +171,6 @@ class EntityRegistry:
175
  value_getter=rc.get_backend_ready,
176
  ))
177
 
178
- entities.append(TextSensorEntity(
179
- server=self.server,
180
- key=get_entity_key("error_message"),
181
- name="Error Message",
182
- object_id="error_message",
183
- icon="mdi:alert-circle",
184
- value_getter=rc.get_error_message,
185
- ))
186
-
187
  entities.append(NumberEntity(
188
  server=self.server,
189
  key=get_entity_key("speaker_volume"),
@@ -200,7 +187,7 @@ class EntityRegistry:
200
  value_setter=rc.set_speaker_volume,
201
  ))
202
 
203
- _LOGGER.debug("Phase 1 entities registered: daemon_state, backend_ready, error_message, speaker_volume")
204
 
205
  def _setup_phase2_entities(self, entities: List) -> None:
206
  """Setup Phase 2 entities: Motor control."""
@@ -448,6 +435,7 @@ class EntityRegistry:
448
  unit_of_measurement="Hz",
449
  accuracy_decimals=1,
450
  state_class="measurement",
 
451
  value_getter=rc.get_control_loop_frequency,
452
  ))
453
 
@@ -457,6 +445,7 @@ class EntityRegistry:
457
  name="SDK Version",
458
  object_id="sdk_version",
459
  icon="mdi:information",
 
460
  value_getter=rc.get_sdk_version,
461
  ))
462
 
@@ -466,6 +455,7 @@ class EntityRegistry:
466
  name="Robot Name",
467
  object_id="robot_name",
468
  icon="mdi:robot",
 
469
  value_getter=rc.get_robot_name,
470
  ))
471
 
@@ -476,6 +466,7 @@ class EntityRegistry:
476
  object_id="wireless_version",
477
  icon="mdi:wifi",
478
  device_class="connectivity",
 
479
  value_getter=rc.get_wireless_version,
480
  ))
481
 
@@ -485,6 +476,7 @@ class EntityRegistry:
485
  name="Simulation Mode",
486
  object_id="simulation_mode",
487
  icon="mdi:virtual-reality",
 
488
  value_getter=rc.get_simulation_mode,
489
  ))
490
 
@@ -494,10 +486,21 @@ class EntityRegistry:
494
  name="WLAN IP",
495
  object_id="wlan_ip",
496
  icon="mdi:ip-network",
 
497
  value_getter=rc.get_wlan_ip,
498
  ))
499
 
500
- _LOGGER.debug("Phase 6 entities registered: control_loop_frequency, sdk_version, robot_name, wireless_version, simulation_mode, wlan_ip")
 
 
 
 
 
 
 
 
 
 
501
 
502
  def _setup_phase7_entities(self, entities: List) -> None:
503
  """Setup Phase 7 entities: IMU sensors (wireless only)."""
@@ -723,32 +726,6 @@ class EntityRegistry:
723
 
724
  _LOGGER.debug("Phase 12 entities registered: agc_enabled, agc_max_gain, noise_suppression, echo_cancellation_converged")
725
 
726
- def _setup_phase13_entities(self, entities: List) -> None:
727
- """Setup Phase 13 entities: Robot joints as JSON sensor."""
728
- rc = self.reachy_controller
729
-
730
- entities.append(TextSensorEntity(
731
- server=self.server,
732
- key=get_entity_key("head_joints"),
733
- name="Head Joints",
734
- object_id="head_joints",
735
- icon="mdi:robot",
736
- value_getter=rc.get_head_joints_json,
737
- ))
738
-
739
- _LOGGER.debug("Phase 13 entities registered: head_joints")
740
-
741
- # Phase 14: Passive joints for 3D visualization
742
- entities.append(TextSensorEntity(
743
- server=self.server,
744
- key=get_entity_key("passive_joints"),
745
- name="Passive Joints",
746
- object_id="passive_joints",
747
- value_getter=rc.get_passive_joints_json,
748
- ))
749
-
750
- _LOGGER.debug("Phase 14 entities registered: passive_joints")
751
-
752
  def find_entity_references(self, entities: List) -> None:
753
  """Find and store references to special entities from existing list.
754
 
 
25
  # Phase 1: Basic status and volume
26
  "daemon_state": 100,
27
  "backend_ready": 101,
 
28
  "speaker_volume": 103,
29
  # Phase 2: Motor control
30
  "motors_enabled": 200,
 
52
  "wireless_version": 603,
53
  "simulation_mode": 604,
54
  "wlan_ip": 605,
55
+ "error_message": 606, # Moved to diagnostic
56
  # Phase 7: IMU sensors
57
  "imu_accel_x": 700,
58
  "imu_accel_y": 701,
 
79
  "agc_max_gain": 1201,
80
  "noise_suppression": 1202,
81
  "echo_cancellation_converged": 1203,
 
 
 
 
82
  }
83
 
84
 
 
144
  self._setup_phase10_entities(entities)
145
  # Phase 11 (LED control) disabled - LEDs are inside the robot and not visible
146
  self._setup_phase12_entities(entities)
147
+ # Phase 13-14 (head_joints, passive_joints) removed - not needed
148
 
149
  _LOGGER.info("All entities registered: %d total", len(entities))
150
 
 
171
  value_getter=rc.get_backend_ready,
172
  ))
173
 
 
 
 
 
 
 
 
 
 
174
  entities.append(NumberEntity(
175
  server=self.server,
176
  key=get_entity_key("speaker_volume"),
 
187
  value_setter=rc.set_speaker_volume,
188
  ))
189
 
190
+ _LOGGER.debug("Phase 1 entities registered: daemon_state, backend_ready, speaker_volume")
191
 
192
  def _setup_phase2_entities(self, entities: List) -> None:
193
  """Setup Phase 2 entities: Motor control."""
 
435
  unit_of_measurement="Hz",
436
  accuracy_decimals=1,
437
  state_class="measurement",
438
+ entity_category=2, # diagnostic
439
  value_getter=rc.get_control_loop_frequency,
440
  ))
441
 
 
445
  name="SDK Version",
446
  object_id="sdk_version",
447
  icon="mdi:information",
448
+ entity_category=2, # diagnostic
449
  value_getter=rc.get_sdk_version,
450
  ))
451
 
 
455
  name="Robot Name",
456
  object_id="robot_name",
457
  icon="mdi:robot",
458
+ entity_category=2, # diagnostic
459
  value_getter=rc.get_robot_name,
460
  ))
461
 
 
466
  object_id="wireless_version",
467
  icon="mdi:wifi",
468
  device_class="connectivity",
469
+ entity_category=2, # diagnostic
470
  value_getter=rc.get_wireless_version,
471
  ))
472
 
 
476
  name="Simulation Mode",
477
  object_id="simulation_mode",
478
  icon="mdi:virtual-reality",
479
+ entity_category=2, # diagnostic
480
  value_getter=rc.get_simulation_mode,
481
  ))
482
 
 
486
  name="WLAN IP",
487
  object_id="wlan_ip",
488
  icon="mdi:ip-network",
489
+ entity_category=2, # diagnostic
490
  value_getter=rc.get_wlan_ip,
491
  ))
492
 
493
+ entities.append(TextSensorEntity(
494
+ server=self.server,
495
+ key=get_entity_key("error_message"),
496
+ name="Error Message",
497
+ object_id="error_message",
498
+ icon="mdi:alert-circle",
499
+ entity_category=2, # diagnostic
500
+ value_getter=rc.get_error_message,
501
+ ))
502
+
503
+ _LOGGER.debug("Phase 6 entities registered: control_loop_frequency, sdk_version, robot_name, wireless_version, simulation_mode, wlan_ip, error_message")
504
 
505
  def _setup_phase7_entities(self, entities: List) -> None:
506
  """Setup Phase 7 entities: IMU sensors (wireless only)."""
 
726
 
727
  _LOGGER.debug("Phase 12 entities registered: agc_enabled, agc_max_gain, noise_suppression, echo_cancellation_converged")
728
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
729
  def find_entity_references(self, entities: List) -> None:
730
  """Find and store references to special entities from existing list.
731
 
reachy_mini_ha_voice/reachy_controller.py CHANGED
@@ -1120,57 +1120,3 @@ class ReachyController:
1120
  except Exception as e:
1121
  logger.debug(f"Error getting AEC converged status: {e}")
1122
  return False
1123
-
1124
- # ========== Phase 13: Robot Joints ==========
1125
-
1126
- def get_head_joints_json(self) -> str:
1127
- """
1128
- Get head joints as JSON string.
1129
-
1130
- Returns:
1131
- JSON string: "[yaw_body, stewart_1, stewart_2, stewart_3, stewart_4, stewart_5, stewart_6]"
1132
- Values in radians
1133
- """
1134
- if not self.is_available:
1135
- return "[]"
1136
- try:
1137
- import json
1138
- head_joints, _ = self.reachy.get_current_joint_positions()
1139
- if head_joints and len(head_joints) >= 7:
1140
- # Convert radians to list
1141
- joints_list = [float(j) for j in head_joints[:7]]
1142
- return json.dumps(joints_list)
1143
- return "[]"
1144
- except Exception as e:
1145
- logger.error(f"Error getting head joints JSON: {e}")
1146
- return "[]"
1147
-
1148
- def get_passive_joints_json(self) -> str:
1149
- """
1150
- Get passive joints as JSON string with cached status.
1151
-
1152
- Returns:
1153
- JSON string: "[passive_1_x, passive_1_y, passive_1_z, ..., passive_7_z]"
1154
- Values in radians (21 values total)
1155
- """
1156
- if not self.is_available:
1157
- return "[]"
1158
- try:
1159
- import json
1160
- # Get WLAN IP from cached daemon status
1161
- status = self._get_cached_status()
1162
- if status is None:
1163
- return "[]"
1164
- wlan_ip = status.get('wlan_ip', 'localhost')
1165
- # Call the backend API to get passive joints
1166
- backend_url = f"http://{wlan_ip}:8000/api/state/full?with_passive_joints=true"
1167
- response = requests.get(backend_url, timeout=0.5)
1168
- if response.status_code == 200:
1169
- data = response.json()
1170
- passive_joints = data.get("passive_joints")
1171
- if passive_joints and len(passive_joints) >= 21:
1172
- return json.dumps(passive_joints)
1173
- return "[]"
1174
- except Exception as e:
1175
- logger.error(f"Error getting passive joints JSON: {e}")
1176
- return "[]"
 
1120
  except Exception as e:
1121
  logger.debug(f"Error getting AEC converged status: {e}")
1122
  return False