Compare commits
11 Commits
1c00338d2d
...
7868add638
| Author | SHA1 | Date | |
|---|---|---|---|
| 7868add638 | |||
| 31dcf88642 | |||
| 50fc3ceaa7 | |||
| dbfb3b6bb0 | |||
| 5fc07ef69f | |||
| 8049646a8a | |||
| 0e4b212f99 | |||
| 0c4644e6b7 | |||
| ee8988056a | |||
| aef1113061 | |||
| f03ac31ae4 |
@@ -1,13 +1,15 @@
|
||||
package ru.spbstu.telematics.java;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*
|
||||
*/
|
||||
public class App
|
||||
{
|
||||
public static void main( String[] args )
|
||||
{
|
||||
System.out.println( "Hello World!" );
|
||||
import java.util.Locale;
|
||||
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
Locale.setDefault(Locale.ENGLISH);
|
||||
|
||||
Room room = new Room();
|
||||
Settings settings = new Settings(28, 0.4);
|
||||
Controller controller = new Controller(room, settings);
|
||||
Thread controllerThread = new Thread(controller);
|
||||
controllerThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,93 @@ public class Controller implements Runnable {
|
||||
private Room room;
|
||||
private Settings settings;
|
||||
private Sensor sensor;
|
||||
private Thread sensorThread;
|
||||
private Heater heater;
|
||||
private Thread heaterThread;
|
||||
private Fan fan;
|
||||
private Thread fanThread;
|
||||
|
||||
public Controller(Room room, Settings settings) {
|
||||
this.room = room;
|
||||
this.settings = settings;
|
||||
|
||||
sensor = new Sensor(room);
|
||||
sensorThread = new Thread(sensor);
|
||||
|
||||
heater = new Heater(room);
|
||||
heaterThread = new Thread(heater);
|
||||
|
||||
fan = new Fan(room);
|
||||
fanThread = new Thread(fan);
|
||||
}
|
||||
|
||||
private long updateIntervalMs = 500;
|
||||
private double tolerance = 0.01;
|
||||
|
||||
private void log(String string) {
|
||||
System.out.printf("[Controller in room %s] %s\n", room.name, string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
sensorThread.start();
|
||||
heaterThread.start();
|
||||
fanThread.start();
|
||||
log("Started sensor, heater and fan threads");
|
||||
|
||||
while (!Thread.interrupted()) {
|
||||
double realTemperature = room.getTemperature();
|
||||
double sensorTemperature = sensor.getTemperature();
|
||||
double desiredTemperature = settings.getTemperature();
|
||||
|
||||
if (sensorTemperature < desiredTemperature * (1 - tolerance)) {
|
||||
if (!heater.isOn()) {
|
||||
log(String.format(
|
||||
"Turning heater ON (real - %.2fC°, sensor - %.2fC°, desired %.2fC°)",
|
||||
realTemperature, sensorTemperature, desiredTemperature));
|
||||
heater.turnOn();
|
||||
}
|
||||
} else {
|
||||
if (heater.isOn()) {
|
||||
log(String.format(
|
||||
"Turning heater OFF (real - %.2fC°, sensor - %.2fC°, desired %.2fC°)",
|
||||
realTemperature, sensorTemperature, desiredTemperature));
|
||||
heater.turnOff();
|
||||
}
|
||||
}
|
||||
|
||||
double realHumidity = room.getHumidity();
|
||||
double sensorHumidity = sensor.getHumidity();
|
||||
double desiredHumidity = settings.getHumidity();
|
||||
if (sensorHumidity > desiredHumidity * (1 + tolerance)) {
|
||||
if (!fan.isOn()) {
|
||||
log(String.format(
|
||||
"Turning fan ON (real - %.2f%%, sensor - %.2f%%, desired %.2f%%)",
|
||||
realHumidity * 100, sensorHumidity * 100, desiredHumidity * 100));
|
||||
fan.turnOn();
|
||||
}
|
||||
} else {
|
||||
if (fan.isOn()) {
|
||||
log(String.format(
|
||||
"Turning fan OFF (real - %.2f%%, sensor - %.2f%%, desired %.2f%%)",
|
||||
realHumidity * 100, sensorHumidity * 100, desiredHumidity * 100));
|
||||
fan.turnOff();
|
||||
}
|
||||
}
|
||||
|
||||
Utils.sleep(updateIntervalMs);
|
||||
}
|
||||
|
||||
sensorThread.interrupt();
|
||||
heaterThread.interrupt();
|
||||
fanThread.interrupt();
|
||||
|
||||
try {
|
||||
sensorThread.join();
|
||||
heaterThread.join();
|
||||
fanThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,43 @@
|
||||
package ru.spbstu.telematics.java;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/*
|
||||
* Симулирует вентилятор, установленный в комнате. Может изменять поля комнаты,
|
||||
* а именно - уменьшать влажность в ней.
|
||||
*/
|
||||
public class Fan implements Runnable {
|
||||
Room room;
|
||||
private boolean isOn;
|
||||
private Room room;
|
||||
|
||||
public Fan(Room room) {
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
private volatile boolean isOn;
|
||||
|
||||
public boolean isOn() {
|
||||
return isOn;
|
||||
}
|
||||
|
||||
public void turnOn() {
|
||||
this.isOn = true;
|
||||
}
|
||||
|
||||
public void turnOff() {
|
||||
this.isOn = false;
|
||||
}
|
||||
|
||||
private Random random = new Random();
|
||||
private double humidityMaxStep = 0.03;
|
||||
private long maxStepTimeMs = 3000;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!Thread.interrupted()) {
|
||||
if (isOn)
|
||||
room.adjustHumidity(-random.nextDouble() * humidityMaxStep);
|
||||
|
||||
Utils.sleepRandomTime((long) (maxStepTimeMs * 0.5), maxStepTimeMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,43 @@
|
||||
package ru.spbstu.telematics.java;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/*
|
||||
* Симулирует нагреватель, установленный в комнате. Может изменять поля комнаты,
|
||||
* а именно - увеличивать температуру в ней.
|
||||
*/
|
||||
public class Heater implements Runnable {
|
||||
Room room;
|
||||
private boolean isOn;
|
||||
private Room room;
|
||||
|
||||
public Heater(Room room) {
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
private volatile boolean isOn;
|
||||
|
||||
public boolean isOn() {
|
||||
return isOn;
|
||||
}
|
||||
|
||||
public void turnOn() {
|
||||
this.isOn = true;
|
||||
}
|
||||
|
||||
public void turnOff() {
|
||||
this.isOn = false;
|
||||
}
|
||||
|
||||
private Random random = new Random();
|
||||
private double temperatureMaxStep = 1;
|
||||
private long maxStepTimeMs = 3000;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!Thread.interrupted()) {
|
||||
if (isOn)
|
||||
room.adjustTemperature(random.nextDouble() * temperatureMaxStep);
|
||||
|
||||
Utils.sleepRandomTime((long) (maxStepTimeMs * 0.5), maxStepTimeMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,15 @@ import java.util.Random;
|
||||
* Симулирует физические процессы, протекающие в команте.
|
||||
*/
|
||||
public class Room implements Runnable {
|
||||
static private int roomCounter;
|
||||
|
||||
public final String name;
|
||||
|
||||
public Room() {
|
||||
roomCounter++;
|
||||
this.name = "#" + roomCounter;
|
||||
}
|
||||
|
||||
// Температура измеряется в градусах цельсия
|
||||
private volatile double temperature = 24.0;
|
||||
|
||||
@@ -13,6 +22,10 @@ public class Room implements Runnable {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public synchronized void adjustTemperature(double delta) {
|
||||
this.temperature += delta;
|
||||
}
|
||||
|
||||
// Относительная влажность в процентах
|
||||
private volatile double humidity = 0.5;
|
||||
|
||||
@@ -20,6 +33,10 @@ public class Room implements Runnable {
|
||||
return humidity;
|
||||
}
|
||||
|
||||
public synchronized void adjustHumidity(double delta) {
|
||||
this.humidity += delta;
|
||||
}
|
||||
|
||||
// Параметры произвольного изменения температуры и влажности в комнате
|
||||
private Random random = new Random();
|
||||
private double temperatureMaxStep = 1;
|
||||
@@ -33,16 +50,7 @@ public class Room implements Runnable {
|
||||
temperature += (random.nextDouble() - 0.5) * 2 * temperatureMaxStep;
|
||||
humidity += (random.nextDouble() - 0.5) * 2 * humidityMaxStep;
|
||||
|
||||
try {
|
||||
Thread.sleep(getStepTime());
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
Utils.sleepRandomTime((long) (maxStepTimeMs * 0.5), maxStepTimeMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long getStepTime() {
|
||||
// Спим от 0.5 * maxStepTimeMs до maxSteTimeMs миллисекунд
|
||||
return (long) (random.nextDouble() * 0.5 + 0.5) * maxStepTimeMs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,11 +40,7 @@ public class Sensor implements Runnable {
|
||||
temperature = room.getTemperature() + (random.nextDouble() - 0.5) * 2 * maxTemperatureError;
|
||||
humidity = room.getHumidity() + (random.nextDouble() - 0.5) * 2 * maxHumidityError;
|
||||
|
||||
try {
|
||||
Thread.sleep(updateIntervalMs);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
Utils.sleep(updateIntervalMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,41 @@
|
||||
package ru.spbstu.telematics.java;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/*
|
||||
* Симулирует переодическое изменение настроек пользователем.
|
||||
*/
|
||||
public class Settings implements Runnable {
|
||||
private double temperature;
|
||||
|
||||
public double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
private double humidity;
|
||||
|
||||
public double getHumidity() {
|
||||
return humidity;
|
||||
}
|
||||
|
||||
public Settings(double temperature, double humidity) {
|
||||
this.temperature = temperature;
|
||||
this.humidity = humidity;
|
||||
}
|
||||
|
||||
// Параметры произвольного изменения настроек температуры и влажности в комнате
|
||||
private Random random = new Random();
|
||||
private double temperatureMaxStep = 10;
|
||||
private double humidityMaxStep = 0.15;
|
||||
private long maxStepTimeMs = 20000;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!Thread.interrupted()) {
|
||||
temperature += (random.nextDouble() - 0.5) * 2 * temperatureMaxStep;
|
||||
humidity += (random.nextDouble() - 0.5) * 2 * humidityMaxStep;
|
||||
|
||||
Utils.sleepRandomTime((long) (maxStepTimeMs * 0.5), maxStepTimeMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
21
lab3/src/main/java/ru/spbstu/telematics/java/Utils.java
Normal file
21
lab3/src/main/java/ru/spbstu/telematics/java/Utils.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package ru.spbstu.telematics.java;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class Utils {
|
||||
static public void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
static public void sleepRandomTime(long from, long to) {
|
||||
try {
|
||||
Thread.sleep(ThreadLocalRandom.current().nextLong(from, to));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
57
lab3/src/test/java/ru/spbstu/telematics/java/FanTests.java
Normal file
57
lab3/src/test/java/ru/spbstu/telematics/java/FanTests.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package ru.spbstu.telematics.java;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class FanTests {
|
||||
Room room;
|
||||
double initialTemperature;
|
||||
double initialHumidity;
|
||||
Fan fan;
|
||||
Thread fanThread;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
room = new Room();
|
||||
initialTemperature = room.getTemperature();
|
||||
initialHumidity = room.getHumidity();
|
||||
fan = new Fan(room);
|
||||
fanThread = new Thread(fan);
|
||||
}
|
||||
|
||||
/*
|
||||
* Проверяет, что включенный вентилятор уменьшает влажность в комнате
|
||||
* и при этом не изменяет температуру.
|
||||
*/
|
||||
@Test
|
||||
public void testFanOn() throws InterruptedException {
|
||||
fan.turnOn();
|
||||
fanThread.start();
|
||||
|
||||
Thread.sleep(5000);
|
||||
|
||||
assertEquals(initialTemperature, room.getTemperature());
|
||||
assertTrue(initialHumidity > room.getHumidity());
|
||||
|
||||
fanThread.interrupt();
|
||||
fanThread.join();
|
||||
}
|
||||
|
||||
/*
|
||||
* Проверяет, что выключенный вентилятор не изменяет температуру и влажность
|
||||
* в комнате.
|
||||
*/
|
||||
@Test
|
||||
public void testFanOff() throws InterruptedException {
|
||||
fanThread.start();
|
||||
|
||||
Thread.sleep(5000);
|
||||
|
||||
assertEquals(initialHumidity, room.getHumidity());
|
||||
assertEquals(initialTemperature, room.getTemperature());
|
||||
|
||||
fanThread.interrupt();
|
||||
fanThread.join();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package ru.spbstu.telematics.java;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class HeaterTests {
|
||||
Room room;
|
||||
double initialTemperature;
|
||||
double initialHumidity;
|
||||
Heater heater;
|
||||
Thread heaterThread;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
room = new Room();
|
||||
initialTemperature = room.getTemperature();
|
||||
initialHumidity = room.getHumidity();
|
||||
heater = new Heater(room);
|
||||
heaterThread = new Thread(heater);
|
||||
}
|
||||
|
||||
/*
|
||||
* Проверяет, что включенный нагреватель увеличивает температуру в комнате
|
||||
* и при этом не изменяет влажность.
|
||||
*/
|
||||
@Test
|
||||
public void testHeaterOn() throws InterruptedException {
|
||||
heater.turnOn();
|
||||
heaterThread.start();
|
||||
|
||||
Thread.sleep(5000);
|
||||
|
||||
assertEquals(initialHumidity, room.getHumidity());
|
||||
assertTrue(initialTemperature < room.getTemperature());
|
||||
|
||||
heaterThread.interrupt();
|
||||
heaterThread.join();
|
||||
}
|
||||
|
||||
/*
|
||||
* Проверяет, что выключенный нагреватель не изменяет температуру и влажность
|
||||
* в комнате.
|
||||
*/
|
||||
@Test
|
||||
public void testHeaterOff() throws InterruptedException {
|
||||
heaterThread.start();
|
||||
|
||||
Thread.sleep(5000);
|
||||
|
||||
assertEquals(initialHumidity, room.getHumidity());
|
||||
assertEquals(initialTemperature, room.getTemperature());
|
||||
|
||||
heaterThread.interrupt();
|
||||
heaterThread.join();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package ru.spbstu.telematics.java;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
public class RoomTests {
|
||||
/*
|
||||
* Проверяет, что температура и влажность изменяются со временем.
|
||||
|
||||
@@ -3,7 +3,6 @@ package ru.spbstu.telematics.java;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
public class SensorTests {
|
||||
/*
|
||||
* Моковый класс комнаты для упрощения тестирования сенсоров.
|
||||
@@ -29,7 +28,8 @@ public class SensorTests {
|
||||
}
|
||||
|
||||
/*
|
||||
* Проверяет, что сенсоры выдают реальную температуру и влажность комнаты в пределах
|
||||
* Проверяет, что сенсоры выдают реальную температуру и влажность комнаты в
|
||||
* пределах
|
||||
* некоторой погрешности.
|
||||
*/
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user