Gson gson) throws DataParsingException {
if (response instanceof PortalIotCommandJsonResponse jsonResponse) {
ErrorReport resp = jsonResponse.getResponsePayloadAs(gson, ErrorReport.class);
- if (resp.errorCodes.isEmpty()) {
- return Optional.empty();
- }
- return Optional.of(resp.errorCodes.get(0));
+ int responseCode = resp.errorCodes.isEmpty() ? 0 : resp.errorCodes.get(0);
+ return Optional.of(responseCode);
} else {
String payload = ((PortalIotCommandXmlResponse) response).getResponsePayloadXml();
return DeviceInfo.parseErrorInfo(payload);
*/
@NonNullByDefault
public class SpotAreaCleaningCommand extends AbstractAreaCleaningCommand {
- public SpotAreaCleaningCommand(List<String> roomIds, int cleanPasses) {
- super("spotArea", String.join(",", roomIds), cleanPasses);
+ public SpotAreaCleaningCommand(List<String> roomIds, int cleanPasses, boolean usesFreeClean) {
+ super(usesFreeClean ? "freeClean" : "spotArea", prepareRoomIds(roomIds, usesFreeClean), cleanPasses);
+ }
+
+ private static String prepareRoomIds(List<String> roomIds, boolean usesFreeClean) {
+ String prefix = usesFreeClean ? "1," : "";
+ String separator = usesFreeClean ? ";" : ",";
+ return prefix + String.join(separator, roomIds);
}
}
}
case "error": {
ErrorReport report = payloadAs(response, ErrorReport.class);
- for (Integer code : report.errorCodes) {
- listener.onErrorReported(device, code);
+ if (report.errorCodes.isEmpty()) {
+ listener.onErrorReported(device, 0);
+ } else {
+ for (Integer code : report.errorCodes) {
+ listener.onErrorReported(device, code);
+ }
}
}
case "stats": {
EDGE,
@SerializedName("spot")
SPOT,
- @SerializedName(value = "SpotArea", alternate = { "spotArea" })
+ @SerializedName(value = "SpotArea", alternate = { "spotArea", "freeClean" })
SPOT_AREA,
@SerializedName(value = "CustomArea", alternate = { "customArea" })
CUSTOM_AREA,
VOICE_REPORTING,
@SerializedName("spot_area_cleaning")
SPOT_AREA_CLEANING,
+ @SerializedName("free_clean_command")
+ FREE_CLEAN_FOR_SPOT_AREA,
@SerializedName("custom_area_cleaning")
CUSTOM_AREA_CLEANING,
@SerializedName("single_room_cleaning")
}
}
if (!roomIds.isEmpty()) {
- return new SpotAreaCleaningCommand(roomIds, passes);
+ return new SpotAreaCleaningCommand(roomIds, passes,
+ device.hasCapability(DeviceCapability.FREE_CLEAN_FOR_SPOT_AREA));
}
} else {
logger.info("{}: spotArea command needs to have the form spotArea:<room1>[;<room2>][;<...roomX>][:x2]",
"modelName": "DEEBOT U2 SE",
"deviceClass": "zjna8m",
"deviceClassLink": "ipzjy0"
+ },
+
+ {
+ "modelName": "DEEBOT X2",
+ "deviceClass": "e6ofmn",
+ "protoVersion": "json_v2",
+ "usesMqtt": true,
+ "capabilities": [
+ "mopping_system",
+ "main_brush",
+ "spot_area_cleaning",
+ "free_clean_command",
+ "custom_area_cleaning",
+ "clean_speed_control",
+ "voice_reporting",
+ "read_network_info",
+ "unit_care_lifespan",
+ "true_detect_3d",
+ "mapping",
+ "auto_empty_station"
+ ]
+ },
+ {
+ "modelName": "DEEBOT X2 OMNI",
+ "deviceClass": "lf3bn4",
+ "deviceClassLink": "e6ofmn"
+ },
+ {
+ "modelName": "DEEBOT X2 COMBO",
+ "deviceClass": "e6rcnf",
+ "deviceClassLink": "e6ofmn"
+ },
+ {
+ "modelName": "DEEBOT X2 PRO OMNI",
+ "deviceClass": "ip3mmy",
+ "deviceClassLink": "e6ofmn"
}
]