/*******************************************************************************
* Copyright (c) 2011, 2016 Eurotech and/or its affiliates
*
* 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
*
* Contributors:
* Eurotech
*******************************************************************************/
package org.eclipse.kura.core.cloud;
import java.io.IOException;
import java.util.Date;
import org.eclipse.kura.KuraInvalidMessageException;
import org.eclipse.kura.KuraInvalidMetricTypeException;
import org.eclipse.kura.core.message.protobuf.KuraPayloadProto;
import org.eclipse.kura.core.util.GZipUtil;
import org.eclipse.kura.message.KuraPayload;
import org.eclipse.kura.message.KuraPosition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
public class CloudPayloadProtoBufDecoderImpl {
private static final Logger s_logger = LoggerFactory.getLogger(CloudPayloadProtoBufDecoderImpl.class);
private byte[] m_bytes;
public CloudPayloadProtoBufDecoderImpl(byte[] bytes) {
this.m_bytes = bytes;
}
/**
* Factory method to build an KuraPayload instance from a byte array.
*
* @param bytes
* @return
* @throws InvalidProtocolBufferException
* @throws IOException
*/
public KuraPayload buildFromByteArray() throws KuraInvalidMessageException, IOException {
// Check if a compressed payload and try to decompress it
if (GZipUtil.isCompressed(this.m_bytes)) {
try {
this.m_bytes = GZipUtil.decompress(this.m_bytes);
} catch (IOException e) {
s_logger.info("Decompression failed");
// do not rethrow the exception here as isCompressed may return some false positives
}
}
// build the KuraPayloadProto.KuraPayload
KuraPayloadProto.KuraPayload protoMsg = null;
try {
protoMsg = KuraPayloadProto.KuraPayload.parseFrom(this.m_bytes);
} catch (InvalidProtocolBufferException ipbe) {
throw new KuraInvalidMessageException(ipbe);
}
// build the KuraPayload
KuraPayload kuraMsg = new KuraPayload();
// set the timestamp
if (protoMsg.hasTimestamp()) {
kuraMsg.setTimestamp(new Date(protoMsg.getTimestamp()));
}
// set the position
if (protoMsg.hasPosition()) {
kuraMsg.setPosition(buildFromProtoBuf(protoMsg.getPosition()));
}
// set the metrics
for (int i = 0; i < protoMsg.getMetricCount(); i++) {
String name = protoMsg.getMetric(i).getName();
try {
Object value = getProtoKuraMetricValue(protoMsg.getMetric(i), protoMsg.getMetric(i).getType());
kuraMsg.addMetric(name, value);
} catch (KuraInvalidMetricTypeException ihte) {
s_logger.warn("During deserialization, ignoring metric named: {}. Unrecognized value type: {}", name,
protoMsg.getMetric(i).getType(), ihte);
}
}
// set the body
if (protoMsg.hasBody()) {
kuraMsg.setBody(protoMsg.getBody().toByteArray());
}
return kuraMsg;
}
private KuraPosition buildFromProtoBuf(KuraPayloadProto.KuraPayload.KuraPosition protoPosition) {
KuraPosition position = new KuraPosition();
if (protoPosition.hasLatitude()) {
position.setLatitude(protoPosition.getLatitude());
}
if (protoPosition.hasLongitude()) {
position.setLongitude(protoPosition.getLongitude());
}
if (protoPosition.hasAltitude()) {
position.setAltitude(protoPosition.getAltitude());
}
if (protoPosition.hasPrecision()) {
position.setPrecision(protoPosition.getPrecision());
}
if (protoPosition.hasHeading()) {
position.setHeading(protoPosition.getHeading());
}
if (protoPosition.hasSpeed()) {
position.setSpeed(protoPosition.getSpeed());
}
if (protoPosition.hasSatellites()) {
position.setSatellites(protoPosition.getSatellites());
}
if (protoPosition.hasStatus()) {
position.setStatus(protoPosition.getStatus());
}
if (protoPosition.hasTimestamp()) {
position.setTimestamp(new Date(protoPosition.getTimestamp()));
}
return position;
}
private Object getProtoKuraMetricValue(KuraPayloadProto.KuraPayload.KuraMetric metric,
KuraPayloadProto.KuraPayload.KuraMetric.ValueType type) throws KuraInvalidMetricTypeException {
switch (type) {
case DOUBLE:
return metric.getDoubleValue();
case FLOAT:
return metric.getFloatValue();
case INT64:
return metric.getLongValue();
case INT32:
return metric.getIntValue();
case BOOL:
return metric.getBoolValue();
case STRING:
return metric.getStringValue();
case BYTES:
ByteString bs = metric.getBytesValue();
return bs.toByteArray();
default:
throw new KuraInvalidMetricTypeException(type);
}
}
}