Skip to content

Commit

Permalink
Merge pull request #1172 from OSGP/feature/SMHE-1841_WithList
Browse files Browse the repository at this point in the history
SMHE-1841: Make get/set WithList more efficient
  • Loading branch information
stefanermens authored Feb 20, 2024
2 parents 4a4061d + b20824e commit e64723f
Show file tree
Hide file tree
Showing 22 changed files with 162 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public class PlatformSmartmeteringDefaults
public static final Instant TECHNICAL_INSTALLATION_DATE = Instant.now();
public static final Date VALID_TO = null;
public static final Long VERSION = 0L;
public static final boolean WITH_LIST_SUPPORTED = false;
public static final Integer WITH_LIST_MAX = 32;

public static final String DAYLIGHT_SAVINGS_BEGIN = "FFFF03FE0702000000FFC400";
public static final String DAYLIGHT_SAVINGS_END = "FFFF0AFE0703000000FF8880";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public class PlatformSmartmeteringKeys
public static final String TECHNICAL_INSTALLATION_DATE = "TechnicalInstallationDate";
public static final String VALID_FROM = "ValidFrom";
public static final String VERSION = "Version";
public static final String WITH_LIST_SUPPORTED = "WithListSupported";
public static final String WITH_LIST_MAX = "WithListMax";
public static final String MODULE_ACTIVE_FIRMWARE_VERSION = "ModuleActiveFirmwareVersion";

public static final String DAYLIGHT_SAVINGS_BEGIN = "DaylightSavingsBegin";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class DlmsDeviceBuilder implements CucumberBuilder<DlmsDevice> {
private boolean useHdlc = PlatformSmartmeteringDefaults.USE_HDLC;
private boolean polyphase = PlatformSmartmeteringDefaults.POLYPHASE;
private Integer challengeLength = PlatformSmartmeteringDefaults.CHALLENGE_LENGTH;
private boolean withListSupported = PlatformSmartmeteringDefaults.WITH_LIST_SUPPORTED;
private Integer withListMax = PlatformSmartmeteringDefaults.WITH_LIST_MAX;
private boolean selectiveAccessSupported =
PlatformSmartmeteringDefaults.SELECTIVE_ACCESS_SUPPORTED;
private boolean ipAddressIsStatic = PlatformSmartmeteringDefaults.IP_ADDRESS_IS_STATIC;
Expand Down Expand Up @@ -111,8 +111,8 @@ public DlmsDeviceBuilder setChallengeLength(final Integer challengeLength) {
return this;
}

public DlmsDeviceBuilder setWithListSupported(final boolean withListSupported) {
this.withListSupported = withListSupported;
public DlmsDeviceBuilder setWithListMax(final Integer withListMax) {
this.withListMax = withListMax;
return this;
}

Expand Down Expand Up @@ -222,9 +222,9 @@ public DlmsDeviceBuilder withSettings(final Map<String, String> inputSettings) {
this.setChallengeLength(
Integer.parseInt(inputSettings.get(PlatformSmartmeteringKeys.CHALLENGE_LENGTH)));
}
if (inputSettings.containsKey(PlatformSmartmeteringKeys.WITH_LIST_SUPPORTED)) {
this.setWithListSupported(
Boolean.parseBoolean(inputSettings.get(PlatformSmartmeteringKeys.WITH_LIST_SUPPORTED)));
if (inputSettings.containsKey(PlatformSmartmeteringKeys.WITH_LIST_MAX)) {
this.setWithListMax(
Integer.parseInt(inputSettings.get(PlatformSmartmeteringKeys.WITH_LIST_MAX)));
}
if (inputSettings.containsKey(PlatformSmartmeteringKeys.SELECTIVE_ACCESS_SUPPORTED)) {
this.setSelectiveAccessSupported(
Expand Down Expand Up @@ -311,7 +311,7 @@ public DlmsDevice build() {
dlmsDevice.setUseSn(this.useSn);
dlmsDevice.setPolyphase(this.polyphase);
dlmsDevice.setChallengeLength(this.challengeLength);
dlmsDevice.setWithListSupported(this.withListSupported);
dlmsDevice.setWithListMax(this.withListMax);
dlmsDevice.setSelectiveAccessSupported(this.selectiveAccessSupported);
dlmsDevice.setIpAddressIsStatic(this.ipAddressIsStatic);
dlmsDevice.setPort(this.port);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,24 @@ public void theDeviceShouldBeInTheDatabaseWithAttributes(
final DlmsDevice device =
this.dlmsDeviceRepository.findByDeviceIdentification(deviceIdentification);

final int expectedResult =
final int expectedResultChallengeLength =
getInteger(
settings,
PlatformSmartmeteringKeys.CHALLENGE_LENGTH,
PlatformSmartmeteringDefaults.CHALLENGE_LENGTH);

final int expectedResultGetWithListMax =
getInteger(
settings,
PlatformSmartmeteringKeys.WITH_LIST_MAX,
PlatformSmartmeteringDefaults.WITH_LIST_MAX);

assertThat(device.getChallengeLength().intValue())
.as("Number of challenge length should match")
.isEqualTo(expectedResult);
assertThat(device.isWithListSupported())
.as("With list supported should match")
.isEqualTo(getBoolean(settings, PlatformSmartmeteringKeys.WITH_LIST_SUPPORTED));
.isEqualTo(expectedResultChallengeLength);
assertThat(device.getWithListMax().intValue())
.as("With list max should match")
.isEqualTo(expectedResultGetWithListMax);
assertThat(device.isSelectiveAccessSupported())
.as("Selective access supported should match")
.isEqualTo(getBoolean(settings, PlatformSmartmeteringKeys.SELECTIVE_ACCESS_SUPPORTED));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ public static SetDeviceCommunicationSettingsData fromParameterMap(

setDeviceCommunicationSettingsData.setChallengeLength(
BigInteger.valueOf(getInteger(parameters, PlatformSmartmeteringKeys.CHALLENGE_LENGTH)));
setDeviceCommunicationSettingsData.setWithListSupported(
getBoolean(
parameters,
PlatformSmartmeteringKeys.WITH_LIST_SUPPORTED,
PlatformSmartmeteringDefaults.WITH_LIST_SUPPORTED));
setDeviceCommunicationSettingsData.setWithListMax(
BigInteger.valueOf(
getInteger(
parameters,
PlatformSmartmeteringKeys.WITH_LIST_MAX,
PlatformSmartmeteringDefaults.WITH_LIST_MAX)));
setDeviceCommunicationSettingsData.setSelectiveAccessSupported(
getBoolean(
parameters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Feature: SmartMetering Management - Set Device Communication Settings
| DeviceIdentification | TEST1024000000001 |
| DeviceType | SMART_METER_E |
| ChallengeLength | 8 |
| WithListSupported | true |
| WithListMax | 32 |
| SelectiveAccessSupported | true |
| IpAddressIsStatic | true |
| UseSn | true |
Expand All @@ -22,7 +22,7 @@ Feature: SmartMetering Management - Set Device Communication Settings
When the set device communication settings request is received
| DeviceIdentification | TEST1024000000001 |
| ChallengeLength | 16 |
| WithListSupported | false |
| WithListMax | 1 |
| SelectiveAccessSupported | false |
| IpAddressIsStatic | false |
| UseSn | false |
Expand All @@ -31,7 +31,7 @@ Feature: SmartMetering Management - Set Device Communication Settings
Then the set device communication settings response should be "OK"
And the device "TEST1024000000001" should be in the database with attributes
| ChallengeLength | 16 |
| WithListSupported | false |
| WithListMax | 1 |
| SelectiveAccessSupported | false |
| IpAddressIsStatic | false |
| UseSn | false |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class DeviceMappingTest {
private static final String SUPPLIER = "supplier1";
private static final Long PORT = 3000L;
private static final int CHALLENGE_LENGTH = 15;
private static final int WITH_LIST_MAX = 32;
private static final boolean IS_ACTIVE = true;
private static final boolean LLS1_ACTIVE = true;

Expand Down Expand Up @@ -62,7 +63,7 @@ private void checkDeviceToSmartMeteringDeviceMapping(
assertThat(smartMeteringDevice.isPolyphase()).isEqualTo(IS_ACTIVE);
assertThat(smartMeteringDevice.isIpAddressIsStatic()).isEqualTo(IS_ACTIVE);
assertThat(smartMeteringDevice.isSelectiveAccessSupported()).isEqualTo(IS_ACTIVE);
assertThat(smartMeteringDevice.isWithListSupported()).isEqualTo(IS_ACTIVE);
assertThat(smartMeteringDevice.getWithListMax()).isEqualTo(WITH_LIST_MAX);
assertThat(smartMeteringDevice.getChallengeLength()).isEqualTo(CHALLENGE_LENGTH);

// convert a Date object to a joda DateTime object, because the
Expand Down Expand Up @@ -136,7 +137,7 @@ private Device createDevice() {
device.setChallengeLength(CHALLENGE_LENGTH);
device.setIpAddressIsStatic(IS_ACTIVE);
device.setSelectiveAccessSupported(IS_ACTIVE);
device.setWithListSupported(IS_ACTIVE);
device.setWithListMax(WITH_LIST_MAX);
return device;
}

Expand Down Expand Up @@ -165,7 +166,7 @@ private SmartMeteringDevice createSmartMeteringDevice() {
smartMeteringDevice.setPort(PORT);
smartMeteringDevice.setChallengeLength(CHALLENGE_LENGTH);
smartMeteringDevice.setIpAddressIsStatic(IS_ACTIVE);
smartMeteringDevice.setWithListSupported(IS_ACTIVE);
smartMeteringDevice.setWithListMax(WITH_LIST_MAX);
smartMeteringDevice.setSelectiveAccessSupported(IS_ACTIVE);

return smartMeteringDevice;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class SetDeviceCommunicationSettingsData implements Serializable, ActionR
private static final long serialVersionUID = -6825967173128763377L;

private final int challengeLength;
private final boolean withListSupported;
private final int withListMax;
private final boolean selectiveAccessSupported;
private final boolean ipAddressIsStatic;
private final boolean useSn;
Expand All @@ -22,14 +22,14 @@ public class SetDeviceCommunicationSettingsData implements Serializable, ActionR

public SetDeviceCommunicationSettingsData(
final int challengeLength,
final boolean withListSupported,
final int withListMax,
final boolean selectiveAccessSupported,
final boolean ipAddressIsStatic,
final boolean useSn,
final boolean useHdlc,
final boolean polyphase) {
this.challengeLength = challengeLength;
this.withListSupported = withListSupported;
this.withListMax = withListMax;
this.selectiveAccessSupported = selectiveAccessSupported;
this.ipAddressIsStatic = ipAddressIsStatic;
this.useSn = useSn;
Expand All @@ -41,8 +41,8 @@ public int getChallengeLength() {
return this.challengeLength;
}

public boolean isWithListSupported() {
return this.withListSupported;
public int getWithListMax() {
return this.withListMax;
}

public boolean isSelectiveAccessSupported() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ public class SmartMeteringDevice implements Serializable {
private Long port;
private Integer challengeLength;
private boolean ipAddressIsStatic;
private boolean withListSupported;
private Integer withListMax;
private boolean selectiveAccessSupported;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public DlmsDevice convertTo(
dlmsDevice.setProtocol(source.getProtocolName(), source.getProtocolVersion());
dlmsDevice.setTimezone(source.getTimezone());
dlmsDevice.setIpAddressIsStatic(source.isIpAddressIsStatic());
dlmsDevice.setWithListSupported(source.isWithListSupported());
dlmsDevice.setWithListMax(source.getWithListMax());
dlmsDevice.setSelectiveAccessSupported(source.isSelectiveAccessSupported());
dlmsDevice.setPolyphase(source.isPolyphase());
if (source.getPort() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private DlmsDevice setDeviceCommunicationSettings(
final DlmsDevice device,
final SetDeviceCommunicationSettingsRequestDataDto setCommunicationSettingsDataDto) {
device.setChallengeLength(setCommunicationSettingsDataDto.getChallengeLength());
device.setWithListSupported(setCommunicationSettingsDataDto.isWithListSupported());
device.setWithListMax(setCommunicationSettingsDataDto.getWithListMax());
device.setSelectiveAccessSupported(
setCommunicationSettingsDataDto.isSelectiveAccessSupported());
device.setIpAddressIsStatic(setCommunicationSettingsDataDto.isIpAddressIsStatic());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ public class DlmsHelper {
private static final Map<Integer, TransportServiceTypeDto> TRANSPORT_SERVICE_TYPE_PER_ENUM_VALUE =
new TreeMap<>();

private static final int MAX_CONCURRENT_ATTRIBUTE_ADDRESSES = 32;

static {
TRANSPORT_SERVICE_TYPE_PER_ENUM_VALUE.put(0, TransportServiceTypeDto.TCP);
TRANSPORT_SERVICE_TYPE_PER_ENUM_VALUE.put(1, TransportServiceTypeDto.UDP);
Expand Down Expand Up @@ -195,25 +193,22 @@ public List<GetResult> getWithList(
final DlmsConnectionManager conn, final DlmsDevice device, final AttributeAddress... params)
throws ProtocolAdapterException {
try {
if (device.isWithListSupported()) {
// Getting a too large list of attribute addresses in one get
// from the DlmsConnection
// might result in a SCOPE_OF_ACCESS_VIOLATED error
final List<GetResult> getResults = new ArrayList<>();
final List<AttributeAddress[]> maximizedSubsetsOfParams =
this.getMaximizedSubsetsOfParams(params);
for (final AttributeAddress[] maximizedSubsetOfParams : maximizedSubsetsOfParams) {
getResults.addAll(conn.getConnection().get(Arrays.asList(maximizedSubsetOfParams)));
}
return getResults;
} else {
return this.getWithListWorkaround(conn, params);
// Getting a too large list of attribute addresses in one get from the DlmsConnection
// might result in a SCOPE_OF_ACCESS_VIOLATED error
Integer maxItemsInRequest = device.getWithListMax();
if (maxItemsInRequest == null || maxItemsInRequest < 1) {
maxItemsInRequest = 1;
}
final List<GetResult> getResults = new ArrayList<>();
final List<AttributeAddress[]> maximizedSubsetsOfParams =
this.getMaximizedSubsetsOfParams(maxItemsInRequest, params);
for (final AttributeAddress[] maximizedSubsetOfParams : maximizedSubsetsOfParams) {
getResults.addAll(conn.getConnection().get(Arrays.asList(maximizedSubsetOfParams)));
}
return getResults;
} catch (final IOException | NullPointerException e) {
// The jDMLS code throws a NullPointerException instead of a
// ResponseTimeoutException
// (specific type of IOException via NonFatalJDlmsException and
// JDlmsException).
// The jDMLS code throws a NullPointerException instead of a ResponseTimeoutException
// (specific type of IOException via NonFatalJDlmsException and JDlmsException).
throw new ConnectionException(
"Connection error retrieving values with-list for device: "
+ device.getDeviceIdentification(),
Expand All @@ -222,15 +217,14 @@ public List<GetResult> getWithList(
throw new ProtocolAdapterException(
"Error retrieving values with-list for device: "
+ device.getDeviceIdentification()
+ ", with-list: "
+ (device.isWithListSupported() ? "supported" : "not supported"),
+ ", with-list max: "
+ device.getWithListMax(),
e);
}
}

private List<AttributeAddress[]> getMaximizedSubsetsOfParams(
final AttributeAddress[] attributeAddresses) {
final int chunk = MAX_CONCURRENT_ATTRIBUTE_ADDRESSES;
final int chunk, final AttributeAddress[] attributeAddresses) {
final List<AttributeAddress[]> maximizedCurrentSets = new ArrayList<>();
for (int i = 0; i < attributeAddresses.length; i += chunk) {
maximizedCurrentSets.add(
Expand Down Expand Up @@ -375,21 +369,6 @@ public DataObject getAMRProfileDefinition() {
return DataObjectDefinitions.getAMRProfileDefinition();
}

/**
* Workaround method mimicking a Get-Request with-list for devices that do not support the actual
* functionality from DLMS.
*
* @see #getWithList(DlmsConnectionManager, DlmsDevice, AttributeAddress...)
*/
private List<GetResult> getWithListWorkaround(
final DlmsConnectionManager conn, final AttributeAddress... params) throws IOException {
final List<GetResult> getResultList = new ArrayList<>();
for (final AttributeAddress param : params) {
getResultList.add(conn.getConnection().get(param));
}
return getResultList;
}

private void checkResultCode(final GetResult getResult, final String description)
throws ProtocolAdapterException {
final AccessResultCode resultCode = getResult.getResultCode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class DlmsDevice extends AbstractEntity {

@Column private Integer challengeLength;

@Column private boolean withListSupported;
@Column private Integer withListMax;

@Column private boolean selectiveAccessSupported;

Expand Down Expand Up @@ -229,12 +229,12 @@ public void setChallengeLength(final Integer challengeLength) {
this.challengeLength = challengeLength;
}

public boolean isWithListSupported() {
return this.withListSupported;
public Integer getWithListMax() {
return this.withListMax;
}

public void setWithListSupported(final boolean withListSupported) {
this.withListSupported = withListSupported;
public void setWithListMax(final Integer withListMax) {
this.withListMax = withListMax;
}

public boolean isSelectiveAccessSupported() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ALTER TABLE dlms_device ADD COLUMN with_list_max integer DEFAULT 1;

UPDATE dlms_device
SET with_list_max = 32
WHERE with_list_supported = true;

UPDATE dlms_device
SET with_list_max = 1
WHERE with_list_supported = false;

ALTER TABLE dlms_device DROP COLUMN with_list_supported;
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private DlmsDevice converted(final SmartMeteringDeviceDto dto) {
dlmsDevice.setPort(dto.getPort());
dlmsDevice.setChallengeLength(dto.getChallengeLength());
dlmsDevice.setIpAddressIsStatic(dto.isIpAddressIsStatic());
dlmsDevice.setWithListSupported(dto.isWithListSupported());
dlmsDevice.setWithListMax(dto.getWithListMax());
dlmsDevice.setSelectiveAccessSupported(dto.isSelectiveAccessSupported());
return dlmsDevice;
}
Expand Down
Loading

0 comments on commit e64723f

Please sign in to comment.