Skip to content

Commit a40da3a

Browse files
committed
[roborock] Fix reset of consumables (openhab#21498)
* Fix reset of consumables Signed-off-by: Paul Smedley <paul@smedley.id.au>
1 parent 4be3703 commit a40da3a

4 files changed

Lines changed: 49 additions & 23 deletions

File tree

bundles/org.openhab.binding.roborock/src/main/java/org/openhab/binding/roborock/internal/RoborockVacuumHandler.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,11 @@ public void handleCommand(ChannelUID channelUID, Command command) {
351351
return;
352352
}
353353
if (channelUID.getId().equals(CHANNEL_CONSUMABLE_RESET)) {
354-
sendRPCCommand(COMMAND_CONSUMABLES_RESET, "[" + command.toString() + "]");
354+
String consumable = command.toString();
355+
if (!"none".equals(consumable)) {
356+
consumable = consumable.replace('-', '_');
357+
sendRPCCommand(COMMAND_CONSUMABLES_RESET, gson.toJson(List.of(consumable)));
358+
}
355359
updateState(CHANNEL_CONSUMABLE_RESET, new StringType("none"));
356360
}
357361

bundles/org.openhab.binding.roborock/src/main/resources/OH-INF/i18n/roborock.properties

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,6 @@ thing-type.config.roborock.account.email.label = Email Address
1616
thing-type.config.roborock.account.email.description = email address for Roborock account
1717
thing-type.config.roborock.account.twofa.label = 2FA
1818
thing-type.config.roborock.account.twofa.description = 2FA code from email. Leave blank until code is received via email
19-
thing-type.config.roborock.vacuum.duid.label = Device ID
20-
thing-type.config.roborock.vacuum.duid.description = Specifies the vacuum's Device UID.
21-
thing-type.config.roborock.vacuum.communication.label = Communication Mode
22-
thing-type.config.roborock.vacuum.communication.description = Select cloud or direct communication transport for command routing.
23-
thing-type.config.roborock.vacuum.communication.option.cloud = Cloud
24-
thing-type.config.roborock.vacuum.communication.option.direct = Direct
25-
thing-type.config.roborock.vacuum.localHost.label = Local Host Override
26-
thing-type.config.roborock.vacuum.localHost.description = Optional local IP/hostname override used in direct mode.
27-
thing-type.config.roborock.vacuum.localPort.label = Local Port
28-
thing-type.config.roborock.vacuum.localPort.description = Local port used for direct mode communication.
2919
thing-type.config.roborock.vacuum.cloudMapRefresh.label = Cloud Map Refresh
3020
thing-type.config.roborock.vacuum.cloudMapRefresh.description = Controls cloud map retrieval while communication mode is direct.
3121
thing-type.config.roborock.vacuum.cloudMapRefresh.option.on = On
@@ -34,16 +24,26 @@ thing-type.config.roborock.vacuum.cloudMetadataRefresh.label = Cloud Metadata Re
3424
thing-type.config.roborock.vacuum.cloudMetadataRefresh.description = Controls cloud metadata refresh (routines and cloud-only metadata) while communication mode is direct.
3525
thing-type.config.roborock.vacuum.cloudMetadataRefresh.option.on = On
3626
thing-type.config.roborock.vacuum.cloudMetadataRefresh.option.off = Off
37-
thing-type.config.roborock.vacuum.refresh.label = Refresh Interval
38-
thing-type.config.roborock.vacuum.refresh.description = Legacy compatibility refresh interval in minutes. Existing Thing configurations continue to use this setting.
27+
thing-type.config.roborock.vacuum.cloudRefreshInterval.label = Cloud Refresh Interval
28+
thing-type.config.roborock.vacuum.cloudRefreshInterval.description = Specifies the refresh interval in seconds for cloud-only refresh tasks in direct mode. Falls back to Refresh Interval when unset; enforced minimum is 60 seconds.
29+
thing-type.config.roborock.vacuum.communication.label = Communication Mode
30+
thing-type.config.roborock.vacuum.communication.description = Select cloud or direct communication transport for command routing.
31+
thing-type.config.roborock.vacuum.communication.option.cloud = Cloud
32+
thing-type.config.roborock.vacuum.communication.option.direct = Direct
33+
thing-type.config.roborock.vacuum.duid.label = Device ID
34+
thing-type.config.roborock.vacuum.duid.description = Specifies the vacuum's Device UID.
3935
thing-type.config.roborock.vacuum.fastRefreshInterval.label = Fast Refresh Interval
4036
thing-type.config.roborock.vacuum.fastRefreshInterval.description = Specifies direct-mode status refresh interval in seconds while Vacuum channel is ON.
37+
thing-type.config.roborock.vacuum.localHost.label = Local Host Override
38+
thing-type.config.roborock.vacuum.localHost.description = Optional local IP/hostname override used in direct mode.
39+
thing-type.config.roborock.vacuum.localPort.label = Local Port
40+
thing-type.config.roborock.vacuum.localPort.description = Local port used for direct mode communication.
4141
thing-type.config.roborock.vacuum.mapRefreshCloudCleaningInterval.label = Map Refresh While Cleaning (Cloud Mode)
4242
thing-type.config.roborock.vacuum.mapRefreshCloudCleaningInterval.description = Specifies map refresh interval in seconds while cleaning when communication mode is cloud. Minimum value is 30 seconds.
4343
thing-type.config.roborock.vacuum.mapRefreshDirectCleaningInterval.label = Map Refresh While Cleaning (Direct Mode)
4444
thing-type.config.roborock.vacuum.mapRefreshDirectCleaningInterval.description = Specifies map refresh interval in seconds while cleaning when communication mode is direct. Minimum value is 15 seconds.
45-
thing-type.config.roborock.vacuum.cloudRefreshInterval.label = Cloud Refresh Interval
46-
thing-type.config.roborock.vacuum.cloudRefreshInterval.description = Specifies the refresh interval in seconds for cloud-only refresh tasks in direct mode. Falls back to Refresh Interval when unset; enforced minimum is 60 seconds.
45+
thing-type.config.roborock.vacuum.refresh.label = Refresh Interval
46+
thing-type.config.roborock.vacuum.refresh.description = Legacy compatibility refresh interval in minutes. Existing Thing configurations continue to use this setting.
4747

4848
# channel group types
4949

@@ -71,10 +71,10 @@ channel-type.roborock.collect-dust.description = Once the vacuum cleaner is back
7171
channel-type.roborock.commands.label = Execute Command
7272
channel-type.roborock.consumable-reset.label = Reset Consumable
7373
channel-type.roborock.consumable-reset.state.option.none = Select Consumable
74-
channel-type.roborock.consumable-reset.state.option.main-brush-work-time = Reset Mainbrush
75-
channel-type.roborock.consumable-reset.state.option.side-brush-work-time = Reset Sidebrush
76-
channel-type.roborock.consumable-reset.state.option.filter-work-time = Reset Filter
77-
channel-type.roborock.consumable-reset.state.option.sensor-dirty-time = Reset Sensors
74+
channel-type.roborock.consumable-reset.state.option.main_brush_work_time = Reset Mainbrush
75+
channel-type.roborock.consumable-reset.state.option.side_brush_work_time = Reset Sidebrush
76+
channel-type.roborock.consumable-reset.state.option.filter_work_time = Reset Filter
77+
channel-type.roborock.consumable-reset.state.option.sensor_dirty_time = Reset Sensors
7878
channel-type.roborock.control.label = Control Vacuum
7979
channel-type.roborock.control.state.option.vacuum = Vacuum
8080
channel-type.roborock.control.state.option.spot = Spot Clean
@@ -96,6 +96,8 @@ channel-type.roborock.dock-state-id.state.option.42 = Maintenance brush jammed
9696
channel-type.roborock.dock-state-id.state.option.44 = Dirty tank latch open
9797
channel-type.roborock.dock-state-id.state.option.46 = Missing dust container/dust bag
9898
channel-type.roborock.dock-state-id.state.option.53 = Cleaning tank full or blocked
99+
channel-type.roborock.dpcommand.label = Execute DP (cloud) Command
100+
channel-type.roborock.dpcommand.description = Execute a raw flat data-point payload to B01/Q10 devices. (Example payload: {"201": {"cmd": 1}})
99101
channel-type.roborock.error-code.label = Error Code
100102
channel-type.roborock.error-id.label = Error ID
101103
channel-type.roborock.fan-power.label = Fan Power
@@ -257,6 +259,13 @@ channel-type.roborock.water-box-mode.state.option.203 = High
257259
channel-type.roborock.water-box-mode.state.option.204 = Customised
258260
channel-type.roborock.water-box-status.label = Water Box State
259261

262+
# channel types
263+
264+
channel-type.roborock.consumable-reset.state.option.main-brush-work-time = Reset Mainbrush
265+
channel-type.roborock.consumable-reset.state.option.side-brush-work-time = Reset Sidebrush
266+
channel-type.roborock.consumable-reset.state.option.filter-work-time = Reset Filter
267+
channel-type.roborock.consumable-reset.state.option.sensor-dirty-time = Reset Sensors
268+
260269
# actions
261270

262271
action.download-rrmap.label = Download RR map

bundles/org.openhab.binding.roborock/src/main/resources/OH-INF/thing/thing-types.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -698,10 +698,10 @@
698698
<state>
699699
<options>
700700
<option value="none">Select Consumable</option>
701-
<option value="main-brush-work-time">Reset Mainbrush</option>
702-
<option value="side-brush-work-time">Reset Sidebrush</option>
703-
<option value="filter-work-time">Reset Filter</option>
704-
<option value="sensor-dirty-time">Reset Sensors</option>
701+
<option value="main_brush_work_time">Reset Mainbrush</option>
702+
<option value="side_brush_work_time">Reset Sidebrush</option>
703+
<option value="filter_work_time">Reset Filter</option>
704+
<option value="sensor_dirty_time">Reset Sensors</option>
705705
</options>
706706
</state>
707707
</channel-type>

bundles/org.openhab.binding.roborock/src/test/java/org/openhab/binding/roborock/internal/RoborockVacuumHandlerConsumableWriterTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ void liveStatusAndDpsHandlersRemainAuthoritativeWritersForBatteryChannel() throw
8787
"handleMessage should continue writing battery channel from live DPS updates");
8888
}
8989

90+
@Test
91+
void handleCommandFormatsConsumableResetAsJsonArrayAndNormalizesHyphens() throws IOException {
92+
String source = Files.readString(HANDLER_PATH);
93+
String handleCommandBody = extractMethodBody(source,
94+
"public void handleCommand\\(ChannelUID channelUID, Command command\\)");
95+
96+
assertTrue(handleCommandBody.contains("consumable.replace('-', '_')"),
97+
"handleCommand must normalize legacy hyphenated consumable identifiers to underscores to prevent regressions of #21461");
98+
99+
assertTrue(handleCommandBody.contains("gson.toJson(List.of("),
100+
"handleCommand must serialize the consumable reset parameter as a JSON array to prevent regressions of #21461");
101+
}
102+
90103
private static String extractMethodBody(String source, String methodSignatureRegex) {
91104
int signatureStart = source.indexOf(methodSignatureRegex.replace("\\", ""));
92105
assertTrue(signatureStart >= 0, "Method signature not found: " + methodSignatureRegex);

0 commit comments

Comments
 (0)