/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.samsungac.internal; import java.io.IOException; import java.io.StringReader; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.XMLReaderFactory; /** * Parser to read the response from the air conditioner. * Will check responses and see what type they are, and if * they contain any important information. * * @author Stein Tore Tøsse * @since 1.6.0 */ public class ResponseParser { private static final Logger logger = LoggerFactory.getLogger(ResponseParser.class); /** * See if the response from the air conditioner contains a token- * * @param response The response from the air conditioner * @return true if the response contains a token, otherwise false */ public static boolean isResponseWithToken(String response) { return response.contains("Update Type=\"GetToken\" Status=\"Completed\" Token=\""); } /** * Parses the token in the response. * * @param response The response from the AC * @return the token */ public static String parseTokenFromResponse(String response) { Pattern pattern = Pattern.compile("Token=\"(.+)\""); Matcher matcher = pattern.matcher(response); matcher.find(); return matcher.group().replaceFirst("Token=\"", "").replaceAll("\"", ""); } /** * @param response The response from the AC * @return true if authentication failed, otherwise false */ public static boolean isFailedAuthenticationResponse(String response) { return response.contains("<Response Status=\"Fail\" Type=\"Authenticate\" ErrorCode=\"301\" />"); } /** * * @param response The response from the AC * @return true if response if marked as failed, otherwise false */ public static boolean isFailedResponse(String response) { return response.contains("<Response Status=\"Fail\" Type=\"Authenticate\" ErrorCode=\"103\" />"); } /** * * @param response The response from the AC * @param commandId The id of the command we sent * @return true if the response is the correct response, otherwise false */ public static boolean isCorrectCommandResponse(String response, String commandId) { return response.contains("CommandID=\"" + commandId + "\""); } /** * * @param response The response from the AC * @return true if we logged in to the AC successfully, otherwise false */ public static boolean isSuccessfulLoginResponse(String response) { return response.contains("Response Type=\"AuthToken\" Status=\"Okay\""); } /** * * @param response The response from the AC * @return true if it is the first line, otherwise false */ public static boolean isFirstLine(String response) { return response.contains("DRC-1.00") || response.contains("DPLUG-1.6"); } /** * * @param response The response from the AC * @return true if response lets us know we are not logged in, otherwise false */ public static boolean isNotLoggedInResponse(String response) { return response.contains("Type=\"InvalidateAccount\""); } /** * * @param response The response from the AC * @return true if air conditioner is ready for sending a token, otherwise false */ public static boolean isReadyForTokenResponse(String response) { return response.contains("<Response Type=\"GetToken\" Status=\"Ready\"/>"); } /** * * @param response The response from the AC * @return true if response is someone controlling the device(e.g. from a remote), otherwise false */ public static boolean isDeviceControl(String response) { return response.contains("Response Type=\"DeviceControl\""); } /** * * @param response The response from the AC * @return true if we get a state from the ac, otherwise false */ public static boolean isDeviceState(String response) { return response.contains("Response Type=\"DeviceState\" Status=\"Okay\"") && !response.contains("CommandID=\"cmd"); } /** * * @param response The response from the AC * @return true if we get a status update, otherwise false */ public static boolean isUpdateStatus(String response) { return response.contains("Update Type=\"Status\""); } /** * * @param response The response from the AC * @return A Map with all the commands and the status of each item * @throws SAXException If we cannot read the response from the AC */ public static Map<CommandEnum, String> parseStatusResponse(String response) throws SAXException { Map<CommandEnum, String> status = new HashMap<CommandEnum, String>(); try { XMLReader reader = XMLReaderFactory.createXMLReader(); StatusHandler statusHandler = new StatusHandler(); reader.setContentHandler(statusHandler); reader.parse(new InputSource(new StringReader(response))); status = statusHandler.getStatusMap(); } catch (IOException e) { e.printStackTrace(); } return status; } /** * Class to hold the status and to parse the XML from the air conditioner * * @author Stein Tore Tøsse * @since 1.6.0 * */ static private class StatusHandler extends DefaultHandler { private Map<CommandEnum, String> values = new HashMap<CommandEnum, String>(); @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("Attr".equals(qName)) { try { CommandEnum cmd = CommandEnum.valueOf(attributes.getValue("ID")); if (cmd != null) { values.put(cmd, attributes.getValue("Value")); } } catch (IllegalArgumentException e) { logger.debug("Does not support attribute: '{}'", attributes.getValue("ID")); } } } public Map<CommandEnum, String> getStatusMap() { return values; } } }