feat(socket): update smart socket defaults #12

Merged
KremeCN merged 1 commits from feat/update-smart-socket into main 2026-08-28 07:07:22 +08:00
7 changed files with 16 additions and 55 deletions
@@ -49,7 +49,7 @@ class ABoxDefaultContentInitializer @Inject constructor(
is DomainResult.Failure -> return false
}
val defaults = listOf(
DeviceName("Zigbee插座控制器") to DeviceType.SOCKET,
DeviceName("智能插座") to DeviceType.SOCKET,
DeviceName("温湿度传感器") to DeviceType.TEMPERATURE_HUMIDITY,
DeviceName("红外控制器") to DeviceType.INFRARED,
)
@@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
@@ -24,7 +23,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
@@ -208,42 +206,11 @@ fun SocketScreen(
}
}
Text(
text = stringResource(R.string.socket_direct_control),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp),
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
OutlinedButton(
onClick = { onEvent(SocketUiEvent.SetPower(SocketPowerState.ON)) },
enabled = state.isActionEnabled && state.powerState != SocketPowerState.ON,
modifier = Modifier.weight(1f).height(56.dp),
) {
ABoxIcon(ABoxIconKey.POWER, "开启插座", modifier = Modifier.size(20.dp))
Spacer(Modifier.width(8.dp))
Text(stringResource(R.string.socket_action_turn_on))
}
OutlinedButton(
onClick = { onEvent(SocketUiEvent.SetPower(SocketPowerState.OFF)) },
enabled = state.isActionEnabled && state.powerState != SocketPowerState.OFF,
modifier = Modifier.weight(1f).height(56.dp),
) {
ABoxIcon(ABoxIconKey.POWER, "关闭插座", modifier = Modifier.size(20.dp))
Spacer(Modifier.width(8.dp))
Text(stringResource(R.string.socket_action_turn_off))
}
}
Text(
text = stringResource(R.string.socket_confirmation_hint),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.fillMaxWidth().padding(top = 14.dp),
modifier = Modifier.fillMaxWidth(),
)
}
}
@@ -223,8 +223,6 @@
<string name="socket_status_offline">已离线</string>
<string name="socket_status_unknown">未知状态</string>
<string name="socket_action_toggle">切换电源</string>
<string name="socket_action_turn_on">开启插座</string>
<string name="socket_action_turn_off">关闭插座</string>
<string name="socket_operating_label">正在切换状态…</string>
<string name="socket_confirmed_at">已于 %1$s 确认状态</string>
@@ -361,7 +359,6 @@
<string name="gateway_device_name_socket_desc">用于匹配和控制网关设备,必须与网关中的名称完全一致。</string>
<string name="gateway_device_name_sensor_desc">用于匹配和读取网关设备,必须与网关中的名称完全一致。</string>
<string name="action_save_device_name">保存设备名称</string>
<string name="socket_direct_control">直接控制</string>
<string name="socket_confirmation_hint">指令只有在网关回读到结果状态后才会确认。等待确认时可使用刷新操作。</string>
<string name="sensor_current_readings">当前读数</string>
<string name="sensor_monitoring_title">实时环境监控</string>
@@ -223,8 +223,6 @@
<string name="socket_status_offline">Offline</string>
<string name="socket_status_unknown">Unknown</string>
<string name="socket_action_toggle">Toggle Power</string>
<string name="socket_action_turn_on">Turn ON</string>
<string name="socket_action_turn_off">Turn OFF</string>
<string name="socket_operating_label">Updating socket state…</string>
<string name="socket_confirmed_at">Confirmed at %1$s</string>
@@ -361,7 +359,6 @@
<string name="gateway_device_name_socket_desc">Used to match and control the gateway device. It must exactly match the gateway name.</string>
<string name="gateway_device_name_sensor_desc">Used to match and read the gateway device. It must exactly match the gateway name.</string>
<string name="action_save_device_name">Save device name</string>
<string name="socket_direct_control">Direct control</string>
<string name="socket_confirmation_hint">A command is confirmed only after the gateway reports the resulting state. Refresh while confirmation is pending.</string>
<string name="sensor_current_readings">Current readings</string>
<string name="sensor_monitoring_title">Live environment monitoring</string>
@@ -99,14 +99,14 @@ class RoomSceneRepository(
private fun defaultScenes(profileId: ProviderProfileId): List<Scene> = listOf(
Scene(
SceneId("${profileId.value}:scene-arriving-home"), profileId, "回家模式", "开启 Zigbee 插座控制器",
SceneId("${profileId.value}:scene-arriving-home"), profileId, "回家模式", "开启智能插座",
AutomationType.MANUAL, true, SceneIcon.HOME, SceneColor("#4CAF50"),
actions = listOf(SceneAction.SocketPower(SceneActionId("${profileId.value}:arrive:socket"), profileId, DeviceName("Zigbee插座控制器"), SocketPowerState.ON)),
actions = listOf(SceneAction.SocketPower(SceneActionId("${profileId.value}:arrive:socket"), profileId, DeviceName("智能插座"), SocketPowerState.ON)),
),
Scene(
SceneId("${profileId.value}:scene-leaving-home"), profileId, "离家模式", "关闭 Zigbee 插座控制器",
SceneId("${profileId.value}:scene-leaving-home"), profileId, "离家模式", "关闭智能插座",
AutomationType.MANUAL, true, SceneIcon.AWAY, SceneColor("#FF8A65"),
actions = listOf(SceneAction.SocketPower(SceneActionId("${profileId.value}:leave:socket"), profileId, DeviceName("Zigbee插座控制器"), SocketPowerState.OFF)),
actions = listOf(SceneAction.SocketPower(SceneActionId("${profileId.value}:leave:socket"), profileId, DeviceName("智能插座"), SocketPowerState.OFF)),
),
Scene(
SceneId("${profileId.value}:scene-temperature-alert"), profileId, "高温提醒", "室温高于 28°C 时发送提醒",
@@ -118,8 +118,8 @@ class RoomSceneRepository(
SceneId("${profileId.value}:scene-cooling-auto"), profileId, "高温自动降温", "当室温高于 28°C 时开启插座",
AutomationType.AUTOMATIC, true, SceneIcon.THERMOSTAT, SceneColor("#26A69A"),
triggers = listOf(SceneTrigger.Temperature(SceneTriggerId("${profileId.value}:cooling-temp"), DeviceName("温湿度传感器"), ComparisonOperator.GREATER_THAN, 28.0, "温度高于 28°C")),
conditions = listOf(SceneCondition.SocketPower(SceneConditionId("${profileId.value}:cooling-socket"), DeviceName("Zigbee插座控制器"), SocketPowerState.OFF)),
actions = listOf(SceneAction.SocketPower(SceneActionId("${profileId.value}:cooling:on"), profileId, DeviceName("Zigbee插座控制器"), SocketPowerState.ON)),
conditions = listOf(SceneCondition.SocketPower(SceneConditionId("${profileId.value}:cooling-socket"), DeviceName("智能插座"), SocketPowerState.OFF)),
actions = listOf(SceneAction.SocketPower(SceneActionId("${profileId.value}:cooling:on"), profileId, DeviceName("智能插座"), SocketPowerState.ON)),
),
)
}
@@ -111,7 +111,7 @@ class InMemorySceneRepository : SceneRepository {
id = SceneId("${profileId.value}:scene-arriving-home"),
profileId = profileId,
name = "回家模式",
description = "开启 Zigbee 插座控制器",
description = "开启智能插座",
type = AutomationType.MANUAL,
enabled = true,
icon = SceneIcon.HOME,
@@ -120,7 +120,7 @@ class InMemorySceneRepository : SceneRepository {
SceneAction.SocketPower(
id = SceneActionId("${profileId.value}:scene-arriving-home:socket-1"),
profileId = profileId,
deviceName = DeviceName("Zigbee插座控制器"),
deviceName = DeviceName("智能插座"),
powerState = SocketPowerState.ON,
),
),
@@ -129,7 +129,7 @@ class InMemorySceneRepository : SceneRepository {
id = SceneId("${profileId.value}:scene-leaving-home"),
profileId = profileId,
name = "离家模式",
description = "关闭 Zigbee 插座控制器",
description = "关闭智能插座",
type = AutomationType.MANUAL,
enabled = true,
icon = SceneIcon.AWAY,
@@ -138,7 +138,7 @@ class InMemorySceneRepository : SceneRepository {
SceneAction.SocketPower(
id = SceneActionId("${profileId.value}:scene-leaving-home:socket-1"),
profileId = profileId,
deviceName = DeviceName("Zigbee插座控制器"),
deviceName = DeviceName("智能插座"),
powerState = SocketPowerState.OFF,
),
),
@@ -191,7 +191,7 @@ class InMemorySceneRepository : SceneRepository {
conditions = listOf(
SceneCondition.SocketPower(
id = SceneConditionId("${profileId.value}:cond-cooling-socket"),
deviceName = DeviceName("Zigbee插座控制器"),
deviceName = DeviceName("智能插座"),
expectedState = SocketPowerState.OFF,
),
),
@@ -199,7 +199,7 @@ class InMemorySceneRepository : SceneRepository {
SceneAction.SocketPower(
id = SceneActionId("${profileId.value}:scene-cooling:socket-1"),
profileId = profileId,
deviceName = DeviceName("Zigbee插座控制器"),
deviceName = DeviceName("智能插座"),
powerState = SocketPowerState.ON,
),
),
@@ -29,9 +29,9 @@ class SimulationDeviceCatalog : DeviceCatalog {
private fun defaultDevices(profileId: ProviderProfileId): List<DeviceDescriptor> = listOf(
DeviceDescriptor(
id = DeviceId("${profileId.value}:Zigbee插座控制器"),
KremeCN marked this conversation as resolved
Review

场景失效

本地体验的设备目录在进程重建后只会生成名为 智能插座 的设备,但已有持久化场景不会迁移,仍通过 DeviceName("Zigbee插座控制器") 定位设备。用户升级并重启后,原有回家、离家及高温降温场景将无法匹配模拟插座。需要迁移旧场景,或为模拟设备保留旧名称的兼容映射。

**场景失效** 本地体验的设备目录在进程重建后只会生成名为 `智能插座` 的设备,但已有持久化场景不会迁移,仍通过 `DeviceName("Zigbee插座控制器")` 定位设备。用户升级并重启后,原有回家、离家及高温降温场景将无法匹配模拟插座。需要迁移旧场景,或为模拟设备保留旧名称的兼容映射。 <!-- pr-agent-dedup: d017d6d80c2d --> <!-- pr-agent-key-issue-location: abe40af512a4 -->
Review

预期行为

预期行为
id = DeviceId("${profileId.value}:智能插座"),
profileId = profileId,
name = DeviceName("Zigbee插座控制器"),
name = DeviceName("智能插座"),
type = DeviceType.SOCKET,
),
DeviceDescriptor(