Adding DataAmount (bit and derivatives) and DataTransferRates (bits per second) (#681)

* Adding DataAmount (bit and derivatives) and DataTransferRates (bits per second) to UoM

Signed-off-by: Gaël L'hopital <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital
2019-03-30 21:43:15 +01:00
committed by Christoph Weitkamp
parent d1a343d8b2
commit c6a9085a74
5 changed files with 294 additions and 0 deletions
@@ -0,0 +1,28 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.core.library.dimension;
import javax.measure.Quantity;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Represents a measure of data amount.
* The metric system unit for this quantity is "bit".
*
* @author Gaël L'hopital - Initial contribution
*
*/
@NonNullByDefault
public interface DataAmount extends Quantity<DataAmount> {
}
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.core.library.dimension;
import javax.measure.Quantity;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Represents a measure of data or data blocks per unit time passing through a communication link
*
* @author Gaël L'hopital - Initial contribution
*
*/
@NonNullByDefault
public interface DataTransferRate extends Quantity<DataTransferRate> {
}
@@ -0,0 +1,178 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.core.library.unit;
import java.math.BigInteger;
import javax.measure.Quantity;
import javax.measure.Unit;
import javax.measure.UnitConverter;
import org.eclipse.jdt.annotation.NonNullByDefault;
import tec.uom.lib.common.function.SymbolSupplier;
import tec.uom.lib.common.function.UnitConverterSupplier;
import tec.uom.se.function.RationalConverter;
/**
* The binary prefixes used to derive units by specific powers of 2.
*
* @author Gaël L'hopital - Initial contribution
*
*/
@NonNullByDefault
public enum BinaryPrefix implements SymbolSupplier, UnitConverterSupplier {
YOBI("Yi", new RationalConverter(BigInteger.valueOf(2).pow(80), BigInteger.ONE)),
ZEBI("Zi", new RationalConverter(BigInteger.valueOf(2).pow(70), BigInteger.ONE)),
EXBI("Ei", new RationalConverter(BigInteger.valueOf(2).pow(60), BigInteger.ONE)),
PEBI("Pi", new RationalConverter(BigInteger.valueOf(2).pow(50), BigInteger.ONE)),
TEBI("Ti", new RationalConverter(BigInteger.valueOf(2).pow(40), BigInteger.ONE)),
GIBI("Gi", new RationalConverter(BigInteger.valueOf(2).pow(30), BigInteger.ONE)),
MEBI("Mi", new RationalConverter(BigInteger.valueOf(2).pow(20), BigInteger.ONE)),
KIBI("Ki", new RationalConverter(BigInteger.valueOf(2).pow(10), BigInteger.ONE));
/**
* The symbol of this prefix, as returned by {@link #getSymbol}.
*
* @see #getSymbol()
*/
private final String symbol;
/**
* The <code>UnitConverter</code> of this prefix, as returned by {@link #getConverter}.
*
* @see #getConverter()
* @see {@link UnitConverter}
*/
private final UnitConverter converter;
/**
* Creates a new prefix.
*
* @param symbol the symbol of this prefix.
* @param converter the associated unit converter.
*/
BinaryPrefix(String symbol, RationalConverter converter) {
this.symbol = symbol;
this.converter = converter;
}
/**
* Returns the symbol of this prefix.
*
* @return this prefix symbol, not {@code null}.
*/
@Override
public String getSymbol() {
return symbol;
}
/**
* Returns the corresponding unit converter.
*
* @return the unit converter.
*/
@Override
public UnitConverter getConverter() {
return converter;
}
/**
* Returns the specified unit multiplied by the factor <code>2<sup>80</sup></code>
*
* @param <Q> The type of the quantity measured by the unit.
* @param unit any unit.
* @return <code>unit.times(2e80)</code>.
*/
public static <Q extends Quantity<Q>> Unit<Q> YOBI(Unit<Q> unit) {
return unit.transform(YOBI.getConverter());
}
/**
* Returns the specified unit multiplied by the factor <code>2<sup>70</sup></code>
*
* @param <Q> The type of the quantity measured by the unit.
* @param unit any unit.
* @return <code>unit.times(2e70)</code>.
*/
public static <Q extends Quantity<Q>> Unit<Q> ZEBI(Unit<Q> unit) {
return unit.transform(ZEBI.getConverter());
}
/**
* Returns the specified unit multiplied by the factor <code>2<sup>60</sup></code>
*
* @param <Q> The type of the quantity measured by the unit.
* @param unit any unit.
* @return <code>unit.times(2e60)</code>.
*/
public static <Q extends Quantity<Q>> Unit<Q> EXBI(Unit<Q> unit) {
return unit.transform(EXBI.getConverter());
}
/**
* Returns the specified unit multiplied by the factor <code>2<sup>50</sup></code>
*
* @param <Q> The type of the quantity measured by the unit.
* @param unit any unit.
* @return <code>unit.times(2e50)</code>.
*/
public static <Q extends Quantity<Q>> Unit<Q> PEBI(Unit<Q> unit) {
return unit.transform(PEBI.getConverter());
}
/**
* Returns the specified unit multiplied by the factor <code>2<sup>40</sup></code>
*
* @param <Q> The type of the quantity measured by the unit.
* @param unit any unit.
* @return <code>unit.times(2e40)</code>.
*/
public static <Q extends Quantity<Q>> Unit<Q> TEBI(Unit<Q> unit) {
return unit.transform(TEBI.getConverter());
}
/**
* Returns the specified unit multiplied by the factor <code>2<sup>30</sup></code>
*
* @param <Q> The type of the quantity measured by the unit.
* @param unit any unit.
* @return <code>unit.times(2e30)</code>.
*/
public static <Q extends Quantity<Q>> Unit<Q> GIBI(Unit<Q> unit) {
return unit.transform(GIBI.getConverter());
}
/**
* Returns the specified unit multiplied by the factor <code>2<sup>20</sup></code>
*
* @param <Q> The type of the quantity measured by the unit.
* @param unit any unit.
* @return <code>unit.times(2e20)</code>.
*/
public static <Q extends Quantity<Q>> Unit<Q> MEBI(Unit<Q> unit) {
return unit.transform(MEBI.getConverter());
}
/**
* Returns the specified unit multiplied by the factor <code>2<sup>10</sup></code>
*
* @param <Q> The type of the quantity measured by the unit.
* @param unit any unit.
* @return <code>unit.times(2e10)</code>.
*/
public static <Q extends Quantity<Q>> Unit<Q> KIBI(Unit<Q> unit) {
return unit.transform(KIBI.getConverter());
}
}
@@ -49,6 +49,8 @@ import javax.measure.spi.SystemOfUnits;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.core.library.dimension.ArealDensity;
import org.eclipse.smarthome.core.library.dimension.DataAmount;
import org.eclipse.smarthome.core.library.dimension.DataTransferRate;
import org.eclipse.smarthome.core.library.dimension.Density;
import org.eclipse.smarthome.core.library.dimension.Intensity;
import org.eclipse.smarthome.core.library.dimension.VolumetricFlowRate;
@@ -162,6 +164,24 @@ public final class SmartHomeUnits extends CustomUnits {
new ProductUnit<VolumetricFlowRate>(Units.CUBIC_METRE.divide(Units.HOUR)));
public static final Unit<VolumetricFlowRate> CUBICMETRE_PER_DAY = addUnit(
new ProductUnit<VolumetricFlowRate>(Units.CUBIC_METRE.divide(Units.DAY)));
public static final Unit<DataAmount> BIT = addUnit(new AlternateUnit<DataAmount>(ONE, "bit"));
public static final Unit<DataAmount> MEGABIT = addUnit(MetricPrefix.MEGA(BIT));
public static final Unit<DataAmount> KILOBIT = addUnit(MetricPrefix.KILO(BIT));
public static final Unit<DataAmount> GIGABIT = addUnit(MetricPrefix.GIGA(BIT));
public static final Unit<DataAmount> TERABIT = addUnit(MetricPrefix.TERA(BIT));
public static final Unit<DataAmount> BYTE = addUnit(BIT.multiply(8));
public static final Unit<DataAmount> OCTET = BYTE;
public static final Unit<DataAmount> KIBIOCTET = addUnit(BinaryPrefix.KIBI(OCTET));
public static final Unit<DataAmount> MEBIOCTET = addUnit(BinaryPrefix.MEBI(OCTET));
public static final Unit<DataAmount> GIBIOCTET = addUnit(BinaryPrefix.GIBI(OCTET));
public static final Unit<DataTransferRate> BIT_PER_SECOND = addUnit(
new ProductUnit<DataTransferRate>(BIT.divide(Units.SECOND)));
public static final Unit<DataTransferRate> KILOBIT_PER_SECOND = addUnit(MetricPrefix.KILO(BIT_PER_SECOND));
public static final Unit<DataTransferRate> MEGABIT_PER_SECOND = addUnit(MetricPrefix.MEGA(BIT_PER_SECOND));
public static final Unit<DataTransferRate> GIGABIT_PER_SECOND = addUnit(MetricPrefix.GIGA(BIT_PER_SECOND));
public static final Unit<DataTransferRate> TERABIT_PER_SECOND = addUnit(MetricPrefix.TERA(BIT_PER_SECOND));
/**
* Add unit symbols for custom openHAB units.
@@ -169,6 +189,9 @@ public final class SmartHomeUnits extends CustomUnits {
static {
// Ordered alphabetical by name
SimpleUnitFormat.getInstance().label(BAR, BAR.getSymbol());
SimpleUnitFormat.getInstance().label(BIT, BIT.getSymbol());
SimpleUnitFormat.getInstance().label(BIT_PER_SECOND, "bit/s");
SimpleUnitFormat.getInstance().label(BYTE, "o");
SimpleUnitFormat.getInstance().label(CUBICMETRE_PER_DAY, "m³/d");
SimpleUnitFormat.getInstance().label(CUBICMETRE_PER_HOUR, "m³/h");
SimpleUnitFormat.getInstance().label(CUBICMETRE_PER_MINUTE, "m³/min");
@@ -178,10 +201,19 @@ public final class SmartHomeUnits extends CustomUnits {
SimpleUnitFormat.getInstance().label(DEGREE_ANGLE, "°");
SimpleUnitFormat.getInstance().label(DEUTSCHE_HAERTE, "°dH");
SimpleUnitFormat.getInstance().label(DOBSON_UNIT, "DU");
SimpleUnitFormat.getInstance().label(GIBIOCTET, "Gio");
SimpleUnitFormat.getInstance().label(GIGABIT, "Gbit");
SimpleUnitFormat.getInstance().label(GIGABIT_PER_SECOND, "Gbit/s");
SimpleUnitFormat.getInstance().label(IRRADIANCE, "W/m²");
SimpleUnitFormat.getInstance().label(KIBIOCTET, "Kio");
SimpleUnitFormat.getInstance().label(KILOBIT, "kbit");
SimpleUnitFormat.getInstance().label(KILOBIT_PER_SECOND, "kbit/s");
SimpleUnitFormat.getInstance().label(KILOWATT_HOUR, "kWh");
SimpleUnitFormat.getInstance().label(KNOT, KNOT.getSymbol());
SimpleUnitFormat.getInstance().label(LITRE_PER_MINUTE, "l/min");
SimpleUnitFormat.getInstance().label(MEBIOCTET, "Mio");
SimpleUnitFormat.getInstance().label(MEGABIT, "Mbit");
SimpleUnitFormat.getInstance().label(MEGABIT_PER_SECOND, "Mbit/s");
SimpleUnitFormat.getInstance().label(MEGAWATT_HOUR, "MWh");
SimpleUnitFormat.getInstance().label(MICROGRAM_PER_CUBICMETRE, "µg/m³");
SimpleUnitFormat.getInstance().label(MICROWATT_PER_SQUARE_CENTIMETRE, "µW/cm²");
@@ -189,6 +221,8 @@ public final class SmartHomeUnits extends CustomUnits {
SimpleUnitFormat.getInstance().label(MILLIMETRE_OF_MERCURY, MILLIMETRE_OF_MERCURY.getSymbol());
SimpleUnitFormat.getInstance().label(PARTS_PER_MILLION, "ppm");
SimpleUnitFormat.getInstance().label(STANDARD_GRAVITY, "gₙ");
SimpleUnitFormat.getInstance().label(TERABIT, "Tbit");
SimpleUnitFormat.getInstance().label(TERABIT_PER_SECOND, "Tbit/s");
SimpleUnitFormat.getInstance().label(WATT_HOUR, "Wh");
SimpleUnitFormat.getInstance().label(WATT_SECOND, "Ws");
}
@@ -25,6 +25,8 @@ import javax.measure.quantity.Pressure;
import javax.measure.quantity.Speed;
import javax.measure.quantity.Temperature;
import org.eclipse.smarthome.core.library.dimension.DataAmount;
import org.eclipse.smarthome.core.library.dimension.DataTransferRate;
import org.eclipse.smarthome.core.library.dimension.Density;
import org.eclipse.smarthome.core.library.dimension.Intensity;
import org.eclipse.smarthome.core.library.unit.MetricPrefix;
@@ -33,6 +35,7 @@ import org.eclipse.smarthome.core.library.unit.SmartHomeUnits;
import org.junit.Test;
import tec.uom.se.quantity.QuantityDimension;
import tec.uom.se.unit.Units;
/**
* @author Gaël L'hopital - initial contribution
@@ -293,4 +296,28 @@ public class QuantityTypeTest {
QuantityType<Speed> rate = new QuantityType<>("3 mm/h");
assertEquals("0.1181102362204724409448818897637795 in/h", rate.toUnit("in/h").toString());
}
@Test
public void testDataAmount() {
QuantityType<DataAmount> amount = new QuantityType<>("8 bit");
QuantityType<DataAmount> octet = amount.toUnit(SmartHomeUnits.BYTE);
assertEquals(1, octet.byteValue());
QuantityType<DataAmount> bigAmount = new QuantityType<>("1 Kio");
QuantityType<DataAmount> octets = bigAmount.toUnit(SmartHomeUnits.OCTET);
assertEquals(1024, octets.intValue());
QuantityType<DataAmount> hugeAmount = new QuantityType<>("1024Gio");
QuantityType<DataAmount> lotOfOctets = hugeAmount.toUnit(SmartHomeUnits.OCTET);
assertEquals("1099511627776 o", lotOfOctets.toString());
}
@Test
public void testDataTransferRate() {
QuantityType<DataTransferRate> speed = new QuantityType<>("1024 bit/s");
QuantityType<DataTransferRate> octet = speed.toUnit(SmartHomeUnits.OCTET.divide(Units.SECOND));
assertEquals(128, octet.intValue());
QuantityType<DataTransferRate> gsm2G = new QuantityType<>("115 Mbit/s");
QuantityType<DataTransferRate> octets = gsm2G
.toUnit(MetricPrefix.KILO(SmartHomeUnits.OCTET).divide(Units.SECOND));
assertEquals(14375, octets.intValue());
}
}