/*******************************************************************************
* Copyright (c) 2013-2015 Sierra Wireless and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Sierra Wireless - initial API and implementation
* Gemalto M2M GmbH
*******************************************************************************/
package org.eclipse.leshan.core.node.codec;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.leshan.core.model.LwM2mModel;
import org.eclipse.leshan.core.model.ObjectLoader;
import org.eclipse.leshan.core.node.LwM2mMultipleResource;
import org.eclipse.leshan.core.node.LwM2mObject;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mSingleResource;
import org.eclipse.leshan.core.node.TimestampedLwM2mNode;
import org.eclipse.leshan.core.request.ContentFormat;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Unit tests for {@link LwM2mNodeEncoder}
*/
public class LwM2mNodeEncoderTest {
private static LwM2mModel model;
private static LwM2mNodeEncoder encoder;
@BeforeClass
public static void loadModel() {
model = new LwM2mModel(ObjectLoader.loadDefault());
encoder = new DefaultLwM2mNodeEncoder();
}
@Test
public void text_encode_single_resource() {
byte[] encoded = encoder.encode(LwM2mSingleResource.newFloatResource(15, 56.4D), ContentFormat.TEXT,
new LwM2mPath("/323/0/15"), model);
Assert.assertEquals("56.4", new String(encoded, StandardCharsets.UTF_8));
}
@Test
public void text_encode_date_as_long() {
byte[] encoded = encoder.encode(LwM2mSingleResource.newStringResource(13, "2010-01-01T12:00:00+01:00"),
ContentFormat.TEXT, new LwM2mPath("/3/0/13"), model);
Assert.assertEquals("1262343600", new String(encoded, StandardCharsets.UTF_8));
}
@Test
public void text_encode_date_as_iso_string() {
byte[] encoded = encoder.encode(LwM2mSingleResource.newIntegerResource(13, 1367491215000L), ContentFormat.TEXT,
new LwM2mPath("/3/0/13"), model);
Assert.assertEquals("1367491215", new String(encoded, StandardCharsets.UTF_8));
}
@Test(expected = CodecException.class)
public void text_encode_multiple_instances() {
Map<Integer, Long> values = new HashMap<>();
values.put(0, 1L);
values.put(1, 5L);
encoder.encode(LwM2mMultipleResource.newIntegerResource(6, values), ContentFormat.TEXT, new LwM2mPath("/3/0/6"),
model);
}
// device instance encoded as an array of resources
private static byte[] ENCODED_DEVICE = new byte[] { -56, 0, 20, 79, 112, 101, 110, 32, 77, 111, 98, 105, 108, 101,
32, 65, 108, 108, 105, 97, 110, 99, 101, -56, 1, 22, 76, 105, 103, 104, 116, 119, 101, 105,
103, 104, 116, 32, 77, 50, 77, 32, 67, 108, 105, 101, 110, 116, -56, 2, 9, 51, 52, 53, 48,
48, 48, 49, 50, 51, -61, 3, 49, 46, 48, -122, 6, 65, 0, 1, 65, 1, 5, -120, 7, 8, 66, 0, 14,
-40, 66, 1, 19, -120, -121, 8, 65, 0, 125, 66, 1, 3, -124, -63, 9, 100, -63, 10, 15, -63,
11, 0, -60, 13, 81, -126, 66, -113, -58, 14, 43, 48, 50, 58, 48, 48, -63, 15, 85 };
private Collection<LwM2mResource> getDeviceResources() {
Collection<LwM2mResource> resources = new ArrayList<>();
resources.add(LwM2mSingleResource.newStringResource(0, "Open Mobile Alliance"));
resources.add(LwM2mSingleResource.newStringResource(1, "Lightweight M2M Client"));
resources.add(LwM2mSingleResource.newStringResource(2, "345000123"));
resources.add(LwM2mSingleResource.newStringResource(3, "1.0"));
Map<Integer, Long> values = new HashMap<>();
values.put(0, 1L);
values.put(1, 5L);
resources.add(LwM2mMultipleResource.newIntegerResource(6, values));
values = new HashMap<>();
values.put(0, 3800L);
values.put(1, 5000L);
resources.add(LwM2mMultipleResource.newIntegerResource(7, values));
values = new HashMap<>();
values.put(0, 125L);
values.put(1, 900L);
resources.add(LwM2mMultipleResource.newIntegerResource(8, values));
resources.add(LwM2mSingleResource.newIntegerResource(9, 100));
resources.add(LwM2mSingleResource.newIntegerResource(10, 15));
resources.add(LwM2mSingleResource.newIntegerResource(11, 0));
resources.add(LwM2mSingleResource.newDateResource(13, new Date(1367491215000L)));
resources.add(LwM2mSingleResource.newStringResource(14, "+02:00"));
resources.add(LwM2mSingleResource.newStringResource(15, "U"));
return resources;
}
@Test
public void tlv_encode_device_object_instance_as_resources_array() {
LwM2mObjectInstance oInstance = new LwM2mObjectInstance(0, getDeviceResources());
byte[] encoded = encoder.encode(oInstance, ContentFormat.TLV, new LwM2mPath("/3/0"), model);
Assert.assertArrayEquals(ENCODED_DEVICE, encoded);
}
@Test
public void tlv_encode_device_object_instance_as_resources_array__undefined_instance_id() {
LwM2mObjectInstance oInstance = new LwM2mObjectInstance(LwM2mObjectInstance.UNDEFINED, getDeviceResources());
byte[] encoded = encoder.encode(oInstance, ContentFormat.TLV, new LwM2mPath("/3"), model);
Assert.assertArrayEquals(ENCODED_DEVICE, encoded);
}
@Test
public void tlv_encode_device_object_instance_as_instance() {
LwM2mObjectInstance oInstance = new LwM2mObjectInstance(0, getDeviceResources());
byte[] encoded = encoder.encode(oInstance, ContentFormat.TLV, new LwM2mPath("/3"), model);
// TLV instance = { type=INSTANCE, instanceId=0, length=DEVICE_ENCODED.lentgh, value=DEVICE_ENCODED }
byte[] instanceTlv = new byte[ENCODED_DEVICE.length + 3];
System.arraycopy(new byte[] { 8, 0, 119 }, 0, instanceTlv, 0, 3);
System.arraycopy(ENCODED_DEVICE, 0, instanceTlv, 3, ENCODED_DEVICE.length);
Assert.assertArrayEquals(instanceTlv, encoded);
}
@Test
public void tlv_encode_device_object() {
LwM2mObject object = new LwM2mObject(3, new LwM2mObjectInstance(0, getDeviceResources()));
byte[] encoded = encoder.encode(object, ContentFormat.TLV, new LwM2mPath("/3"), model);
// encoded as an array of resource TLVs
Assert.assertArrayEquals(ENCODED_DEVICE, encoded);
}
@Test
public void json_encode_device_object_instance() {
LwM2mObjectInstance oInstance = new LwM2mObjectInstance(0, getDeviceResources());
byte[] encoded = encoder.encode(oInstance, ContentFormat.JSON, new LwM2mPath("/3/0"), model);
StringBuilder b = new StringBuilder();
b.append("{\"e\":[");
b.append("{\"n\":\"0\",\"sv\":\"Open Mobile Alliance\"},");
b.append("{\"n\":\"1\",\"sv\":\"Lightweight M2M Client\"},");
b.append("{\"n\":\"2\",\"sv\":\"345000123\"},");
b.append("{\"n\":\"3\",\"sv\":\"1.0\"},");
b.append("{\"n\":\"6/0\",\"v\":1},");
b.append("{\"n\":\"6/1\",\"v\":5},");
b.append("{\"n\":\"7/0\",\"v\":3800},");
b.append("{\"n\":\"7/1\",\"v\":5000},");
b.append("{\"n\":\"8/0\",\"v\":125},");
b.append("{\"n\":\"8/1\",\"v\":900},");
b.append("{\"n\":\"9\",\"v\":100},");
b.append("{\"n\":\"10\",\"v\":15},");
b.append("{\"n\":\"11\",\"v\":0},");
b.append("{\"n\":\"13\",\"v\":1367491215},");
b.append("{\"n\":\"14\",\"sv\":\"+02:00\"},");
b.append("{\"n\":\"15\",\"sv\":\"U\"}]}");
String expected = b.toString();
Assert.assertEquals(expected, new String(encoded));
}
@Test
public void json_encode_timestamped_resources() throws CodecException {
List<TimestampedLwM2mNode> data = new ArrayList<>();
data.add(new TimestampedLwM2mNode(500L, LwM2mSingleResource.newFloatResource(1, 22.9)));
data.add(new TimestampedLwM2mNode(510L, LwM2mSingleResource.newFloatResource(1, 22.4)));
data.add(new TimestampedLwM2mNode(520L, LwM2mSingleResource.newFloatResource(1, 24.1)));
byte[] encoded = encoder.encodeTimestampedData(data, ContentFormat.JSON, new LwM2mPath(1024, 0, 1), model);
StringBuilder b = new StringBuilder();
b.append("{\"e\":[");
b.append("{\"n\":\"\",\"v\":22.9,\"t\":500},");
b.append("{\"n\":\"\",\"v\":22.4,\"t\":510},");
b.append("{\"n\":\"\",\"v\":24.1,\"t\":520}]}");
String expected = b.toString();
Assert.assertEquals(expected, new String(encoded));
}
@Test
public void json_encode_timestamped_instances() throws CodecException {
List<TimestampedLwM2mNode> data = new ArrayList<>();
LwM2mObjectInstance instanceAt110 = new LwM2mObjectInstance(0, LwM2mSingleResource.newFloatResource(1, 22.9));
LwM2mObjectInstance instanceAt120 = new LwM2mObjectInstance(0, LwM2mSingleResource.newFloatResource(1, 22.4),
LwM2mSingleResource.newStringResource(0, "a string"));
LwM2mObjectInstance instanceAt130 = new LwM2mObjectInstance(0, LwM2mSingleResource.newFloatResource(1, 24.1));
data.add(new TimestampedLwM2mNode(110L, instanceAt110));
data.add(new TimestampedLwM2mNode(120L, instanceAt120));
data.add(new TimestampedLwM2mNode(130L, instanceAt130));
byte[] encoded = encoder.encodeTimestampedData(data, ContentFormat.JSON, new LwM2mPath(1024, 0), model);
StringBuilder b = new StringBuilder();
b.append("{\"e\":[");
b.append("{\"n\":\"1\",\"v\":22.9,\"t\":110},");
b.append("{\"n\":\"0\",\"sv\":\"a string\",\"t\":120},");
b.append("{\"n\":\"1\",\"v\":22.4,\"t\":120},");
b.append("{\"n\":\"1\",\"v\":24.1,\"t\":130}]}");
String expected = b.toString();
Assert.assertEquals(expected, new String(encoded));
}
@Test
public void json_encode_timestamped_Object() throws CodecException {
List<TimestampedLwM2mNode> data = new ArrayList<>();
LwM2mObject objectAt210 = new LwM2mObject(1204,
new LwM2mObjectInstance(0, LwM2mSingleResource.newFloatResource(1, 22.9)));
LwM2mObject objectAt220 = new LwM2mObject(1204,
new LwM2mObjectInstance(0, LwM2mSingleResource.newFloatResource(1, 22.4),
LwM2mSingleResource.newStringResource(0, "a string")),
new LwM2mObjectInstance(1, LwM2mSingleResource.newFloatResource(1, 23)));
LwM2mObject objetAt230 = new LwM2mObject(1204,
new LwM2mObjectInstance(0, LwM2mSingleResource.newFloatResource(1, 24.1)));
data.add(new TimestampedLwM2mNode(210L, objectAt210));
data.add(new TimestampedLwM2mNode(220L, objectAt220));
data.add(new TimestampedLwM2mNode(230L, objetAt230));
byte[] encoded = encoder.encodeTimestampedData(data, ContentFormat.JSON, new LwM2mPath(1024), model);
StringBuilder b = new StringBuilder();
b.append("{\"e\":[");
b.append("{\"n\":\"0/1\",\"v\":22.9,\"t\":210},");
b.append("{\"n\":\"0/0\",\"sv\":\"a string\",\"t\":220},");
b.append("{\"n\":\"0/1\",\"v\":22.4,\"t\":220},");
b.append("{\"n\":\"1/1\",\"v\":23.0,\"t\":220},");
b.append("{\"n\":\"0/1\",\"v\":24.1,\"t\":230}]}");
String expected = b.toString();
Assert.assertEquals(expected, new String(encoded));
}
}