diff --git a/pom.xml b/pom.xml
index d89b013..b690daa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,13 +7,16 @@
test.com
1.0-SNAPSHOT
-
com.fasterxml.jackson.core
jackson-databind
2.11.1
-
+
+ org.slf4j
+ slf4j-api
+ 1.7.32
+
com.google.guava
guava
diff --git a/src/main/java/home/automation/modbus/ModbusCachedWrapper.java b/src/main/java/home/automation/modbus/ModbusCachedWrapper.java
index 71716e3..983b84f 100644
--- a/src/main/java/home/automation/modbus/ModbusCachedWrapper.java
+++ b/src/main/java/home/automation/modbus/ModbusCachedWrapper.java
@@ -2,25 +2,27 @@ package home.automation.modbus;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
+import lombok.extern.slf4j.Slf4j;
+import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-public class ModbusCachedWrapper implements ModbusRepository {
+@Slf4j
+public class ModbusCachedWrapper implements Repository {
private final Cache repositoryCache;
private final Cache> repositoryCacheAllElements;
- private final ModbusRepository repository;
+ private final Repository repository;
public static final int ALL_ELEMENTS = 1;
- public ModbusCachedWrapper(ModbusRepository repository) {
+ public ModbusCachedWrapper(Repository repository, Duration prevenstionTime) {
this.repository = repository;
repositoryCacheAllElements = CacheBuilder.newBuilder()
- .expireAfterWrite(1, TimeUnit.MINUTES)
+ .expireAfterWrite(prevenstionTime)
.build();
repositoryCache = CacheBuilder.newBuilder()
- .expireAfterWrite(1, TimeUnit.MINUTES)
+ .expireAfterWrite(prevenstionTime)
.build();
}
@@ -29,7 +31,7 @@ public class ModbusCachedWrapper implements ModbusRepository {
try {
return repositoryCacheAllElements.get(ALL_ELEMENTS, repository::getAll);
} catch (ExecutionException e) {
- e.printStackTrace();
+ log.error("Cannot get all keys due to: ", e);
return Collections.singletonList(Registry.builder().registry(0).desc("").value("").build());
}
}
@@ -39,7 +41,7 @@ public class ModbusCachedWrapper implements ModbusRepository {
try {
return repositoryCache.get(register, () -> repository.get(register));
} catch (ExecutionException e) {
- e.printStackTrace();
+ log.error("Cannot get" + register + "due to: ", e);
return Registry.builder().registry(0).desc("").value("").build();
}
}
diff --git a/src/main/java/home/automation/modbus/ModbusConnection.java b/src/main/java/home/automation/modbus/ModbusConnection.java
index c4c079a..00484f6 100644
--- a/src/main/java/home/automation/modbus/ModbusConnection.java
+++ b/src/main/java/home/automation/modbus/ModbusConnection.java
@@ -16,8 +16,8 @@ public class ModbusConnection {
public ModbusConnection(ConfigurationStrategy config) {
this.config = config;
- Runtime.getRuntime().addShutdownHook(new Thread(()->{
- if(Objects.nonNull(connection)){
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ if (Objects.nonNull(connection)) {
connection.destroy();
}
}));
@@ -29,7 +29,7 @@ public class ModbusConnection {
.orElseThrow(() -> new RuntimeException("Missing configuration"));
}
- public ModbusMaster getConnection() throws Exception {
+ synchronized public ModbusMaster getConnection() throws Exception {
if (isNull(connection) || !connection.isConnected()) {
if (Objects.nonNull(connection)) {
connection.destroy();
diff --git a/src/main/java/home/automation/modbus/ModbusRtuTcpRepository.java b/src/main/java/home/automation/modbus/ModbusRtuTcpRepository.java
index 3e9612b..06bf731 100644
--- a/src/main/java/home/automation/modbus/ModbusRtuTcpRepository.java
+++ b/src/main/java/home/automation/modbus/ModbusRtuTcpRepository.java
@@ -14,10 +14,10 @@ import java.util.stream.Collectors;
import static com.serotonin.modbus4j.code.DataType.TWO_BYTE_INT_SIGNED;
-public class ModbusRtuTcpRepository implements ModbusRepository {
+public class ModbusRtuTcpRepository implements Repository {
- public static final int ZERO = 0;
- public static final int HALF_SHORT_INT = 32768;
+ private static final int ZERO = 0;
+ private static final int HALF_SHORT_INT = 32768;
private final ModbusConnection connection;
private final List registryMappings;
@@ -63,7 +63,7 @@ public class ModbusRtuTcpRepository implements ModbusRepository {
@Override
public Registry get(int register) {
try {
- ReadHoldingRegistersResponse response = gerRegistry(register);
+ ReadHoldingRegistersResponse response = getRegistry(register);
final String value = normalizeRegistryValue(response.getShortData()[0]);
final RegistryMapping mapping = findRegistryMapping(register);
@@ -77,7 +77,7 @@ public class ModbusRtuTcpRepository implements ModbusRepository {
}
@NotNull
- private ReadHoldingRegistersResponse gerRegistry(int register) throws Exception {
+ private ReadHoldingRegistersResponse getRegistry(int register) throws Exception {
ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(1, register, 1);
ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) connection.getConnection().send(request);
diff --git a/src/main/java/home/automation/modbus/ModbusService.java b/src/main/java/home/automation/modbus/ModbusService.java
index 31dd3bc..56a246d 100644
--- a/src/main/java/home/automation/modbus/ModbusService.java
+++ b/src/main/java/home/automation/modbus/ModbusService.java
@@ -4,9 +4,9 @@ import java.util.List;
public class ModbusService {
- private final ModbusRtuTcpRepository repository;
+ private final Repository repository;
- public ModbusService(ModbusRtuTcpRepository repository) {
+ public ModbusService(Repository repository) {
this.repository = repository;
}
diff --git a/src/main/java/home/automation/modbus/ModbusRepository.java b/src/main/java/home/automation/modbus/Repository.java
similarity index 77%
rename from src/main/java/home/automation/modbus/ModbusRepository.java
rename to src/main/java/home/automation/modbus/Repository.java
index f227170..bb095eb 100644
--- a/src/main/java/home/automation/modbus/ModbusRepository.java
+++ b/src/main/java/home/automation/modbus/Repository.java
@@ -2,7 +2,7 @@ package home.automation.modbus;
import java.util.List;
-public interface ModbusRepository {
+public interface Repository {
List getAll();
Registry get(int register);
diff --git a/src/test/java/home/automation/configuration/JsonFileBasedConfigurationTest.java b/src/test/java/home/automation/configuration/JsonFileBasedConfigurationTest.java
index 25aacea..b9c1e88 100644
--- a/src/test/java/home/automation/configuration/JsonFileBasedConfigurationTest.java
+++ b/src/test/java/home/automation/configuration/JsonFileBasedConfigurationTest.java
@@ -11,6 +11,5 @@ class JsonFileBasedConfigurationTest {
ConfigurationStrategy configuration = new JsonFileBasedConfiguration();
final Optional config = configuration.getConfig();
assert (config.isPresent());
- System.out.println(config.get());
}
}
\ No newline at end of file
diff --git a/src/test/java/home/automation/modbus/ModbusCachedWrapperTest.java b/src/test/java/home/automation/modbus/ModbusCachedWrapperTest.java
new file mode 100644
index 0000000..ab170f0
--- /dev/null
+++ b/src/test/java/home/automation/modbus/ModbusCachedWrapperTest.java
@@ -0,0 +1,81 @@
+package home.automation.modbus;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.Duration;
+import java.util.List;
+
+import static java.lang.Thread.sleep;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+class ModbusCachedWrapperTest {
+
+ public static final int MAX_TESTS = 10;
+ private final RepositoryInMemory repository = new RepositoryInMemory();
+ private final ModbusCachedWrapper cachedRepository = new ModbusCachedWrapper(repository, Duration.ofSeconds(1));
+
+ @Test
+ public void givenRepositoryInMemoryAndCacheDurationOf1Seconds_WhenGetRegistryFromCachedRepository2times_ThenValuesAreTheSame() {
+ final Registry firstTry = cachedRepository.get(4065);
+ final Registry secondTry = cachedRepository.get(4065);
+ assert (firstTry.getValue().equals(secondTry.getValue()));
+ }
+
+ @Test
+ public void givenRepositoryInMemoryAndCacheDurationOf1Seconds_WhenGetRegistryFromCachedRepository2timesWithDelayMoreThan1Sec_ThenValuesAreTheDifferent() throws InterruptedException {
+ final Registry firstTry = cachedRepository.get(4065);
+ final long currentTimeMillis = System.currentTimeMillis();
+ final long desireTimeoutInMs = 1000;
+ while (desireTimeoutInMs > System.currentTimeMillis() - currentTimeMillis) {
+ sleep(510);
+ }
+ final Registry secondTry = cachedRepository.get(4065);
+ assert (!firstTry.getValue().equals(secondTry.getValue()));
+ }
+
+ @Test
+ public void givenRepositoryInMemoryAndCacheDurationOf3Seconds_WhenGetRegistryFromCachedRepositoryMultipleTimesWithIn3SecondDelay_ThenAllValuesAreTheSame() throws InterruptedException {
+ final Registry firstTry = cachedRepository.get(4065);
+ final long currentTimeMillis = System.currentTimeMillis();
+ final long desireTimeoutInMs = 500;
+ int count = 0;
+ while (desireTimeoutInMs > System.currentTimeMillis() - currentTimeMillis || count == MAX_TESTS) {
+ count++;
+ final Registry secondTry = cachedRepository.get(4065);
+ assert (firstTry.getValue().equals(secondTry.getValue()));
+ }
+ }
+
+ @Test
+ public void givenRepositoryInMemoryAndCacheDurationOf3Seconds_WhenGetAllFromCachedRepository2times_ThenValuesAreTheSame() {
+ final List firstTry = cachedRepository.getAll();
+ final List secondTry = cachedRepository.getAll();
+ assertEquals(firstTry, secondTry);
+ }
+
+ @Test
+ public void givenRepositoryInMemoryAndCacheDurationOf3Seconds_WhenGetAllFromCachedRepository2timesWith4SecondDelay_ThenValuesAreTheDifferent() throws InterruptedException {
+ final List firstTry = cachedRepository.getAll();
+ final long currentTimeMillis = System.currentTimeMillis();
+ final long desireTimeoutInMs = 1000;
+ while (desireTimeoutInMs > System.currentTimeMillis() - currentTimeMillis) {
+ sleep(510);
+ }
+ final List secondTry = cachedRepository.getAll();
+ assertNotEquals(firstTry, secondTry);
+ }
+
+ @Test
+ public void givenRepositoryInMemoryAndCacheDurationOf3Seconds_WhenGetAllFromCachedRepositoryMultipleTimesWithIn3SecondDelay_ThenAllValuesAreTheSame() throws InterruptedException {
+ final List firstTry = cachedRepository.getAll();
+ final long currentTimeMillis = System.currentTimeMillis();
+ final long desireTimeoutInMs = 500;
+ int count = 0;
+ while (desireTimeoutInMs > System.currentTimeMillis() - currentTimeMillis || count == MAX_TESTS) {
+ count++;
+ final List secondTry = cachedRepository.getAll();
+ assertEquals(firstTry, secondTry);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/home/automation/modbus/ModbusServiceTest.java b/src/test/java/home/automation/modbus/ModbusServiceTest.java
new file mode 100644
index 0000000..f7c25d7
--- /dev/null
+++ b/src/test/java/home/automation/modbus/ModbusServiceTest.java
@@ -0,0 +1,28 @@
+package home.automation.modbus;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ModbusServiceTest {
+
+ @Test
+ public void givenRegistryWhenGetRegistryThenValueFromRepositoryIsReturned(){
+ ModbusService service = new ModbusService(new RepositoryInMemory());
+ int givenRegistry = 4065;
+ final Registry registry = service.get(givenRegistry);
+ assertTrue(Objects.nonNull(registry));
+ }
+
+ @Test
+ public void givenNoRegistryWhenGetAllRegistryThenListOfValuesFromRepositoryIsReturned(){
+ ModbusService service = new ModbusService(new RepositoryInMemory());
+ final List registry = service.readAll();
+ assertTrue(Objects.nonNull(registry));
+ assertFalse(registry.isEmpty());
+ }
+}
diff --git a/src/test/java/home/automation/modbus/RepositoryInMemory.java b/src/test/java/home/automation/modbus/RepositoryInMemory.java
new file mode 100644
index 0000000..6ccc6c6
--- /dev/null
+++ b/src/test/java/home/automation/modbus/RepositoryInMemory.java
@@ -0,0 +1,31 @@
+package home.automation.modbus;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+public class RepositoryInMemory implements Repository {
+ private final List DEFINED_REGISTRY_FOR_TEST =
+ Arrays.asList(4065, 4070, 4071, 4072, 4067, 4202, 4069, 4203, 4066, 4201, 4199);
+
+ @Override
+ public List getAll() {
+ return DEFINED_REGISTRY_FOR_TEST.stream()
+ .map(this::generateRandomResponse)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Registry get(int register) {
+ return generateRandomResponse(register);
+ }
+
+ private Registry generateRandomResponse(int registry) {
+ final Random random = new Random();
+ return Registry.builder()
+ .registry(registry)
+ .value(Double.toString(random.nextDouble()))
+ .desc("TEST").build();
+ }
+}