Commit e6183d6e authored by Ishankha K.C's avatar Ishankha K.C

create device controller to control device

parent b8e9d3aa
......@@ -47,7 +47,8 @@ public class SecurityConfig {
"/webjars/**",
"/swagger-ui.html",
"/emotional/video-process",
"/test/**"
"/test/**",
"/activity-logs/add"
};
@Bean
......
package com.kaluwa.enterprises.babycarebackendservice.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kaluwa.enterprises.babycarebackendservice.dao.DevicesDao;
import com.kaluwa.enterprises.babycarebackendservice.dto.ActivityLogDto;
import com.kaluwa.enterprises.babycarebackendservice.model.Devices;
import com.kaluwa.enterprises.babycarebackendservice.service.ActivityLogService;
import com.kaluwa.enterprises.babycarebackendservice.socketHandlers.EmotionPrediction;
import lombok.Setter;
......@@ -12,8 +14,8 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import static com.kaluwa.enterprises.babycarebackendservice.constants.Configs.WEBSOCKET_URL;
import static com.kaluwa.enterprises.babycarebackendservice.constants.LogTypes.EMOTION;
......@@ -23,12 +25,51 @@ public class WebSocketClient {
private ConcurrentHashMap<String, WebSocketSession> activeSessions = new ConcurrentHashMap<>();
private ActivityLogService activityLogService;
private DevicesDao devicesDao;
// Method to set the VideoFrameHandler reference
@Setter
private WebSocketConfig.VideoFrameHandler videoFrameHandler; // Reference to VideoFrameHandler
public WebSocketClient(ActivityLogService activityLogService) {
public WebSocketClient(ActivityLogService activityLogService, DevicesDao devicesDao) {
this.activityLogService = activityLogService;
this.devicesDao = devicesDao;
connectionLooper(); // Connect to WebSocket when the application starts
}
private void connectToWebSocket() {
List<Devices> devices = devicesDao.findAll();
for (Devices device : devices) {
if (!activeSessions.containsKey(device.getDeviceUid())) {
connectToWebSocket(device.getDeviceUid());
}
}
}
public void connectionLooper() {
new Thread(() -> {
// run until activeSessions.deviceIds = devicesDao.deviceIds
while (true) {
List<Devices> devices = devicesDao.findAll();
for (Devices device : devices) {
if (!activeSessions.containsKey(device.getDeviceUid())) {
connectToWebSocket(device.getDeviceUid());
}
}
try {
Thread.sleep(10000); // Check every 10 seconds
} catch (InterruptedException e) {
log.error("Error in connectionLooper: {}", e.getMessage());
}
}
}).start();
}
public void clientConnectToWebSocket(String deviceId) {
// Check if the session is already active
if (activeSessions.containsKey(deviceId)) {
log.info("WebSocket connection already active for device: {}", deviceId);
}
}
public void connectToWebSocket(String deviceId) {
......@@ -41,7 +82,6 @@ public class WebSocketClient {
log.info("Connected to WebSocket for device: {}", deviceId);
} catch (Exception e) {
log.error("Failed to connect to WebSocket for device: {}", deviceId);
// e.printStackTrace();
}
}
......@@ -103,13 +143,15 @@ public class WebSocketClient {
}
}
private String getDeviceIdFromSession(WebSocketSession session) {
String uri = session.getUri().toString();
return uri.substring(uri.lastIndexOf('/') + 1); // Extract device_id from the URI path
}
@Override
public void afterConnectionClosed(WebSocketSession session, org.springframework.web.socket.CloseStatus status) {
for (String key : webSocketClient.activeSessions.keySet()) {
if (webSocketClient.activeSessions.get(key).getId().equals(session.getId())) {
webSocketClient.activeSessions.remove(key); // Remove session from the map
log.info("Connection closed with device: {}", key);
break;
}
}
log.info("WebSocket connection closed. Status: {}", status);
}
}
......
......@@ -2,6 +2,7 @@ package com.kaluwa.enterprises.babycarebackendservice.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kaluwa.enterprises.babycarebackendservice.dao.ActivityLogDao;
import com.kaluwa.enterprises.babycarebackendservice.dao.DevicesDao;
import com.kaluwa.enterprises.babycarebackendservice.model.ActivityLog;
import com.kaluwa.enterprises.babycarebackendservice.service.ActivityLogService;
import com.kaluwa.enterprises.babycarebackendservice.socketHandlers.EmotionPrediction;
......@@ -33,9 +34,11 @@ import static com.kaluwa.enterprises.babycarebackendservice.constants.Configs.SE
public class WebSocketConfig implements WebSocketConfigurer {
private final ActivityLogService activityLogService;
private final DevicesDao devicesDao;
public WebSocketConfig(ActivityLogService activityLogService) {
public WebSocketConfig(ActivityLogService activityLogService, DevicesDao devicesDao) {
this.activityLogService = activityLogService;
this.devicesDao = devicesDao;
}
@Override
......@@ -48,7 +51,7 @@ public class WebSocketConfig implements WebSocketConfigurer {
@Bean
@Qualifier("customWebsocketClient")
public WebSocketClient customWebSocketClient() {
return new WebSocketClient(activityLogService);
return new WebSocketClient(activityLogService, devicesDao);
}
@Component
......@@ -65,7 +68,7 @@ public class WebSocketConfig implements WebSocketConfigurer {
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String deviceId = getDeviceIdFromSession(session);
activeSessions.put(deviceId, session); // Store the session in the map
webSocketClient.connectToWebSocket(deviceId);
webSocketClient.clientConnectToWebSocket(deviceId);
log.info("Connection established with client for device: {}", deviceId);
super.afterConnectionEstablished(session);
}
......@@ -89,7 +92,7 @@ public class WebSocketConfig implements WebSocketConfigurer {
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
String deviceId = getDeviceIdFromSession(session);
activeSessions.remove(deviceId); // Remove session from the map
webSocketClient.disconnectWebSocket(deviceId);
// webSocketClient.disconnectWebSocket(deviceId);
log.info("Connection closed with client: {}", session);
super.afterConnectionClosed(session, status);
}
......@@ -125,7 +128,7 @@ public class WebSocketConfig implements WebSocketConfigurer {
public void sendTextMessageToClient(String deviceId, EmotionPrediction emotionPrediction) {
try {
WebSocketSession session = activeSessions.get(deviceId);
if (session.isOpen()) {
if (session != null && session.isOpen()) {
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(emotionPrediction);
session.sendMessage(new TextMessage(json));
......
......@@ -3,4 +3,6 @@ package com.kaluwa.enterprises.babycarebackendservice.constants;
public class Configs {
public static String WEBSOCKET_URL = "ws://localhost:8000/ws/emotion/{device_id}";
public static final String SERVER_WS_PATH_TO_ANDROID = "/emotional/video-process/{device_id}";
public static final String DEVICE_URL_FORMAT = "http://%s/%s";
}
......@@ -3,5 +3,9 @@ package com.kaluwa.enterprises.babycarebackendservice.constants;
public class LogTypes {
public static final String EMOTION = "EMOTION";
public static final String FLASH_LIGHT = "FLASH_LIGHT";
public static final String C_SWING = "C_SWING";
public static final String C_MOTION = "C_MOTION";
public static final String C_WET = "C_WET";
}
......@@ -9,4 +9,6 @@ import java.util.List;
@Repository
public interface ActivityLogDao extends JpaRepository<ActivityLog, Long> {
List<ActivityLog> findAllByOrderByActivityLogIdDesc();
List<ActivityLog> findAllByActivityLogTypeOrderByActivityLogIdDesc(String activityLogType);
}
\ No newline at end of file
......@@ -3,6 +3,10 @@ package com.kaluwa.enterprises.babycarebackendservice.dao;
import com.kaluwa.enterprises.babycarebackendservice.model.Devices;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface DevicesDao extends JpaRepository<Devices, Long> {
boolean existsByDeviceUid(String deviceUid);
Optional<Devices> findByDeviceUid(String deviceUid);
}
\ No newline at end of file
package com.kaluwa.enterprises.babycarebackendservice.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class FlashlightResponseDto {
private String status;
private String message;
}
package com.kaluwa.enterprises.babycarebackendservice.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SwingRequestDto {
private boolean start;
private String speed; // LOW, MEDIUM, HIGH
}
package com.kaluwa.enterprises.babycarebackendservice.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class SwingResponseDto {
private String status;
}
......@@ -18,5 +18,7 @@ public class Devices {
@GeneratedValue(strategy= GenerationType.AUTO)
private Long deviceId;
private String deviceUid;
private String camIp;
private String devIp;
}
......@@ -4,11 +4,9 @@ import com.kaluwa.enterprises.babycarebackendservice.dto.ActivityLogDto;
import com.kaluwa.enterprises.babycarebackendservice.dto.ResponseDto;
import com.kaluwa.enterprises.babycarebackendservice.service.ActivityLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
......@@ -24,9 +22,11 @@ public class ActivityLogController {
}
@GetMapping
public ResponseEntity<List<ActivityLogDto>> getAllActivityLogs() {
public ResponseEntity<List<ActivityLogDto>> getAllActivityLogs(
@RequestParam(value = "activityLogType", required = false) String activityLogType
) {
log.info("Inside activity log controller getAllActivityLogs method");
return activityLogService.getAllActivityLogs();
return activityLogService.getAllActivityLogs(activityLogType);
}
@DeleteMapping
......@@ -35,4 +35,10 @@ public class ActivityLogController {
return activityLogService.clearNotifications();
}
@PostMapping("/add")
public ResponseEntity<ActivityLogDto> saveActivityLog(@RequestBody ActivityLogDto activityLogDto) {
log.info("Inside activity log controller saveActivityLog method");
return new ResponseEntity<>(activityLogService.saveActivityLog(activityLogDto), HttpStatus.CREATED);
}
}
package com.kaluwa.enterprises.babycarebackendservice.rest;
import com.kaluwa.enterprises.babycarebackendservice.dto.ResponseDto;
import com.kaluwa.enterprises.babycarebackendservice.dto.SwingRequestDto;
import com.kaluwa.enterprises.babycarebackendservice.service.DeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/device")
@Slf4j
public class DeviceController {
private final DeviceService deviceService;
public DeviceController(DeviceService deviceService) {
this.deviceService = deviceService;
}
// flash light control
@GetMapping("/flashlight/{deviceUid}/{status}")
public ResponseEntity<ResponseDto> flashlight(@PathVariable String deviceUid, @PathVariable String status) {
log.info("Inside DeviceController: flashlight method");
return deviceService.flashlight(deviceUid, status);
}
// c swing control
@PostMapping("/swing/{deviceUid}")
public ResponseEntity<ResponseDto> swing(@PathVariable String deviceUid, @RequestBody SwingRequestDto swingRequest) {
log.info("Inside DeviceController: swing method");
return deviceService.swing(deviceUid, swingRequest);
}
}
......@@ -10,7 +10,7 @@ public interface ActivityLogService {
ActivityLogDto saveActivityLog(ActivityLogDto activityLogDto);
ResponseEntity<List<ActivityLogDto>> getAllActivityLogs();
ResponseEntity<List<ActivityLogDto>> getAllActivityLogs(String activityLogType);
ResponseEntity<ResponseDto> clearNotifications();
}
package com.kaluwa.enterprises.babycarebackendservice.service;
import com.kaluwa.enterprises.babycarebackendservice.dto.ResponseDto;
import com.kaluwa.enterprises.babycarebackendservice.dto.SwingRequestDto;
import org.springframework.http.ResponseEntity;
public interface DeviceService {
ResponseEntity<ResponseDto> flashlight(String deviceUid, String status);
ResponseEntity<ResponseDto> swing(String deviceUid, SwingRequestDto swingRequest);
}
......@@ -39,10 +39,14 @@ public class ActivityLogServiceImpl implements ActivityLogService {
}
@Override
public ResponseEntity<List<ActivityLogDto>> getAllActivityLogs() {
public ResponseEntity<List<ActivityLogDto>> getAllActivityLogs(String activityLogType) {
log.info("Inside getAllActivityLogs method in ActivityLogServiceImpl");
try {
return ResponseEntity.ok(activityLogMapper.listToDto(activityLogDao.findAllByOrderByActivityLogIdDesc()));
if (activityLogType != null && !activityLogType.isEmpty()) {
return ResponseEntity.ok(activityLogMapper.listToDto(activityLogDao.findAllByActivityLogTypeOrderByActivityLogIdDesc(activityLogType)));
} else {
return ResponseEntity.ok(activityLogMapper.listToDto(activityLogDao.findAllByOrderByActivityLogIdDesc()));
}
} catch (Exception e) {
log.error("Error occurred while fetching activity logs: {}", e.getMessage());
e.printStackTrace();
......
package com.kaluwa.enterprises.babycarebackendservice.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kaluwa.enterprises.babycarebackendservice.dao.DevicesDao;
import com.kaluwa.enterprises.babycarebackendservice.dto.*;
import com.kaluwa.enterprises.babycarebackendservice.error.BadRequestAlertException;
import com.kaluwa.enterprises.babycarebackendservice.model.Devices;
import com.kaluwa.enterprises.babycarebackendservice.service.ActivityLogService;
import com.kaluwa.enterprises.babycarebackendservice.service.DeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Optional;
import static com.kaluwa.enterprises.babycarebackendservice.constants.Configs.DEVICE_URL_FORMAT;
import static com.kaluwa.enterprises.babycarebackendservice.constants.LogTypes.C_SWING;
import static com.kaluwa.enterprises.babycarebackendservice.constants.LogTypes.FLASH_LIGHT;
@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {
private final DevicesDao devicesDao;
private final ActivityLogService activityLogService;
private final RestTemplate restTemplate = new RestTemplate();
public DeviceServiceImpl(DevicesDao devicesDao, ActivityLogService activityLogService) {
this.devicesDao = devicesDao;
this.activityLogService = activityLogService;
}
@Override
public ResponseEntity<ResponseDto> flashlight(String deviceUid, String status) {
log.info("Inside DeviceService: flashlight method");
try {
Optional<Devices> devices = devicesDao.findByDeviceUid(deviceUid);
if (devices.isEmpty()) {
throw new BadRequestAlertException("Device is not registered in the system by deviceUid: " + deviceUid, "DeviceService", "flashlight");
}
// status only accepts ON or OFF
if (!status.equalsIgnoreCase("ON") && !status.equalsIgnoreCase("OFF")) {
throw new BadRequestAlertException("Invalid status: " + status, "DeviceService", "flashlight");
}
String deviceCamIp = devices.get().getCamIp();
String url = String.format(DEVICE_URL_FORMAT+"/flashlight/%s", deviceCamIp, deviceUid, status);
// Making the HTTP get for entity call
ResponseEntity<FlashlightResponseDto> response = restTemplate.getForEntity(url, FlashlightResponseDto.class);
if (response.getStatusCode() == HttpStatus.OK) {
ActivityLogDto activityLogDto = new ActivityLogDto();
activityLogDto.setActivityLogType(FLASH_LIGHT);
activityLogDto.setActivityLogDescription(response.getBody().getMessage());
activityLogService.saveActivityLog(activityLogDto);
return ResponseEntity.ok(new ResponseDto(Long.parseLong("200"), response.getBody().getMessage()));
} else {
throw new BadRequestAlertException("No response from device flashlight endpoint", "DeviceService", "flashlight");
}
} catch (Exception e) {
log.error("Error in DeviceService: flashlight method", e);
e.printStackTrace();
throw new BadRequestAlertException(e.getMessage(), "DeviceService", "flashlight");
}
}
@Override
public ResponseEntity<ResponseDto> swing(String deviceUid, SwingRequestDto swingRequest) {
log.info("Inside DeviceService: swing method");
try {
Optional<Devices> devices = devicesDao.findByDeviceUid(deviceUid);
if (devices.isEmpty()) {
throw new BadRequestAlertException("Device is not registered in the system by deviceUid: " + deviceUid, "DeviceService", "flashlight");
}
// check if swing speed is between LOW, MEDIUM, HIGH
if (!swingRequest.getSpeed().equalsIgnoreCase("LOW") && !swingRequest.getSpeed().equalsIgnoreCase("MEDIUM") && !swingRequest.getSpeed().equalsIgnoreCase("HIGH")) {
throw new BadRequestAlertException("Invalid swing speed: " + swingRequest.getSpeed(), "DeviceService", "swing");
}
swingRequest.setSpeed(swingRequest.getSpeed().toLowerCase());
String devIp = devices.get().getDevIp();
String url = String.format(DEVICE_URL_FORMAT+"/oscillate", devIp, deviceUid);
// Convert swingRequest to JSON and set up headers
ObjectMapper objectMapper = new ObjectMapper();
String jsonRequest = objectMapper.writeValueAsString(swingRequest);
// Create HttpHeaders
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// Create HttpEntity with the request body and headers
HttpEntity<String> requestEntity = new HttpEntity<>(jsonRequest, headers);
// Making the HTTP post call
ResponseEntity<SwingResponseDto> response = restTemplate.postForEntity(url, requestEntity, SwingResponseDto.class);
// Check if the response is not null and has a body
if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
ActivityLogDto activityLogDto = new ActivityLogDto();
activityLogDto.setActivityLogType(C_SWING);
activityLogDto.setActivityLogDescription(response.getBody().getStatus());
activityLogService.saveActivityLog(activityLogDto);
return ResponseEntity.ok(new ResponseDto(Long.parseLong("200"), response.getBody().getStatus()));
} else if (response.getStatusCode() == HttpStatus.OK) {
// Handle the case where the response is OK but the body is null
throw new BadRequestAlertException("Received empty response from device swing endpoint", "DeviceService", "swing");
} else {
// Handle unexpected status codes
throw new BadRequestAlertException("Unexpected response from device swing endpoint: " + response.getStatusCode(), "DeviceService", "swing");
}
} catch (Exception e) {
log.error("Error in DeviceService: swing method", e);
e.printStackTrace();
throw new BadRequestAlertException(e.getMessage(), "DeviceService", "swing");
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment