From b4489b1c0ab55c9d123bc99c11a02badba84883d Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Mon, 27 May 2024 11:29:41 +0900 Subject: [PATCH 01/16] marker --- .../Lantern_Of_Dusk_BE/entity/ConnectionDTO.java | 4 ---- .../Lantern_Of_Dusk_BE/entity/Marker.java | 2 ++ .../repository/MarkerRepository.java | 12 ++++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/ConnectionDTO.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Marker.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/MarkerRepository.java diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/ConnectionDTO.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/ConnectionDTO.java deleted file mode 100644 index 82cd901..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/ConnectionDTO.java +++ /dev/null @@ -1,4 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.entity; - -public class ConnectionDTO { -} diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Marker.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Marker.java new file mode 100644 index 0000000..8b0b99c --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Marker.java @@ -0,0 +1,2 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.entity;public class Marker { +} diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/MarkerRepository.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/MarkerRepository.java new file mode 100644 index 0000000..3bac93a --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/MarkerRepository.java @@ -0,0 +1,12 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.repository; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface ConnectionRepository extends JpaRepository { + Optional findByApplicationEntity(String ae); +} From e90cf98908a55925d47bd4941f612caa56b0b71b Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Mon, 27 May 2024 11:31:56 +0900 Subject: [PATCH 02/16] dev --- .DS_Store | Bin 6148 -> 14340 bytes src/.DS_Store | Bin 6148 -> 6148 bytes src/main/.DS_Store | Bin 6148 -> 6148 bytes .../controller/ApiController.java | 83 +++++++++++------- .../Lantern_Of_Dusk_BE/entity/Connection.java | 3 +- .../Lantern_Of_Dusk_BE/entity/Marker.java | 25 +++++- .../Lantern_Of_Dusk_BE/entity/Position.java | 1 - .../repository/MarkerRepository.java | 5 +- .../service/ApiService.java | 37 +++++--- 9 files changed, 104 insertions(+), 50 deletions(-) diff --git a/.DS_Store b/.DS_Store index 3e85b552d9b05f9e8d63e6351830c16927aaf58f..288f8d338ce406f89b7739481d368703b188fc86 100644 GIT binary patch literal 14340 zcmeGiYiJxr`1>|VvunG}_GMGgv{w(c)TF(nNo}pI*W^-Do7hL5O{?+lc5RmK?Z(@^ zq#CPHL3~oF4}760h)+~Rv5Id|`$zB*6%|B81QD#Ff^Yq1cQ4t!YYL)>l^NLmX1~XL zGv9sR%r|ob0N9*Y>jB~bAkxF2GJ{@M0z?@M6h>!HNhu=?(o;td)fE683{bOHGMP3? zxJwZNp_qI*Jr$6Kd{Ev>6IR@E@cU0r|NXV~;CQWi*!a4el0@Z&TYy`DTYy`DTYy{O zuUmkvy;Q{M9^`Ls0d4_qfe8z+`5{UVg9#swdC;9Y=*3caMrSF!Tc}R^02deaVZw)F z9&|-X#uX*#iK4&7Ku?_TQN~U%;lnWxdg6edIH0c?{T&Lr+DR_zvI8bO$lu%o+ybQ* zs3ufs@2%3_y=dq)b_H>Ywt*jJZj8Rl$~2fc``V zviCjlzLsjC@f*7)Ee`O|(`JJ+C5s%CODu}*<^-|8Oz*~(-^%sV;T9ZX%8r~GASdIH&Twa-Y`1#i!{Pj*_oVW z7+Wk`XU%NyPwnZ__Bf2%=lGQpuD*WT$~i4=y90`nx3z5=HLDM6Now5g(@8sPVeW(- zyb4N>R#n%WaMCI9rqkB7oVjW9xH4<@9C@BRzjs)-^|YaNkLap1xIJZOG*i{hUH$Zv zn2vtFuH~dzSSxjzsjN0WXVz?G!EupDUp}p0kk_3Hm6#~H*oBKC@=ldH(P61fN>!c` zC6^Lg6p8F$l$M-EZ`Bt#c}Ya>vZ=31%4e*tljW}6ZSx5E zrjKnStothxo(Z+8x?>fH?KFz*thx27>W+aKFtRn$DJt)X^i$~OuukznzoZuyQmpV3 z#1c!rs%t_imWcZl5f(usY=E;VydAg{u7ca)J~#j`!#nUUdEEY}>VnVG@CoC7@LW__T zI)ol!hp^M@xljnY{=yi2yhbn_boQ`6kqA#r6;y2-H@2N6w;zo`^A@~7)Ly7!6f>AsX8*weR;wJ3I9k`P``#enJ zZZyy&|7PAjihJ=A9K);e8uIY#aUb4_x8WUlC*DO~{s8$o^YW+gX*__>;;Z-?zK(C; zTlhA0xe47}At3I7L!yc??QPunk%%fk;9J!DWyIwMgQp zB8e)nL8E!gp}!kU(rF(lH4#`U6Vz8m{5i;kbqMbro-2@!JX4rO{pWOqq{dM?`8-;0(|Hf8Y0qn?g*;2Iu(0 z(L=L*`QxnjmEnaqqM_x=T~dTExDgmv$KkaYW$px!svuIupAxC!c{ z&QfYfA8w&WgXcDZMCE8cHwm0X1+7@ta`8vu@f!ThgrAx4Gn2o4W)ciIeq!Ps?(q|o zsZIv}%O@sN{58S%|9tKo zJlUCSCS>8?@gll=RWC}&^XOqbFVVva)m;&Kx!3Usy4UgOgI&j42*~eD{DXHU`2L?=+&LO=O#BH>-fp-6 delta 165 zcmZoEXfcprU|?W$DortDU=RQ@Ie-{Mvv5r;6q~3gIoZI3MH0wo-~?huuv`j*9z!}q z5kn$F%EpV!nHf1JrwOEQ&XBmkxOs)t5yr*r92|noAT2=E+(5z=WZK4y-B!ku~2NHo+2a9#(>?7ixZfc7|1sn6{FivdH+04$t e&jAdn&4J9{nJ4p$IC3yDFff7CY>p6F!wdi~m`-~D delta 71 zcmZoMXfc=|#>B)qu~2NHo+2a5#(>?7j4YdZSXdb+ce0vq7UK|Pnb@#yGdl-A2T<8& ZL5}atlles)IT(O|k%56_bA-qmW&n5$5FY>l diff --git a/src/main/.DS_Store b/src/main/.DS_Store index 1fdbd60cfab72c3c83bbfdba55e0c9a8e270f62b..4c341bc26e9ebaf708b7ef2b6bfcdf374e1ae227 100644 GIT binary patch delta 358 zcmZoMXfc=|#>B!ku~2NHo+2a9#(>?7ixZfc7&3AE0%E?axigB>s`0Zo%@2DfHdB)qu~2NHo+2a5#(>?7j4YdZSXdb+cd|Ne7UK|Pnb@#oGdl-A2T<8& ZL5}atlles)IT(O|k%56_bA-qmW&n6x5FY>l diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/ApiController.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/ApiController.java index 6c023d7..90e098a 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/ApiController.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/ApiController.java @@ -1,6 +1,7 @@ package IOT_Platform.Lantern_Of_Dusk_BE.controller; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Marker; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; import IOT_Platform.Lantern_Of_Dusk_BE.service.ApiService; import lombok.AllArgsConstructor; @@ -8,11 +9,11 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; import java.util.*; @RestController @AllArgsConstructor +@CrossOrigin @RequestMapping("/api") public class ApiController { @@ -20,15 +21,15 @@ public class ApiController { // GET /api/connection/list ⇒ 모든 연결 정보 / X @GetMapping("/connection/list") - public List getConnectionAll() { - return apiService.findAll(); + public List readConnectionList() { + return apiService.getConnectionList(); } // GET /api/connection/:id ⇒ 특정 아이디의 연결 정보 / (int id) @GetMapping("/connection/{id}") - public ResponseEntity getConnection(@PathVariable int id) { + public ResponseEntity readConnection(@PathVariable int id) { try { - Connection connection = apiService.findById(id); + Connection connection = apiService.getConnection(id); if (connection != null) { return new ResponseEntity<>(connection, HttpStatus.OK); } else { @@ -39,13 +40,13 @@ public ResponseEntity getConnection(@PathVariable int id) { } } - // POST /api/connection ⇒ 연결 정보 생성 / json {id, name, applicationEntity} + // POST /api/connection ⇒ 연결 정보 생성 / json {name, applicationEntity} @PostMapping("/connection") - public ResponseEntity postConnection(@RequestBody Connection connectionContext) { + public ResponseEntity createConnection(@RequestBody Connection connection) { try { - if (apiService.findByAe(connectionContext.getApplicationEntity()) == null) { - apiService.save(connectionContext); - return new ResponseEntity<>(apiService.findByAe(connectionContext.getApplicationEntity()), HttpStatus.CREATED); + if (apiService.getConnection(connection.getAe()) == null) { + apiService.saveConnection(connection); + return new ResponseEntity<>(HttpStatus.CREATED); } else return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } catch (Exception e) { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); @@ -55,15 +56,14 @@ public ResponseEntity postConnection(@RequestBody Connection connect // PUT /api/connection/{id} ⇒ 연결 정보 업데이트 / (int id), json {id, name, applicationEntity} @PutMapping("/connection/{id}") public ResponseEntity updateConnection(@PathVariable int id, @RequestBody Connection updatedConnection) { - try { - if (apiService.findById(id) != null) { - Connection pastConnection = apiService.findById(id); + if (apiService.getConnection(id) != null) { + Connection pastConnection = apiService.getConnection(id); pastConnection.setId(updatedConnection.getId()); pastConnection.setName(updatedConnection.getName()); - pastConnection.setApplicationEntity(updatedConnection.getApplicationEntity()); - apiService.save(pastConnection); - return new ResponseEntity<>(apiService.findById(id), HttpStatus.OK); + pastConnection.setAe(updatedConnection.getAe()); + apiService.saveConnection(pastConnection); + return new ResponseEntity<>(apiService.getConnection(id), HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @@ -75,10 +75,9 @@ public ResponseEntity updateConnection(@PathVariable int id, @Reques // DELETE /api/connection/:id ⇒ 연결 정보 삭제 / (int id) @DeleteMapping("/connection/{id}") public ResponseEntity deleteConnection(@PathVariable int id) { - try { - if (apiService.findById(id) != null) { - apiService.deleteById(id); + if (apiService.getConnection(id) != null) { + apiService.deleteDevice(id); return new ResponseEntity<>("ID의 ae가 삭제되었습니다", HttpStatus.OK); } else { return new ResponseEntity<>("요청에 문제가 있습니다.", HttpStatus.BAD_REQUEST); @@ -88,25 +87,49 @@ public ResponseEntity deleteConnection(@PathVariable int id) { } } - // DELETE /api/connection ⇒ 연결 정보 삭제 - @DeleteMapping("/connection") - public ResponseEntity deleteAllConnection() { - - apiService.deleteAll(); - return new ResponseEntity<>("전체 connection-ae가 삭제되었습니다.", HttpStatus.OK); - } // GET /api/position/:deviceId ⇒ deviceId 위치정보 / (int deviceId) @GetMapping("/position/{deviceId}") - public ResponseEntity getPositionByDeviceId(@PathVariable int deviceId) { - + public ResponseEntity readPosition(@PathVariable int deviceId) { try { - if (apiService.findById(deviceId) != null && apiService.getApplicationEntityByDeviceId(deviceId) != null) { - Position position = apiService.getApplicationEntityByDeviceId(deviceId); + if (apiService.getConnection(deviceId) != null && apiService.getPosition(deviceId) != null) { + Position position = apiService.getPosition(deviceId); return new ResponseEntity<>(position, HttpStatus.OK); } else return new ResponseEntity<>(HttpStatus.NOT_FOUND); } catch (Exception e) { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } + + // GET /api/marker/list ⇒ 마커 정보 / x + @GetMapping("/marker/list") + public List readMarkerList() { + return apiService.getMarkerList(); + } + + // POST /api/marker ⇒ 마커 정보 / json {x, y, z} + @PostMapping("/marker") + public ResponseEntity createMarker(@RequestBody Marker marker) { + try { + apiService.saveMarker(marker); + return new ResponseEntity<>(HttpStatus.CREATED); + } catch (Exception e) { + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + // DELETE /api/marker/:id ⇒ 마커 삭제 / (int id) + @DeleteMapping("/marker/{id}") + public ResponseEntity deleteMarker(@PathVariable int id) { + try { + if (apiService.getMarker(id) != null) { + apiService.deleteMarker(id); + return new ResponseEntity<>("Marker가 삭제되었습니다.", HttpStatus.OK); + } else { + return new ResponseEntity<>("요청에 문제가 있습니다.", HttpStatus.BAD_REQUEST); + } + } catch (Exception e) { + return new ResponseEntity<>("서버에 오류 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR); + } + } } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java index adb6905..ed4293e 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java @@ -13,10 +13,9 @@ @AllArgsConstructor @Entity public class Connection { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; - private String applicationEntity; + private String ae; } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Marker.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Marker.java index 8b0b99c..5c78c1b 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Marker.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Marker.java @@ -1,2 +1,25 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.entity;public class Marker { +package IOT_Platform.Lantern_Of_Dusk_BE.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +public class Marker { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + private String name; + private double x; + private double y; + private double z; } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java index 3eb091d..23e03d6 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java @@ -15,7 +15,6 @@ @AllArgsConstructor @Entity public class Position { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/MarkerRepository.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/MarkerRepository.java index 3bac93a..f4e3f44 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/MarkerRepository.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/MarkerRepository.java @@ -1,12 +1,13 @@ package IOT_Platform.Lantern_Of_Dusk_BE.repository; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Marker; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository -public interface ConnectionRepository extends JpaRepository { - Optional findByApplicationEntity(String ae); +public interface MarkerRepository extends JpaRepository { + } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java index 710d4b6..009b663 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java @@ -1,8 +1,10 @@ package IOT_Platform.Lantern_Of_Dusk_BE.service; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Marker; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.MarkerRepository; import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -14,38 +16,45 @@ public class ApiService { private final ConnectionRepository connectionRepository; private final PositionRepository positionRepository; + private final MarkerRepository markerRepository; @Autowired - public ApiService(ConnectionRepository connectionRepository, PositionRepository positionRepository) { + public ApiService(ConnectionRepository connectionRepository, PositionRepository positionRepository, MarkerRepository markerRepository) { this.connectionRepository = connectionRepository; this.positionRepository = positionRepository; + this.markerRepository = markerRepository; } - public void save(Connection connection) { + public void saveConnection(Connection connection) { connectionRepository.save(connection); } - - public Connection findById(int id) { + public Connection getConnection(int id) { return connectionRepository.findById(id).orElse(null); } - - public Connection findByAe(String ae) { + public Connection getConnection(String ae) { return connectionRepository.findByApplicationEntity(ae).orElse(null); } - - public List findAll() { + public List getConnectionList() { return connectionRepository.findAll(); } - - public void deleteById(int id) { + public void deleteDevice(int id) { connectionRepository.deleteById(id); } - public void deleteAll() { - connectionRepository.deleteAll(); + public Position getPosition(int deviceId) { + return positionRepository.findTopByDeviceIdOrderByIdDesc(deviceId).orElse(null); } - public Position getApplicationEntityByDeviceId(int deviceId) { - return positionRepository.findTopByDeviceIdOrderByIdDesc(deviceId).orElse(null); + public void saveMarker(Marker marker) { + markerRepository.save(marker); + } + public List getMarkerList() { + return markerRepository.findAll(); + } + public Marker getMarker(int id) { + return markerRepository.findById(id).orElse(null); + } + public void deleteMarker(int id) { + markerRepository.deleteById(id); } } \ No newline at end of file From b05d6cd70e40abf58a29dfefc4addded2abd3d8f Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Mon, 27 May 2024 13:35:10 +0900 Subject: [PATCH 03/16] remove --- .../Lantern_Of_Dusk_BE/CommonMobiusMethod.java | 4 ---- .../exception/MissingIdException.java | 8 -------- .../Lantern_Of_Dusk_BE/service/MobiusService.java | 12 ------------ 3 files changed, 24 deletions(-) delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/CommonMobiusMethod.java delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/exception/MissingIdException.java delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/CommonMobiusMethod.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/CommonMobiusMethod.java deleted file mode 100644 index c613679..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/CommonMobiusMethod.java +++ /dev/null @@ -1,4 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE; - -public class CommonMobiusMethod { -} diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/exception/MissingIdException.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/exception/MissingIdException.java deleted file mode 100644 index 913f3eb..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/exception/MissingIdException.java +++ /dev/null @@ -1,8 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.exception; - -public class MissingIdException extends RuntimeException { - - public MissingIdException(String message) { - super(message); - } -} diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java deleted file mode 100644 index 113be61..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java +++ /dev/null @@ -1,12 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.service; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; -import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; - -@Service -public class MobiusService { - -} From f51c423f34442e561a79f8986c2a0d0131fd377b Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Mon, 27 May 2024 13:35:50 +0900 Subject: [PATCH 04/16] edit --- .../Lantern_Of_Dusk_BE/repository/ConnectionRepository.java | 2 +- .../IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/ConnectionRepository.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/ConnectionRepository.java index 3bac93a..48cd89e 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/ConnectionRepository.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/repository/ConnectionRepository.java @@ -8,5 +8,5 @@ @Repository public interface ConnectionRepository extends JpaRepository { - Optional findByApplicationEntity(String ae); + Optional findByAe(String ae); } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java index 009b663..dd98b62 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ApiService.java @@ -32,7 +32,7 @@ public Connection getConnection(int id) { return connectionRepository.findById(id).orElse(null); } public Connection getConnection(String ae) { - return connectionRepository.findByApplicationEntity(ae).orElse(null); + return connectionRepository.findByAe(ae).orElse(null); } public List getConnectionList() { return connectionRepository.findAll(); From 071dfd132cc1ddae40e3472b36507a21994a6821 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Mon, 27 May 2024 20:32:12 +0900 Subject: [PATCH 05/16] jj --- .../IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java new file mode 100644 index 0000000..26dab6b --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java @@ -0,0 +1,2 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.service;public class MobiusService { +} From baaaa0f0de90005b4a072441473601ca71dc772b Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Mon, 27 May 2024 20:32:31 +0900 Subject: [PATCH 06/16] sadf --- .../config/SwaggerConfiguration.java | 2 +- .../service/MobiusService.java | 124 +++++++++++++++++- 2 files changed, 123 insertions(+), 3 deletions(-) diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/config/SwaggerConfiguration.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/config/SwaggerConfiguration.java index 0caa101..ca9c6c2 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/config/SwaggerConfiguration.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/config/SwaggerConfiguration.java @@ -38,4 +38,4 @@ public OpenAPI openAPI() { .addSecurityItem(securityRequirement) .components(components); } -} +} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java index 26dab6b..3df0d71 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java @@ -1,2 +1,122 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.service;public class MobiusService { -} +package IOT_Platform.Lantern_Of_Dusk_BE.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; + +@Service +public class MobiusService { + + private final RestTemplate restTemplate; + private final ConnectionRepository connectionRepository; + + @Value("${mobius.server.url}") + private String mobiusServerUrl; + + private static final Logger logger = LoggerFactory.getLogger(MobiusService.class); + + @Autowired + public MobiusService(RestTemplateBuilder restTemplateBuilder, ConnectionRepository connectionRepository) { + this.restTemplate = restTemplateBuilder.build(); + this.connectionRepository = connectionRepository; + } + + /** + * 특정 AE에 해당하는 데이터를 Mobius로부터 가져오는 메서드입니다. + * @param ae Application Entity의 이름 + * @return Mobius로부터 받은 데이터 + */ + public String fetchDataFromMobiusForAE(String ae) { + // Connection 테이블에서 AE에 대한 정보를 가져옵니다. + Optional connection = connectionRepository.findByApplicationEntity(ae); + + // Connection 정보가 없는 경우 예외 처리 + if (connection.isEmpty()) { + throw new IllegalArgumentException("Connection not found for AE: " + ae); + } + + // 각 센서에 대한 데이터를 가져옵니다. + String accelerationData = fetchDataForSensor(connection.orElse(null), "ACCEL"); + String gyroscopeData = fetchDataForSensor(connection.orElse(null), "GYRO"); + String pressureData = fetchDataForSensor(connection.orElse(null), "PRESSURE"); + + // 데이터 조합 + String combinedData = "ACCEL: " + accelerationData + "\n" + + "GYRO: " + gyroscopeData + "\n" + + "PRESSURE: " + pressureData; + + return combinedData; + } + + + public String fetchDataForSensor(Connection connection, String sensor) { + // Mobius 서버로 요청할 URL 생성 + String url = mobiusServerUrl + connection.getName() + "/" + sensor; + try { + // Mobius 서버에 GET 요청을 보내 데이터를 받아옵니다. + String responseData = restTemplate.getForObject(url, String.class); + + // 받아온 JSON 데이터를 파싱하여 컨테이너 값들을 추출합니다. + Map containerData = parseJsonData(responseData); + + // 센서에 해당하는 데이터 반환 + return containerData.toString(); + } catch (RestClientException e) { + // 요청에 실패한 경우 에러를 로그에 기록하고 예외를 던집니다. + logger.error("Error fetching data for AE {} from Mobius: ", connection.getApplicationEntity(), e); + throw new RuntimeException("Failed to fetch data from Mobius for AE: " + connection.getApplicationEntity(), e); + } + } + + + + + + + /** + * JSON 데이터를 파싱하여 Map으로 변환하는 메서드입니다. + * @param jsonData JSON 형식의 데이터 + * @return 파싱된 데이터가 담긴 Map 객체 + */ + private Map parseJsonData(String jsonData) { + try { + // JSON 데이터를 파싱하는 ObjectMapper 객체 생성 + ObjectMapper objectMapper = new ObjectMapper(); + // JSON 데이터를 JsonNode 객체로 읽어옵니다. + JsonNode rootNode = objectMapper.readTree(jsonData); + + // 각 센서의 값을 추출하여 Map에 저장합니다. + Map containerData = new HashMap<>(); + containerData.put("acceleration_x", rootNode.get("acceleration").get("x").asText()); + containerData.put("acceleration_y", rootNode.get("acceleration").get("y").asText()); + containerData.put("acceleration_z", rootNode.get("acceleration").get("z").asText()); + + containerData.put("gyroscope_x", rootNode.get("gyroscope").get("x").asText()); + containerData.put("gyroscope_y", rootNode.get("gyroscope").get("y").asText()); + containerData.put("gyroscope_z", rootNode.get("gyroscope").get("z").asText()); + + containerData.put("pressure", rootNode.get("pressure").asText()); + + return containerData; + } catch (IOException e) { + // JSON 파싱 중 에러가 발생한 경우 에러를 로그에 기록하고 예외를 던집니다. + logger.error("Error parsing JSON data: ", e); + throw new RuntimeException("Failed to parse JSON data", e); + } + } +} \ No newline at end of file From 5373b214c9ef5f887042e87fda479fdf13718580 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Mon, 27 May 2024 20:54:56 +0900 Subject: [PATCH 07/16] final save --- build.gradle | 1 + gradlew | 0 .../Lantern_Of_Dusk_BE/entity/Connection.java | 8 +- .../Lantern_Of_Dusk_BE/entity/Data.java | 71 +++++++++++ .../Lantern_Of_Dusk_BE/entity/Position.java | 14 +++ .../filter/ExtendedKalmanFilter.java | 73 ++++++++++++ .../service/DataService.java | 72 +++++++++++ .../service/FilterService.java | 112 ++++++++++++++++++ .../service/MobiusService.java | 11 +- src/main/resources/application.properties | 4 +- .../servicetest/DataServiceTest.java | 77 ++++++++++++ .../servicetest/FilterServiceTest.java | 63 ++++++++++ .../servicetest/MobiusServiceTest.java | 75 ++++++++++++ 13 files changed, 566 insertions(+), 15 deletions(-) mode change 100644 => 100755 gradlew create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Data.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/filter/ExtendedKalmanFilter.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/FilterService.java create mode 100644 src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/DataServiceTest.java create mode 100644 src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/FilterServiceTest.java create mode 100644 src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java diff --git a/build.gradle b/build.gradle index 40a8b31..848ea9a 100644 --- a/build.gradle +++ b/build.gradle @@ -32,6 +32,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation("org.assertj:assertj-core:3.23.1") + implementation 'org.apache.commons:commons-math3:3.6.1' } tasks.named('test') { diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java index ed4293e..a2f02a1 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java @@ -1,11 +1,7 @@ package IOT_Platform.Lantern_Of_Dusk_BE.entity; import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - +import lombok.*; @Getter @Setter @@ -16,6 +12,8 @@ public class Connection { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; + + @Getter private String name; private String ae; } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Data.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Data.java new file mode 100644 index 0000000..f2b5df0 --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Data.java @@ -0,0 +1,71 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +public class Data { + @Id + private int id; + private double x; + private double y; + private double z; + private double pitch; + private double yaw; + private double roll; + private double pressure; + + public Data(double x, double y, double z, double pitch, double yaw, double roll, double pressure) { + this.x = x; + this.y = y; + this.z = z; + this.pitch = pitch; + this.yaw = yaw; + this.roll = roll; + this.pressure = pressure; + } + + // JSON 데이터를 파싱해서 Data 객체로 변환하는 메서드 + public static Data fromJson(String jsonData) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonData); + return new Data( + rootNode.get("x").asDouble(), + rootNode.get("y").asDouble(), + rootNode.get("z").asDouble(), + rootNode.get("pitch").asDouble(), + rootNode.get("yaw").asDouble(), + rootNode.get("roll").asDouble(), + rootNode.get("pressure").asDouble() // 기압 데이터 파싱 + ); + } catch (IOException e) { + throw new RuntimeException("Failed to parse JSON data", e); + } + } + + @Override + public String toString() { + return "Data{" + + "id=" + id + + ", x=" + x + + ", y=" + y + + ", z=" + z + + ", pitch=" + pitch + + ", yaw=" + yaw + + ", roll=" + roll + + ", pressure=" + pressure + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java index 23e03d6..11ffc27 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java @@ -27,4 +27,18 @@ public class Position { private double yaw ; // z @CreationTimestamp private LocalDateTime timeStamp; + + @Override + public String toString() { + return "Position{" + + "deviceId=" + deviceId + + ", x=" + x + + ", y=" + y + + ", z=" + z + + ", roll=" + roll + + ", pitch=" + pitch + + ", yaw=" + yaw + + '}'; + } } + diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/filter/ExtendedKalmanFilter.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/filter/ExtendedKalmanFilter.java new file mode 100644 index 0000000..030b13c --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/filter/ExtendedKalmanFilter.java @@ -0,0 +1,73 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.filter; + +import org.apache.commons.math3.linear.MatrixUtils; +import org.apache.commons.math3.linear.RealMatrix; + +/** + * 클래스: ExtendedKalmanFilter + * 설명: 확장 칼만 필터 (EKF)를 구현한 클래스입니다. + */ +public class ExtendedKalmanFilter { + private RealMatrix state; // 상태 벡터 + private RealMatrix covariance; // 상태 공분산 행렬 + private RealMatrix stateTransition; // 상태 전이 행렬 + private RealMatrix processNoise; // 프로세스 노이즈 공분산 행렬 + private RealMatrix measurementNoise; // 측정 노이즈 공분산 행렬 + private RealMatrix observationMatrix; // 관측 행렬 + + /** + * 생성자: ExtendedKalmanFilter + * 설명: 확장 칼만 필터의 초기 상태와 매개변수를 설정합니다. + * + * @param initialState 초기 상태 벡터 + * @param initialCovariance 초기 상태 공분산 행렬 + * @param stateTransition 상태 전이 행렬 + * @param processNoise 프로세스 노이즈 공분산 행렬 + * @param measurementNoise 측정 노이즈 공분산 행렬 + * @param observationMatrix 관측 행렬 + */ + public ExtendedKalmanFilter(RealMatrix initialState, RealMatrix initialCovariance, + RealMatrix stateTransition, RealMatrix processNoise, + RealMatrix measurementNoise, RealMatrix observationMatrix) { + this.state = initialState; + this.covariance = initialCovariance; + this.stateTransition = stateTransition; + this.processNoise = processNoise; + this.measurementNoise = measurementNoise; + this.observationMatrix = observationMatrix; + } + + /** + * 메서드: predict + * 설명: 상태와 공분산을 예측합니다. + */ + public void predict() { + state = stateTransition.multiply(state); + covariance = stateTransition.multiply(covariance).multiply(stateTransition.transpose()).add(processNoise); + } + + /** + * 메서드: update + * 설명: 새로운 측정값을 사용하여 상태와 공분산을 갱신합니다. + * + * @param measurement 새로운 측정값 벡터 + */ + public void update(RealMatrix measurement) { + RealMatrix y = measurement.subtract(observationMatrix.multiply(state)); // 잔차 계산 + RealMatrix s = observationMatrix.multiply(covariance).multiply(observationMatrix.transpose()).add(measurementNoise); // 잔차 공분산 + RealMatrix k = covariance.multiply(observationMatrix.transpose()).multiply(MatrixUtils.inverse(s)); // 칼만 이득 계산 + state = state.add(k.multiply(y)); // 상태 업데이트 + RealMatrix i = MatrixUtils.createRealIdentityMatrix(state.getRowDimension()); + covariance = (i.subtract(k.multiply(observationMatrix))).multiply(covariance); // 공분산 업데이트 + } + + /** + * 메서드: getState + * 설명: 현재 상태 벡터를 반환합니다. + * + * @return 현재 상태 벡터 + */ + public RealMatrix getState() { + return state; + } +} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java new file mode 100644 index 0000000..afd030e --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java @@ -0,0 +1,72 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.service; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Data; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.util.*; + +@Service +public class DataService { + + private final MobiusService mobiusService; + private final ConnectionRepository connectionRepository; + private final FilterService filterService; + private final Map> dataArrays; + + @Autowired + public DataService(MobiusService mobiusService, ConnectionRepository connectionRepository, FilterService filterService) { + this.mobiusService = mobiusService; + this.connectionRepository = connectionRepository; + this.filterService = filterService; + this.dataArrays = new HashMap<>(); + } + + /** + * 7ms마다 Mobius 서버에서 데이터를 가져와 배열에 저장하는 메서드. + */ + @Scheduled(fixedRate = 7) + public void fetchDataFromMobius() { + + // 데이터베이스에서 모든 Connection을 가져옵니다. + List connections = connectionRepository.findAll(); + + for (Connection connection : connections) { + String aeName = connection.getAe(); + + try { + // Mobius 서버에서 JSON 데이터를 가져옴 + String jsonData = mobiusService.fetchDataFromMobiusForAE(aeName); + // JSON 데이터를 Data 객체로 변환 + Data data = Data.fromJson(jsonData); + + // 해당 AE의 데이터 배열을 가져옴 + List dataArray = dataArrays.computeIfAbsent(aeName, k -> new ArrayList<>()); + + // 데이터 배열에 추가 + dataArray.add(data); + + // 1초 동안의 데이터(약 143개)를 초과하면 앞의 데이터를 제거 + if (dataArray.size() > 143) { + dataArray.remove(0); + } + + // 데이터 배열이 143개가 되면 필터링 수행 + if (dataArray.size() == 143) { + filterService.applyFilter(new ArrayList<>(dataArray), Integer.parseInt(connection.getName())); + } + } catch (Exception e) { + // 에러 처리 + System.err.println("Error fetching data for AE " + aeName + ": " + e.getMessage()); + } + } + } + + //테스트용 매서드 + public List getDataArray(String aeName) { + return dataArrays.getOrDefault(aeName, new ArrayList<>()); + } +} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/FilterService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/FilterService.java new file mode 100644 index 0000000..94b7211 --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/FilterService.java @@ -0,0 +1,112 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.service; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Data; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; +import IOT_Platform.Lantern_Of_Dusk_BE.filter.ExtendedKalmanFilter; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; +import lombok.Getter; +import org.apache.commons.math3.linear.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class FilterService { + + private final PositionRepository positionRepository; + private final ExtendedKalmanFilter kalmanFilter; + + @Autowired + public FilterService(PositionRepository positionRepository) { + this.positionRepository = positionRepository; + + // 초기 상태 벡터 및 공분산 행렬 설정 (모든 값이 0인 상태로 초기화) + RealMatrix initialState = MatrixUtils.createColumnRealMatrix(new double[]{0, 0, 0, 0, 0, 0}); // [x, y, z, roll, pitch, yaw] + RealMatrix initialCovariance = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); + + // 상태 전이 행렬, 프로세스 노이즈, 측정 노이즈, 관측 행렬 설정 (임의의 예시 값, 실제 응용에 따라 조정 필요) + RealMatrix stateTransition = MatrixUtils.createRealIdentityMatrix(6); + RealMatrix processNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{0.1, 0.1, 0.1, 0.1, 0.1, 0.1}); + RealMatrix measurementNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); + RealMatrix observationMatrix = MatrixUtils.createRealIdentityMatrix(6); + + this.kalmanFilter = new ExtendedKalmanFilter(initialState, initialCovariance, stateTransition, processNoise, measurementNoise, observationMatrix); + } + + /** + * 메서드: applyFilter + * 설명: 수집된 데이터를 필터링하고 위치 정보를 저장합니다. + * + * @param dataList 143개의 센서 데이터 리스트 + * @param deviceId 장치 ID + */ + public void applyFilter(List dataList, int deviceId) { + for (Data data : dataList) { + // 측정값 벡터 생성 + RealMatrix measurement = MatrixUtils.createColumnRealMatrix(new double[]{ + data.getX(), data.getY(), data.getZ(), + data.getRoll(), data.getPitch(), data.getYaw() + }); + + // 예측 단계 + kalmanFilter.predict(); + + // 업데이트 단계 + kalmanFilter.update(measurement); + } + + // 필터링된 상태 벡터 가져오기 + RealMatrix state = kalmanFilter.getState(); + + // 상태 벡터에서 위치 정보 추출 + double x = state.getEntry(0, 0); + double y = state.getEntry(1, 0); + double z = state.getEntry(2, 0); + double roll = state.getEntry(3, 0); + double pitch = state.getEntry(4, 0); + double yaw = state.getEntry(5, 0); + + // 위치 정보 저장 + Position position = new Position(); + position.setDeviceId(deviceId); + position.setX(x); + position.setY(y); + position.setZ(z); + position.setRoll(roll); + position.setPitch(pitch); + position.setYaw(yaw); + + positionRepository.save(position); + } + + /** + * 메서드: getFilteredPosition + * 설명: 필터링된 위치 정보를 반환합니다. + * + * @return 필터링된 위치 정보 + */ + public Position getFilteredPosition() { + // 필터링된 상태 벡터 가져오기 + RealMatrix state = kalmanFilter.getState(); + + // 상태 벡터에서 위치 정보 추출 + double x = state.getEntry(0, 0); + double y = state.getEntry(1, 0); + double z = state.getEntry(2, 0); + double roll = state.getEntry(3, 0); + double pitch = state.getEntry(4, 0); + double yaw = state.getEntry(5, 0); + + // 필터링된 위치 정보 반환 + Position position = new Position(); + position.setX(x); + position.setY(y); + position.setZ(z); + position.setRoll(roll); + position.setPitch(pitch); + position.setYaw(yaw); + + return position; + } +} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java index 3df0d71..480b567 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java @@ -43,7 +43,7 @@ public MobiusService(RestTemplateBuilder restTemplateBuilder, ConnectionReposito */ public String fetchDataFromMobiusForAE(String ae) { // Connection 테이블에서 AE에 대한 정보를 가져옵니다. - Optional connection = connectionRepository.findByApplicationEntity(ae); + Optional connection = connectionRepository.findByAe(ae); // Connection 정보가 없는 경우 예외 처리 if (connection.isEmpty()) { @@ -78,16 +78,11 @@ public String fetchDataForSensor(Connection connection, String sensor) { return containerData.toString(); } catch (RestClientException e) { // 요청에 실패한 경우 에러를 로그에 기록하고 예외를 던집니다. - logger.error("Error fetching data for AE {} from Mobius: ", connection.getApplicationEntity(), e); - throw new RuntimeException("Failed to fetch data from Mobius for AE: " + connection.getApplicationEntity(), e); + logger.error("Error fetching data for AE {} from Mobius: ", connection.getAe(), e); + throw new RuntimeException("Failed to fetch data from Mobius for AE: " + connection.getAe(), e); } } - - - - - /** * JSON 데이터를 파싱하여 Map으로 변환하는 메서드입니다. * @param jsonData JSON 형식의 데이터 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 260c2f4..35d44c6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,10 +1,10 @@ spring.application.name=Lantern_Of_Dusk_BE -mobius.url=http://yhttp://203.253.128.177:7575//Mobius +mobius.url=http://203.253.128.177:7575//Mobius/ server.port=7777 spring.datasource.url=jdbc:mysql://localhost:3306/lod spring.datasource.username=root -spring.datasource.password=root +spring.datasource.password=1234 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true diff --git a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/DataServiceTest.java b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/DataServiceTest.java new file mode 100644 index 0000000..56e280d --- /dev/null +++ b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/DataServiceTest.java @@ -0,0 +1,77 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.servicetest; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Data; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; +import IOT_Platform.Lantern_Of_Dusk_BE.service.DataService; +import IOT_Platform.Lantern_Of_Dusk_BE.service.MobiusService; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.scheduling.annotation.EnableScheduling; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.Queue; + +@SpringBootTest +@EnableScheduling +public class DataServiceTest { + + @Mock + private MobiusService mobiusService; + + @Mock + private ConnectionRepository connectionRepository; + + @InjectMocks + private DataService dataService; + + /** + * + * 첫 번째 테스트는 fetchDataFromMobius 메서드를 테스트합니다. 이 메서드는 Mobius 서비스에서 데이터를 가져와서 처리하는데, 이를 테스트하기 위해 Mock 객체를 사용하여 Mobius 서비스와 연결정보를 대체합니다. 이 테스트는 Mobius 서비스가 정확한 AE(Application Entity) 이름을 사용하여 데이터를 가져오는지를 확인합니다. + */ + + @Test + public void testFetchDataFromMobius() { + // Mock 객체로 반환될 Connection 객체 생성 + Connection connection = new Connection(); + connection.setAe("device1"); + when(connectionRepository.findAll()).thenReturn(Collections.singletonList(connection)); + + // MobiusService에서 반환될 더미 데이터 설정 + String jsonData = "{\"acceleration\": {\"x\": \"0.1\", \"y\": \"0.2\", \"z\": \"0.3\"}, \"gyroscope\": {\"x\": \"0.4\", \"y\": \"0.5\", \"z\": \"0.6\"}, \"pressure\": \"1013.25\"}"; + when(mobiusService.fetchDataFromMobiusForAE(anyString())).thenReturn(jsonData); + + // fetchDataFromMobius 메서드 호출 + dataService.fetchDataFromMobius(); + + // 검증: MobiusService의 fetchDataFromMobiusForAE 메서드가 호출되었는지 확인 + verify(mobiusService, atLeastOnce()).fetchDataFromMobiusForAE("device1"); + } + + /** + * + * 두 번째 테스트는 saveData 메서드를 테스트합니다. 이 메서드는 수집된 데이터를 저장하는 역할을 담당합니다. 이 테스트는 데이터가 제대로 저장되고 저장 후에는 데이터 큐가 비워지는지를 확인합니다. + */ + + @Test + public void testSaveData() { + // AE 이름과 큐 생성 + String aeName = "device1"; + Queue queue = new LinkedList<>(); + for (int i = 0; i < 143; i++) { + queue.add(new Data()); // 예시로 더미 데이터를 큐에 추가 + } + + + // 데이터 큐의 크기가 0인지 확인 (saveData 호출 후에는 큐가 비워져야 함) + assertEquals(143, queue.size()); + // 데이터 큐의 크기가 0인지 확인 (saveData 호출 후에는 큐가 비워져야 함) + System.out.println("Remaining elements in the queue: " + queue.size()); + } +} diff --git a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/FilterServiceTest.java b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/FilterServiceTest.java new file mode 100644 index 0000000..dcae5c5 --- /dev/null +++ b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/FilterServiceTest.java @@ -0,0 +1,63 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.servicetest; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Data; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; +import IOT_Platform.Lantern_Of_Dusk_BE.service.FilterService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class FilterServiceTest { + + @Mock + private PositionRepository positionRepository; + + @InjectMocks + private FilterService filterService; + + private List mockDataList; + + @BeforeEach + public void setUp() { + // Mock 데이터를 생성합니다. + mockDataList = new ArrayList<>(); + for (int i = 0; i < 143; i++) { + mockDataList.add(new Data(i, i * 0.1, i * 0.1, i * 0.1, i * 0.01, i * 0.01, i * 0.01, 1000 + i * 0.1)); + } + } + + @Test + public void testApplyFilter() { + + + System.out.println("Original Data:"); + for (Data data : mockDataList) { + System.out.println(data); + } + // 필터링 적용 + filterService.applyFilter(mockDataList, 1); + + // 필터링된 위치 정보가 저장되었는지 확인 + verify(positionRepository, times(1)).save(any(Position.class)); + + + + // 데이터 개수 출력 + System.out.println("Number of data: " + mockDataList.size()); + + // 필터링된 데이터 개수 및 내용 출력 + Position filteredPosition = filterService.getFilteredPosition(); + System.out.println("Number of filtered data: 1"); // 필터링된 데이터는 한 개이므로 개수는 1 + System.out.println("Filtered Position: " + filteredPosition); + } +} diff --git a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java new file mode 100644 index 0000000..3e01ae7 --- /dev/null +++ b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java @@ -0,0 +1,75 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.servicetest; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; +import IOT_Platform.Lantern_Of_Dusk_BE.service.DataService; +import IOT_Platform.Lantern_Of_Dusk_BE.service.MobiusService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.PeriodicTrigger; + +import java.util.Collections; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +// 테스트 어노테이션 및 import 생략 + +public class MobiusServiceTest { + + @Mock + private MobiusService mobiusService; + + @Mock + private ConnectionRepository connectionRepository; + + @InjectMocks + private DataService dataService; + + private ThreadPoolTaskScheduler taskScheduler; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + + // Mock 객체로 반환될 Connection 객체 생성 + Connection connection = new Connection(); + connection.setAe("device1"); + + // connectionRepository.findAll()이 호출되었을 때 Mock 객체 반환 설정 + when(connectionRepository.findAll()).thenReturn(Collections.singletonList(connection)); + + // MobiusService에서 반환될 더미 데이터 설정 + String jsonData = "{\"acceleration\": {\"x\": \"0.1\", \"y\": \"0.2\", \"z\": \"0.3\"}, \"gyroscope\": {\"x\": \"0.4\", \"y\": \"0.5\", \"z\": \"0.6\"}, \"pressure\": \"1013.25\"}"; + when(mobiusService.fetchDataFromMobiusForAE(anyString())).thenReturn(jsonData); + + // TaskScheduler 초기화 및 스케줄링 설정 + taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.initialize(); + PeriodicTrigger trigger = new PeriodicTrigger(1000, TimeUnit.MILLISECONDS); // 1초로 변경 + taskScheduler.schedule(dataService::fetchDataFromMobius, trigger); + } + + /** + * MobiusService 클래스의 fetchDataFromMobiusForAE 메서드를 테스트하는 테스트 케이스입니다. + * fetchDataFromMobiusForAE 메서드가 호출되었는지, connectionRepository.findAll()이 한 번 호출되었는지, + * 반환된 Mock 객체의 속성이 정확히 설정되었는지를 확인합니다. + */ + @Test + public void testFetchDataFromMobius() throws InterruptedException { + // fetchDataFromMobiusForAE가 호출되었는지 확인 + verify(mobiusService, atLeast(1)).fetchDataFromMobiusForAE("device1"); + + // connectionRepository.findAll()이 호출되었는지 확인 + verify(connectionRepository, times(1)).findAll(); + + // 반환된 Mock 객체의 속성이 예상한 대로 설정되었는지 확인 + Connection connection = connectionRepository.findAll().get(0); + assertEquals("device1", connection.getApplicationEntity()); + } +} From 441663176930051e52c7ba16ea70d049538cde78 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Mon, 27 May 2024 20:56:30 +0900 Subject: [PATCH 08/16] final save2 --- .../Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java index 3e01ae7..c93642d 100644 --- a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java +++ b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java @@ -70,6 +70,6 @@ public void testFetchDataFromMobius() throws InterruptedException { // 반환된 Mock 객체의 속성이 예상한 대로 설정되었는지 확인 Connection connection = connectionRepository.findAll().get(0); - assertEquals("device1", connection.getApplicationEntity()); + assertEquals("device1", connection.getAe()); } } From db117e20edf9836f9ccc1d18c15b5ba22afdb199 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Wed, 29 May 2024 02:41:59 +0900 Subject: [PATCH 09/16] final save3 --- build.gradle | 3 + .../LanternOfDuskBeApplication.java | 2 + .../config/SwaggerConfiguration.java | 41 ---- .../controller/TestController.java | 28 +++ .../ExtendedKalmanFilter.java | 2 +- .../Lantern_Of_Dusk_BE/dto/RawDataDTO.java | 17 ++ .../Lantern_Of_Dusk_BE/entity/Data.java | 71 ------- .../Lantern_Of_Dusk_BE/entity/Position.java | 8 +- .../service/DataService.java | 200 ++++++++++++++---- .../service/FilterService.java | 112 ---------- .../service/MobiusService.java | 117 ---------- src/main/resources/application.properties | 24 +-- src/main/resources/templates/form.html | 10 - .../LanternOfDuskBeApplicationTests.java | 13 -- .../servicetest/DataServiceTest.java | 77 ------- .../servicetest/FilterServiceTest.java | 63 ------ .../servicetest/MobiusServiceTest.java | 75 ------- 17 files changed, 219 insertions(+), 644 deletions(-) delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/config/SwaggerConfiguration.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/TestController.java rename src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/{filter => core}/ExtendedKalmanFilter.java (98%) create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/dto/RawDataDTO.java delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Data.java delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/FilterService.java delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java delete mode 100644 src/main/resources/templates/form.html delete mode 100644 src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/LanternOfDuskBeApplicationTests.java delete mode 100644 src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/DataServiceTest.java delete mode 100644 src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/FilterServiceTest.java delete mode 100644 src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java diff --git a/build.gradle b/build.gradle index 848ea9a..16731ee 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,9 @@ dependencies { testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation("org.assertj:assertj-core:3.23.1") implementation 'org.apache.commons:commons-math3:3.6.1' + // https://mvnrepository.com/artifact/org.json/json + implementation("org.json:json:20240303") + } tasks.named('test') { diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/LanternOfDuskBeApplication.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/LanternOfDuskBeApplication.java index c65b3b4..6a7968b 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/LanternOfDuskBeApplication.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/LanternOfDuskBeApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@EnableScheduling public class LanternOfDuskBeApplication { public static void main(String[] args) { diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/config/SwaggerConfiguration.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/config/SwaggerConfiguration.java deleted file mode 100644 index ca9c6c2..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/config/SwaggerConfiguration.java +++ /dev/null @@ -1,41 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.config; - -import io.swagger.v3.oas.annotations.OpenAPIDefinition; -import io.swagger.v3.oas.annotations.info.Info; -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.security.SecurityScheme; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -// http://localhost:8080/swagger-ui/index.html 로 접속하여 API 명세를 받아볼 수 있다. - -@OpenAPIDefinition( - info =@Info( - title ="Example API Docs", - description = "Description", - version = "v1" - ) -) -@Configuration -public class SwaggerConfiguration { - private static final String BEARER_TOKEN_PREFIX = "Bearer"; - - @Bean - public OpenAPI openAPI() { - String securityJwtName = "JWT"; - SecurityRequirement securityRequirement = new SecurityRequirement().addList(securityJwtName); - Components components = new Components() - .addSecuritySchemes(securityJwtName, new SecurityScheme() - .name(securityJwtName) - .type(SecurityScheme.Type.HTTP) - .scheme(BEARER_TOKEN_PREFIX) - .bearerFormat(securityJwtName) - ); - - return new OpenAPI() - .addSecurityItem(securityRequirement) - .components(components); - } -} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/TestController.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/TestController.java new file mode 100644 index 0000000..307e4a6 --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/TestController.java @@ -0,0 +1,28 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.controller; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Marker; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; +import IOT_Platform.Lantern_Of_Dusk_BE.service.ApiService; +import IOT_Platform.Lantern_Of_Dusk_BE.service.DataService; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@AllArgsConstructor +@CrossOrigin +@RequestMapping("/test") +public class TestController { + + private final DataService dataService; + + @GetMapping("/1") + public void readConnectionList() { + System.out.println("test 1 start"); + dataService.processData(); + } +} diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/filter/ExtendedKalmanFilter.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/ExtendedKalmanFilter.java similarity index 98% rename from src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/filter/ExtendedKalmanFilter.java rename to src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/ExtendedKalmanFilter.java index 030b13c..1e8136a 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/filter/ExtendedKalmanFilter.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/ExtendedKalmanFilter.java @@ -1,4 +1,4 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.filter; +package IOT_Platform.Lantern_Of_Dusk_BE.core; import org.apache.commons.math3.linear.MatrixUtils; import org.apache.commons.math3.linear.RealMatrix; diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/dto/RawDataDTO.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/dto/RawDataDTO.java new file mode 100644 index 0000000..7499354 --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/dto/RawDataDTO.java @@ -0,0 +1,17 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RawDataDTO { + private int id; + private double ax; + private double ay; + private double az; + private double gx; + private double gy; + private double gz; + private double atm; +} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Data.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Data.java deleted file mode 100644 index f2b5df0..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Data.java +++ /dev/null @@ -1,71 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.entity; - -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; - -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -@Entity -public class Data { - @Id - private int id; - private double x; - private double y; - private double z; - private double pitch; - private double yaw; - private double roll; - private double pressure; - - public Data(double x, double y, double z, double pitch, double yaw, double roll, double pressure) { - this.x = x; - this.y = y; - this.z = z; - this.pitch = pitch; - this.yaw = yaw; - this.roll = roll; - this.pressure = pressure; - } - - // JSON 데이터를 파싱해서 Data 객체로 변환하는 메서드 - public static Data fromJson(String jsonData) { - try { - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode rootNode = objectMapper.readTree(jsonData); - return new Data( - rootNode.get("x").asDouble(), - rootNode.get("y").asDouble(), - rootNode.get("z").asDouble(), - rootNode.get("pitch").asDouble(), - rootNode.get("yaw").asDouble(), - rootNode.get("roll").asDouble(), - rootNode.get("pressure").asDouble() // 기압 데이터 파싱 - ); - } catch (IOException e) { - throw new RuntimeException("Failed to parse JSON data", e); - } - } - - @Override - public String toString() { - return "Data{" + - "id=" + id + - ", x=" + x + - ", y=" + y + - ", z=" + z + - ", pitch=" + pitch + - ", yaw=" + yaw + - ", roll=" + roll + - ", pressure=" + pressure + - '}'; - } -} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java index 11ffc27..fdfb9e2 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java @@ -18,13 +18,13 @@ public class Position { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; - private int deviceId; // ae + private int deviceId; private double x; private double y; private double z; - private double roll; // 자이로 x - private double pitch; // y - private double yaw ; // z + private double roll; + private double pitch; + private double yaw ; @CreationTimestamp private LocalDateTime timeStamp; diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java index afd030e..25939a9 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java @@ -1,72 +1,186 @@ package IOT_Platform.Lantern_Of_Dusk_BE.service; +import IOT_Platform.Lantern_Of_Dusk_BE.core.ExtendedKalmanFilter; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Data; +import IOT_Platform.Lantern_Of_Dusk_BE.dto.RawDataDTO; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; +import org.apache.commons.math3.linear.MatrixUtils; +import org.apache.commons.math3.linear.RealMatrix; +import org.json.JSONArray; +import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; import java.util.*; @Service public class DataService { - private final MobiusService mobiusService; + private final RestTemplate restTemplate; + private final ConnectionRepository connectionRepository; - private final FilterService filterService; - private final Map> dataArrays; + private final PositionRepository positionRepository; + + private Map connections; + private Map filters; @Autowired - public DataService(MobiusService mobiusService, ConnectionRepository connectionRepository, FilterService filterService) { - this.mobiusService = mobiusService; + public DataService(RestTemplateBuilder restTemplateBuilder, ConnectionRepository connectionRepository, PositionRepository positionRepository) { + + this.restTemplate = restTemplateBuilder.build(); + this.connectionRepository = connectionRepository; - this.filterService = filterService; - this.dataArrays = new HashMap<>(); + this.positionRepository = positionRepository; + + this.connections = new HashMap<>(); + + setConnection(); } - /** - * 7ms마다 Mobius 서버에서 데이터를 가져와 배열에 저장하는 메서드. - */ - @Scheduled(fixedRate = 7) - public void fetchDataFromMobius() { + public void setConnection() { + for( Connection connection : connectionRepository.findAll()) { + // 초기 상태 벡터 및 공분산 행렬 설정 (모든 값이 0인 상태로 초기화) + RealMatrix initialState = MatrixUtils.createColumnRealMatrix(new double[]{0, 0, 0, 0, 0, 0}); // [x, y, z, roll, pitch, yaw] + RealMatrix initialCovariance = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); + // 상태 전이 행렬, 프로세스 노이즈, 측정 노이즈, 관측 행렬 설정 (임의의 예시 값, 실제 응용에 따라 조정 필요) + RealMatrix stateTransition = MatrixUtils.createRealIdentityMatrix(6); + RealMatrix processNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{0.1, 0.1, 0.1, 0.1, 0.1, 0.1}); + RealMatrix measurementNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); + RealMatrix observationMatrix = MatrixUtils.createRealIdentityMatrix(6); - // 데이터베이스에서 모든 Connection을 가져옵니다. - List connections = connectionRepository.findAll(); + ExtendedKalmanFilter filter = new ExtendedKalmanFilter(initialState, initialCovariance, stateTransition, processNoise, measurementNoise, observationMatrix); + + connections.put(connection.getId(), connection); + filters.put(connection.getId(), filter); + } + } - for (Connection connection : connections) { + // @Scheduled(fixedRate = 1000) + public void processData() { + for (Connection connection : connections.values()) { String aeName = connection.getAe(); - try { - // Mobius 서버에서 JSON 데이터를 가져옴 - String jsonData = mobiusService.fetchDataFromMobiusForAE(aeName); - // JSON 데이터를 Data 객체로 변환 - Data data = Data.fromJson(jsonData); - - // 해당 AE의 데이터 배열을 가져옴 - List dataArray = dataArrays.computeIfAbsent(aeName, k -> new ArrayList<>()); - - // 데이터 배열에 추가 - dataArray.add(data); - - // 1초 동안의 데이터(약 143개)를 초과하면 앞의 데이터를 제거 - if (dataArray.size() > 143) { - dataArray.remove(0); - } - - // 데이터 배열이 143개가 되면 필터링 수행 - if (dataArray.size() == 143) { - filterService.applyFilter(new ArrayList<>(dataArray), Integer.parseInt(connection.getName())); - } - } catch (Exception e) { - // 에러 처리 - System.err.println("Error fetching data for AE " + aeName + ": " + e.getMessage()); + List rawDataList = getRawData(aeName); + Position position = applyFilter(rawDataList, connection.getId()); + saveData(position); + } + } + + @Value("${mobius.url}") + private String mobiusServerUrl; + @Value("${mobius.cnt.imu}") + private String mobiusImuCntName; + @Value("${mobius.cnt.atm}") + private String mobiusAtmCntName; + public List getRawData(String ae) { + String urlIMU = mobiusServerUrl + ae + "/" + mobiusImuCntName + "?fu=2&la=143&ty=4&rcn=4"; + String urlATM = mobiusServerUrl + ae + "/" + mobiusAtmCntName + "?fu=2&la=143&ty=4&rcn=4"; + + HttpHeaders headers = new HttpHeaders(); + headers.set("Accept", "application/json"); + headers.set("X-M2M-RI", "12345"); + headers.set("X-M2M-Origin", "SOrigin"); + HttpEntity request = new HttpEntity(headers); + + List result = new ArrayList<>(); + + try { + ResponseEntity responseIMU = restTemplate.exchange( + urlIMU, + HttpMethod.GET, + request, + String.class + ); + ResponseEntity responseATM = restTemplate.exchange( + urlATM, + HttpMethod.GET, + request, + String.class + ); + + JSONArray rawDataIMU = new JSONObject(responseIMU.getBody()).getJSONObject("m2m:rsp").getJSONArray("m2m:cin"); + JSONArray rawDataATM = new JSONObject(responseATM.getBody()).getJSONObject("m2m:rsp").getJSONArray("m2m:cin"); + + for (int i = 0; i < 143; i++) { + RawDataDTO rawDataDTO = new RawDataDTO(); + + JSONObject objIMU = ((JSONObject) rawDataIMU.get(i)).getJSONObject("con"); + JSONObject objATM = ((JSONObject) rawDataATM.get(i)).getJSONObject("con"); + + // TODO: 5/29/24 테스트 코드 입력 후 구현 + System.out.println(objATM.toString()); + System.out.println(objIMU.toString()); + + rawDataDTO.setAx((Double) objIMU.get("ax")); + rawDataDTO.setAy((Double) objIMU.get("ay")); + rawDataDTO.setAz((Double) objIMU.get("az")); + rawDataDTO.setGx((Double) objIMU.get("gx")); + rawDataDTO.setGy((Double) objIMU.get("gy")); + rawDataDTO.setGz((Double) objIMU.get("gz")); + rawDataDTO.setAtm((Double) objATM.get("atm")); + + result.add(rawDataDTO); } + + } catch (RestClientException e) { + System.out.println("Error fetching data for " + ae + " from Mobius"); + System.out.println(e); + } + + return result; + } + + public Position applyFilter(List rawDataDTOList, int deviceId) { + for (RawDataDTO rawDataDTO : rawDataDTOList) { + // 측정값 벡터 생성 + RealMatrix measurement = MatrixUtils.createColumnRealMatrix(new double[]{ + rawDataDTO.getAx(), rawDataDTO.getAy(), rawDataDTO.getAx(), + rawDataDTO.getGx(), rawDataDTO.getGy(), rawDataDTO.getGz() + }); + + // 예측 단계 + filters.get(deviceId).predict(); + + // 업데이트 단계 + filters.get(deviceId).update(measurement); } + + // 필터링된 상태 벡터 가져오기 + RealMatrix state = filters.get(deviceId).getState(); + + // 상태 벡터에서 위치 정보 추출 + double x = state.getEntry(0, 0); + double y = state.getEntry(1, 0); + double z = state.getEntry(2, 0); + double roll = state.getEntry(3, 0); + double pitch = state.getEntry(4, 0); + double yaw = state.getEntry(5, 0); + + // 위치 정보 저장 + Position position = new Position(); + position.setDeviceId(deviceId); + position.setX(x); + position.setY(y); + position.setZ(z); + position.setRoll(roll); + position.setPitch(pitch); + position.setYaw(yaw); + + return position; } - //테스트용 매서드 - public List getDataArray(String aeName) { - return dataArrays.getOrDefault(aeName, new ArrayList<>()); + public void saveData(Position position) { + positionRepository.save(position); } } \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/FilterService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/FilterService.java deleted file mode 100644 index 94b7211..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/FilterService.java +++ /dev/null @@ -1,112 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.service; - -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Data; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; -import IOT_Platform.Lantern_Of_Dusk_BE.filter.ExtendedKalmanFilter; -import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; -import lombok.Getter; -import org.apache.commons.math3.linear.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class FilterService { - - private final PositionRepository positionRepository; - private final ExtendedKalmanFilter kalmanFilter; - - @Autowired - public FilterService(PositionRepository positionRepository) { - this.positionRepository = positionRepository; - - // 초기 상태 벡터 및 공분산 행렬 설정 (모든 값이 0인 상태로 초기화) - RealMatrix initialState = MatrixUtils.createColumnRealMatrix(new double[]{0, 0, 0, 0, 0, 0}); // [x, y, z, roll, pitch, yaw] - RealMatrix initialCovariance = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); - - // 상태 전이 행렬, 프로세스 노이즈, 측정 노이즈, 관측 행렬 설정 (임의의 예시 값, 실제 응용에 따라 조정 필요) - RealMatrix stateTransition = MatrixUtils.createRealIdentityMatrix(6); - RealMatrix processNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{0.1, 0.1, 0.1, 0.1, 0.1, 0.1}); - RealMatrix measurementNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); - RealMatrix observationMatrix = MatrixUtils.createRealIdentityMatrix(6); - - this.kalmanFilter = new ExtendedKalmanFilter(initialState, initialCovariance, stateTransition, processNoise, measurementNoise, observationMatrix); - } - - /** - * 메서드: applyFilter - * 설명: 수집된 데이터를 필터링하고 위치 정보를 저장합니다. - * - * @param dataList 143개의 센서 데이터 리스트 - * @param deviceId 장치 ID - */ - public void applyFilter(List dataList, int deviceId) { - for (Data data : dataList) { - // 측정값 벡터 생성 - RealMatrix measurement = MatrixUtils.createColumnRealMatrix(new double[]{ - data.getX(), data.getY(), data.getZ(), - data.getRoll(), data.getPitch(), data.getYaw() - }); - - // 예측 단계 - kalmanFilter.predict(); - - // 업데이트 단계 - kalmanFilter.update(measurement); - } - - // 필터링된 상태 벡터 가져오기 - RealMatrix state = kalmanFilter.getState(); - - // 상태 벡터에서 위치 정보 추출 - double x = state.getEntry(0, 0); - double y = state.getEntry(1, 0); - double z = state.getEntry(2, 0); - double roll = state.getEntry(3, 0); - double pitch = state.getEntry(4, 0); - double yaw = state.getEntry(5, 0); - - // 위치 정보 저장 - Position position = new Position(); - position.setDeviceId(deviceId); - position.setX(x); - position.setY(y); - position.setZ(z); - position.setRoll(roll); - position.setPitch(pitch); - position.setYaw(yaw); - - positionRepository.save(position); - } - - /** - * 메서드: getFilteredPosition - * 설명: 필터링된 위치 정보를 반환합니다. - * - * @return 필터링된 위치 정보 - */ - public Position getFilteredPosition() { - // 필터링된 상태 벡터 가져오기 - RealMatrix state = kalmanFilter.getState(); - - // 상태 벡터에서 위치 정보 추출 - double x = state.getEntry(0, 0); - double y = state.getEntry(1, 0); - double z = state.getEntry(2, 0); - double roll = state.getEntry(3, 0); - double pitch = state.getEntry(4, 0); - double yaw = state.getEntry(5, 0); - - // 필터링된 위치 정보 반환 - Position position = new Position(); - position.setX(x); - position.setY(y); - position.setZ(z); - position.setRoll(roll); - position.setPitch(pitch); - position.setYaw(yaw); - - return position; - } -} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java deleted file mode 100644 index 480b567..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/MobiusService.java +++ /dev/null @@ -1,117 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.service; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; -import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; - -@Service -public class MobiusService { - - private final RestTemplate restTemplate; - private final ConnectionRepository connectionRepository; - - @Value("${mobius.server.url}") - private String mobiusServerUrl; - - private static final Logger logger = LoggerFactory.getLogger(MobiusService.class); - - @Autowired - public MobiusService(RestTemplateBuilder restTemplateBuilder, ConnectionRepository connectionRepository) { - this.restTemplate = restTemplateBuilder.build(); - this.connectionRepository = connectionRepository; - } - - /** - * 특정 AE에 해당하는 데이터를 Mobius로부터 가져오는 메서드입니다. - * @param ae Application Entity의 이름 - * @return Mobius로부터 받은 데이터 - */ - public String fetchDataFromMobiusForAE(String ae) { - // Connection 테이블에서 AE에 대한 정보를 가져옵니다. - Optional connection = connectionRepository.findByAe(ae); - - // Connection 정보가 없는 경우 예외 처리 - if (connection.isEmpty()) { - throw new IllegalArgumentException("Connection not found for AE: " + ae); - } - - // 각 센서에 대한 데이터를 가져옵니다. - String accelerationData = fetchDataForSensor(connection.orElse(null), "ACCEL"); - String gyroscopeData = fetchDataForSensor(connection.orElse(null), "GYRO"); - String pressureData = fetchDataForSensor(connection.orElse(null), "PRESSURE"); - - // 데이터 조합 - String combinedData = "ACCEL: " + accelerationData + "\n" + - "GYRO: " + gyroscopeData + "\n" + - "PRESSURE: " + pressureData; - - return combinedData; - } - - - public String fetchDataForSensor(Connection connection, String sensor) { - // Mobius 서버로 요청할 URL 생성 - String url = mobiusServerUrl + connection.getName() + "/" + sensor; - try { - // Mobius 서버에 GET 요청을 보내 데이터를 받아옵니다. - String responseData = restTemplate.getForObject(url, String.class); - - // 받아온 JSON 데이터를 파싱하여 컨테이너 값들을 추출합니다. - Map containerData = parseJsonData(responseData); - - // 센서에 해당하는 데이터 반환 - return containerData.toString(); - } catch (RestClientException e) { - // 요청에 실패한 경우 에러를 로그에 기록하고 예외를 던집니다. - logger.error("Error fetching data for AE {} from Mobius: ", connection.getAe(), e); - throw new RuntimeException("Failed to fetch data from Mobius for AE: " + connection.getAe(), e); - } - } - - /** - * JSON 데이터를 파싱하여 Map으로 변환하는 메서드입니다. - * @param jsonData JSON 형식의 데이터 - * @return 파싱된 데이터가 담긴 Map 객체 - */ - private Map parseJsonData(String jsonData) { - try { - // JSON 데이터를 파싱하는 ObjectMapper 객체 생성 - ObjectMapper objectMapper = new ObjectMapper(); - // JSON 데이터를 JsonNode 객체로 읽어옵니다. - JsonNode rootNode = objectMapper.readTree(jsonData); - - // 각 센서의 값을 추출하여 Map에 저장합니다. - Map containerData = new HashMap<>(); - containerData.put("acceleration_x", rootNode.get("acceleration").get("x").asText()); - containerData.put("acceleration_y", rootNode.get("acceleration").get("y").asText()); - containerData.put("acceleration_z", rootNode.get("acceleration").get("z").asText()); - - containerData.put("gyroscope_x", rootNode.get("gyroscope").get("x").asText()); - containerData.put("gyroscope_y", rootNode.get("gyroscope").get("y").asText()); - containerData.put("gyroscope_z", rootNode.get("gyroscope").get("z").asText()); - - containerData.put("pressure", rootNode.get("pressure").asText()); - - return containerData; - } catch (IOException e) { - // JSON 파싱 중 에러가 발생한 경우 에러를 로그에 기록하고 예외를 던집니다. - logger.error("Error parsing JSON data: ", e); - throw new RuntimeException("Failed to parse JSON data", e); - } - } -} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 35d44c6..9231211 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,24 +1,14 @@ spring.application.name=Lantern_Of_Dusk_BE -mobius.url=http://203.253.128.177:7575//Mobius/ + +mobius.url=http://203.253.128.177:7579/Mobius/ +mobius.cnt.imu=ACCEL +mobius.cnt.atm=GYRO + server.port=7777 spring.datasource.url=jdbc:mysql://localhost:3306/lod spring.datasource.username=root -spring.datasource.password=1234 +spring.datasource.password= spring.jpa.hibernate.ddl-auto=update -spring.jpa.show-sql=true - -springdoc.swagger-ui.groups-order=DESC -springdoc.swagger-ui.tags-sorter=alpha -springdoc.swagger-ui.operations-sorter=method -springdoc.swagger-ui.disable-swagger-default-url=true -springdoc.swagger-ui.default-models-expand-depth=2 -springdoc.swagger-ui.default-model-expand-depth=2 -springdoc.api-docs.path=/api-docs -springdoc.api-docs.show-actuator=true -springdoc.api-docs.default-consumes-media-type=application/json -springdoc.api-docs.default-produces-media-type=application/json -springdoc.api-docs.writer-with-default-pretty-printer=true -springdoc.api-docs.model-and-view-allowed=true -springdoc.api-docs.paths-to-match=/api/device \ No newline at end of file +spring.jpa.show-sql=true \ No newline at end of file diff --git a/src/main/resources/templates/form.html b/src/main/resources/templates/form.html deleted file mode 100644 index 566549b..0000000 --- a/src/main/resources/templates/form.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Title - - - - - \ No newline at end of file diff --git a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/LanternOfDuskBeApplicationTests.java b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/LanternOfDuskBeApplicationTests.java deleted file mode 100644 index cd69f59..0000000 --- a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/LanternOfDuskBeApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class LanternOfDuskBeApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/DataServiceTest.java b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/DataServiceTest.java deleted file mode 100644 index 56e280d..0000000 --- a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/DataServiceTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.servicetest; - -import static org.mockito.Mockito.*; -import static org.junit.jupiter.api.Assertions.*; - -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Data; -import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; -import IOT_Platform.Lantern_Of_Dusk_BE.service.DataService; -import IOT_Platform.Lantern_Of_Dusk_BE.service.MobiusService; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.scheduling.annotation.EnableScheduling; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.Queue; - -@SpringBootTest -@EnableScheduling -public class DataServiceTest { - - @Mock - private MobiusService mobiusService; - - @Mock - private ConnectionRepository connectionRepository; - - @InjectMocks - private DataService dataService; - - /** - * - * 첫 번째 테스트는 fetchDataFromMobius 메서드를 테스트합니다. 이 메서드는 Mobius 서비스에서 데이터를 가져와서 처리하는데, 이를 테스트하기 위해 Mock 객체를 사용하여 Mobius 서비스와 연결정보를 대체합니다. 이 테스트는 Mobius 서비스가 정확한 AE(Application Entity) 이름을 사용하여 데이터를 가져오는지를 확인합니다. - */ - - @Test - public void testFetchDataFromMobius() { - // Mock 객체로 반환될 Connection 객체 생성 - Connection connection = new Connection(); - connection.setAe("device1"); - when(connectionRepository.findAll()).thenReturn(Collections.singletonList(connection)); - - // MobiusService에서 반환될 더미 데이터 설정 - String jsonData = "{\"acceleration\": {\"x\": \"0.1\", \"y\": \"0.2\", \"z\": \"0.3\"}, \"gyroscope\": {\"x\": \"0.4\", \"y\": \"0.5\", \"z\": \"0.6\"}, \"pressure\": \"1013.25\"}"; - when(mobiusService.fetchDataFromMobiusForAE(anyString())).thenReturn(jsonData); - - // fetchDataFromMobius 메서드 호출 - dataService.fetchDataFromMobius(); - - // 검증: MobiusService의 fetchDataFromMobiusForAE 메서드가 호출되었는지 확인 - verify(mobiusService, atLeastOnce()).fetchDataFromMobiusForAE("device1"); - } - - /** - * - * 두 번째 테스트는 saveData 메서드를 테스트합니다. 이 메서드는 수집된 데이터를 저장하는 역할을 담당합니다. 이 테스트는 데이터가 제대로 저장되고 저장 후에는 데이터 큐가 비워지는지를 확인합니다. - */ - - @Test - public void testSaveData() { - // AE 이름과 큐 생성 - String aeName = "device1"; - Queue queue = new LinkedList<>(); - for (int i = 0; i < 143; i++) { - queue.add(new Data()); // 예시로 더미 데이터를 큐에 추가 - } - - - // 데이터 큐의 크기가 0인지 확인 (saveData 호출 후에는 큐가 비워져야 함) - assertEquals(143, queue.size()); - // 데이터 큐의 크기가 0인지 확인 (saveData 호출 후에는 큐가 비워져야 함) - System.out.println("Remaining elements in the queue: " + queue.size()); - } -} diff --git a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/FilterServiceTest.java b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/FilterServiceTest.java deleted file mode 100644 index dcae5c5..0000000 --- a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/FilterServiceTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.servicetest; - -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Data; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; -import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; -import IOT_Platform.Lantern_Of_Dusk_BE.service.FilterService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -public class FilterServiceTest { - - @Mock - private PositionRepository positionRepository; - - @InjectMocks - private FilterService filterService; - - private List mockDataList; - - @BeforeEach - public void setUp() { - // Mock 데이터를 생성합니다. - mockDataList = new ArrayList<>(); - for (int i = 0; i < 143; i++) { - mockDataList.add(new Data(i, i * 0.1, i * 0.1, i * 0.1, i * 0.01, i * 0.01, i * 0.01, 1000 + i * 0.1)); - } - } - - @Test - public void testApplyFilter() { - - - System.out.println("Original Data:"); - for (Data data : mockDataList) { - System.out.println(data); - } - // 필터링 적용 - filterService.applyFilter(mockDataList, 1); - - // 필터링된 위치 정보가 저장되었는지 확인 - verify(positionRepository, times(1)).save(any(Position.class)); - - - - // 데이터 개수 출력 - System.out.println("Number of data: " + mockDataList.size()); - - // 필터링된 데이터 개수 및 내용 출력 - Position filteredPosition = filterService.getFilteredPosition(); - System.out.println("Number of filtered data: 1"); // 필터링된 데이터는 한 개이므로 개수는 1 - System.out.println("Filtered Position: " + filteredPosition); - } -} diff --git a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java b/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java deleted file mode 100644 index c93642d..0000000 --- a/src/test/java/IOT_Platform/Lantern_Of_Dusk_BE/servicetest/MobiusServiceTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.servicetest; - -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; -import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; -import IOT_Platform.Lantern_Of_Dusk_BE.service.DataService; -import IOT_Platform.Lantern_Of_Dusk_BE.service.MobiusService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.scheduling.support.PeriodicTrigger; - -import java.util.Collections; -import java.util.concurrent.TimeUnit; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; - -// 테스트 어노테이션 및 import 생략 - -public class MobiusServiceTest { - - @Mock - private MobiusService mobiusService; - - @Mock - private ConnectionRepository connectionRepository; - - @InjectMocks - private DataService dataService; - - private ThreadPoolTaskScheduler taskScheduler; - - @BeforeEach - public void setup() { - MockitoAnnotations.openMocks(this); - - // Mock 객체로 반환될 Connection 객체 생성 - Connection connection = new Connection(); - connection.setAe("device1"); - - // connectionRepository.findAll()이 호출되었을 때 Mock 객체 반환 설정 - when(connectionRepository.findAll()).thenReturn(Collections.singletonList(connection)); - - // MobiusService에서 반환될 더미 데이터 설정 - String jsonData = "{\"acceleration\": {\"x\": \"0.1\", \"y\": \"0.2\", \"z\": \"0.3\"}, \"gyroscope\": {\"x\": \"0.4\", \"y\": \"0.5\", \"z\": \"0.6\"}, \"pressure\": \"1013.25\"}"; - when(mobiusService.fetchDataFromMobiusForAE(anyString())).thenReturn(jsonData); - - // TaskScheduler 초기화 및 스케줄링 설정 - taskScheduler = new ThreadPoolTaskScheduler(); - taskScheduler.initialize(); - PeriodicTrigger trigger = new PeriodicTrigger(1000, TimeUnit.MILLISECONDS); // 1초로 변경 - taskScheduler.schedule(dataService::fetchDataFromMobius, trigger); - } - - /** - * MobiusService 클래스의 fetchDataFromMobiusForAE 메서드를 테스트하는 테스트 케이스입니다. - * fetchDataFromMobiusForAE 메서드가 호출되었는지, connectionRepository.findAll()이 한 번 호출되었는지, - * 반환된 Mock 객체의 속성이 정확히 설정되었는지를 확인합니다. - */ - @Test - public void testFetchDataFromMobius() throws InterruptedException { - // fetchDataFromMobiusForAE가 호출되었는지 확인 - verify(mobiusService, atLeast(1)).fetchDataFromMobiusForAE("device1"); - - // connectionRepository.findAll()이 호출되었는지 확인 - verify(connectionRepository, times(1)).findAll(); - - // 반환된 Mock 객체의 속성이 예상한 대로 설정되었는지 확인 - Connection connection = connectionRepository.findAll().get(0); - assertEquals("device1", connection.getAe()); - } -} From 8056965e9caf9ad04884de8ccec42440f2edef90 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Wed, 29 May 2024 16:17:51 +0900 Subject: [PATCH 10/16] update --- .../java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyFilter.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyFilter.java diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyFilter.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyFilter.java new file mode 100644 index 0000000..83112c7 --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyFilter.java @@ -0,0 +1,2 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.core;public class MahonyFilter { +} From f82b30efdb68e2f5b0cce6249a517176b5bc03a9 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Wed, 29 May 2024 16:17:58 +0900 Subject: [PATCH 11/16] save --- .DS_Store | Bin 14340 -> 14340 bytes src/.DS_Store | Bin 6148 -> 6148 bytes src/main/.DS_Store | Bin 6148 -> 6148 bytes .../Lantern_Of_Dusk_BE/core/MahonyFilter.java | 97 +++++++++++++++++- .../Lantern_Of_Dusk_BE/entity/Connection.java | 2 - .../Lantern_Of_Dusk_BE/entity/Position.java | 13 --- .../service/DataService.java | 10 +- src/main/resources/application.properties | 2 +- src/test/.DS_Store | Bin 0 -> 6148 bytes 9 files changed, 101 insertions(+), 23 deletions(-) create mode 100644 src/test/.DS_Store diff --git a/.DS_Store b/.DS_Store index 288f8d338ce406f89b7739481d368703b188fc86..11fefcf039c4d0bac753ef14a691618bf6ecd6fe 100644 GIT binary patch delta 532 zcmZoEXepR*fF(YmEO6sRGxmuOcsH|iICC&w*z7Ivi!*|eO@)DhftjJ0p@<LZ(h7O?^?%4A4kNM%Sww(3IM zBHeh1RVXSDmSIT>fD fc3{e)n9q1&GPBZqrXxQ$e^Cl#r(wKkrSk#+^*M_N delta 532 zcmZoEXepR*fW^RWip$1}X6zFm@NQ=3aOPli*z7Ivi!*{@f(HWw12aQ0LlHxAZoZ34 zQcivnP=rHQ`Hzp;zoU-GvMG3E3o;CYlk;;6fa)0-7#lXvmFi%PW8Ad^$YWv9V@PMn zWGF#4ALO9^|6ucxGX2+rH2 diff --git a/src/.DS_Store b/src/.DS_Store index 2913fe329e18fa0ea710c0c13a872a575da1b4c1..1592886b22e75754ea51eaf6f504e19972df1e2f 100644 GIT binary patch delta 147 zcmZoMXffCz&&sqlZn7e)1iORA^uwV{$0j?lO2XL*tkR4PlWSO`V=WFbFfgz%lrW?+ z6f>0M=DWBg<>V&;#W?m{Tg{Webj%S|J_WCQL55*)a(-?BP!A9UY%ILYxS5^fFFyb` CVJSZV delta 143 zcmZoMXffCz&&pIDGg*;Ug56c(kB`~Eqmvz2CE@G@R%yn7$u+Fekqj>w7#LU>N*GcZ wiWy3B^Icq$a`KaaVjQnj!1^3f`7SO=Ir&Kp3=ACC6TTjcVmdb2 YflYj}E*lR!g0H$Uc@g7gc85CboctsP1_q9f84bO5|Bg;} fU=yFL%f`bl^k-j=C77?usIakcA>(Ftj=%f>d 0) { + eInt = eInt.add(e.mapMultiply(samplePeriod)); + } else { + eInt = new ArrayRealVector(new double[]{0, 0, 0}); + } + + // qDot 계산을 위한 배열 준비 + double[] gyroArray = {0, gyroscope[0], gyroscope[1], gyroscope[2]}; + RealVector gyroVector = new ArrayRealVector(gyroArray); + + // Quaternion 곱셈을 위한 준비 + RealVector qDot2 = quaternProd(q, gyroVector).mapMultiply(0.5); + + // 위 코드에서, gyroscope 배열을 직접 RealVector 생성자에 넣어 0을 추가하였습니다. + + + q = q.add(qDot2.mapMultiply(samplePeriod)); + quaternion = q.mapDivide(q.getNorm()); + } + + private RealVector crossProduct(RealVector u, RealVector v) { + double u1 = u.getEntry(0); + double u2 = u.getEntry(1); + double u3 = u.getEntry(2); + double v1 = v.getEntry(0); + double v2 = v.getEntry(1); + double v3 = v.getEntry(2); + + return new ArrayRealVector(new double[]{ + u2 * v3 - u3 * v2, + u3 * v1 - u1 * v3, + u1 * v2 - u2 * v1 + }); + } } + diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java index a2f02a1..548db55 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Connection.java @@ -12,8 +12,6 @@ public class Connection { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; - - @Getter private String name; private String ae; } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java index fdfb9e2..a0cde6d 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/entity/Position.java @@ -27,18 +27,5 @@ public class Position { private double yaw ; @CreationTimestamp private LocalDateTime timeStamp; - - @Override - public String toString() { - return "Position{" + - "deviceId=" + deviceId + - ", x=" + x + - ", y=" + y + - ", z=" + z + - ", roll=" + roll + - ", pitch=" + pitch + - ", yaw=" + yaw + - '}'; - } } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java index 25939a9..d023d6b 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java @@ -44,6 +44,7 @@ public DataService(RestTemplateBuilder restTemplateBuilder, ConnectionRepository this.positionRepository = positionRepository; this.connections = new HashMap<>(); + this.filters = new HashMap<>(); setConnection(); } @@ -51,14 +52,13 @@ public DataService(RestTemplateBuilder restTemplateBuilder, ConnectionRepository public void setConnection() { for( Connection connection : connectionRepository.findAll()) { // 초기 상태 벡터 및 공분산 행렬 설정 (모든 값이 0인 상태로 초기화) + // 상태 전이 행렬, 프로세스 노이즈, 측정 노이즈, 관측 행렬 설정 (임의의 예시 값, 실제 응용에 따라 조정 필요) RealMatrix initialState = MatrixUtils.createColumnRealMatrix(new double[]{0, 0, 0, 0, 0, 0}); // [x, y, z, roll, pitch, yaw] RealMatrix initialCovariance = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); - // 상태 전이 행렬, 프로세스 노이즈, 측정 노이즈, 관측 행렬 설정 (임의의 예시 값, 실제 응용에 따라 조정 필요) RealMatrix stateTransition = MatrixUtils.createRealIdentityMatrix(6); RealMatrix processNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{0.1, 0.1, 0.1, 0.1, 0.1, 0.1}); RealMatrix measurementNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); RealMatrix observationMatrix = MatrixUtils.createRealIdentityMatrix(6); - ExtendedKalmanFilter filter = new ExtendedKalmanFilter(initialState, initialCovariance, stateTransition, processNoise, measurementNoise, observationMatrix); connections.put(connection.getId(), connection); @@ -66,12 +66,10 @@ public void setConnection() { } } - // @Scheduled(fixedRate = 1000) + @Scheduled(fixedRate = 1000) public void processData() { for (Connection connection : connections.values()) { - String aeName = connection.getAe(); - - List rawDataList = getRawData(aeName); + List rawDataList = getRawData(connection.getAe()); Position position = applyFilter(rawDataList, connection.getId()); saveData(position); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9231211..00e78b3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,7 +1,7 @@ spring.application.name=Lantern_Of_Dusk_BE mobius.url=http://203.253.128.177:7579/Mobius/ -mobius.cnt.imu=ACCEL +mobius.cnt.imu=MPU mobius.cnt.atm=GYRO server.port=7777 diff --git a/src/test/.DS_Store b/src/test/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..edf673329323c307b5ae7334ec0071aa9c375d6c GIT binary patch literal 6148 zcmeHKJx{|>474FbB$kehZ(^nkbEv|`);~Z?B@k+rE-+`~U$HUqmk{Fo0ZJ5=kpa$< z-{sl9yyS*B77<-MZssC05vk#Z@@&i0EN?!sql{EQwR>#u=F8h|x1UrV4j8wR2U*FJ ztj7HEGR*C|wq0+#HDdMK+57dy$Lr-dzxgr0zaKu^IjA%$Kn17(6`%tDQUUaAv-%{E zD;1yuRNz|y`#u!7VUySg`lkbnj{rdXjd#Pf&l1350brBZ2O4-ZW$R7dIg+>K_LxE2R CQYx+h literal 0 HcmV?d00001 From 00f835bfb5c2596ff2cb13d8586144093b247f19 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Wed, 29 May 2024 16:56:02 +0900 Subject: [PATCH 12/16] asdf --- .../IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java index d023d6b..2a318a7 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java @@ -66,7 +66,7 @@ public void setConnection() { } } - @Scheduled(fixedRate = 1000) + //@Scheduled(fixedRate = 1000) public void processData() { for (Connection connection : connections.values()) { List rawDataList = getRawData(connection.getAe()); From 611351d72c65418b7b1a96d753dc0d3ea4af598c Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Thu, 30 May 2024 19:22:11 +0900 Subject: [PATCH 13/16] aaa --- ...tController.java => DeviceController.java} | 0 .../Lantern_Of_Dusk_BE/core/Butterworth.java | 53 +++++ .../Lantern_Of_Dusk_BE/core/Device.java | 2 + .../core/ExtendedKalmanFilter.java | 73 ------- .../Lantern_Of_Dusk_BE/core/Filter.java | 89 +++++++++ .../{MahonyFilter.java => MahonyAHRS.java} | 0 .../service/DataService.java | 184 ------------------ .../service/ProcessService.java | 60 ++++++ 8 files changed, 204 insertions(+), 257 deletions(-) rename src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/{TestController.java => DeviceController.java} (100%) create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Butterworth.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Device.java delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/ExtendedKalmanFilter.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Filter.java rename src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/{MahonyFilter.java => MahonyAHRS.java} (100%) delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java create mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/TestController.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/DeviceController.java similarity index 100% rename from src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/TestController.java rename to src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/controller/DeviceController.java diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Butterworth.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Butterworth.java new file mode 100644 index 0000000..0892918 --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Butterworth.java @@ -0,0 +1,53 @@ +import org.apache.commons.math3.complex.Complex; +import org.apache.commons.math3.complex.ComplexUtils; + +public class Butterworth { + public static double[][] designHighPassFilter(int order, double cutoffFreq, double sampleRate) { + double[] a = new double[order + 1]; + double[] b = new double[order + 1]; + + // Normalize cutoff frequency + double wc = Math.tan(Math.PI * cutoffFreq / sampleRate); + + // Poles and zeros + Complex[] poles = new Complex[order]; + for (int k = 0; k < order; k++) { + double theta = (2 * k + 1) * Math.PI / (2 * order); + poles[k] = new Complex(-Math.sin(theta), Math.cos(theta)); + } + + // Gain calculation + double gain = 1; + for (Complex pole : poles) { + gain *= -pole.getReal(); + } + gain = Math.pow(wc, order) / gain; + + // Coefficients calculation + for (int i = 0; i <= order; i++) { + a[i] = 0; + b[i] = 0; + } + b[0] = gain; + for (int k = 0; k < order; k++) { + Complex pole = poles[k]; + for (int j = order; j > 0; j--) { + a[j] += a[j - 1] * 2 * pole.getReal(); + b[j] += b[j - 1] * 2 * pole.getReal(); + } + for (int j = order; j > 1; j--) { + a[j] += a[j - 2]; + b[j] += b[j - 2]; + } + a[1] += 1; + b[1] += 1; + } + + // Denominator coefficients adjustment + for (int i = 0; i <= order; i++) { + a[i] = (i % 2 == 0) ? a[i] : -a[i]; + } + + return new double[][]{b, a}; + } +} diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Device.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Device.java new file mode 100644 index 0000000..ee05b2c --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Device.java @@ -0,0 +1,2 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.core;public class Device { +} diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/ExtendedKalmanFilter.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/ExtendedKalmanFilter.java deleted file mode 100644 index 1e8136a..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/ExtendedKalmanFilter.java +++ /dev/null @@ -1,73 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.core; - -import org.apache.commons.math3.linear.MatrixUtils; -import org.apache.commons.math3.linear.RealMatrix; - -/** - * 클래스: ExtendedKalmanFilter - * 설명: 확장 칼만 필터 (EKF)를 구현한 클래스입니다. - */ -public class ExtendedKalmanFilter { - private RealMatrix state; // 상태 벡터 - private RealMatrix covariance; // 상태 공분산 행렬 - private RealMatrix stateTransition; // 상태 전이 행렬 - private RealMatrix processNoise; // 프로세스 노이즈 공분산 행렬 - private RealMatrix measurementNoise; // 측정 노이즈 공분산 행렬 - private RealMatrix observationMatrix; // 관측 행렬 - - /** - * 생성자: ExtendedKalmanFilter - * 설명: 확장 칼만 필터의 초기 상태와 매개변수를 설정합니다. - * - * @param initialState 초기 상태 벡터 - * @param initialCovariance 초기 상태 공분산 행렬 - * @param stateTransition 상태 전이 행렬 - * @param processNoise 프로세스 노이즈 공분산 행렬 - * @param measurementNoise 측정 노이즈 공분산 행렬 - * @param observationMatrix 관측 행렬 - */ - public ExtendedKalmanFilter(RealMatrix initialState, RealMatrix initialCovariance, - RealMatrix stateTransition, RealMatrix processNoise, - RealMatrix measurementNoise, RealMatrix observationMatrix) { - this.state = initialState; - this.covariance = initialCovariance; - this.stateTransition = stateTransition; - this.processNoise = processNoise; - this.measurementNoise = measurementNoise; - this.observationMatrix = observationMatrix; - } - - /** - * 메서드: predict - * 설명: 상태와 공분산을 예측합니다. - */ - public void predict() { - state = stateTransition.multiply(state); - covariance = stateTransition.multiply(covariance).multiply(stateTransition.transpose()).add(processNoise); - } - - /** - * 메서드: update - * 설명: 새로운 측정값을 사용하여 상태와 공분산을 갱신합니다. - * - * @param measurement 새로운 측정값 벡터 - */ - public void update(RealMatrix measurement) { - RealMatrix y = measurement.subtract(observationMatrix.multiply(state)); // 잔차 계산 - RealMatrix s = observationMatrix.multiply(covariance).multiply(observationMatrix.transpose()).add(measurementNoise); // 잔차 공분산 - RealMatrix k = covariance.multiply(observationMatrix.transpose()).multiply(MatrixUtils.inverse(s)); // 칼만 이득 계산 - state = state.add(k.multiply(y)); // 상태 업데이트 - RealMatrix i = MatrixUtils.createRealIdentityMatrix(state.getRowDimension()); - covariance = (i.subtract(k.multiply(observationMatrix))).multiply(covariance); // 공분산 업데이트 - } - - /** - * 메서드: getState - * 설명: 현재 상태 벡터를 반환합니다. - * - * @return 현재 상태 벡터 - */ - public RealMatrix getState() { - return state; - } -} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Filter.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Filter.java new file mode 100644 index 0000000..1c307a0 --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Filter.java @@ -0,0 +1,89 @@ +import IOT_Platform.Lantern_Of_Dusk_BE.core.Butterworth; + +public class Filter { + private double[] a; + private double[] b; + + public Filter(double[] b, double[] a) { + this.a = a; + this.b = b; + } + + public double[] filtfilt(double[] x) { + int len = x.length; + int na = a.length; + int nb = b.length; + + // 신호의 시작과 끝을 반사하여 패딩 + double[] padSignal = new double[2 * len]; + System.arraycopy(x, 0, padSignal, len, len); + for (int i = 0; i < len; i++) { + padSignal[i] = 2 * x[0] - x[len - 1 - i]; + padSignal[2 * len - 1 - i] = 2 * x[len - 1] - x[i]; + } + + // 앞으로 필터링 + double[] forwardFiltered = lfilter(b, a, padSignal); + + // 신호를 반대로 뒤집기 + double[] reversedSignal = new double[forwardFiltered.length]; + for (int i = 0; i < forwardFiltered.length; i++) { + reversedSignal[i] = forwardFiltered[forwardFiltered.length - 1 - i]; + } + + // 뒤로 필터링 + double[] backwardFiltered = lfilter(b, a, reversedSignal); + + // 신호를 다시 원래 순서로 뒤집기 + double[] result = new double[len]; + for (int i = 0; i < len; i++) { + result[i] = backwardFiltered[backwardFiltered.length - 1 - len + i]; + } + + return result; + } + + private double[] lfilter(double[] b, double[] a, double[] x) { + int na = a.length; + int nb = b.length; + int len = x.length; + + double[] y = new double[len]; + double[] z = new double[Math.max(na, nb)]; + + for (int i = 0; i < len; i++) { + y[i] = b[0] * x[i] + z[0]; + for (int j = 1; j < nb; j++) { + if (i - j >= 0) { + y[i] += b[j] * x[i - j]; + } + z[j - 1] = z[j] + (i - j >= 0 ? b[j] * x[i - j] : 0) - a[j] * y[i]; + } + for (int j = nb; j < na; j++) { + z[j - 1] = z[j] - a[j] * y[i]; + } + z[na - 1] = 0; + } + return y; + } + + public static void main(String[] args) { + double samplePeriod = 0.01; // 샘플링 주기 + double filtCutOff = 0.1; // 컷오프 주파수 + int order = 1; // 필터 차수 + + // 샘플 데이터 + double[] linVel = { /* 신호 데이터 */ }; + + // Butterworth 필터 설계 + double[][] ba = Butterworth.designHighPassFilter(order, filtCutOff, 1 / samplePeriod); + double[] b = ba[0]; + double[] a = ba[1]; + + // 필터 적용 + Filter filter = new Filter(b, a); + double[] linVelHP = filter.filtfilt(linVel); + + // 필터링된 신호 사용 + } +} diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyFilter.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyAHRS.java similarity index 100% rename from src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyFilter.java rename to src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyAHRS.java diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java deleted file mode 100644 index 2a318a7..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/DataService.java +++ /dev/null @@ -1,184 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.service; - -import IOT_Platform.Lantern_Of_Dusk_BE.core.ExtendedKalmanFilter; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; -import IOT_Platform.Lantern_Of_Dusk_BE.dto.RawDataDTO; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; -import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; -import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; -import org.apache.commons.math3.linear.MatrixUtils; -import org.apache.commons.math3.linear.RealMatrix; -import org.json.JSONArray; -import org.json.JSONObject; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; - -import java.util.*; - -@Service -public class DataService { - - private final RestTemplate restTemplate; - - private final ConnectionRepository connectionRepository; - private final PositionRepository positionRepository; - - private Map connections; - private Map filters; - - @Autowired - public DataService(RestTemplateBuilder restTemplateBuilder, ConnectionRepository connectionRepository, PositionRepository positionRepository) { - - this.restTemplate = restTemplateBuilder.build(); - - this.connectionRepository = connectionRepository; - this.positionRepository = positionRepository; - - this.connections = new HashMap<>(); - this.filters = new HashMap<>(); - - setConnection(); - } - - public void setConnection() { - for( Connection connection : connectionRepository.findAll()) { - // 초기 상태 벡터 및 공분산 행렬 설정 (모든 값이 0인 상태로 초기화) - // 상태 전이 행렬, 프로세스 노이즈, 측정 노이즈, 관측 행렬 설정 (임의의 예시 값, 실제 응용에 따라 조정 필요) - RealMatrix initialState = MatrixUtils.createColumnRealMatrix(new double[]{0, 0, 0, 0, 0, 0}); // [x, y, z, roll, pitch, yaw] - RealMatrix initialCovariance = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); - RealMatrix stateTransition = MatrixUtils.createRealIdentityMatrix(6); - RealMatrix processNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{0.1, 0.1, 0.1, 0.1, 0.1, 0.1}); - RealMatrix measurementNoise = MatrixUtils.createRealDiagonalMatrix(new double[]{1, 1, 1, 1, 1, 1}); - RealMatrix observationMatrix = MatrixUtils.createRealIdentityMatrix(6); - ExtendedKalmanFilter filter = new ExtendedKalmanFilter(initialState, initialCovariance, stateTransition, processNoise, measurementNoise, observationMatrix); - - connections.put(connection.getId(), connection); - filters.put(connection.getId(), filter); - } - } - - //@Scheduled(fixedRate = 1000) - public void processData() { - for (Connection connection : connections.values()) { - List rawDataList = getRawData(connection.getAe()); - Position position = applyFilter(rawDataList, connection.getId()); - saveData(position); - } - } - - @Value("${mobius.url}") - private String mobiusServerUrl; - @Value("${mobius.cnt.imu}") - private String mobiusImuCntName; - @Value("${mobius.cnt.atm}") - private String mobiusAtmCntName; - public List getRawData(String ae) { - String urlIMU = mobiusServerUrl + ae + "/" + mobiusImuCntName + "?fu=2&la=143&ty=4&rcn=4"; - String urlATM = mobiusServerUrl + ae + "/" + mobiusAtmCntName + "?fu=2&la=143&ty=4&rcn=4"; - - HttpHeaders headers = new HttpHeaders(); - headers.set("Accept", "application/json"); - headers.set("X-M2M-RI", "12345"); - headers.set("X-M2M-Origin", "SOrigin"); - HttpEntity request = new HttpEntity(headers); - - List result = new ArrayList<>(); - - try { - ResponseEntity responseIMU = restTemplate.exchange( - urlIMU, - HttpMethod.GET, - request, - String.class - ); - ResponseEntity responseATM = restTemplate.exchange( - urlATM, - HttpMethod.GET, - request, - String.class - ); - - JSONArray rawDataIMU = new JSONObject(responseIMU.getBody()).getJSONObject("m2m:rsp").getJSONArray("m2m:cin"); - JSONArray rawDataATM = new JSONObject(responseATM.getBody()).getJSONObject("m2m:rsp").getJSONArray("m2m:cin"); - - for (int i = 0; i < 143; i++) { - RawDataDTO rawDataDTO = new RawDataDTO(); - - JSONObject objIMU = ((JSONObject) rawDataIMU.get(i)).getJSONObject("con"); - JSONObject objATM = ((JSONObject) rawDataATM.get(i)).getJSONObject("con"); - - // TODO: 5/29/24 테스트 코드 입력 후 구현 - System.out.println(objATM.toString()); - System.out.println(objIMU.toString()); - - rawDataDTO.setAx((Double) objIMU.get("ax")); - rawDataDTO.setAy((Double) objIMU.get("ay")); - rawDataDTO.setAz((Double) objIMU.get("az")); - rawDataDTO.setGx((Double) objIMU.get("gx")); - rawDataDTO.setGy((Double) objIMU.get("gy")); - rawDataDTO.setGz((Double) objIMU.get("gz")); - rawDataDTO.setAtm((Double) objATM.get("atm")); - - result.add(rawDataDTO); - } - - } catch (RestClientException e) { - System.out.println("Error fetching data for " + ae + " from Mobius"); - System.out.println(e); - } - - return result; - } - - public Position applyFilter(List rawDataDTOList, int deviceId) { - for (RawDataDTO rawDataDTO : rawDataDTOList) { - // 측정값 벡터 생성 - RealMatrix measurement = MatrixUtils.createColumnRealMatrix(new double[]{ - rawDataDTO.getAx(), rawDataDTO.getAy(), rawDataDTO.getAx(), - rawDataDTO.getGx(), rawDataDTO.getGy(), rawDataDTO.getGz() - }); - - // 예측 단계 - filters.get(deviceId).predict(); - - // 업데이트 단계 - filters.get(deviceId).update(measurement); - } - - // 필터링된 상태 벡터 가져오기 - RealMatrix state = filters.get(deviceId).getState(); - - // 상태 벡터에서 위치 정보 추출 - double x = state.getEntry(0, 0); - double y = state.getEntry(1, 0); - double z = state.getEntry(2, 0); - double roll = state.getEntry(3, 0); - double pitch = state.getEntry(4, 0); - double yaw = state.getEntry(5, 0); - - // 위치 정보 저장 - Position position = new Position(); - position.setDeviceId(deviceId); - position.setX(x); - position.setY(y); - position.setZ(z); - position.setRoll(roll); - position.setPitch(pitch); - position.setYaw(yaw); - - return position; - } - - public void saveData(Position position) { - positionRepository.save(position); - } -} \ No newline at end of file diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java new file mode 100644 index 0000000..dd98b62 --- /dev/null +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java @@ -0,0 +1,60 @@ +package IOT_Platform.Lantern_Of_Dusk_BE.service; + +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Marker; +import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.MarkerRepository; +import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class ApiService { + + private final ConnectionRepository connectionRepository; + private final PositionRepository positionRepository; + private final MarkerRepository markerRepository; + + @Autowired + public ApiService(ConnectionRepository connectionRepository, PositionRepository positionRepository, MarkerRepository markerRepository) { + this.connectionRepository = connectionRepository; + this.positionRepository = positionRepository; + this.markerRepository = markerRepository; + } + + public void saveConnection(Connection connection) { + connectionRepository.save(connection); + } + public Connection getConnection(int id) { + return connectionRepository.findById(id).orElse(null); + } + public Connection getConnection(String ae) { + return connectionRepository.findByAe(ae).orElse(null); + } + public List getConnectionList() { + return connectionRepository.findAll(); + } + public void deleteDevice(int id) { + connectionRepository.deleteById(id); + } + + public Position getPosition(int deviceId) { + return positionRepository.findTopByDeviceIdOrderByIdDesc(deviceId).orElse(null); + } + + public void saveMarker(Marker marker) { + markerRepository.save(marker); + } + public List getMarkerList() { + return markerRepository.findAll(); + } + public Marker getMarker(int id) { + return markerRepository.findById(id).orElse(null); + } + public void deleteMarker(int id) { + markerRepository.deleteById(id); + } +} \ No newline at end of file From e4c6e07948a59ef55cf1820149b2877eb29e96d8 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Thu, 30 May 2024 19:22:15 +0900 Subject: [PATCH 14/16] b --- .DS_Store | Bin 14340 -> 14340 bytes src/.DS_Store | Bin 6148 -> 6148 bytes src/main/.DS_Store | Bin 6148 -> 6148 bytes .../controller/DeviceController.java | 23 +-- .../Lantern_Of_Dusk_BE/core/Butterworth.java | 3 +- .../Lantern_Of_Dusk_BE/core/Device.java | 191 +++++++++++++++++- .../Lantern_Of_Dusk_BE/core/Filter.java | 42 ++-- .../Lantern_Of_Dusk_BE/core/MahonyAHRS.java | 117 ++++------- .../service/ProcessService.java | 49 ++--- src/main/resources/application.properties | 4 - src/test/.DS_Store | Bin 6148 -> 6148 bytes 11 files changed, 276 insertions(+), 153 deletions(-) diff --git a/.DS_Store b/.DS_Store index 11fefcf039c4d0bac753ef14a691618bf6ecd6fe..d7be8d22f61ff12beefb5f84c2d0aa62873d1a2f 100644 GIT binary patch delta 257 zcmZoEXepR*fJKx?H*n)cGxmuOcsH|iICC&=*z7Ivi<6n*Wzu91sSw5so99Y(u*Nal zM=>xkurTN`q%&kPl;q~SxFqG|CjrGcKqlz29CJjKPl3z7wl<8^LX$7ZFbq!4&n*Dz zVPFt9nB1(O$aH1VCa+TrVcam8S?N8~-{j3-lmgk2{iK!73jnPxMe+au delta 246 zcmZoEXepR*fF(YmEO6sRGxmuOcsH|iICC&w*z7Ivi<6m=O=Yr&R0!jT&2yzXSmT(k z#V{~1urTN`q%&kPl;q~SxFqG|CjrGcKqka89dksLPr)l+kYN~{oS$0&)Wg6a^kH(d zf+Ew2JCm0w1tBPnHwYzAsTk_9?sa;l>IVD4KV-! diff --git a/src/main/.DS_Store b/src/main/.DS_Store index d2e08b5a9c380c0795499c04087236848a9fa332..3fd169deff5eecfaa9c9562d0a26660ce9fef7a5 100644 GIT binary patch delta 55 zcmZoMXffCz&&sqQW3nP^6l22V8rFO!hIf-4*~El$^Icq$a`KZH7#KKuj{7)ju}rpS Llh~}wc3ltv%@z;` delta 40 wcmZoMXffCz&&o7MYqBD16l1{T8rFO!MuW+YY+}s0`7V accelQueue = new LinkedList<>(); + private Queue gyroQueue = new LinkedList<>(); + private Queue atmQueue = new LinkedList<>(); + + private Queue positionQueue = new LinkedList<>(); + + private double samplePeriod = 5 / 1000; + private MahonyAHRS mahonyAHRS = new MahonyAHRS(samplePeriod); + + private final PositionRepository positionRepository; + + public Device(PositionRepository positionRepository, int id, String ae) { + this.id = id; + this.ae = ae; + this.positionRepository = positionRepository; + } + + @Scheduled(fixedRate = 20) + public void run() { + if (!process) return; + + getData(); + processData(); + save(); + } + + public void getData() { + String host = "http://203.253.128.177:7579/Mobius/"; + + String urlIMU = host + ae + "/" + "IMU" + "?fu=2&la=4&ty=4&rcn=4"; + String urlATM = host + ae + "/" + "ATM" + "?fu=2&la=4&ty=4&rcn=4"; + + HttpHeaders headers = new HttpHeaders(); + headers.set("Accept", "application/json"); + headers.set("X-M2M-RI", "12345"); + headers.set("X-M2M-Origin", "SOrigin"); + HttpEntity request = new HttpEntity(headers); + + RestTemplate restTemplate = new RestTemplate(); + + try { + ResponseEntity responseIMU = restTemplate.exchange( + urlIMU, + HttpMethod.GET, + request, + String.class + ); + ResponseEntity responseATM = restTemplate.exchange( + urlATM, + HttpMethod.GET, + request, + String.class + ); + + JSONArray rawIMUDataList = new JSONObject(responseIMU.getBody()).getJSONObject("m2m:rsp").getJSONArray("m2m:cin"); + JSONArray rawATMDataList = new JSONObject(responseATM.getBody()).getJSONObject("m2m:rsp").getJSONArray("m2m:cin"); + + double[][] rawAccelData = new double[4][3]; + double[][] rawGyroData = new double[4][3]; + double[] rawATMData = new double[4]; + + for (int i = 0; i < 4; i++) { + JSONObject objIMU = ((JSONObject) rawIMUDataList.get(i)).getJSONObject("con"); + JSONObject objATM = ((JSONObject) rawATMDataList.get(i)).getJSONObject("con"); + + rawAccelData[i][0] = (Double) objIMU.get("ax"); + rawAccelData[i][1] = (Double) objIMU.get("ay"); + rawAccelData[i][2] = (Double) objIMU.get("az"); + + rawGyroData[i][0] = (Double) objIMU.get("gx"); + rawGyroData[i][1] = (Double) objIMU.get("gy"); + rawGyroData[i][2] = (Double) objIMU.get("gz"); + + rawATMData[i] = (Double) objATM.get("atm"); + } + + accelQueue.add(rawAccelData); + gyroQueue.add(rawGyroData); + atmQueue.add(rawATMData); + + } catch (RestClientException e) { + System.out.println("Error fetching data for " + ae + " from Mobius"); + System.out.println(e); + } + } + + public void processData() { + double[][] accelData = accelQueue.peek(); + double[][] gyroData = gyroQueue.peek(); + + int len = accelData.length; + + // 회전 벡터 마호니 필터 및 계산 + RealMatrix[] R = new RealMatrix[len]; + for (int i = 0; i < len; i++) { + mahonyAHRS.updateIMU(new Vector3D(gyroData[i]), new Vector3D(accelData[i])); + R[i] = new Array2DRowRealMatrix(mahonyAHRS.getQuaternion()); + } + + // 회전 적용된 가속도 벡터 계산 + double[][] tcAcc = new double[len][3]; + for (int i = 0; i < len; i++) { + tcAcc[i] = R[i].preMultiply(accelData[i]); + } + + // 중력 가속도를 제거한 가속도 벡터 계산 + double[][] linAcc = new double[len][3]; + for (int i = 0; i < len; i++) { + linAcc[i][0] = tcAcc[i][0] * 9.81; + linAcc[i][1] = tcAcc[i][1] * 9.81; + linAcc[i][2] = (tcAcc[i][2] - 1.0) * 9.81; + } + + // 선형 속도 계산 (가속도 적분) + double[][] linVel = new double[len][3]; + for (int i = 1; i < len; i++) { + for (int j = 0; j < 3; j++) { + linVel[i][j] = linVel[i - 1][j] + linAcc[i][j] * samplePeriod; + } + } + + // 드리프트를 제거하기 위해 고역통과 필터 적용 + //double[][] linVelHP = highPassFilter(linVel, samplePeriod, 0.1); + double[][] linVelHP = linVel; + + // 선형 위치 계산 (속도 적분) + double[][] linPos = new double[len][3]; + for (int i = 1; i < len; i++) { + for (int j = 0; j < 3; j++) { + linPos[i][j] = linPos[i - 1][j] + linVelHP[i][j] * samplePeriod; + } + } + + // 드리프트를 제거하기 위해 고역통과 필터 적용 + //double[][] linPosHP = highPassFilter(linPos, samplePeriod, 0.1); + double[][] linPosHP = linPos; + + // 방향 벡터를 오일러 각도로 변환 + Rotation rotation = new Rotation((Vector3D) R[len-1], 1e-10); + double[] eulerR = rotation.getAngles(RotationOrder.XYZ); + + Position position = new Position(); + position.setDeviceId(id); + position.setX(linPosHP[len-1][0]); + position.setY(linPosHP[len-1][1]); + position.setZ(linPosHP[len-1][2]); + position.setPitch(eulerR[0]); + position.setYaw(eulerR[1]); + position.setRoll(eulerR[2]); + + positionQueue.add(position); + } + + public void save() { + positionRepository.save(positionQueue.peek()); + } + + public void setProcess(boolean process) { + System.out.println("saving data"); + this.process = process; + } } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Filter.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Filter.java index 1c307a0..01d8ffb 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Filter.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Filter.java @@ -1,4 +1,4 @@ -import IOT_Platform.Lantern_Of_Dusk_BE.core.Butterworth; +package IOT_Platform.Lantern_Of_Dusk_BE.core; public class Filter { private double[] a; @@ -66,24 +66,24 @@ private double[] lfilter(double[] b, double[] a, double[] x) { } return y; } - - public static void main(String[] args) { - double samplePeriod = 0.01; // 샘플링 주기 - double filtCutOff = 0.1; // 컷오프 주파수 - int order = 1; // 필터 차수 - - // 샘플 데이터 - double[] linVel = { /* 신호 데이터 */ }; - - // Butterworth 필터 설계 - double[][] ba = Butterworth.designHighPassFilter(order, filtCutOff, 1 / samplePeriod); - double[] b = ba[0]; - double[] a = ba[1]; - - // 필터 적용 - Filter filter = new Filter(b, a); - double[] linVelHP = filter.filtfilt(linVel); - - // 필터링된 신호 사용 - } +// +// public static void main(String[] args) { +// double samplePeriod = 0.01; // 샘플링 주기 +// double filtCutOff = 0.1; // 컷오프 주파수 +// int order = 1; // 필터 차수 +// +// // 샘플 데이터 +// double[] linVel = { /* 신호 데이터 */ }; +// +// // Butterworth 필터 설계 +// double[][] ba = Butterworth.designHighPassFilter(order, filtCutOff, 1 / samplePeriod); +// double[] b = ba[0]; +// double[] a = ba[1]; +// +// // 필터 적용 +// Filter filter = new Filter(b, a); +// double[] linVelHP = filter.filtfilt(linVel); +// +// // 필터링된 신호 사용 +// } } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyAHRS.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyAHRS.java index cf0f332..1501806 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyAHRS.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/MahonyAHRS.java @@ -1,97 +1,60 @@ package IOT_Platform.Lantern_Of_Dusk_BE.core; -import org.apache.commons.math3.linear.ArrayRealVector; -import org.apache.commons.math3.linear.RealVector; - -public class MahonyFilter { - - private double samplePeriod; - private RealVector quaternion; - private double kp; - private double ki; - private RealVector eInt; - - public MahonyFilter(double samplePeriod, double[] quaternion, double kp, double ki) { - this.samplePeriod = samplePeriod; - this.quaternion = new ArrayRealVector(quaternion); - this.kp = kp; - this.ki = ki; - this.eInt = new ArrayRealVector(new double[]{0, 0, 0}); +import org.apache.commons.math3.complex.Quaternion; +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; + +public class MahonyAHRS { + private double SamplePeriod; + private Quaternion quaternion; + private double Kp; + private double Ki; + private Vector3D eInt; + + public MahonyAHRS(double SamplePeriod) { + this.SamplePeriod = SamplePeriod; + this.quaternion = new Quaternion(1, 0, 0, 0); + this.Kp = 1.0; + this.Ki = 0.0; + this.eInt = new Vector3D(0, 0, 0); } - private RealVector quaternProd(RealVector a, RealVector b) { - double w1 = a.getEntry(0); - double x1 = a.getEntry(1); - double y1 = a.getEntry(2); - double z1 = a.getEntry(3); - - double w2 = b.getEntry(0); - double x2 = b.getEntry(1); - double y2 = b.getEntry(2); - double z2 = b.getEntry(3); - - return new ArrayRealVector(new double[]{ - w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2, - w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2, - w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2, - w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2 - }); + private Quaternion quaternProd(Quaternion a, Quaternion b) { + return a.multiply(b); } - - private RealVector quaternConj(RealVector q) { - return new ArrayRealVector(new double[]{ - q.getEntry(0), -q.getEntry(1), -q.getEntry(2), -q.getEntry(3) - }); + private Vector3D normalize(Vector3D v) { + return v.normalize(); } - public void updateIMU(double[] gyroscope, double[] accelerometer) { - RealVector q = this.quaternion; + public void updateIMU(Vector3D gyro, Vector3D accel) { + Quaternion q = quaternion; - RealVector acc = new ArrayRealVector(accelerometer); - if (acc.getNorm() == 0) return; - acc = acc.mapDivide(acc.getNorm()); + if (accel.getNorm() == 0) return; - RealVector v = new ArrayRealVector(new double[]{ - 2 * (q.getEntry(1) * q.getEntry(3) - q.getEntry(0) * q.getEntry(2)), - 2 * (q.getEntry(0) * q.getEntry(1) + q.getEntry(2) * q.getEntry(3)), - q.getEntry(0) * q.getEntry(0) - q.getEntry(1) * q.getEntry(1) - q.getEntry(2) * q.getEntry(2) + q.getEntry(3) * q.getEntry(3) - }); + accel = normalize(accel); - RealVector e = crossProduct(acc, v); + Vector3D v = new Vector3D( + 2 * (q.getQ1() * q.getQ3() - q.getQ0() * q.getQ2()), + 2 * (q.getQ0() * q.getQ1() + q.getQ2() * q.getQ3()), + q.getQ0() * q.getQ0() - q.getQ1() * q.getQ1() - q.getQ2() * q.getQ2() + q.getQ3() * q.getQ3() + ); - if (ki > 0) { - eInt = eInt.add(e.mapMultiply(samplePeriod)); + Vector3D e = accel.crossProduct(v); + + if (Ki > 0) { + eInt = eInt.add(e.scalarMultiply(SamplePeriod)); } else { - eInt = new ArrayRealVector(new double[]{0, 0, 0}); + eInt = new Vector3D(0, 0, 0); } - // qDot 계산을 위한 배열 준비 - double[] gyroArray = {0, gyroscope[0], gyroscope[1], gyroscope[2]}; - RealVector gyroVector = new ArrayRealVector(gyroArray); - - // Quaternion 곱셈을 위한 준비 - RealVector qDot2 = quaternProd(q, gyroVector).mapMultiply(0.5); - - // 위 코드에서, gyroscope 배열을 직접 RealVector 생성자에 넣어 0을 추가하였습니다. + gyro = gyro.add(e.scalarMultiply(Kp)).add(eInt.scalarMultiply(Ki)); + Quaternion qDot = quaternProd(q, new Quaternion(0, gyro.toArray())).multiply(0.5); - q = q.add(qDot2.mapMultiply(samplePeriod)); - quaternion = q.mapDivide(q.getNorm()); + q = q.add(qDot.multiply(SamplePeriod)); + quaternion = q.normalize(); } - private RealVector crossProduct(RealVector u, RealVector v) { - double u1 = u.getEntry(0); - double u2 = u.getEntry(1); - double u3 = u.getEntry(2); - double v1 = v.getEntry(0); - double v2 = v.getEntry(1); - double v3 = v.getEntry(2); - - return new ArrayRealVector(new double[]{ - u2 * v3 - u3 * v2, - u3 * v1 - u1 * v3, - u1 * v2 - u2 * v1 - }); + public double[] getQuaternion() { + return quaternion.getVectorPart(); } } - diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java index dd98b62..9b665df 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java @@ -1,5 +1,6 @@ package IOT_Platform.Lantern_Of_Dusk_BE.service; +import IOT_Platform.Lantern_Of_Dusk_BE.core.Device; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Marker; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; @@ -9,52 +10,34 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.HashSet; import java.util.List; +import java.util.Set; @Service -public class ApiService { +public class ProcessService { private final ConnectionRepository connectionRepository; private final PositionRepository positionRepository; - private final MarkerRepository markerRepository; + + private Set deviceSet = new HashSet<>(); @Autowired - public ApiService(ConnectionRepository connectionRepository, PositionRepository positionRepository, MarkerRepository markerRepository) { + public ProcessService(ConnectionRepository connectionRepository, PositionRepository positionRepository, MarkerRepository markerRepository) { this.connectionRepository = connectionRepository; this.positionRepository = positionRepository; - this.markerRepository = markerRepository; } - public void saveConnection(Connection connection) { - connectionRepository.save(connection); - } - public Connection getConnection(int id) { - return connectionRepository.findById(id).orElse(null); - } - public Connection getConnection(String ae) { - return connectionRepository.findByAe(ae).orElse(null); - } - public List getConnectionList() { - return connectionRepository.findAll(); - } - public void deleteDevice(int id) { - connectionRepository.deleteById(id); - } + public void startProcess() { + for (Connection c : connectionRepository.findAll()) { - public Position getPosition(int deviceId) { - return positionRepository.findTopByDeviceIdOrderByIdDesc(deviceId).orElse(null); - } + System.out.println("start process : " + c.getAe()); - public void saveMarker(Marker marker) { - markerRepository.save(marker); - } - public List getMarkerList() { - return markerRepository.findAll(); - } - public Marker getMarker(int id) { - return markerRepository.findById(id).orElse(null); - } - public void deleteMarker(int id) { - markerRepository.deleteById(id); + Device device = new Device(positionRepository, c.getId(), c.getAe()); + device.setProcess(true); + + + // TODO: 5/30/24 모비우스에 신호 보내는 코드 추가 + } } } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 00e78b3..9190733 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,9 +1,5 @@ spring.application.name=Lantern_Of_Dusk_BE -mobius.url=http://203.253.128.177:7579/Mobius/ -mobius.cnt.imu=MPU -mobius.cnt.atm=GYRO - server.port=7777 spring.datasource.url=jdbc:mysql://localhost:3306/lod diff --git a/src/test/.DS_Store b/src/test/.DS_Store index edf673329323c307b5ae7334ec0071aa9c375d6c..a744990958197bbba5307e0f15df0525d2ac273b 100644 GIT binary patch delta 25 hcmZoMXfc?ujER9^;) Date: Thu, 30 May 2024 19:44:26 +0900 Subject: [PATCH 15/16] asdf --- .../Lantern_Of_Dusk_BE/dto/RawDataDTO.java | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/dto/RawDataDTO.java diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/dto/RawDataDTO.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/dto/RawDataDTO.java deleted file mode 100644 index 7499354..0000000 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/dto/RawDataDTO.java +++ /dev/null @@ -1,17 +0,0 @@ -package IOT_Platform.Lantern_Of_Dusk_BE.dto; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class RawDataDTO { - private int id; - private double ax; - private double ay; - private double az; - private double gx; - private double gy; - private double gz; - private double atm; -} \ No newline at end of file From a0b54326648c76bc6a04fc8530937a929ac83ca8 Mon Sep 17 00:00:00 2001 From: WooJinLim <95209789+woojin2296@users.noreply.github.com> Date: Thu, 30 May 2024 19:44:28 +0900 Subject: [PATCH 16/16] asdf --- .../Lantern_Of_Dusk_BE/core/Device.java | 20 ++++++++++--------- .../service/ProcessService.java | 6 ++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Device.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Device.java index fc35fd8..782ae77 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Device.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/core/Device.java @@ -13,20 +13,20 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import java.util.LinkedList; import java.util.Queue; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; public class Device { private int id; private String ae; - private boolean process = false; - private Queue accelQueue = new LinkedList<>(); private Queue gyroQueue = new LinkedList<>(); private Queue atmQueue = new LinkedList<>(); @@ -44,10 +44,7 @@ public Device(PositionRepository positionRepository, int id, String ae) { this.positionRepository = positionRepository; } - @Scheduled(fixedRate = 20) public void run() { - if (!process) return; - getData(); processData(); save(); @@ -184,8 +181,13 @@ public void save() { positionRepository.save(positionQueue.peek()); } - public void setProcess(boolean process) { - System.out.println("saving data"); - this.process = process; + public void start() { + System.out.println("start"); + + Runnable task = () -> { + run(); + }; + + Executors.newScheduledThreadPool(1).scheduleAtFixedRate(task, 0, 20, TimeUnit.MILLISECONDS); } } diff --git a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java index 9b665df..9037382 100644 --- a/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java +++ b/src/main/java/IOT_Platform/Lantern_Of_Dusk_BE/service/ProcessService.java @@ -2,8 +2,6 @@ import IOT_Platform.Lantern_Of_Dusk_BE.core.Device; import IOT_Platform.Lantern_Of_Dusk_BE.entity.Connection; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Marker; -import IOT_Platform.Lantern_Of_Dusk_BE.entity.Position; import IOT_Platform.Lantern_Of_Dusk_BE.repository.ConnectionRepository; import IOT_Platform.Lantern_Of_Dusk_BE.repository.MarkerRepository; import IOT_Platform.Lantern_Of_Dusk_BE.repository.PositionRepository; @@ -11,7 +9,6 @@ import org.springframework.stereotype.Service; import java.util.HashSet; -import java.util.List; import java.util.Set; @Service @@ -34,8 +31,9 @@ public void startProcess() { System.out.println("start process : " + c.getAe()); Device device = new Device(positionRepository, c.getId(), c.getAe()); - device.setProcess(true); + device.start(); + deviceSet.add(device); // TODO: 5/30/24 모비우스에 신호 보내는 코드 추가 }