Add implementation and test for ota package contructor

This commit is contained in:
Volodymyr Babak 2022-06-21 17:53:30 +03:00
parent 3b3a41a2ec
commit 2bf8e9d5b4
3 changed files with 126 additions and 50 deletions

View File

@ -16,59 +16,54 @@
package org.thingsboard.server.service.edge.rpc.constructor; package org.thingsboard.server.service.edge.rpc.constructor;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.OtaPackage; import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.OtaPackageId; import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.transport.util.DataDecodingEncodingService;
import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg; import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType; import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import java.nio.charset.StandardCharsets;
@Component @Component
@TbCoreComponent @TbCoreComponent
public class OtaPackageMsgConstructor { public class OtaPackageMsgConstructor {
@Autowired
private DataDecodingEncodingService dataDecodingEncodingService;
public OtaPackageUpdateMsg constructOtaPackageUpdatedMsg(UpdateMsgType msgType, OtaPackage otaPackage) { public OtaPackageUpdateMsg constructOtaPackageUpdatedMsg(UpdateMsgType msgType, OtaPackage otaPackage) {
OtaPackageUpdateMsg.Builder builder = OtaPackageUpdateMsg.newBuilder() OtaPackageUpdateMsg.Builder builder = OtaPackageUpdateMsg.newBuilder()
.setMsgType(msgType) .setMsgType(msgType)
.setIdMSB(otaPackage.getId().getId().getMostSignificantBits()) .setIdMSB(otaPackage.getId().getId().getMostSignificantBits())
.setIdLSB(otaPackage.getId().getId().getLeastSignificantBits()); .setIdLSB(otaPackage.getId().getId().getLeastSignificantBits())
// .setName(deviceProfile.getName()) .setDeviceProfileIdMSB(otaPackage.getDeviceProfileId().getId().getMostSignificantBits())
// .setDefault(deviceProfile.isDefault()) .setDeviceProfileIdLSB(otaPackage.getDeviceProfileId().getId().getLeastSignificantBits())
// .setType(deviceProfile.getType().name()) .setType(otaPackage.getType().name())
// .setProfileDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile.getProfileData()))); .setTitle(otaPackage.getTitle())
// TODO: @voba - add possibility to setup edge rule chain as device profile default .setVersion(otaPackage.getVersion())
// if (deviceProfile.getDefaultRuleChainId() != null) { .setTag(otaPackage.getTag());
// builder.setDefaultRuleChainIdMSB(deviceProfile.getDefaultRuleChainId().getId().getMostSignificantBits())
// .setDefaultRuleChainIdLSB(deviceProfile.getDefaultRuleChainId().getId().getLeastSignificantBits()); if (otaPackage.getUrl() != null) {
// } builder.setUrl(otaPackage.getUrl());
// if (deviceProfile.getDefaultQueueName() != null) { }
// builder.setDefaultQueueName(deviceProfile.getDefaultQueueName()); if (otaPackage.getAdditionalInfo() != null) {
// } builder.setAdditionalInfo(JacksonUtil.toString(otaPackage.getAdditionalInfo()));
// if (deviceProfile.getDescription() != null) { }
// builder.setDescription(deviceProfile.getDescription()); if (otaPackage.getFileName() != null) {
// } builder.setFileName(otaPackage.getFileName());
// if (deviceProfile.getTransportType() != null) { }
// builder.setTransportType(deviceProfile.getTransportType().name()); if (otaPackage.getContentType() != null) {
// } builder.setContentType(otaPackage.getContentType());
// if (deviceProfile.getProvisionType() != null) { }
// builder.setProvisionType(deviceProfile.getProvisionType().name()); if (otaPackage.getChecksumAlgorithm() != null) {
// } builder.setChecksumAlgorithm(otaPackage.getChecksumAlgorithm().name());
// if (deviceProfile.getProvisionDeviceKey() != null) { }
// builder.setProvisionDeviceKey(deviceProfile.getProvisionDeviceKey()); if (otaPackage.getChecksum() != null) {
// } builder.setChecksum(otaPackage.getChecksum());
// if (deviceProfile.getImage() != null) { }
// builder.setImage(ByteString.copyFrom(deviceProfile.getImage().getBytes(StandardCharsets.UTF_8))); if (otaPackage.getDataSize() != null) {
// } builder.setDataSize(otaPackage.getDataSize());
}
if (otaPackage.getData() != null) {
builder.setData(ByteString.copyFrom(otaPackage.getData().array()));
}
return builder.build(); return builder.build();
} }

View File

@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.protobuf.AbstractMessage; import com.google.protobuf.AbstractMessage;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite; import com.google.protobuf.MessageLite;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
@ -32,7 +33,10 @@ import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
@ -72,6 +76,8 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.query.EntityKeyValueType; import org.thingsboard.server.common.data.query.EntityKeyValueType;
@ -126,6 +132,7 @@ import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg;
import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg; import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -213,7 +220,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
thermostatDeviceProfile = this.createDeviceProfile(THERMOSTAT_DEVICE_PROFILE_NAME, transportConfiguration); thermostatDeviceProfile = this.createDeviceProfile(THERMOSTAT_DEVICE_PROFILE_NAME, transportConfiguration);
extendDeviceProfileData(thermostatDeviceProfile); extendDeviceProfileData(thermostatDeviceProfile);
doPost("/api/deviceProfile", thermostatDeviceProfile, DeviceProfile.class); thermostatDeviceProfile = doPost("/api/deviceProfile", thermostatDeviceProfile, DeviceProfile.class);
Device savedDevice = saveDevice("Edge Device 1", THERMOSTAT_DEVICE_PROFILE_NAME); Device savedDevice = saveDevice("Edge Device 1", THERMOSTAT_DEVICE_PROFILE_NAME);
doPost("/api/edge/" + edge.getUuidId() doPost("/api/edge/" + edge.getUuidId()
@ -1650,15 +1657,16 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
} }
@Test @Test
public void testOtaPackages() throws Exception { public void testOtaPackages_usesUrl() throws Exception {
// 1 // 1
SaveOtaPackageInfoRequest firmwareInfo = new SaveOtaPackageInfoRequest(); SaveOtaPackageInfoRequest firmwareInfo = new SaveOtaPackageInfoRequest();
firmwareInfo.setDeviceProfileId(thermostatDeviceProfile.getId()); firmwareInfo.setDeviceProfileId(thermostatDeviceProfile.getId());
firmwareInfo.setType(FIRMWARE); firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle("My firmware"); firmwareInfo.setTitle("My firmware #1");
firmwareInfo.setVersion("v1.0"); firmwareInfo.setVersion("v1.0");
firmwareInfo.setTag("My firmware #1 v1.0");
firmwareInfo.setUsesUrl(true); firmwareInfo.setUsesUrl(true);
firmwareInfo.setUrl("http://thingsboard.io/v1"); firmwareInfo.setUrl("http://localhost:8080/v1/package");
firmwareInfo.setAdditionalInfo(JacksonUtil.newObjectNode()); firmwareInfo.setAdditionalInfo(JacksonUtil.newObjectNode());
edgeImitator.expectMessageAmount(1); edgeImitator.expectMessageAmount(1);
@ -1669,10 +1677,75 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertTrue(latestMessage instanceof OtaPackageUpdateMsg); Assert.assertTrue(latestMessage instanceof OtaPackageUpdateMsg);
OtaPackageUpdateMsg otaPackageUpdateMsg = (OtaPackageUpdateMsg) latestMessage; OtaPackageUpdateMsg otaPackageUpdateMsg = (OtaPackageUpdateMsg) latestMessage;
Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, otaPackageUpdateMsg.getMsgType()); Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, otaPackageUpdateMsg.getMsgType());
Assert.assertEquals(savedFirmwareInfo.getUuidId().getMostSignificantBits(), otaPackageUpdateMsg.getIdMSB());
Assert.assertEquals(savedFirmwareInfo.getUuidId().getLeastSignificantBits(), otaPackageUpdateMsg.getIdLSB());
Assert.assertEquals(thermostatDeviceProfile.getUuidId().getMostSignificantBits(), otaPackageUpdateMsg.getDeviceProfileIdMSB());
Assert.assertEquals(thermostatDeviceProfile.getUuidId().getLeastSignificantBits(), otaPackageUpdateMsg.getDeviceProfileIdLSB());
Assert.assertEquals(FIRMWARE, OtaPackageType.valueOf(otaPackageUpdateMsg.getType()));
Assert.assertEquals("My firmware #1", otaPackageUpdateMsg.getTitle());
Assert.assertEquals("v1.0", otaPackageUpdateMsg.getVersion());
Assert.assertEquals("My firmware #1 v1.0", otaPackageUpdateMsg.getTag());
Assert.assertEquals("http://localhost:8080/v1/package", otaPackageUpdateMsg.getUrl());
Assert.assertFalse(otaPackageUpdateMsg.hasData());
Assert.assertFalse(otaPackageUpdateMsg.hasFileName());
Assert.assertFalse(otaPackageUpdateMsg.hasContentType());
Assert.assertFalse(otaPackageUpdateMsg.hasChecksumAlgorithm());
Assert.assertFalse(otaPackageUpdateMsg.hasChecksum());
Assert.assertFalse(otaPackageUpdateMsg.hasDataSize());
// 2
edgeImitator.expectMessageAmount(1);
doDelete("/api/otaPackage/" + savedFirmwareInfo.getUuidId())
.andExpect(status().isOk());
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof OtaPackageUpdateMsg);
otaPackageUpdateMsg = (OtaPackageUpdateMsg) latestMessage;
Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, otaPackageUpdateMsg.getMsgType());
Assert.assertEquals(otaPackageUpdateMsg.getIdMSB(), savedFirmwareInfo.getUuidId().getMostSignificantBits()); Assert.assertEquals(otaPackageUpdateMsg.getIdMSB(), savedFirmwareInfo.getUuidId().getMostSignificantBits());
Assert.assertEquals(otaPackageUpdateMsg.getIdLSB(), savedFirmwareInfo.getUuidId().getLeastSignificantBits()); Assert.assertEquals(otaPackageUpdateMsg.getIdLSB(), savedFirmwareInfo.getUuidId().getLeastSignificantBits());
}
// TODO - add check of content - constructor fix @Test
public void testOtaPackages_hasData() throws Exception {
// 1
SaveOtaPackageInfoRequest firmwareInfo = new SaveOtaPackageInfoRequest();
firmwareInfo.setDeviceProfileId(thermostatDeviceProfile.getId());
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle("My firmware #2");
firmwareInfo.setVersion("v2.0");
firmwareInfo.setTag("My firmware #2 v2.0");
firmwareInfo.setUsesUrl(false);
firmwareInfo.setHasData(false);
firmwareInfo.setAdditionalInfo(JacksonUtil.newObjectNode());
edgeImitator.expectMessageAmount(1);
OtaPackageInfo savedFirmwareInfo = doPost("/api/otaPackage", firmwareInfo, OtaPackageInfo.class);
MockMultipartFile testData = new MockMultipartFile("file", "firmware.bin", "image/png", ByteBuffer.wrap(new byte[]{1, 3, 5}).array());
savedFirmwareInfo = saveData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksumAlgorithm={checksumAlgorithm}", testData, ChecksumAlgorithm.SHA256.name());
Assert.assertTrue(edgeImitator.waitForMessages());
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof OtaPackageUpdateMsg);
OtaPackageUpdateMsg otaPackageUpdateMsg = (OtaPackageUpdateMsg) latestMessage;
Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, otaPackageUpdateMsg.getMsgType());
Assert.assertEquals(savedFirmwareInfo.getUuidId().getMostSignificantBits(), otaPackageUpdateMsg.getIdMSB());
Assert.assertEquals(savedFirmwareInfo.getUuidId().getLeastSignificantBits(), otaPackageUpdateMsg.getIdLSB());
Assert.assertEquals(thermostatDeviceProfile.getUuidId().getMostSignificantBits(), otaPackageUpdateMsg.getDeviceProfileIdMSB());
Assert.assertEquals(thermostatDeviceProfile.getUuidId().getLeastSignificantBits(), otaPackageUpdateMsg.getDeviceProfileIdLSB());
Assert.assertEquals(FIRMWARE, OtaPackageType.valueOf(otaPackageUpdateMsg.getType()));
Assert.assertEquals("My firmware #2", otaPackageUpdateMsg.getTitle());
Assert.assertEquals("v2.0", otaPackageUpdateMsg.getVersion());
Assert.assertEquals("My firmware #2 v2.0", otaPackageUpdateMsg.getTag());
Assert.assertFalse(otaPackageUpdateMsg.hasUrl());
Assert.assertEquals("firmware.bin", otaPackageUpdateMsg.getFileName());
Assert.assertEquals("image/png", otaPackageUpdateMsg.getContentType());
Assert.assertEquals(ChecksumAlgorithm.SHA256.name(), otaPackageUpdateMsg.getChecksumAlgorithm());
Assert.assertEquals("62467691cf583d4fa78b18fafaf9801f505e0ef03baf0603fd4b0cd004cd1e75", otaPackageUpdateMsg.getChecksum());
Assert.assertEquals(3L, otaPackageUpdateMsg.getDataSize());
Assert.assertEquals(ByteString.copyFrom(new byte[]{1, 3, 5}), otaPackageUpdateMsg.getData());
// 2 // 2
edgeImitator.expectMessageAmount(1); edgeImitator.expectMessageAmount(1);
@ -1767,4 +1840,12 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(source, target); Assert.assertEquals(source, target);
Assert.assertEquals(source.hashCode(), target.hashCode()); Assert.assertEquals(source.hashCode(), target.hashCode());
} }
private OtaPackageInfo saveData(String urlTemplate, MockMultipartFile content, String... params) throws Exception {
MockMultipartHttpServletRequestBuilder postRequest = MockMvcRequestBuilders.multipart(urlTemplate, params);
postRequest.file(content);
setJwtToken(postRequest);
return readResponse(mockMvc.perform(postRequest).andExpect(status().isOk()), OtaPackageInfo.class);
}
} }

View File

@ -432,13 +432,13 @@ message OtaPackageUpdateMsg {
string version = 8; string version = 8;
string tag = 9; string tag = 9;
optional string url = 10; optional string url = 10;
bool hasData = 11; optional string fileName = 11;
optional string fileName = 12; optional string contentType = 12;
optional string contentType = 13; optional string checksumAlgorithm = 13;
optional string checksumAlgorithm = 14; optional string checksum = 14;
optional string checksum = 15; optional int64 dataSize = 15;
optional int64 dataSize = 16; optional bytes data = 16;
optional bytes data = 17; optional string additionalInfo = 17;
} }
/** /**