com.whizzosoftware.hobson.dsc.api.codec.DSCFrameDecoder.java Source code

Java tutorial

Introduction

Here is the source code for com.whizzosoftware.hobson.dsc.api.codec.DSCFrameDecoder.java

Source

/*******************************************************************************
 * Copyright (c) 2016 Whizzo Software, LLC.
 * 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 com.whizzosoftware.hobson.dsc.api.codec;

import com.whizzosoftware.hobson.dsc.api.command.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.CorruptedFrameException;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A Netty decoder for RadioRA command frames.
 *
 * @author Dan Noguerol
 */
public class DSCFrameDecoder extends DelimiterBasedFrameDecoder {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    private final static int MAX_FRAME_LENGTH = 1024;

    public DSCFrameDecoder() {
        super(MAX_FRAME_LENGTH, Unpooled.copiedBuffer("\n", CharsetUtil.UTF_8));
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
        logger.trace("decode: {}", buffer.toString(CharsetUtil.UTF_8));

        ByteBuf frame = (ByteBuf) super.decode(ctx, buffer);

        if (frame != null) {
            try {
                if (frame.readableBytes() >= 3) {
                    String cmdId = new String(new byte[] { frame.getByte(0), frame.getByte(1), frame.getByte(2) });
                    switch (cmdId) {
                    case CodeRequired.ID:
                        return new CodeRequired();
                    case CommandAcknowledge.ID:
                        return new CommandAcknowledge();
                    case CommandError.ID:
                        return new CommandError();
                    case LCDUpdate.ID:
                        int lineNumber = frame.getByte(3) - '0';
                        int columnNumber = Integer
                                .parseInt(new String(new byte[] { frame.getByte(4), frame.getByte(5) }));
                        int length = Integer
                                .parseInt(new String(new byte[] { frame.getByte(6), frame.getByte(7) }));
                        return new LCDUpdate(lineNumber, columnNumber,
                                frame.slice(8, length).toString(CharsetUtil.UTF_8));
                    case LEDStatus.ID:
                        return new LEDStatus(LEDStatus.LEDType.forOrdinal(frame.getByte(3) - '0'),
                                LEDStatus.Status.forOrdinal(frame.getByte(4) - '0'));
                    case SoftwareVersion.ID:
                        return new SoftwareVersion(frame.slice(3, 4).toString(CharsetUtil.UTF_8));
                    case PartitionBusy.ID:
                        return new PartitionBusy(frame.getByte(3) - '0');
                    case PartitionNotReady.ID:
                        return new PartitionNotReady(frame.getByte(3) - '0');
                    case PartitionReady.ID:
                        return new PartitionReady(frame.getByte(3) - '0');
                    case TroubleLEDOff.ID:
                        return new TroubleLEDOff(frame.getByte(3) - '0');
                    case ZoneOpen.ID:
                        return new ZoneOpen(Integer.parseInt(
                                new String(new byte[] { frame.getByte(3), frame.getByte(4), frame.getByte(5) })));
                    case ZoneRestored.ID:
                        return new ZoneRestored(Integer.parseInt(
                                new String(new byte[] { frame.getByte(3), frame.getByte(4), frame.getByte(5) })));
                    case TimeDateBroadcast.ID:
                        return new TimeDateBroadcast(frame.slice(3, 10).toString(CharsetUtil.UTF_8));
                    default:
                        logger.debug("Ignoring unknown command frame: {}", buffer.toString(CharsetUtil.UTF_8));
                        return null;
                    }
                } else {
                    throw new CorruptedFrameException("Frame should not be less than 3 bytes");
                }
            } finally {
                frame.release();
            }
        } else {
            return null;
        }
    }
}