/** * 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.lcn.mappingtarget; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.openhab.binding.lcn.common.LcnAddr; import org.openhab.binding.lcn.common.LcnDefs; import org.openhab.binding.lcn.common.PckGenerator; import org.openhab.binding.lcn.connection.Connection; import org.openhab.binding.lcn.input.ModStatusBinSensors; import org.openhab.binding.lcn.input.ModStatusKeyLocks; import org.openhab.binding.lcn.input.ModStatusLedsAndLogicOps; import org.openhab.binding.lcn.input.ModStatusOutput; import org.openhab.binding.lcn.input.ModStatusRelays; import org.openhab.binding.lcn.input.ModStatusVar; import org.openhab.core.events.EventPublisher; import org.openhab.core.items.Item; import org.openhab.core.types.Command; /** * Sets dynamic text in an LCN-GTxD. * * @author Tobias J�ttner * */ public class DynText extends TargetWithLcnAddr { /** Pattern to parse dynamic-text commands. */ private static final Pattern PATTERN_DYNTEXT = Pattern.compile("(?<rowId>[1234])\\.(?<text>.*)", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); /** 0..3 */ private final int rowId; /** The text to set. */ private final String text; /** * Constructor. * * @param addr the target LCN address * @param rowId 0..3 * @param text the text to set */ DynText(LcnAddr addr, int rowId, String text) { super(addr); this.rowId = rowId; this.text = text; } /** * Tries to parse the given input text. * * @param input the text to parse * @return the parsed {@link DynText} or null */ static Target tryParseTarget(String input) { CmdAndAddressRet header = CmdAndAddressRet.parse(input, true); if (header != null) { Matcher matcher; switch (header.getCmd().toUpperCase()) { case "DYNTEXT": if ((matcher = PATTERN_DYNTEXT.matcher(header.getRestInput())).matches()) { return new DynText(header.getAddr(), Integer.parseInt(matcher.group("rowId")) - 1, matcher.group("text")); } break; } } return null; } /** {@inheritDoc} */ @Override public void send(Connection conn, Item item, Command cmd) { // Encode the text and split it into parts with max. 12 bytes each LinkedList<ByteBuffer> l = new LinkedList<ByteBuffer>(); try { byte[] buf = this.text.getBytes(LcnDefs.LCN_ENCODING); int pos = 0, part = 0; while (pos < buf.length) { ByteBuffer data = ByteBuffer.allocate(64); data.put(PckGenerator.dynTextHeader(this.rowId, part++).getBytes(LcnDefs.LCN_ENCODING)); int partPos = 0; while (pos < buf.length && partPos < 12) { data.put(buf[partPos++]); } data.flip(); l.add(data); pos += partPos; // Write empty termination-packet if everything fitted exactly (see LCN-PCK docs) if (pos == buf.length && partPos == 12 && part < 5) { data = ByteBuffer.allocate(64); data.put(PckGenerator.dynTextHeader(this.rowId, part++).getBytes(LcnDefs.LCN_ENCODING)); data.flip(); l.add(data); } } } catch (UnsupportedEncodingException ex) { } if (l.size() <= 5) { for (ByteBuffer data : l) { conn.queue(this.addr, !this.addr.isGroup(), data); } } else { logger.error(String.format("Cannot send dynamic text (too long): %s", this.text)); } } /** {@inheritDoc} */ @Override public void register(Connection conn) { } /** {@inheritDoc} */ @Override public boolean visualizationHandleOutputStatus(ModStatusOutput pchkInput, Command cmd, Item item, EventPublisher eventPublisher) { return false; } /** {@inheritDoc} */ @Override public boolean visualizationHandleRelaysStatus(ModStatusRelays pchkInput, Command cmd, Item item, EventPublisher eventPublisher) { return false; } /** {@inheritDoc} */ @Override public boolean visualizationBinSensorsStatus(ModStatusBinSensors pchkInput, Command cmd, Item item, EventPublisher eventPublisher) { return false; } /** {@inheritDoc} */ @Override public boolean visualizationVarStatus(ModStatusVar pchkInput, Command cmd, Item item, EventPublisher eventPublisher) { return false; } /** {@inheritDoc} */ @Override public boolean visualizationLedsAndLogicOpsStatus(ModStatusLedsAndLogicOps pchkInput, Command cmd, Item item, EventPublisher eventPublisher) { return false; } /** {@inheritDoc} */ @Override public boolean visualizationKeyLocksStatus(ModStatusKeyLocks pchkInput, Command cmd, Item item, EventPublisher eventPublisher) { return false; } }