package org.yamcs.xtceproc; import java.nio.ByteBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yamcs.parameter.ParameterValue; import org.yamcs.parameter.Value; import org.yamcs.protobuf.Pvalue.AcquisitionStatus; import org.yamcs.protobuf.Yamcs.Value.Type; import org.yamcs.xtce.BinaryParameterType; import org.yamcs.xtce.BooleanParameterType; import org.yamcs.xtce.EnumeratedParameterType; import org.yamcs.xtce.FloatParameterType; import org.yamcs.xtce.IntegerParameterType; import org.yamcs.xtce.Parameter; import org.yamcs.xtce.ParameterType; import org.yamcs.xtce.StringParameterType; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Multimap; public class ParameterTypeProcessor { ProcessorData pcontext; static Logger log=LoggerFactory.getLogger(ParameterTypeProcessor.class.getName()); public ParameterTypeProcessor(ProcessorData pcontext) { this.pcontext = pcontext; } static Multimap<Class<? extends ParameterType>, org.yamcs.protobuf.Yamcs.Value.Type> allowedAssignments = new ImmutableSetMultimap.Builder<Class<? extends ParameterType>, org.yamcs.protobuf.Yamcs.Value.Type>() .putAll(BinaryParameterType.class, org.yamcs.protobuf.Yamcs.Value.Type.BINARY) .putAll(BooleanParameterType.class, org.yamcs.protobuf.Yamcs.Value.Type.BOOLEAN) .putAll(EnumeratedParameterType.class, org.yamcs.protobuf.Yamcs.Value.Type.STRING) .putAll(FloatParameterType.class, org.yamcs.protobuf.Yamcs.Value.Type.FLOAT, org.yamcs.protobuf.Yamcs.Value.Type.DOUBLE) .putAll(IntegerParameterType.class, org.yamcs.protobuf.Yamcs.Value.Type.UINT32, org.yamcs.protobuf.Yamcs.Value.Type.SINT32, org.yamcs.protobuf.Yamcs.Value.Type.SINT64, org.yamcs.protobuf.Yamcs.Value.Type.UINT64) .putAll(StringParameterType.class, org.yamcs.protobuf.Yamcs.Value.Type.STRING) .build(); /** * Sets the value of a pval, based on the raw value and the applicable calibrator * @param pval */ public void calibrate(ParameterValue pval) { doCalibrate(pval, pval.getParameter().getParameterType()); } private void doCalibrate(ParameterValue pval, ParameterType ptype) { if (ptype instanceof EnumeratedParameterType) { calibrateEnumerated((EnumeratedParameterType) ptype, pval); } else if (ptype instanceof IntegerParameterType) { calibrateInteger((IntegerParameterType) ptype, pval); } else if (ptype instanceof FloatParameterType) { calibrateFloat((FloatParameterType) ptype, pval); } else if (ptype instanceof BinaryParameterType) { calibrateBinary((BinaryParameterType) ptype, pval); } else if (ptype instanceof StringParameterType) { calibrateString((StringParameterType) ptype, pval); } else if (ptype instanceof BooleanParameterType) { calibrateBoolean((BooleanParameterType) ptype, pval); } else { throw new IllegalArgumentException("Extraction of "+ptype+" not implemented"); } } private static void calibrateEnumerated(EnumeratedParameterType ept, ParameterValue pval) { Value rawValue = pval.getRawValue(); if (rawValue.getType() == Type.UINT32) { pval.setStringValue(ept.calibrate(rawValue.getUint32Value())); } else if (rawValue.getType() == Type.UINT64) { pval.setStringValue(ept.calibrate(rawValue.getUint64Value())); } else if (rawValue.getType() == Type.SINT32) { pval.setStringValue(ept.calibrate(rawValue.getSint32Value())); } else if (rawValue.getType() == Type.SINT64) { pval.setStringValue(ept.calibrate(rawValue.getSint64Value())); } else if (rawValue.getType() == Type.FLOAT) { // added for obcp simulator pval.setStringValue(ept.calibrate((long)rawValue.getFloatValue())); } else if (rawValue.getType() == Type.STRING) { try { long l = Long.decode(rawValue.getStringValue()); pval.setStringValue(ept.calibrate(l)); } catch (NumberFormatException e) { log.warn("{}: failed to parse string '{}' to long", ept.getName(), rawValue.getStringValue()); pval.setAcquisitionStatus(AcquisitionStatus.INVALID); } } else { throw new IllegalStateException("Unsupported raw value type '"+rawValue.getType()+"' cannot be calibrated as an enumeration"); } } private static void calibrateBoolean(BooleanParameterType bpt, ParameterValue pval) { Value rawValue = pval.getRawValue(); if (rawValue.getType() == Type.UINT32) { pval.setBooleanValue(rawValue.getUint32Value() != 0); } else if (rawValue.getType() == Type.UINT64) { pval.setBooleanValue(rawValue.getUint64Value() != 0); } else if (rawValue.getType() == Type.SINT32) { pval.setBooleanValue(rawValue.getSint32Value() != 0); } else if (rawValue.getType() == Type.SINT64) { pval.setBooleanValue(rawValue.getSint64Value() != 0); } else if (rawValue.getType() == Type.FLOAT) { pval.setBooleanValue(rawValue.getFloatValue() != 0); } else if (rawValue.getType() == Type.DOUBLE) { pval.setBooleanValue(rawValue.getDoubleValue() != 0); } else if (rawValue.getType() == Type.STRING) { pval.setBooleanValue(rawValue.getStringValue() != null && !rawValue.getStringValue().isEmpty()); } else if (rawValue.getType() == Type.BOOLEAN) { pval.setBooleanValue(rawValue.getBooleanValue()); } else if (rawValue.getType() == Type.BINARY) { ByteBuffer buf = ByteBuffer.wrap(rawValue.getBinaryValue()); pval.setBooleanValue(false); while(buf.hasRemaining()) { if(buf.get()!=0xFF) { pval.setBooleanValue(true); break; } } } else { throw new IllegalStateException("Unsupported raw value type '"+rawValue.getType()+"' cannot be calibrated as a boolean"); } } private static void calibrateBinary(BinaryParameterType bpt, ParameterValue pval) { pval.setBinaryValue(pval.getRawValue().getBinaryValue()); } private void calibrateInteger(IntegerParameterType ipt, ParameterValue pval) { Value rawValue = pval.getRawValue(); if (rawValue.getType() == Type.UINT32) { doIntegerCalibration(ipt, pval, rawValue.getUint32Value()&0xFFFFFFFFL); } else if (rawValue.getType() == Type.UINT64) { doIntegerCalibration(ipt, pval, rawValue.getUint64Value()); } else if (rawValue.getType() == Type.SINT32) { doIntegerCalibration(ipt, pval, rawValue.getSint32Value()); } else if (rawValue.getType() == Type.SINT64) { doIntegerCalibration(ipt, pval, rawValue.getSint64Value()); } else if (rawValue.getType() == Type.FLOAT) { doIntegerCalibration(ipt, pval, (long)rawValue.getFloatValue()); } else if (rawValue.getType() == Type.STRING) { try { long l = Long.decode(rawValue.getStringValue()); doIntegerCalibration(ipt, pval, l); } catch (NumberFormatException e) { log.warn("{}: failed to parse string '{}' to long", ipt.getName(), rawValue.getStringValue()); pval.setAcquisitionStatus(AcquisitionStatus.INVALID); } } else { throw new IllegalStateException("Unsupported raw value type '"+rawValue.getType()+"' cannot be converted to integer"); } } private void doIntegerCalibration(IntegerParameterType ipt, ParameterValue pval, long longValue) { CalibratorProc calibrator = pcontext.getCalibrator(ipt.getEncoding()); long longCalValue = (calibrator == null) ? longValue: (long)calibrator.calibrate(longValue); if (ipt.getSizeInBits() <= 32) { if (ipt.isSigned()) pval.setSignedIntegerValue((int) longCalValue); else pval.setUnsignedIntegerValue((int) longCalValue); } else { if (ipt.isSigned()) pval.setSignedLongValue(longCalValue); else pval.setUnsignedLongValue(longCalValue); } } private static void calibrateString(StringParameterType spt, ParameterValue pval) { Value rawValue = pval.getRawValue(); if(rawValue.getType() == Type.STRING) { pval.setStringValue(rawValue.getStringValue()); } else { throw new IllegalStateException("Unsupported raw value type '"+rawValue.getType()+"' cannot be converted to string"); } } private void calibrateFloat(FloatParameterType fpt, ParameterValue pval) { Value rawValue = pval.getRawValue(); if(rawValue.getType() == Type.FLOAT) { doFloatCalibration(fpt, pval, rawValue.getFloatValue()); } else if(rawValue.getType() == Type.DOUBLE) { doFloatCalibration(fpt, pval, rawValue.getDoubleValue()); } else if(rawValue.getType() == Type.STRING) { try { Double d = Double.parseDouble(rawValue.getStringValue()); doFloatCalibration(fpt, pval, d); } catch (NumberFormatException e) { log.warn("{}: failed to parse string '{}' to double", fpt.getName(), rawValue.getStringValue()); pval.setAcquisitionStatus(AcquisitionStatus.INVALID); } } else if(rawValue.getType() == Type.UINT32) { doFloatCalibration(fpt, pval, rawValue.getUint32Value()); } else if(rawValue.getType() == Type.UINT64) { doFloatCalibration(fpt, pval, rawValue.getUint64Value()); } else if(rawValue.getType() == Type.SINT32) { doFloatCalibration(fpt, pval, rawValue.getSint32Value()); } else if(rawValue.getType() == Type.SINT64) { doFloatCalibration(fpt, pval, rawValue.getSint64Value()); } else { throw new IllegalStateException("Unsupported raw value type '"+rawValue.getType()+"' cannot be converted to float"); } } private void doFloatCalibration(FloatParameterType fpt, ParameterValue pval, double doubleValue) { CalibratorProc calibrator = pcontext.getCalibrator(fpt.getEncoding()); double doubleCalValue = (calibrator == null) ? doubleValue:calibrator.calibrate(doubleValue); if(fpt.getSizeInBits() == 32) { pval.setFloatValue((float) doubleCalValue); } else { pval.setDoubleValue(doubleCalValue); } } /** * Checks that a value can be assigned to a parameter as enginnering value * Throws an IllegalArgumentException if not * * @param p * @param engValue */ public static void checkEngValueAssignment(Parameter p, Value engValue) { ParameterType ptype = p.getParameterType(); if(!allowedAssignments.containsEntry(ptype.getClass(), engValue.getType())) { throw new IllegalArgumentException("Cannot assign "+ptype.getTypeAsString()+" from "+engValue.getType()); } } }