diff --git a/data-consumer/data-consumer.iml b/data-consumer/data-processor.iml
similarity index 100%
rename from data-consumer/data-consumer.iml
rename to data-consumer/data-processor.iml
diff --git a/data-consumer/src/main/java/com/artgeektech/iotmicroservices/controller/DataConsumerController.java b/data-consumer/src/main/java/com/artgeektech/iotmicroservices/controller/DataConsumerController.java
index 3e0e973..81065c8 100644
--- a/data-consumer/src/main/java/com/artgeektech/iotmicroservices/controller/DataConsumerController.java
+++ b/data-consumer/src/main/java/com/artgeektech/iotmicroservices/controller/DataConsumerController.java
@@ -3,46 +3,38 @@
import com.artgeektech.iotmicroservices.Constants;
import com.artgeektech.iotmicroservices.model.AirData;
import com.artgeektech.iotmicroservices.repository.AirDataRepository;
+import com.artgeektech.iotmicroservices.service.RuleEngineService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Controller;
/**
* Created by guang on 11:56 AM 8/18/18.
*/
-@Component
+@Controller
public class DataConsumerController {
private static final Logger logger = LoggerFactory.getLogger(DataConsumerController.class);
@Autowired
private AirDataRepository airDataRepository;
- @RabbitListener(queues = Constants.QUEUE_NAME)
+ @Autowired
+ private RuleEngineService ruleEngineService;
+
+ @RabbitListener(queues = Constants.QUEUE_NAME) // Subscribe to the Message Queue
public void process(AirData airData) {
logger.info("Received message from MQ '{}'", airData);
- // simple rule engine handling
- if (airData.getTemperature() > 50) {
- triggerActionAlert("Temperature too high!!");
- }
- if (airData.getCo2() > 50) {
- triggerActionAlert("CO2 too high!!!");
- }
- if (airData.getPm2p5() > 50) {
- triggerActionAlert("Too much Dust!!!");
- }
+ // apply rule engine and trigger actions
+ ruleEngineService.applyRules(airData);
// save to DB
airDataRepository.save(airData);
+
logger.info("Saved message to Mongo DB '{}'", airData);
logger.info("Total message saved in Mongo DB is: " + airDataRepository.findAll().size());
-
- }
-
- private void triggerActionAlert(String msg) {
- System.out.println("\n\n!!!!!Sending the Email Alert: " + msg + "\n\n");
}
}
diff --git a/data-consumer/src/main/java/com/artgeektech/iotmicroservices/service/RuleEngineService.java b/data-consumer/src/main/java/com/artgeektech/iotmicroservices/service/RuleEngineService.java
new file mode 100644
index 0000000..8595f13
--- /dev/null
+++ b/data-consumer/src/main/java/com/artgeektech/iotmicroservices/service/RuleEngineService.java
@@ -0,0 +1,27 @@
+package com.artgeektech.iotmicroservices.service;
+
+import com.artgeektech.iotmicroservices.model.AirData;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by guang on 7:16 PM 8/21/18.
+ */
+@Component
+public class RuleEngineService {
+
+ public void applyRules(AirData airData) {
+ if (airData.getTemperature() > 50) {
+ triggerActionAlert("Temperature too high!!");
+ }
+ if (airData.getCo2() > 50) {
+ triggerActionAlert("CO2 too high!!!");
+ }
+ if (airData.getPm2p5() > 50) {
+ triggerActionAlert("Too much Dust!!!");
+ }
+ }
+
+ private void triggerActionAlert(String msg) {
+ System.out.println("\n\n!!!!!Sending the Email Alert: " + msg + "\n\n");
+ }
+}
diff --git a/data-dashboard/data-dashboard.iml b/data-dashboard/data-dashboard.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/data-dashboard/data-dashboard.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data-dashboard/pom.xml b/data-dashboard/pom.xml
new file mode 100644
index 0000000..6ec9a4d
--- /dev/null
+++ b/data-dashboard/pom.xml
@@ -0,0 +1,15 @@
+
+
+
+ iotmicroservices
+ com.artgeektech
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ datadashboard
+
+
+
\ No newline at end of file
diff --git a/data-dashboard/src/main/java/DataDashboardController.java b/data-dashboard/src/main/java/DataDashboardController.java
new file mode 100644
index 0000000..8fc0f3f
--- /dev/null
+++ b/data-dashboard/src/main/java/DataDashboardController.java
@@ -0,0 +1,7 @@
+package PACKAGE_NAME;
+
+/**
+ * Created by guang on 7:51 PM 8/20/18.
+ */
+public class DataDashboardController {
+}
diff --git a/data-dashboard/src/main/resources/templates/js/html/dashboard.html b/data-dashboard/src/main/resources/templates/js/html/dashboard.html
new file mode 100644
index 0000000..e69de29
diff --git a/data-dashboard/src/main/resources/templates/js/html/dashboard.js b/data-dashboard/src/main/resources/templates/js/html/dashboard.js
new file mode 100644
index 0000000..e69de29
diff --git a/data-ingest/pom.xml b/data-ingest/pom.xml
index 21415af..c9c862f 100644
--- a/data-ingest/pom.xml
+++ b/data-ingest/pom.xml
@@ -20,5 +20,19 @@
org.springframework.amqp
spring-rabbit
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jetty
+
\ No newline at end of file
diff --git a/data-ingest/src/main/java/com/artgeektech/iotmicroservices/DataIngestApplication.java b/data-ingest/src/main/java/com/artgeektech/iotmicroservices/DataIngestApplication.java
index 2185ca9..af1f16f 100644
--- a/data-ingest/src/main/java/com/artgeektech/iotmicroservices/DataIngestApplication.java
+++ b/data-ingest/src/main/java/com/artgeektech/iotmicroservices/DataIngestApplication.java
@@ -18,6 +18,11 @@ public Exchange airDataExchange() {
return new TopicExchange(Constants.EXCHANGE_NAME);
}
+// @Bean
+// public SimpMessagingTemplate simpMessagingTemplate() {
+// return new SimpMessagingTemplate();
+// }
+
public static void main(String[] args) {
SpringApplication.run(DataIngestApplication.class, args);
}
diff --git a/data-ingest/src/main/java/com/artgeektech/iotmicroservices/controller/DataIngestController.java b/data-ingest/src/main/java/com/artgeektech/iotmicroservices/controller/DataIngestController.java
index 684d00e..c4cc4b6 100644
--- a/data-ingest/src/main/java/com/artgeektech/iotmicroservices/controller/DataIngestController.java
+++ b/data-ingest/src/main/java/com/artgeektech/iotmicroservices/controller/DataIngestController.java
@@ -2,6 +2,7 @@
import com.artgeektech.iotmicroservices.Constants;
import com.artgeektech.iotmicroservices.model.AirData;
+import com.artgeektech.iotmicroservices.model.AirRawData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Exchange;
@@ -9,7 +10,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@@ -17,28 +17,43 @@
@RestController
-@RequestMapping("/iot/airdata")
public class DataIngestController {
private static final Logger logger = LoggerFactory.getLogger(DataIngestController.class);
+// @Autowired
+// private SimpMessagingTemplate messagingTemplate;
+
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private Exchange exchange;
- @PostMapping("/ingest")
- public AirData ingest(@Valid @RequestBody AirData airData) {
- preprocess(airData);
+ @PostMapping("/airdata/ingest") // validate payload from request body
+ public AirData ingest(@Valid @RequestBody AirRawData rawData) {
+ // preprocess
+ AirData airData = preprocess(rawData);
+ // publish to MQ
rabbitTemplate.convertAndSend(exchange.getName(), Constants.ROUTING_KEY, airData);
logger.info("ingested data: " + airData.toString());
return airData;
}
- private void preprocess(AirData airData) {
+
+
+ private AirData preprocess(AirRawData rawData) {
+ AirData airData = new AirData();
+
+ // add more info from system
airData.setTimestamp(new Date());
- airData.setHumidity(Math.round(airData.getHumidity() * 100.0) / 100.0);
- airData.setTemperature(Math.round(airData.getTemperature() * 100.0) / 100.0);
+
+ // standardize data format
+ airData.setHumidity(Math.round(rawData.getHumidity() * 100.0) / 100.0);
+ airData.setTemperature(Math.round(rawData.getTemperature() * 100.0) / 100.0);
+ airData.setCo2(Math.round(rawData.getCo2() * 100.0) / 100.0);
+ airData.setPm2p5(Math.round(rawData.getPm2p5() * 100.0) / 100.0);
+
+ return airData;
}
}
diff --git a/data-ingest/src/main/java/com/artgeektech/iotmicroservices/model/AirData.java b/data-ingest/src/main/java/com/artgeektech/iotmicroservices/model/AirData.java
index d33ef5b..68ced4b 100644
--- a/data-ingest/src/main/java/com/artgeektech/iotmicroservices/model/AirData.java
+++ b/data-ingest/src/main/java/com/artgeektech/iotmicroservices/model/AirData.java
@@ -4,9 +4,6 @@
import lombok.Data;
import lombok.NoArgsConstructor;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
-import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
@@ -14,26 +11,9 @@
@AllArgsConstructor
@NoArgsConstructor
public class AirData implements Serializable {
-
- @NotNull
- @Min(1)
- @Max(100)
private Double temperature;
-
- @NotNull
- @Min(1)
- @Max(100)
private Double humidity;
-
- @NotNull
- @Min(1)
- @Max(100)
private Double pm2p5;
-
- @NotNull
- @Min(1)
- @Max(100)
private Double co2;
-
private Date timestamp;
}
diff --git a/data-ingest/src/main/java/com/artgeektech/iotmicroservices/model/AirRawData.java b/data-ingest/src/main/java/com/artgeektech/iotmicroservices/model/AirRawData.java
new file mode 100644
index 0000000..70af1cc
--- /dev/null
+++ b/data-ingest/src/main/java/com/artgeektech/iotmicroservices/model/AirRawData.java
@@ -0,0 +1,41 @@
+package com.artgeektech.iotmicroservices.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AirRawData implements Serializable {
+// private Double temperature;
+// private Double humidity;
+// private Double pm2p5;
+// private Double co2;
+
+ @NotNull
+ @Min(1)
+ @Max(100)
+ private Double temperature;
+
+ @NotNull
+ @Min(1)
+ @Max(100)
+ private Double humidity;
+
+ @NotNull
+ @Min(1)
+ @Max(100)
+ private Double pm2p5;
+
+ @NotNull
+ @Min(1)
+ @Max(100)
+ private Double co2;
+
+}
diff --git a/data-service/data-service-api-gateway.iml b/data-service/data-service-api-gateway.iml
new file mode 100644
index 0000000..78b2cc5
--- /dev/null
+++ b/data-service/data-service-api-gateway.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/data-service/pom.xml b/data-service/pom.xml
new file mode 100644
index 0000000..06f732f
--- /dev/null
+++ b/data-service/pom.xml
@@ -0,0 +1,15 @@
+
+
+
+ iotmicroservices
+ com.artgeektech
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ dataservice
+
+
+
\ No newline at end of file
diff --git a/data-simulator/src/main/java/com/artgeektech/iotmicroservices/DataSimulatorApplication.java b/data-simulator/src/main/java/com/artgeektech/iotmicroservices/DataSimulatorApplication.java
index eca825e..89546e5 100644
--- a/data-simulator/src/main/java/com/artgeektech/iotmicroservices/DataSimulatorApplication.java
+++ b/data-simulator/src/main/java/com/artgeektech/iotmicroservices/DataSimulatorApplication.java
@@ -10,7 +10,7 @@
public class DataSimulatorApplication {
- private static final String resourceUrl = "http://data-ingest:9001/iot/airdata/ingest";
+ private static final String resourceUrl = "http://localhost:9001/airdata/ingest";
private static final RestTemplate restTemplate = new RestTemplate();
private static final Random random = new Random();
private static double minVal = 10;
@@ -19,12 +19,13 @@ public class DataSimulatorApplication {
private static int interval = 1000;
public static void main(String[] args) {
+
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
AirRawData payload = new AirRawData(genRandom(), genRandom(), genRandom(), genRandom());
HttpEntity request = new HttpEntity<>(payload);
- restTemplate.postForObject(resourceUrl, request, AirRawData.class);
+ restTemplate.postForObject(resourceUrl, request, Object.class);
}
}, 0, interval);
}
@@ -32,7 +33,7 @@ public void run() {
private static double genRandom() {
int randInt = random.nextInt(5);
if (randInt == 0) {
- return 100;
+ return 99;
} else {
return minVal + random.nextDouble() * (maxVal - minVal);
}
diff --git a/data-simulator/src/main/java/com/artgeektech/iotmicroservices/model/AirRawData.java b/data-simulator/src/main/java/com/artgeektech/iotmicroservices/model/AirRawData.java
index 71f36f3..2adaa4c 100644
--- a/data-simulator/src/main/java/com/artgeektech/iotmicroservices/model/AirRawData.java
+++ b/data-simulator/src/main/java/com/artgeektech/iotmicroservices/model/AirRawData.java
@@ -10,8 +10,8 @@
@AllArgsConstructor
@NoArgsConstructor
public class AirRawData implements Serializable {
- private double temperature;
- private double humidity;
- private double pm2p5;
- private double co2;
+ private Double temperature;
+ private Double humidity;
+ private Double pm2p5;
+ private Double co2;
}
diff --git a/docker-rabbitmq/docker-compose.yml b/docker-rabbitmq/docker-compose.yml
index 7db4553..3358fd4 100644
--- a/docker-rabbitmq/docker-compose.yml
+++ b/docker-rabbitmq/docker-compose.yml
@@ -1,6 +1,10 @@
-rabbitmq:
- image: rabbitmq:management
- container_name: "rabbitmq"
- ports:
- - 5672:5672
- - 15672:15672
\ No newline at end of file
+version: '2'
+services:
+ sonar:
+ container_name: aiwin-rabbit
+ image: aiwin/rabbitmq-stomp:latest
+ ports:
+ - 61613:61613
+ - 15674:15674
+ - 15672:15672
+ - 5672:5672
\ No newline at end of file
diff --git a/service-registry/src/main/resources/application.yml b/service-registry/src/main/resources/application.yml
index a3a8810..d4f57ad 100644
--- a/service-registry/src/main/resources/application.yml
+++ b/service-registry/src/main/resources/application.yml
@@ -7,7 +7,7 @@ server:
eureka:
instance:
- hostname: service-registry # 指定该Eureka实例的主机名
+ hostname: localhost # 指定该Eureka实例的主机名
client:
registerWithEureka: false
fetchRegistry: false
diff --git a/service-registry/target/classes/application.yml b/service-registry/target/classes/application.yml
index a3a8810..d4f57ad 100644
--- a/service-registry/target/classes/application.yml
+++ b/service-registry/target/classes/application.yml
@@ -7,7 +7,7 @@ server:
eureka:
instance:
- hostname: service-registry # 指定该Eureka实例的主机名
+ hostname: localhost # 指定该Eureka实例的主机名
client:
registerWithEureka: false
fetchRegistry: false