TbGpsGeofencingActionNode: added presenceMonitoringStrategyOnEachMessage + tests + node details
This commit is contained in:
parent
3f763e41d6
commit
f27ce0686e
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.rule.engine.geo;
|
package org.thingsboard.rule.engine.geo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
@ -28,6 +30,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
|||||||
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
|
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
|
||||||
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
||||||
import org.thingsboard.server.common.data.plugin.ComponentType;
|
import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||||
|
import org.thingsboard.server.common.data.util.TbPair;
|
||||||
import org.thingsboard.server.common.msg.TbMsg;
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -39,6 +42,11 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.ENTERED;
|
||||||
|
import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.INSIDE;
|
||||||
|
import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.LEFT;
|
||||||
|
import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.OUTSIDE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by ashvayka on 19.01.18.
|
* Created by ashvayka on 19.01.18.
|
||||||
*/
|
*/
|
||||||
@ -46,15 +54,22 @@ import java.util.concurrent.TimeoutException;
|
|||||||
@RuleNode(
|
@RuleNode(
|
||||||
type = ComponentType.ACTION,
|
type = ComponentType.ACTION,
|
||||||
name = "gps geofencing events",
|
name = "gps geofencing events",
|
||||||
|
version = 1,
|
||||||
configClazz = TbGpsGeofencingActionNodeConfiguration.class,
|
configClazz = TbGpsGeofencingActionNodeConfiguration.class,
|
||||||
relationTypes = {"Success", "Entered", "Left", "Inside", "Outside"},
|
relationTypes = {"Success", "Entered", "Left", "Inside", "Outside"},
|
||||||
nodeDescription = "Produces incoming messages using GPS based geofencing",
|
nodeDescription = "Produces incoming messages using GPS based geofencing",
|
||||||
nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns different events based on configuration parameters",
|
nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns different events based on configuration parameters. " +
|
||||||
|
"<br><br>" +
|
||||||
|
"If an object with coordinates extracted from incoming message enters the geofence, sends a message with the type <code>Entered</code>. " +
|
||||||
|
"If an object leaves the geofence, sends a message with the type <code>Left</code>. " +
|
||||||
|
"If the presence monitoring strategy <b>\"On first message\"</b> is selected, sends messages with types <code>Inside</code> or <code>Outside</code> only the first time the geofencing and duration conditions are satisfied; otherwise <code>Success</code>. " +
|
||||||
|
"If the presence monitoring strategy <b>\"On each message\"</b> is selected, sends messages with types <code>Inside</code> or <code>Outside</code> every time the geofencing condition is satisfied.",
|
||||||
uiResources = {"static/rulenode/rulenode-core-config.js"},
|
uiResources = {"static/rulenode/rulenode-core-config.js"},
|
||||||
configDirective = "tbActionNodeGpsGeofencingConfig"
|
configDirective = "tbActionNodeGpsGeofencingConfig"
|
||||||
)
|
)
|
||||||
public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofencingActionNodeConfiguration> {
|
public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofencingActionNodeConfiguration> {
|
||||||
|
|
||||||
|
private static final String PRESENCE_MONITORING_STRATEGY_ON_EACH_MESSAGE = "presenceMonitoringStrategyOnEachMessage";
|
||||||
private final Map<EntityId, EntityGeofencingState> entityStates = new HashMap<>();
|
private final Map<EntityId, EntityGeofencingState> entityStates = new HashMap<>();
|
||||||
private final Gson gson = new Gson();
|
private final Gson gson = new Gson();
|
||||||
private final JsonParser parser = new JsonParser();
|
private final JsonParser parser = new JsonParser();
|
||||||
@ -83,18 +98,21 @@ public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofe
|
|||||||
boolean told = false;
|
boolean told = false;
|
||||||
if (entityState.getStateSwitchTime() == 0L || entityState.isInside() != matches) {
|
if (entityState.getStateSwitchTime() == 0L || entityState.isInside() != matches) {
|
||||||
switchState(ctx, msg.getOriginator(), entityState, matches, ts);
|
switchState(ctx, msg.getOriginator(), entityState, matches, ts);
|
||||||
ctx.tellNext(msg, matches ? "Entered" : "Left");
|
ctx.tellNext(msg, matches ? ENTERED : LEFT);
|
||||||
told = true;
|
told = true;
|
||||||
} else {
|
} else if (!config.isPresenceMonitoringStrategyOnEachMessage()) {
|
||||||
if (!entityState.isStayed()) {
|
if (!entityState.isStayed()) {
|
||||||
long stayTime = ts - entityState.getStateSwitchTime();
|
long stayTime = ts - entityState.getStateSwitchTime();
|
||||||
if (stayTime > (entityState.isInside() ?
|
if (stayTime > (entityState.isInside() ?
|
||||||
TimeUnit.valueOf(config.getMinInsideDurationTimeUnit()).toMillis(config.getMinInsideDuration()) : TimeUnit.valueOf(config.getMinOutsideDurationTimeUnit()).toMillis(config.getMinOutsideDuration()))) {
|
TimeUnit.valueOf(config.getMinInsideDurationTimeUnit()).toMillis(config.getMinInsideDuration()) : TimeUnit.valueOf(config.getMinOutsideDurationTimeUnit()).toMillis(config.getMinOutsideDuration()))) {
|
||||||
setStaid(ctx, msg.getOriginator(), entityState);
|
setStaid(ctx, msg.getOriginator(), entityState);
|
||||||
ctx.tellNext(msg, entityState.isInside() ? "Inside" : "Outside");
|
ctx.tellNext(msg, entityState.isInside() ? INSIDE : OUTSIDE);
|
||||||
told = true;
|
told = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ctx.tellNext(msg, entityState.isInside() ? INSIDE : OUTSIDE);
|
||||||
|
told = true;
|
||||||
}
|
}
|
||||||
if (!told) {
|
if (!told) {
|
||||||
ctx.tellSuccess(msg);
|
ctx.tellSuccess(msg);
|
||||||
@ -127,4 +145,17 @@ public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofe
|
|||||||
protected Class<TbGpsGeofencingActionNodeConfiguration> getConfigClazz() {
|
protected Class<TbGpsGeofencingActionNodeConfiguration> getConfigClazz() {
|
||||||
return TbGpsGeofencingActionNodeConfiguration.class;
|
return TbGpsGeofencingActionNodeConfiguration.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TbPair<Boolean, JsonNode> upgrade(int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
|
||||||
|
boolean hasChanges = false;
|
||||||
|
if (fromVersion == 0) {
|
||||||
|
if (!oldConfiguration.has(PRESENCE_MONITORING_STRATEGY_ON_EACH_MESSAGE)) {
|
||||||
|
hasChanges = true;
|
||||||
|
((ObjectNode) oldConfiguration).put(PRESENCE_MONITORING_STRATEGY_ON_EACH_MESSAGE, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new TbPair<>(hasChanges, oldConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,8 @@ public class TbGpsGeofencingActionNodeConfiguration extends TbGpsGeofencingFilte
|
|||||||
private String minInsideDurationTimeUnit;
|
private String minInsideDurationTimeUnit;
|
||||||
private String minOutsideDurationTimeUnit;
|
private String minOutsideDurationTimeUnit;
|
||||||
|
|
||||||
|
private boolean presenceMonitoringStrategyOnEachMessage;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TbGpsGeofencingActionNodeConfiguration defaultConfiguration() {
|
public TbGpsGeofencingActionNodeConfiguration defaultConfiguration() {
|
||||||
TbGpsGeofencingActionNodeConfiguration configuration = new TbGpsGeofencingActionNodeConfiguration();
|
TbGpsGeofencingActionNodeConfiguration configuration = new TbGpsGeofencingActionNodeConfiguration();
|
||||||
@ -43,6 +45,7 @@ public class TbGpsGeofencingActionNodeConfiguration extends TbGpsGeofencingFilte
|
|||||||
configuration.setMinOutsideDurationTimeUnit(TimeUnit.MINUTES.name());
|
configuration.setMinOutsideDurationTimeUnit(TimeUnit.MINUTES.name());
|
||||||
configuration.setMinInsideDuration(1);
|
configuration.setMinInsideDuration(1);
|
||||||
configuration.setMinOutsideDuration(1);
|
configuration.setMinOutsideDuration(1);
|
||||||
|
configuration.setPresenceMonitoringStrategyOnEachMessage(false);
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2024 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.rule.engine.util;
|
||||||
|
|
||||||
|
public class GpsGeofencingEvents {
|
||||||
|
public static final String ENTERED = "Entered";
|
||||||
|
public static final String INSIDE = "Inside";
|
||||||
|
public static final String LEFT = "Left";
|
||||||
|
public static final String OUTSIDE = "Outside";
|
||||||
|
}
|
||||||
@ -0,0 +1,264 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2024 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.rule.engine.geo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
|
import org.thingsboard.rule.engine.api.TbContext;
|
||||||
|
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||||
|
import org.thingsboard.rule.engine.api.TbNodeException;
|
||||||
|
import org.thingsboard.server.common.data.DataConstants;
|
||||||
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
|
import org.thingsboard.server.common.data.id.EntityId;
|
||||||
|
import org.thingsboard.server.common.data.msg.TbMsgType;
|
||||||
|
import org.thingsboard.server.common.data.util.TbPair;
|
||||||
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
|
import org.thingsboard.server.common.msg.TbMsgMetaData;
|
||||||
|
import org.thingsboard.server.dao.attributes.AttributesService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.ENTERED;
|
||||||
|
import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.INSIDE;
|
||||||
|
import static org.thingsboard.server.common.data.msg.TbNodeConnectionType.SUCCESS;
|
||||||
|
|
||||||
|
class TbGpsGeofencingActionNodeTest {
|
||||||
|
private TbContext ctx;
|
||||||
|
private TbGpsGeofencingActionNode node;
|
||||||
|
private AttributesService attributesService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
ctx = mock(TbContext.class);
|
||||||
|
attributesService = mock(AttributesService.class);
|
||||||
|
node = new TbGpsGeofencingActionNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
node.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Arguments> givenPresenceMonitoringStrategyOnEachMessage_whenOnMsg_thenVerifyOutputMsgTypes() {
|
||||||
|
return Stream.of(
|
||||||
|
// default config with presenceMonitoringStrategyOnEachMessage false
|
||||||
|
Arguments.of(false, List.of(
|
||||||
|
Map.of(ENTERED, 0, INSIDE, 0, SUCCESS, 0),
|
||||||
|
Map.of(ENTERED, 1, INSIDE, 0, SUCCESS, 0),
|
||||||
|
Map.of(ENTERED, 1, INSIDE, 0, SUCCESS, 1),
|
||||||
|
Map.of(ENTERED, 1, INSIDE, 1, SUCCESS, 1),
|
||||||
|
Map.of(ENTERED, 1, INSIDE, 1, SUCCESS, 2)
|
||||||
|
)),
|
||||||
|
// default config with presenceMonitoringStrategyOnEachMessage true
|
||||||
|
Arguments.of(true, List.of(
|
||||||
|
Map.of(ENTERED, 0, INSIDE, 0, SUCCESS, 0),
|
||||||
|
Map.of(ENTERED, 1, INSIDE, 0, SUCCESS, 0),
|
||||||
|
Map.of(ENTERED, 1, INSIDE, 1, SUCCESS, 0),
|
||||||
|
Map.of(ENTERED, 1, INSIDE, 2, SUCCESS, 0),
|
||||||
|
Map.of(ENTERED, 1, INSIDE, 3, SUCCESS, 0)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource
|
||||||
|
void givenPresenceMonitoringStrategyOnEachMessage_whenOnMsg_thenVerifyOutputMsgTypes(
|
||||||
|
boolean presenceMonitoringStrategyOnEachMessage,
|
||||||
|
List<Map<String, Integer>> outputMsgTypesCountList
|
||||||
|
) throws TbNodeException {
|
||||||
|
// GIVEN
|
||||||
|
var config = new TbGpsGeofencingActionNodeConfiguration().defaultConfiguration();
|
||||||
|
config.setPresenceMonitoringStrategyOnEachMessage(presenceMonitoringStrategyOnEachMessage);
|
||||||
|
node.init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
|
||||||
|
|
||||||
|
DeviceId deviceId = new DeviceId(UUID.randomUUID());
|
||||||
|
TbMsgMetaData metadata = getMetadataForNewVersionPolygonPerimeter();
|
||||||
|
TbMsg msg = getTbMsg(deviceId, metadata,
|
||||||
|
GeoUtilTest.POINT_OUTSIDE_SIMPLE_RECT.getLatitude(), GeoUtilTest.POINT_OUTSIDE_SIMPLE_RECT.getLongitude());
|
||||||
|
|
||||||
|
when(ctx.getAttributesService()).thenReturn(attributesService);
|
||||||
|
when(ctx
|
||||||
|
.getAttributesService()
|
||||||
|
.find(ctx.getTenantId(), msg.getOriginator(), DataConstants.SERVER_SCOPE, ctx.getServiceId()))
|
||||||
|
.thenReturn(Futures.immediateFuture(Optional.empty()));
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
ArgumentCaptor<TbMsg> newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class);
|
||||||
|
node.onMsg(ctx, msg);
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
verifyNodeOutputs(newMsgCaptor, outputMsgTypesCountList.get(0));
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
msg = getTbMsg(deviceId, metadata,
|
||||||
|
GeoUtilTest.POINT_INSIDE_SIMPLE_RECT_CENTER.getLatitude(), GeoUtilTest.POINT_INSIDE_SIMPLE_RECT_CENTER.getLongitude());
|
||||||
|
node.onMsg(ctx, msg);
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
verifyNodeOutputs(newMsgCaptor, outputMsgTypesCountList.get(1));
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
node.onMsg(ctx, msg);
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
verifyNodeOutputs(newMsgCaptor, outputMsgTypesCountList.get(2));
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
config.setMinInsideDuration(0);
|
||||||
|
node.init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
|
||||||
|
node.onMsg(ctx, msg);
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
verifyNodeOutputs(newMsgCaptor, outputMsgTypesCountList.get(3));
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
node.onMsg(ctx, msg);
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
verifyNodeOutputs(newMsgCaptor, outputMsgTypesCountList.get(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TbMsg getTbMsg(EntityId entityId, TbMsgMetaData metadata, double latitude, double longitude) {
|
||||||
|
String data = "{\"latitude\": " + latitude + ", \"longitude\": " + longitude + "}";
|
||||||
|
return TbMsg.newMsg(TbMsgType.POST_ATTRIBUTES_REQUEST, entityId, metadata, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TbMsgMetaData getMetadataForNewVersionPolygonPerimeter() {
|
||||||
|
var metadata = new TbMsgMetaData();
|
||||||
|
metadata.putValue("ss_perimeter", GeoUtilTest.SIMPLE_RECT);
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyNodeOutputs(ArgumentCaptor<TbMsg> newMsgCaptor, Map<String, Integer> outputMsgTypesCount) {
|
||||||
|
verify(this.ctx, times(outputMsgTypesCount.get(ENTERED))).tellNext(newMsgCaptor.capture(), eq(ENTERED));
|
||||||
|
verify(this.ctx, times(outputMsgTypesCount.get(INSIDE))).tellNext(newMsgCaptor.capture(), eq(INSIDE));
|
||||||
|
verify(this.ctx, times(outputMsgTypesCount.get(SUCCESS))).tellSuccess(newMsgCaptor.capture());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rule nodes upgrade
|
||||||
|
private static Stream<Arguments> givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() {
|
||||||
|
return Stream.of(
|
||||||
|
// default config for version 0
|
||||||
|
Arguments.of(0,
|
||||||
|
"{\n" +
|
||||||
|
" \"minInsideDuration\": 1,\n" +
|
||||||
|
" \"minOutsideDuration\": 1,\n" +
|
||||||
|
" \"minInsideDurationTimeUnit\": \"MINUTES\",\n" +
|
||||||
|
" \"minOutsideDurationTimeUnit\": \"MINUTES\",\n" +
|
||||||
|
" \"latitudeKeyName\": \"latitude\",\n" +
|
||||||
|
" \"longitudeKeyName\": \"longitude\",\n" +
|
||||||
|
" \"perimeterType\": \"POLYGON\",\n" +
|
||||||
|
" \"fetchPerimeterInfoFromMessageMetadata\": true,\n" +
|
||||||
|
" \"perimeterKeyName\": \"ss_perimeter\",\n" +
|
||||||
|
" \"polygonsDefinition\": null,\n" +
|
||||||
|
" \"centerLatitude\": null,\n" +
|
||||||
|
" \"centerLongitude\": null,\n" +
|
||||||
|
" \"range\": null,\n" +
|
||||||
|
" \"rangeUnit\": null\n" +
|
||||||
|
"}\n",
|
||||||
|
true,
|
||||||
|
"{\n" +
|
||||||
|
" \"minInsideDuration\": 1,\n" +
|
||||||
|
" \"minOutsideDuration\": 1,\n" +
|
||||||
|
" \"minInsideDurationTimeUnit\": \"MINUTES\",\n" +
|
||||||
|
" \"minOutsideDurationTimeUnit\": \"MINUTES\",\n" +
|
||||||
|
" \"presenceMonitoringStrategyOnEachMessage\": false,\n" +
|
||||||
|
" \"latitudeKeyName\": \"latitude\",\n" +
|
||||||
|
" \"longitudeKeyName\": \"longitude\",\n" +
|
||||||
|
" \"perimeterType\": \"POLYGON\",\n" +
|
||||||
|
" \"fetchPerimeterInfoFromMessageMetadata\": true,\n" +
|
||||||
|
" \"perimeterKeyName\": \"ss_perimeter\",\n" +
|
||||||
|
" \"polygonsDefinition\": null,\n" +
|
||||||
|
" \"centerLatitude\": null,\n" +
|
||||||
|
" \"centerLongitude\": null,\n" +
|
||||||
|
" \"range\": null,\n" +
|
||||||
|
" \"rangeUnit\": null\n" +
|
||||||
|
"}\n"),
|
||||||
|
// default config for version 1 with upgrade from version 0
|
||||||
|
Arguments.of(0,
|
||||||
|
"{\n" +
|
||||||
|
" \"minInsideDuration\": 1,\n" +
|
||||||
|
" \"minOutsideDuration\": 1,\n" +
|
||||||
|
" \"minInsideDurationTimeUnit\": \"MINUTES\",\n" +
|
||||||
|
" \"minOutsideDurationTimeUnit\": \"MINUTES\",\n" +
|
||||||
|
" \"presenceMonitoringStrategyOnEachMessage\": false,\n" +
|
||||||
|
" \"latitudeKeyName\": \"latitude\",\n" +
|
||||||
|
" \"longitudeKeyName\": \"longitude\",\n" +
|
||||||
|
" \"perimeterType\": \"POLYGON\",\n" +
|
||||||
|
" \"fetchPerimeterInfoFromMessageMetadata\": true,\n" +
|
||||||
|
" \"perimeterKeyName\": \"ss_perimeter\",\n" +
|
||||||
|
" \"polygonsDefinition\": null,\n" +
|
||||||
|
" \"centerLatitude\": null,\n" +
|
||||||
|
" \"centerLongitude\": null,\n" +
|
||||||
|
" \"range\": null,\n" +
|
||||||
|
" \"rangeUnit\": null\n" +
|
||||||
|
"}\n",
|
||||||
|
false,
|
||||||
|
"{\n" +
|
||||||
|
" \"minInsideDuration\": 1,\n" +
|
||||||
|
" \"minOutsideDuration\": 1,\n" +
|
||||||
|
" \"minInsideDurationTimeUnit\": \"MINUTES\",\n" +
|
||||||
|
" \"minOutsideDurationTimeUnit\": \"MINUTES\",\n" +
|
||||||
|
" \"presenceMonitoringStrategyOnEachMessage\": false,\n" +
|
||||||
|
" \"latitudeKeyName\": \"latitude\",\n" +
|
||||||
|
" \"longitudeKeyName\": \"longitude\",\n" +
|
||||||
|
" \"perimeterType\": \"POLYGON\",\n" +
|
||||||
|
" \"fetchPerimeterInfoFromMessageMetadata\": true,\n" +
|
||||||
|
" \"perimeterKeyName\": \"ss_perimeter\",\n" +
|
||||||
|
" \"polygonsDefinition\": null,\n" +
|
||||||
|
" \"centerLatitude\": null,\n" +
|
||||||
|
" \"centerLongitude\": null,\n" +
|
||||||
|
" \"range\": null,\n" +
|
||||||
|
" \"rangeUnit\": null\n" +
|
||||||
|
"}\n")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource
|
||||||
|
void givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig(int givenVersion, String givenConfigStr, boolean hasChanges, String expectedConfigStr) throws TbNodeException {
|
||||||
|
// GIVEN
|
||||||
|
JsonNode givenConfig = JacksonUtil.toJsonNode(givenConfigStr);
|
||||||
|
JsonNode expectedConfig = JacksonUtil.toJsonNode(expectedConfigStr);
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
TbPair<Boolean, JsonNode> upgradeResult = node.upgrade(givenVersion, givenConfig);
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
assertThat(upgradeResult.getFirst()).isEqualTo(hasChanges);
|
||||||
|
ObjectNode upgradedConfig = (ObjectNode) upgradeResult.getSecond();
|
||||||
|
assertThat(upgradedConfig).isEqualTo(expectedConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user