uk.org.funcube.fcdw.server.processor.FitterMessageProcessorImpl.java Source code

Java tutorial

Introduction

Here is the source code for uk.org.funcube.fcdw.server.processor.FitterMessageProcessorImpl.java

Source

// FUNcube Data Warehouse
// Copyright 2013 (c) David A.Johnson, G4DPZ, AMSAT-UK
// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter
// to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.

package uk.org.funcube.fcdw.server.processor;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.List;
import java.util.SimpleTimeZone;

import org.apache.commons.lang3.StringUtils;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import uk.org.funcube.fcdw.dao.FitterMessageDao;
import uk.org.funcube.fcdw.dao.HexFrameDao;
import uk.org.funcube.fcdw.dao.SatelliteStatusDao;
import uk.org.funcube.fcdw.domain.FitterMessageEntity;
import uk.org.funcube.fcdw.domain.HexFrameEntity;
import uk.org.funcube.fcdw.domain.SatelliteStatusEntity;
import uk.org.funcube.fcdw.server.shared.FitterDebug;

public class FitterMessageProcessorImpl implements FitterMessageProcessor {

    private static Logger LOG = Logger.getLogger(FitterMessageProcessorImpl.class.getName());

    @Autowired
    FitterMessageDao fitterMessageDao;

    @Autowired
    HexFrameDao hexFrameDao;

    @Autowired
    SatelliteStatusDao satelliteStatusDao;

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void process(long satelliteId) {
        Calendar cal = Calendar.getInstance(TZ);
        cal.add(Calendar.HOUR_OF_DAY, -24);

        final List<HexFrameEntity> fitterList = hexFrameDao.findUnprocessedFitter(satelliteId, cal.getTime());

        LOG.debug("Found: " + fitterList.size() + " unprocessed fitter frames");

        for (final HexFrameEntity fitterFrame : fitterList) {

            Timestamp receivedDate = new Timestamp(fitterFrame.getCreatedDate().getTime());

            extractAndSaveFitter(satelliteId, fitterFrame, receivedDate);
        }

        final List<SatelliteStatusEntity> satelliteStatuses = satelliteStatusDao.findBySatelliteId(satelliteId);
        if (!satelliteStatuses.isEmpty()) {
            final SatelliteStatusEntity satelliteStatus = satelliteStatuses.get(0);
            final List<FitterMessageEntity> latestDebug = fitterMessageDao.getLatestDebug(satelliteId,
                    new PageRequest(0, 1));
            if (!latestDebug.isEmpty()) {
                final FitterMessageEntity fitter = latestDebug.get(0);
                final FitterDebug fitterDebug = new FitterDebug(
                        convertHexBytePairToBinary(fitter.getMessageText()));
                satelliteStatus.setEclipseModeForced(fitterDebug.getEclipseForce().equals("1"));
                satelliteStatus.setEclipseSwitch(fitterDebug.getEclipseSwitch().equals("1"));
                satelliteStatusDao.save(satelliteStatus);
            }
        }

    }

    private void extractAndSaveFitter(long satelliteId, HexFrameEntity frame, Timestamp lastReceived) {

        StringBuffer sb = new StringBuffer();

        int frameType = frame.getFrameType().intValue();

        String slot = getSlotFromFrameType(frameType);

        final String messageHex = frame.getHexString().substring(106, frame.getHexString().length());

        // we may be processing a packet after a reset so the frame may contain 000's
        if (messageHex.substring(6, 8).equals("00")) {
            return;
        }

        // we do not process DEBUG frames
        if (!messageHex.substring(6, 8).equals("FF")) {

            for (int i = 6; i < messageHex.length() - 2; i += 2) {
                final int value = Integer.parseInt(messageHex.substring(i, i + 2), 16);
                if (value == 0) {
                    if (i == 6) {
                        break;
                    } else {
                        final String messageText = sb.toString();
                        saveFitter(satelliteId, lastReceived, messageText, false, slot);
                        sb = new StringBuffer();
                    }
                } else {
                    sb.append((char) value);
                }
            }
        } else {
            final String messageText = messageHex.substring(8, messageHex.length());
            saveFitter(satelliteId, lastReceived, messageText, true, slot);
        }

        frame.setFitterProcessed(true);
        hexFrameDao.save(frame);

    }

    /**
     * @param frameType
     * @return
     */
    private String getSlotFromFrameType(int frameType) {

        String slot = "FM";

        switch (frameType) {
        case 13:
        case 14:
        case 15:
            slot += (frameType - 12);
            break;
        case 17:
        case 18:
        case 19:
            slot += (frameType - 13);
            break;
        case 21:
        case 22:
        case 23:
            slot += (frameType - 14);
            break;
        }

        return slot;

    }

    private void saveFitter(long satelliteId, Timestamp lastReceived, final String messageText,
            final Boolean isDebug, final String slot) {
        List<FitterMessageEntity> fitterMessages = fitterMessageDao
                .findBySatelliteIdAndMessageTextAndDebug(satelliteId, messageText, isDebug);

        FitterMessageEntity fitterMessage;

        if (fitterMessages.size() != 0) {
            fitterMessage = fitterMessages.get(0);
            fitterMessage.setLastReceived(lastReceived);
            fitterMessage.setSlot(slot);
        } else {
            fitterMessage = new FitterMessageEntity(messageText, lastReceived, satelliteId, isDebug, slot,
                    lastReceived);
        }

        fitterMessageDao.save(fitterMessage);
    }

    private static final SimpleTimeZone TZ = new SimpleTimeZone(0, "UTC");

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void truncate(long satelliteId) {

        Calendar cal = Calendar.getInstance(TZ);
        cal.add(Calendar.DAY_OF_MONTH, -7);

        List<FitterMessageEntity> messages = fitterMessageDao.getNoneDebugReceivedBefore(satelliteId,
                cal.getTime());

        for (FitterMessageEntity entity : messages) {
            entity.setDisplay(false);
            fitterMessageDao.save(entity);
        }
    }

    private static String convertHexBytePairToBinary(final String hexString) {
        final StringBuffer sb = new StringBuffer();

        for (int i = 0; i < hexString.length(); i += 2) {
            final String hexByte = hexString.substring(i, i + 2);
            final int hexValue = Integer.parseInt(hexByte, 16);
            sb.append(StringUtils.leftPad(Integer.toBinaryString(hexValue), 8, "0"));
        }
        return sb.toString();
    }

}