/* ================================================================== * MessageFactory.java - Jul 7, 2012 2:37:01 PM * * Copyright 2007-2012 SolarNetwork.net Dev Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * ================================================================== * $Id$ * ================================================================== */ package net.solarnetwork.node.rfxcom; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.codec.binary.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Factory for {@link Message} instances. * * @author matt * @version $Revision$ */ public class MessageFactory { private AtomicInteger sequenceNumber = new AtomicInteger(); private final Logger log = LoggerFactory.getLogger(getClass()); public short incrementAndGetSequenceNumber() { return (short) sequenceNumber.incrementAndGet(); } public Message parseMessage(byte[] data, int offset) { if ( log.isTraceEnabled() ) { log.trace("Parsing RFXCOM message: " + Hex.encodeHexString(data)); } if ( data == null || (data.length - offset) < 4 ) { if ( log.isDebugEnabled() ) { log.debug("Insufficient data to parse message: " + Hex.encodeHexString(data)); } return null; } final short msgLength = data[offset]; if ( msgLength < 3 || (msgLength + offset) >= data.length ) { if ( log.isDebugEnabled() ) { log.debug("Insufficient data to parse message: " + Hex.encodeHexString(data)); } return null; } // get offset-normalized message data, without packet header final byte[] msg = new byte[msgLength - 3]; System.arraycopy(data, (offset + 4), msg, 0, msg.length); final short sequenceNumber = data[offset + 3]; Message result = null; // packet type switch (data[offset + 1]) { case 0x1: // Command response if ( msgLength < 13 ) { if ( log.isDebugEnabled() ) { log.debug("Insufficient data to parse command message: " + Hex.encodeHexString(data)); } return null; } Command cmd = Command.valueOf(data[offset + 4]); if ( cmd == Command.Status || cmd == Command.SetMode ) { result = new StatusMessage(sequenceNumber, msg); } else { result = new CommandMessage(sequenceNumber, msg); } break; case 0x59: result = new CurrentMessage(data[offset + 2], sequenceNumber, msg); break; case 0x5a: result = new EnergyMessage(data[offset + 2], sequenceNumber, msg); break; default: if ( log.isDebugEnabled() ) { log.debug("Unsupported message type: " + String.format("%x", msg[1])); } } return result; } public AtomicInteger getSequenceNumber() { return sequenceNumber; } public void setSequenceNumber(AtomicInteger sequenceNumber) { this.sequenceNumber = sequenceNumber; } }