diff --git a/apigateway/src/main/resources/application.yml b/apigateway/src/main/resources/application.yml
index 7a70166..d2d94f9 100644
--- a/apigateway/src/main/resources/application.yml
+++ b/apigateway/src/main/resources/application.yml
@@ -7,15 +7,33 @@ spring:
cloud:
gateway:
+ globalcors:
+ corsConfigurations:
+ '[/**]':
+ allowedOriginPatterns:
+ - "http://localhost:5173"
+ - "http://localhost:3000"
+ - "https://*.azurecontainerapps.io"
+ allowedMethods:
+ - GET
+ - POST
+ - PUT
+ - DELETE
+ - OPTIONS
+ - PATCH
+ allowedHeaders: "*"
+ allowCredentials: true
+ maxAge: 3600
+ default-filters:
+ - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_UNIQUE
routes:
- id: iot-service
order: -10
- uri: http://iot-service:8082
+ uri: lb://iot-service
predicates:
- - Path=/api/sensordata/**
+ - Path=/api/iot/**
filters:
- StripPrefix=0
- - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST
- id: chatbotbackend
uri: lb://chatbotbackend
@@ -38,7 +56,6 @@ spring:
- Path=/api/**
filters:
- StripPrefix=0
- - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST
eureka:
client:
diff --git a/docker-compose.yml b/docker-compose.yml
index eafc52f..6e94ebf 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -84,6 +84,7 @@ services:
JWT_SECRET: ${JWT_SECRET}
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: ${EUREKA_CLIENT_SERVICEURL_DEFAULTZONE}
SPRING_AUTOCONFIGURE_EXCLUDE: org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
+ VITALREPORTS_URL: http://vitalreports:8083
iot-service:
build:
@@ -134,6 +135,8 @@ services:
condition: service_healthy
environment:
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discoveryserver:8761/eureka
+ ECG_PYTHON_PATH: python
+ ECG_SCRIPT_PATH: ecg_predict.py
apigateway:
build:
diff --git a/mainservice/pom.xml b/mainservice/pom.xml
index e04b823..2f57ba7 100644
--- a/mainservice/pom.xml
+++ b/mainservice/pom.xml
@@ -170,4 +170,22 @@
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.34
+
+
+
+
+
+
diff --git a/mainservice/src/main/java/com/example/mainservice/client/VitalReportsClient.java b/mainservice/src/main/java/com/example/mainservice/client/VitalReportsClient.java
new file mode 100644
index 0000000..d0ce408
--- /dev/null
+++ b/mainservice/src/main/java/com/example/mainservice/client/VitalReportsClient.java
@@ -0,0 +1,70 @@
+package com.example.mainservice.client;
+
+import com.example.mainservice.dto.VitalAssessmentResponseDTO;
+import com.example.mainservice.dto.VitalReadingRequestDTO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.http.HttpEntity;
+import java.util.Map;
+
+@Component
+public class VitalReportsClient {
+
+ private static final Logger logger = LoggerFactory.getLogger(VitalReportsClient.class);
+
+ private final RestTemplate restTemplate = new RestTemplate();
+
+ @Value("${vitalreports.url:http://localhost:8081}")
+ private String vitalReportsUrl;
+
+ public VitalAssessmentResponseDTO evaluateVitals(VitalReadingRequestDTO request) {
+ String url = vitalReportsUrl + "/api/vital/vitals/evaluate";
+ try {
+ logger.info("Calling VitalReports-AI at {}", url);
+ ResponseEntity response =
+ restTemplate.postForEntity(url, request, VitalAssessmentResponseDTO.class);
+ return response.getBody();
+ } catch (Exception e) {
+ logger.error("Failed to evaluate vitals via VitalReports-AI: {}", e.getMessage());
+ VitalAssessmentResponseDTO fallback = new VitalAssessmentResponseDTO();
+ fallback.setTriageLevel("UNKNOWN");
+ fallback.setVitalStatus(new VitalAssessmentResponseDTO.VitalStatusDTO(
+ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"
+ ));
+ return fallback;
+ }
+ }
+
+ public Map analyzeECG(String patientId, MultipartFile datFile, MultipartFile heaFile) {
+ String url = vitalReportsUrl + "/api/vital/ecg/analyze";
+ try {
+ logger.info("Sending ECG data to VitalReports-AI at {}", url);
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+
+ MultiValueMap body = new LinkedMultiValueMap<>();
+ body.add("patientId", patientId);
+ body.add("dat_file", datFile.getResource());
+ body.add("hea_file", heaFile.getResource());
+
+ HttpEntity> requestEntity = new HttpEntity<>(body, headers);
+
+ @SuppressWarnings("unchecked")
+ ResponseEntity