package org.zu.ardulink.protocol.parser; import static org.zu.ardulink.util.Preconditions.checkArgument; import static org.zu.ardulink.util.Preconditions.checkNotNull; import org.zu.ardulink.protocol.ALProtocol; import org.zu.ardulink.util.Strings; public class ALProtocolParser implements IProtocolParser { @Override public String getProtocolName() { return ALProtocol.NAME; } @Override public MessageParsedInfo parse(String message) throws ParseException { MessageParsedInfo parsedInfo = new MessageParsedInfo(); parsedInfo.setMessage(message); message = parseEnvelope(message); parseInnerMessage(message, parsedInfo); return parsedInfo; } private String parseEnvelope(String message) throws ParseException { try { checkNotNull(message, "Parsing message must not be null"); checkArgument(message.endsWith(Strings.bytes2String(ALProtocol.DEFAULT_OUTGOING_MESSAGE_DIVIDER)), "Parsing message has to finish with the right divider char."); checkArgument(message.startsWith("alp://"), "Parsing message has to start with alp://"); message = message.substring(0, message.length() - 1); message = message.substring("alp://".length()); return message; } catch(IllegalStateException e) { throw new ParseException(e.getMessage(), e); } } private void parseInnerMessage(String message, MessageParsedInfo parsedInfo) throws ParseException { try { checkArgument(message.length() > 4, "Inner message has to be at least 5 chars: %s", message); String strMessageType = message.substring(0, 4); MessageType messageType = getMessageType(strMessageType); parsedInfo.setMessageType(messageType); int idPosition = message.lastIndexOf("?id="); if(idPosition != -1) { int id = retrieveId(message, idPosition + 4); parsedInfo.setId(id); message = message.substring(0, idPosition); } String[] values = message.substring(5).split("/"); parsedInfo.setValues(values); } catch(IllegalStateException e) { throw new ParseException(e.getMessage(), e); } } private MessageType getMessageType(String strMessageType) throws ParseException { MessageType retvalue = null; if(strMessageType.equals("ppsw")) { retvalue = MessageType.PPSW; } else if(strMessageType.equals("ppin")) { retvalue = MessageType.PPIN; } else if(strMessageType.equals("kprs")) { retvalue = MessageType.KPRS; } else if(strMessageType.equals("tone")) { retvalue = MessageType.TONE; } else if(strMessageType.equals("notn")) { retvalue = MessageType.NOTN; } else if(strMessageType.equals("srld")) { retvalue = MessageType.SRLD; } else if(strMessageType.equals("spld")) { retvalue = MessageType.SPLD; } else if(strMessageType.equals("srla")) { retvalue = MessageType.SRLA; } else if(strMessageType.equals("spla")) { retvalue = MessageType.SPLA; } else if(strMessageType.equals("cust")) { retvalue = MessageType.CUST; // } else if(strMessageType.equals("ared")) { // retvalue = MessageType.ARED; // } else if(strMessageType.equals("dred")) { // retvalue = MessageType.DRED; // } else if(strMessageType.equals("rply")) { // retvalue = MessageType.RPLY; } else { throw new ParseException(strMessageType + " is an unknown message type"); } return retvalue; } private int retrieveId(String message, int i) throws ParseException { int retvalue = -1; String idStr = message.substring(i); try { retvalue = Integer.parseInt(idStr); } catch(NumberFormatException e) { throw new ParseException("ID is not a number: " + idStr); } return retvalue; } @Override public int[] reply(boolean success, MessageParsedInfo messageParsedInfo) { StringBuilder builder = new StringBuilder("alp://rply/"); if(success) { builder.append("ok"); } else { builder.append("ko"); } builder.append("?id="); builder.append(messageParsedInfo.getId()); return Strings.string2Ints(builder.toString()); } @Override public int[] analogRead(int pin, int value) { StringBuilder builder = new StringBuilder("alp://ared/"); builder.append(pin).append("/").append(value); return Strings.string2Ints(builder.toString()); } @Override public int[] digitalRead(int pin, int value) { StringBuilder builder = new StringBuilder("alp://dred/"); builder.append(pin).append("/").append(value); return Strings.string2Ints(builder.toString()); } @Override public int[] customMessage(String message) { throw new UnsupportedOperationException("NOT SUPPORTED EVENT"); } @Override public IProtocolMessageStore getMessageStore() { return new ALProtocolMessageStore(); } }