commit 0a212301a49fe6b03acd97bec58dab6ce240056a Author: dhji(지대한) Date: Tue Sep 5 18:46:41 2023 +0900 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c2065bc2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..033e24c4 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..9f4197d5 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..fcb6fca1 --- /dev/null +++ b/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pav-server/build.gradle b/pav-server/build.gradle new file mode 100644 index 00000000..7391be8a --- /dev/null +++ b/pav-server/build.gradle @@ -0,0 +1,95 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '2.5.1' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' + id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' +} + +group = 'com.palnet' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '11' +} + +compileJava { + options.compilerArgs += [ + '-Amapstruct.unmappedTargetPolicy=IGNORE', + '-Amapstruct.unmappedSourcePolicy=IGNORE' + ] +} + + +repositories { + mavenCentral() +} + +dependencies { + // spring + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-cache' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-jdbc' + // db + runtimeOnly 'mysql:mysql-connector-java' + + // log + implementation 'ch.qos.logback:logback-classic' + // aws + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.0.1.RELEASE' + implementation 'org.springframework.cloud:spring-cloud-aws-context:1.2.1.RELEASE' + implementation 'org.springframework.cloud:spring-cloud-aws-autoconfigure:2.0.1.RELEASE' + + // lombok, mapstruct + implementation 'org.mapstruct:mapstruct:1.5.5.Final' + implementation 'org.projectlombok:lombok:1.18.28' + + annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' + annotationProcessor 'org.projectlombok:lombok:1.18.28' + annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0' + + // querydsl - jpa + implementation 'com.querydsl:querydsl-core:5.0.0' + implementation 'com.querydsl:querydsl-jpa:5.0.0' + annotationProcessor 'com.querydsl:querydsl-apt:5.0.0' + + // other + implementation 'io.jsonwebtoken:jjwt:0.9.1' + implementation 'io.netty:netty-all:4.1.9.Final' + implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4:1.16' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr353' + implementation 'org.apache.httpcomponents:httpclient' + implementation 'org.apache.commons:commons-lang3' + implementation 'commons-httpclient:commons-httpclient:3.1' + implementation 'com.googlecode.json-simple:json-simple:1.1.1' + implementation 'io.springfox:springfox-boot-starter:3.0.0' + implementation 'com.esri.geometry:esri-geometry-api:2.2.4' + implementation 'org.locationtech.proj4j:proj4j:1.1.5' + implementation 'org.locationtech.jts:jts-core:1.18.0' + implementation 'org.json:json:20220320' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testAnnotationProcessor "org.mapstruct:mapstruct-processor:1.5.5.Final" + +} + +tasks.named('test') { + useJUnitPlatform() +} + +def querydslDir = "$buildDir/generated/querydsl" +querydsl { + jpa = true + querydslSourcesDir = querydslDir +} +sourceSets { + main.java.srcDir querydslDir +} +configurations { + querydsl.extendsFrom compileClasspath +} +compileQuerydsl { + options.annotationProcessorPath = configurations.querydsl +} \ No newline at end of file diff --git a/pav-server/lib/opensky-api-1.3.0.jar b/pav-server/lib/opensky-api-1.3.0.jar new file mode 100644 index 00000000..13f5f86b Binary files /dev/null and b/pav-server/lib/opensky-api-1.3.0.jar differ diff --git a/pav-server/settings.gradle b/pav-server/settings.gradle new file mode 100644 index 00000000..0664739e --- /dev/null +++ b/pav-server/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'pav-server' diff --git a/pav-server/src/main/java/com/palnet/PavApplication.java b/pav-server/src/main/java/com/palnet/PavApplication.java new file mode 100644 index 00000000..bc264f9c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/PavApplication.java @@ -0,0 +1,19 @@ +package com.palnet; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +@EnableAsync +@EnableCaching +public class PavApplication { + + public static void main(String[] args) { + SpringApplication.run(PavApplication.class, args); + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/controller/AcntCrtfyhpController.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/controller/AcntCrtfyhpController.java new file mode 100644 index 00000000..fc47b742 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/controller/AcntCrtfyhpController.java @@ -0,0 +1,254 @@ +package com.palnet.biz.api.acnt.crtfyhp.controller; + +import java.util.HashMap; +import java.util.Map; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.acnt.crtfyhp.model.AcntCrtfyhpRsModel; +import com.palnet.biz.api.acnt.crtfyhp.service.AcntCrtfyhpService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.jpa.repository.pty.PtyCstmrQueryRepository; +import com.palnet.comn.code.RSErrorCode; +import com.palnet.comn.utils.EncryptUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/acnt/crtfyhp", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "휴대폰 인증 관리", description = "회원 휴대폰 인증 관련 API") +public class AcntCrtfyhpController { + + @Autowired + private final AcntCrtfyhpService service; + + @Autowired + private PtyCstmrQueryRepository ptyCstmrQueryRepository; + + + @GetMapping(value = "/register/send") + @Tag(name = "휴대폰 인증 관리", description = "회원 휴대폰 인증 관련 API") + @ApiImplicitParam(name = "hnpo",value = "휴대폰번호", dataTypeClass = String.class) + public ResponseEntity send(String hpno) { + + + Map resultMap = new HashMap(); + + try { + + if(hpno == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + //회원정보에 동일한 휴대폰 번호가 있는지 확인 , 암호화 해서 검색 + String encHpno = EncryptUtils.encrypt(hpno); + boolean isHpno = ptyCstmrQueryRepository.findCstmrByHpno(encHpno); + + if(isHpno) { + resultMap.put("result" , false); + resultMap.put("code" , -1); // 동일한 휴대폰 번호 존재 + + + }else { + boolean result = service.registerSend(hpno); + resultMap.put("result" , result); + } + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + + + @GetMapping(value = "/register/confirm") + @Tag(name = "휴대폰 인증 관리", description = "회원 휴대폰 인증 관련 API") + @ApiImplicitParams({ + @ApiImplicitParam(name = "hpno",value = "휴대폰번호", dataTypeClass = String.class), + @ApiImplicitParam(name = "crtfyNo",value = "인증일련번호", dataTypeClass = String.class) + }) + public ResponseEntity confirm(String hpno , String crtfyNo) { + + + Map resultMap = new HashMap(); + + if(hpno == null || crtfyNo == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + + try { + + boolean result = service.registerConfirm(hpno, crtfyNo); + resultMap.put("result" , result); + + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + //아이디 찾기 시 인증번호 발송 로직 + @GetMapping(value = "/find/sendForId") + @ApiOperation(value = "아이디 찾기 시 인증번호 발송") + @Tag(name = "휴대폰 인증 관리", description = "회원 휴대폰 인증 관련 API") + @ApiImplicitParams({ + @ApiImplicitParam(name = "memberName", value = "회원 이름", dataTypeClass = String.class), + @ApiImplicitParam(name = "hpno", value = "휴대폰 번호", dataTypeClass = String.class) + }) + public ResponseEntity sendForId(String memberName, String hpno) { + Map resultMap = new HashMap(); + + if(memberName == null || hpno == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + boolean result = service.certifNum(memberName, hpno); + resultMap.put("result" , result); + if(!result) { + resultMap.put("code", -1); //일치하는 회원 없음 + } else { + resultMap.put("code", 0); //일치하는 회원 존재 + } + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } + + //아이디 찾기 + @GetMapping(value = "/find/findUserId") + @ApiOperation(value = "회원 아이디 찾기") + @Tag(name = "휴대폰 인증 관리", description = "회원 휴대폰 인증 관련 API") + @ApiImplicitParams({ + @ApiImplicitParam(name = "memberName",value = "회원이름", dataTypeClass = String.class), + @ApiImplicitParam(name = "hpno",value = "휴대폰번호", dataTypeClass = String.class) + }) + public ResponseEntity findUserId(String memberName, String hpno) { + Map resultMap = new HashMap(); + + if(memberName == null || hpno == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + String userId = service.findUserId(memberName, hpno); + if(!userId.equals("")) { + resultMap.put("userId", userId); + resultMap.put("code", 0); + } else { + resultMap.put("userId", ""); + resultMap.put("code", -1); + } + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + + return ResponseEntity.ok().body( new SuccessResponse(resultMap)); + } + + //비밀번호 찾기 시 인증번호 발송 로직 + @GetMapping(value = "/find/sendForPw") + @ApiOperation(value = "비밀번호 찾기 시 인증번호 발송") + @Tag(name = "휴대폰 인증 관리", description = "회원 휴대폰 인증 관련 API") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userId",value = "사용자ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "hpno",value = "휴대폰번호", dataTypeClass = String.class) + }) + public ResponseEntity sendForPw(String userId, String hpno) { + Map resultMap = new HashMap(); + + if(userId == null || hpno == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + boolean result = service.certifPw(userId, hpno); + resultMap.put("result", result); + if(!result) { + resultMap.put("code", -1); //일치하는 회원 없음 + } else { + resultMap.put("code", 0); //일치하는 회원 존재 + } + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + + return ResponseEntity.ok().body( new SuccessResponse(resultMap)); + } + + + @GetMapping(value = "/find/updatePw") + @ApiOperation(value = "비밀번호 찾기 및 업데이트") + @Tag(name = "휴대폰 인증 관리", description = "회원 휴대폰 인증 관련 API") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userID",value = "사용자ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "hpno",value = "휴대폰번호", dataTypeClass = String.class), + @ApiImplicitParam(name = "newPw",value = "새로운 비밀번호", dataTypeClass = String.class) + }) + public ResponseEntity updatePw(String userId, String hpno, String newPw) throws Exception { + Map resultMap = new HashMap(); + + if(hpno == null || newPw == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + boolean result = service.updatePw(userId, hpno, newPw); + resultMap.put("result", result); + if(!result) { + resultMap.put("code", -1); + } else { + resultMap.put("code", 0); + } + } catch(Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body( new SuccessResponse(resultMap)); + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/model/AcntCrtfyhpRsModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/model/AcntCrtfyhpRsModel.java new file mode 100644 index 00000000..d1d01fcb --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/model/AcntCrtfyhpRsModel.java @@ -0,0 +1,9 @@ +package com.palnet.biz.api.acnt.crtfyhp.model; + +import lombok.Data; + +@Data +public class AcntCrtfyhpRsModel { +// private int errCode; + private String userId; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/service/AcntCrtfyhpService.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/service/AcntCrtfyhpService.java new file mode 100644 index 00000000..43909277 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/crtfyhp/service/AcntCrtfyhpService.java @@ -0,0 +1,252 @@ +package com.palnet.biz.api.acnt.crtfyhp.service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.Persistence; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestBody; + +import com.palnet.biz.api.acnt.crtfyhp.model.AcntCrtfyhpRsModel; +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrRqModel; +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrRsModel; +import com.palnet.biz.api.acnt.cstmr.model.AnctCstmrTermsModel; +import com.palnet.biz.api.acnt.terms.model.AcntTermsRqModel; +import com.palnet.biz.api.acnt.terms.model.AcntTermsRsModel; +import com.palnet.biz.jpa.entity.PtyCrtfyhpBas; +import com.palnet.biz.jpa.entity.PtyCstmrBas; +import com.palnet.biz.jpa.entity.PtyCstmrDtl; +import com.palnet.biz.jpa.entity.PtyTermsAgreeTxn; +import com.palnet.biz.jpa.entity.SuredataEntity; +import com.palnet.biz.jpa.repository.pty.PtyCrtfyhpBasQueryRepository; +import com.palnet.biz.jpa.repository.pty.PtyCrtfyhpBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrDtlRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrQueryRepository; +import com.palnet.biz.jpa.repository.pty.PtyTermsAgreeTxnRepository; +import com.palnet.biz.jpa.repository.pty.PtyTermsQueryRepository; +import com.palnet.biz.jpa.repository.pty.SuredataRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.DateUtils; +import com.palnet.comn.utils.EncryptUtils; +import com.palnet.comn.utils.HttpUtils; + +@Service +public class AcntCrtfyhpService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Value("${sms.usercode}") + private String USER_CODE; + + + @Value("${sms.deptcode}") + private String DEPT_CODE; + + + @Value("${sms.reqname}") + private String REQ_NAME; + + + @Value("${sms.reqphone}") + private String REQ_PHONE; + + + @Value("${sms.result}") + private String RESULT; + + + @Value("${sms.reqtime}") + private String REQ_TIME; + + + @Value("${sms.kind}") + private String KIND; + + + @Value("${sms.subject.certify}") + private String SUBJECT_CETIFY; + + + @Value("${sms.callname.certify}") + private String CALLNAME_CERTIFY; + + + @Autowired + private PtyCrtfyhpBasQueryRepository query; + + @Autowired + private PtyCstmrQueryRepository cstmrQuery; + + @Autowired + private PtyCrtfyhpBasRepository ptyCrtfyhpBasRepository; + + @Autowired + private PtyCstmrBasRepository ptyCstmrBasRepository; + + @Autowired + private SuredataRepository sureDataRepository; + + + + /** + * + * @param rq + * @return + */ +// public boolean certifySend(String hpno) throws Exception { +// +// //인증번호 만들기 ( 6자리) +// String certifyNo = numberGen(6, 2); +// +// //메시지 만들기 +// String msg = "인증번호 [" + certifyNo + "] 를 입력해 주세요."; +// +// +// //기존 인증 내역 삭제 +// String encHpno = EncryptUtils.encrypt(hpno); +// ptyCrtfyhpBasRepository.prevCrtfyhpYnBlock(hpno); +// +// //인증 테이블 입력 +// PtyCrtfyhpBas ptyEntity = new PtyCrtfyhpBas(); +// ptyEntity.setHpno(hpno); +// ptyEntity.setCrtfyhpNo(certifyNo); +// ptyEntity.setCrtfyhpYn("N"); +// ptyCrtfyhpBasRepository.save(ptyEntity); +// +// return true; +// } + public boolean registerSend(String hpno) throws Exception{ + + //인증번호 만들기 ( 6자리) + String certifyNo = numberGen(6, 2); + + //메시지 만들기 + String msg = "인증번호 [" + certifyNo + "] 를 입력해 주세요."; + + + //기존 인증 내역 삭제 +// String encHpno = EncryptUtils.encrypt(hpno); + ptyCrtfyhpBasRepository.prevCrtfyhpYnBlock(hpno); + + //인증 테이블 입력 + PtyCrtfyhpBas ptyEntity = new PtyCrtfyhpBas(); + ptyEntity.setHpno(hpno); + ptyEntity.setCrtfyhpNo(certifyNo); + ptyEntity.setCrtfyhpYn("N"); + ptyCrtfyhpBasRepository.save(ptyEntity); + + logger.info("certifyNo :: " + certifyNo); + + + //발송 테이블 입력 + SuredataEntity entity = new SuredataEntity(); + entity.setCallphone(hpno); + entity.setMsg(msg); + entity.setSubject(SUBJECT_CETIFY); + entity.setCallname(CALLNAME_CERTIFY); + entity.setUsercode(USER_CODE); + entity.setDeptcode(DEPT_CODE); + entity.setReqphone(REQ_PHONE); + entity.setReqname(REQ_NAME); + entity.setReqtime(REQ_TIME); + entity.setResult(RESULT); + entity.setKind(KIND); + + + SuredataEntity result = sureDataRepository.save(entity); + + if(result == null) { + return false; + } + + return true; + + } + + public boolean registerConfirm(String hpno , String crtfyNo ) throws Exception{ + hpno = EncryptUtils.encrypt(hpno); //암호화 해서 검색 + List entity = query.confirmSms(hpno , crtfyNo); + + return entity.size() == 0 ? false : true; + } + + + public static String numberGen(int len, int dupCd){ + Random rand = new Random(); + String numStr = ""; //난수가 저장될 변수 + for(int i = 0; i < len; i++){ + //0~9 까지 난수 생성 + + String ran = Integer.toString(rand.nextInt(10)); + if(dupCd == 1){ + //중복 허용시 numStr에 append + numStr += ran; + }else if(dupCd == 2){ + //중복을 허용하지 않을시 중복된 값이 있는지 검사한다 + if(!numStr.contains(ran)){ + //중복된 값이 없으면 numStr에 append + numStr += ran; + }else{ + //생성된 난수가 중복되면 루틴을 다시 실행한다 + i -= 1; + } + } + } + return numStr; + } + + public boolean certifNum(String memberName, String hpno) throws Exception{ + String name = EncryptUtils.encrypt(memberName); + String phone = EncryptUtils.encrypt(hpno); + boolean certifNum = cstmrQuery.certifNum(name , phone); + if(certifNum) { + registerSend(hpno); + } + return certifNum; + } + + public String findUserId(String memberName, String hpno) throws Exception{ + String name = EncryptUtils.encrypt(memberName); + String phone = EncryptUtils.encrypt(hpno); + String resultFindId = cstmrQuery.findUserId(name,phone); + + return resultFindId; + } + + public boolean certifPw(String userId, String hpno) throws Exception{ + String phone = EncryptUtils.encrypt(hpno); + PtyCstmrBas certifNum = cstmrQuery.findUserPw(userId , phone); + boolean result = false; + if(certifNum != null) { + registerSend(hpno); + result = true; + } + return result; + } + + public boolean updatePw(String userId, String hpno, String newPw) throws Exception{ + String phone = EncryptUtils.encrypt(hpno); + PtyCstmrBas certifNum = cstmrQuery.findUserPw(userId , phone); + boolean result = false; + if(certifNum != null) { + String encryptPw = EncryptUtils.sha256Encrypt(newPw); + certifNum.setUserPswd(encryptPw); + certifNum.setPswdUpdtDt(DateUtils.nowDate()); + ptyCstmrBasRepository.save(certifNum); + result = true; + } + return result; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/controller/AcntCstmrController.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/controller/AcntCstmrController.java new file mode 100644 index 00000000..beac1ebf --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/controller/AcntCstmrController.java @@ -0,0 +1,198 @@ +package com.palnet.biz.api.acnt.cstmr.controller; + +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrEmModel; +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrGroupModel; +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrPwModel; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrRqModel; +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrRsModel; +import com.palnet.biz.api.acnt.cstmr.model.AnctCstmerRlModel; +import com.palnet.biz.api.acnt.cstmr.service.AcntCstmrService; +import com.palnet.biz.api.acnt.jwt.model.JwtUserModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRqModel; +import com.palnet.biz.api.anls.hstry.service.AnlsHstryService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.api.ctr.cntrl.service.CtrCntrlService; +import com.palnet.biz.jpa.entity.PtyCstmrBas; +import com.palnet.biz.jpa.entity.PtyCstmrDtl; +import com.palnet.biz.sample.entity.SampleEntity; +import com.palnet.biz.sample.service.SampleService; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.model.GPHistoryModel; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/acnt/cstmr", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "회원관리", description = "회원 관련 API") +public class AcntCstmrController { + + @Autowired + private final AcntCstmrService service; + + @PostMapping(value = "/register") + @ApiOperation(value = "회원 가입") + @Tag(name = "회원관리", description = "회원 관련 API") + public ResponseEntity register(@RequestBody AcntCstmrRqModel rq) { + + AcntCstmrRsModel result; +// log.debug("RQ>>>>>>>>" , rq.toString()); + + try { +// result = service.list(rq); + + result = service.register(rq); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + } + + @GetMapping(value = "/profile/{cstmrSno}") + @ApiOperation(value = "회원 정보") + @Tag(name = "회원관리", description = "회원 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity mypage(@PathVariable Integer cstmrSno){ + List result = null; + + try { + + result = service.list(cstmrSno); + + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + + + return ResponseEntity.ok().body(new SuccessResponse(result)); + } + + @PostMapping(value = "/profile/pswdupdate") + @ApiOperation(value = "회원 패스워드 변경") + @Tag(name = "회원관리", description = "회원 관련 API") + public ResponseEntity passwordupdate(@RequestBody AcntCstmrPwModel rq){ + Map resultMap = new HashMap(); + try { + PtyCstmrBas result = service.updatepas(rq); + resultMap.put("result", result); + + } catch (CustomException e) { + log.error("IGNOE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } catch (Exception e) { + log.error("IGONE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ErrorResponse("Server Error", "-1")); + } + + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + } + + @PostMapping(value = "/profile/pwcheck") + @ApiOperation(value = "회원 기존 패스워드 확인") + @Tag(name = "회원관리", description = "회원 관련 API") + public ResponseEntity extendpsw(@RequestBody Map userPswdMap){ + Map resultMap = new HashMap(); + try { + boolean result = service.extendpsw(userPswdMap.get("userPswd")); + resultMap.put("result", result); + + } catch (CustomException e) { + log.error("IGNOE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } catch (Exception e) { + log.error("IGONE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ErrorResponse("Server Error", "-1")); + } + + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + } + + @PutMapping(value = "/profile/update") + @ApiOperation(value = "회원 정보 변경 (이메일,핸드폰)") + @Tag(name = "회원관리", description = "회원 관련 API") + public ResponseEntity updateEmail(@RequestBody AcntCstmrEmModel rq){ + Map resultMap = new HashMap(); + try { + + PtyCstmrDtl result = service.updateEmail(rq); + resultMap.put("result", result); + + } catch (CustomException e) { + log.error("IGNOE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } catch (Exception e) { + log.error("IGONE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + } + + @PostMapping(value = "/profile/delete/{cstmrSno}") + @ApiOperation(value = "회원 탈퇴") + @Tag(name = "회원관리", description = "회원 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity userDelete(@PathVariable Integer cstmrSno){ + Map resultMap = new HashMap(); + try { + + boolean result = service.userDelete(cstmrSno); + + resultMap.put("result", result); + + } catch (CustomException e) { + log.error("IGNOE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + } +} + + diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrEmModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrEmModel.java new file mode 100644 index 00000000..08078253 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrEmModel.java @@ -0,0 +1,21 @@ +package com.palnet.biz.api.acnt.cstmr.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class AcntCstmrEmModel { + + private String email; + + private Date updateDt; + + private String updateUserId; + + private int cstmrSno; + + private String hpno; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrGroupModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrGroupModel.java new file mode 100644 index 00000000..a78bddb4 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrGroupModel.java @@ -0,0 +1,17 @@ +package com.palnet.biz.api.acnt.cstmr.model; + +import lombok.Data; + +@Data +public class AcntCstmrGroupModel { + + private Integer cstmrSno; + private String userId; + private String groupId; + private String groupNm; + private String groupAuthCd; + private Integer arcrftSno; + private String idntfNum; + private String createUserId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrPwModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrPwModel.java new file mode 100644 index 00000000..400f98f6 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrPwModel.java @@ -0,0 +1,17 @@ +package com.palnet.biz.api.acnt.cstmr.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class AcntCstmrPwModel { + + private Date pswdupdtDt; + + private String userPswd; + + private String newPswd; + + private String newPswdConfirm; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrRqModel.java new file mode 100644 index 00000000..3d395dd6 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrRqModel.java @@ -0,0 +1,48 @@ +package com.palnet.biz.api.acnt.cstmr.model; + +import lombok.Data; + +@Data +public class AcntCstmrRqModel{ + + private String cstrmDivCd; + + private String cstrmStatusCd; + + private String userId; + + private String authId; + + private String siteCode; + + private String memberDivCd; + + private String userPswd; + + private String ipinDi; + + private String ipinCi; + + private String joinCrtfyCd; + + private String cntryCd; + + private String genderCd; + + private String memberName; + + private String brthdyDate; + + private String email; + + private String hpno; + + private String clncd; + + private AnctCstmrTermsModel[] terms; + + private String trmnlId; + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrRsModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrRsModel.java new file mode 100644 index 00000000..ff18e868 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AcntCstmrRsModel.java @@ -0,0 +1,13 @@ +package com.palnet.biz.api.acnt.cstmr.model; + +import lombok.Data; + +@Data +public class AcntCstmrRsModel{ + + private int errCode; // 1 : 성공 , -1 : 가입된 ID 존재 , -2 : 동일한 이메일 존재 , -3 동일한 휴대폰번호 존재 + + private String loginId; // 가입 성공된 ID 전달 + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AnctCstmerRlModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AnctCstmerRlModel.java new file mode 100644 index 00000000..69fbb38f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AnctCstmerRlModel.java @@ -0,0 +1,28 @@ +package com.palnet.biz.api.acnt.cstmr.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class AnctCstmerRlModel { + + private String memberName; + + private Date brthdyDate; + + private String genderCd; + + private String cntryCd; + + private String email; + + private String hpno; + + private String userId; + + private Date updateDt; + + private String updateuserId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AnctCstmrTermsModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AnctCstmrTermsModel.java new file mode 100644 index 00000000..a9d3aec7 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/model/AnctCstmrTermsModel.java @@ -0,0 +1,9 @@ +package com.palnet.biz.api.acnt.cstmr.model; + +import lombok.Data; + +@Data +public class AnctCstmrTermsModel { + private int termsSno; + private String agreeYn; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/service/AcntCstmrService.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/service/AcntCstmrService.java new file mode 100644 index 00000000..69bcee22 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/cstmr/service/AcntCstmrService.java @@ -0,0 +1,321 @@ +package com.palnet.biz.api.acnt.cstmr.service; + +import java.util.List; + +import javax.persistence.EntityManagerFactory; + +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrEmModel; +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrPwModel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrRqModel; +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrRsModel; +import com.palnet.biz.api.acnt.cstmr.model.AnctCstmerRlModel; +import com.palnet.biz.api.acnt.cstmr.model.AnctCstmrTermsModel; +import com.palnet.biz.api.acnt.jwt.model.JwtGroupModel; +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.jpa.entity.PtyCstmrBas; +import com.palnet.biz.jpa.entity.PtyCstmrDtl; +import com.palnet.biz.jpa.entity.PtyCstmrGroup; +import com.palnet.biz.jpa.entity.PtyGroupBas; +import com.palnet.biz.jpa.entity.PtyTermsAgreeTxn; +import com.palnet.biz.jpa.repository.pty.PtyCstmrBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrDtlRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrGroupRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrQueryRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyTermsAgreeTxnRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.DateUtils; +import com.palnet.comn.utils.EncryptUtils; +import com.palnet.comn.utils.HttpUtils; + +import lombok.extern.log4j.Log4j2; + +@Service +@Log4j2 +public class AcntCstmrService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + +// @Autowired +// private CtrCntrlBasRepository ctrCntrlBasRepository; + + @Autowired + private PtyCstmrQueryRepository query; + + @Autowired + private PtyCstmrBasRepository ptyCstmrBasRepository; + + @Autowired + private PtyCstmrDtlRepository ptyCstmrDtlRepository; + + @Autowired + private PtyCstmrGroupRepository ptyCstmrGroupRepository; + + @Autowired + private PtyGroupBasRepository ptyGroupBasRepository; + + @Autowired + private PtyTermsAgreeTxnRepository ptyTermsAgreeTxnRepository; + + @Autowired + private EntityManagerFactory emf; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + /** + * + * + * @param rq + * @return + */ + @Transactional + public AcntCstmrRsModel register(AcntCstmrRqModel rq) throws Exception{ + +// logger.debug("ddddddd>>>>" + JsonUtils.toJson(rq)); +// logger.debug("ddddddd>>>>" + rq.getBrthdyDate()); + AcntCstmrRsModel rs = new AcntCstmrRsModel(); + boolean isUserIdFind = false; + try { + + //사전 체크. 동일한 ID 존재 여부 확인 + isUserIdFind = query.findCstmrByUserId(rq.getUserId()); + if(isUserIdFind) { + rs.setErrCode(-1); + return rs; + } + + rq.setHpno(rq.getHpno().replaceAll("-", "")); + //처리 1. 민감정보 암호화 처리(비밀번호 , 이름 , 휴대폰번호 , 이메일) + rq.setUserPswd(EncryptUtils.sha256Encrypt(rq.getUserPswd())); +// rq.setMemberName(EncryptUtils.encrypt(rq.getMemberName())); + rq.setHpno(EncryptUtils.encrypt(rq.getHpno())); + rq.setEmail(EncryptUtils.encrypt(rq.getEmail())); + rq.setBrthdyDate(rq.getBrthdyDate().replaceAll("-", "")); + + + //처리 2. 마스터 정보 저장 + PtyCstmrBas basEntity = this.savePtyCstmrBas(rq); + if(basEntity == null) { + throw new CustomException(ErrorCode.INTERNAL_SERVER_ERROR); + } + + //처리 3. 상세 정보 저장 + this.savePtyCstmrDtl(rq ,basEntity ); + + //처리 4. 약관 동의 정보 저장 + if(rq.getTerms() != null && rq.getTerms().length > 0) { + for(AnctCstmrTermsModel agree : rq.getTerms()) { + this.savePtyTermsAgreeTxn(agree , basEntity); + } + } + + //성공 파람 담기 + if(basEntity != null) { + rs.setErrCode(1); + rs.setLoginId(basEntity.getUserId()); + } + + }catch(Exception e) { + log.error("IGNORE : {}", e); + rs.setErrCode(-2); + return rs; + } + + return rs; + } + + public PtyCstmrBas savePtyCstmrBas(AcntCstmrRqModel rq) throws Exception{ + + + PtyCstmrBas basEntity = new PtyCstmrBas(); + basEntity.setCstmrDivCd(rq.getCstrmDivCd()); + basEntity.setCstmrStatusCd(rq.getCstrmStatusCd()); + basEntity.setUserId(rq.getUserId()); + basEntity.setAuthId(rq.getAuthId()); + basEntity.setSiteCode(rq.getSiteCode()); + basEntity.setMemberDivCd(rq.getMemberDivCd()); + basEntity.setUserPswd(rq.getUserPswd()); + basEntity.setJoinDt(DateUtils.nowDate()); + basEntity.setJoinIp(HttpUtils.getRequestIp()); + basEntity.setTrmnlId(rq.getTrmnlId()); + + return ptyCstmrBasRepository.save(basEntity); + + } + + public PtyCstmrDtl savePtyCstmrDtl(AcntCstmrRqModel rq , PtyCstmrBas basEntity) throws Exception{ + PtyCstmrDtl dtlEntity = new PtyCstmrDtl(); + dtlEntity.setCstmrSno(basEntity.getCstmrSno()); + dtlEntity.setIpinCi(rq.getIpinCi()); + dtlEntity.setIpinDi(rq.getIpinDi()); + dtlEntity.setJoinCrtfyCd(rq.getJoinCrtfyCd()); + dtlEntity.setCntryCd(rq.getCntryCd()); + dtlEntity.setGenderCd(rq.getGenderCd()); + dtlEntity.setMemberName(rq.getMemberName()); + dtlEntity.setBrthdyDate(DateUtils.stringToDate(rq.getBrthdyDate())); + dtlEntity.setEmail(rq.getEmail()); + dtlEntity.setHpno(rq.getHpno()); + dtlEntity.setClncd(rq.getClncd()); + dtlEntity.setUpdateDt(DateUtils.nowDate()); + dtlEntity.setUpdateUserId(rq.getUserId()); + + return ptyCstmrDtlRepository.save(dtlEntity); + + } + + public PtyTermsAgreeTxn savePtyTermsAgreeTxn(AnctCstmrTermsModel agree , PtyCstmrBas basEntity) throws Exception{ + PtyTermsAgreeTxn agreeEntity = new PtyTermsAgreeTxn(); + agreeEntity.setCstmrSno(basEntity.getCstmrSno()); + agreeEntity.setProcIp(HttpUtils.getRequestIp()); + agreeEntity.setTermsSno(agree.getTermsSno()); + agreeEntity.setUpdateDt(DateUtils.nowDate()); + agreeEntity.setUpdateUserId(basEntity.getUserId()); + agreeEntity.setAgreeYn(agree.getAgreeYn()); + if(agree.getAgreeYn().equals("Y")) { + agreeEntity.setAgreeDt(DateUtils.nowDate()); + + } + + return ptyTermsAgreeTxnRepository.save(agreeEntity); + + } + + public List list(int cstmrSno) { + + List resultList = query.list(cstmrSno); + + for(AnctCstmerRlModel model : resultList) { + model.setEmail(EncryptUtils.decrypt(model.getEmail())); +// model.setMemberName(EncryptUtils.decrypt(model.getMemberName())); + model.setHpno(EncryptUtils.decrypt(model.getHpno())); + } + + return resultList; + } + + + public PtyCstmrBas updatepas(AcntCstmrPwModel rq) { + // 1. 토큰 유저 정보 불러오기 + Integer userId = jwtTokenUtil.getCstmrSnoByToken(); + + // 2. DB의 유저정보 조회 + PtyCstmrBas userEntity = ptyCstmrBasRepository.findById(userId).orElse(null); + + // 5. 새로운 비밀번호 검증 + if(!rq.getNewPswd().equals(rq.getNewPswdConfirm())) { + // 5.e 새로운 비밀번호 일치하지 않으면 예외처리 + throw new CustomException(ErrorCode.FAIL); //임시...수정필요 + } + + // 6. 새로운 패스워드 암호화 + String encryptNewPwd = EncryptUtils.sha256Encrypt(rq.getNewPswd()); + + // 7. 유저 정보 저장 + userEntity.setUserPswd(encryptNewPwd); + userEntity.setPswdUpdtDt(DateUtils.nowDate()); + + PtyCstmrBas updateUserEntity = ptyCstmrBasRepository.save(userEntity); + + return updateUserEntity; + } + + public boolean extendpsw(String userPswd){ + boolean result = false; + // 1. 토큰 유저 정보 불러오기 + Integer userId = jwtTokenUtil.getCstmrSnoByToken(); + + // 2. DB의 유저정보 조회 +// AcntCstmrRqModel result = query.findpassword(userId); + PtyCstmrBas userEntity = ptyCstmrBasRepository.findById(userId).orElse(null); + + // 3. RQ의 유저 패스워드를 암호화 처리 + if(userPswd != null && !userPswd.isEmpty()){ + userPswd = EncryptUtils.sha256Encrypt(userPswd); + } + + // 4. RQ의 암호화한 패스워드와 DB에서 조회한 유저의 패스워드랑 비교 + if(!userPswd.equals(userEntity.getUserPswd())) { + log.info("USERPSWD 비밀번호 : {}, DB 비밀번호 : {}", userPswd, userEntity.getUserPswd()); + // 4.e 일치하지 않으면 예외처리 (패스워드 불일치) + + throw new CustomException(ErrorCode.FAIL); // 임시,, 수정해야함 + } + userEntity.setUserPswd(userPswd); + + + PtyCstmrBas extendsPwd = ptyCstmrBasRepository.save(userEntity); + result=true; + + return result; + } + + public PtyCstmrDtl updateEmail(AcntCstmrEmModel rq) { + Integer cstmrSno = jwtTokenUtil.getCstmrSnoByToken(); + String userId = jwtTokenUtil.getUserIdByToken(); + String newEmail = EncryptUtils.encrypt(rq.getEmail()); + String newHpno = EncryptUtils.encrypt(rq.getHpno()); + + PtyCstmrDtl userEntity = ptyCstmrDtlRepository.findById(cstmrSno).orElse(null); + + userEntity.setEmail(newEmail); + userEntity.setUpdateDt(DateUtils.nowDate()); + userEntity.setUpdateUserId(userId); + userEntity.setHpno(newHpno); + + PtyCstmrDtl updateEmailEntity = ptyCstmrDtlRepository.save(userEntity); + + return updateEmailEntity; + } + + public boolean userDelete(int cstmrSno) { + + List groupInfo = jwtTokenUtil.getGroupAuthByToken(); + for(JwtGroupModel group : groupInfo) { +// if(group.getGroupAuthCd().equals("CREATER")) { + if(group.getGroupAuthCd().equals("MASTER")) { + PtyGroupBas groupEntity = ptyGroupBasRepository.findByGroupId(group.getGroupId()); + if(!(groupEntity == null)) { + groupEntity.setUseYn("N"); + ptyGroupBasRepository.save(groupEntity); + } + List cstmrEntity = ptyCstmrGroupRepository.changeGroupJoinYn(group.getGroupId()); + if(!(cstmrEntity == null)) { + for(PtyCstmrGroup cstmr : cstmrEntity) { + cstmr.setJoinYn("N"); + ptyCstmrGroupRepository.save(cstmr); + } + } + } + List AprvlEntity = ptyCstmrGroupRepository.changeGroupAprvlYn(cstmrSno); + if(!(AprvlEntity == null)) { + for(PtyCstmrGroup Aprvl : AprvlEntity) { + Aprvl.setAprvlYn("N"); + Aprvl.setAprvlDt(null); + ptyCstmrGroupRepository.save(Aprvl); + } + PtyCstmrGroup cstmrEntity = ptyCstmrGroupRepository.findGroupId(group.getGroupId(), cstmrSno); + if(!(cstmrEntity == null)) { + cstmrEntity.setJoinYn("N"); + ptyCstmrGroupRepository.save(cstmrEntity); + } + } + } + PtyCstmrBas userEntity = ptyCstmrBasRepository.findByUserGroupId(cstmrSno); + userEntity.setCstmrStatusCd("W"); + userEntity.setCstmrStatusCngDt(DateUtils.nowDate()); + ptyCstmrBasRepository.save(userEntity); + + boolean result = true; + return result; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/controller/JwtAuthenticationController.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/controller/JwtAuthenticationController.java new file mode 100644 index 00000000..8bb65185 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/controller/JwtAuthenticationController.java @@ -0,0 +1,151 @@ +package com.palnet.biz.api.acnt.jwt.controller; + +import java.util.HashMap; +import java.util.Map; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.acnt.jwt.model.JwtProfileRsModel; +import com.palnet.biz.api.acnt.jwt.model.JwtRqModel; +import com.palnet.biz.api.acnt.jwt.model.JwtRsModel; +import com.palnet.biz.api.acnt.jwt.model.JwtUserModel; +import com.palnet.biz.api.acnt.jwt.service.JwtService; +import com.palnet.biz.api.acnt.jwt.service.JwtUserDetailsService; +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.jpa.entity.PtyCstmrBas; +import com.palnet.comn.code.RSErrorCode; +import com.palnet.comn.utils.EncryptUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@RestController +@RequiredArgsConstructor +@Log4j2 +@RequestMapping(value = "/api/acnt/jwt", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "JWT 토큰 이용", description = "JWT 토큰 관련 API") +public class JwtAuthenticationController { + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + @Autowired + private JwtUserDetailsService userDetailsService; + + + @Autowired + private JwtService service; + + @PostMapping(value = "/login") + @ApiOperation(value = "로그인") + @Tag(name = "JWT 토큰 이용", description = "JWT 토큰 관련 API") + public ResponseEntity createAuthenticationToken(@RequestBody JwtRqModel authenticationRequest) throws Exception { + + Map resultMap = service.loginProcess(authenticationRequest); + + int loginError = (int) resultMap.get("loginError"); + + if(loginError < 0) { + + String errorMessage = (String) resultMap.get("errorMessage"); + return ResponseEntity.status(HttpStatus.OK) + + .body(new ErrorResponse(errorMessage, loginError + "")); // 계정 사용하지 못함 + }else { + + JwtRsModel result = (JwtRsModel) resultMap.get("result"); + return ResponseEntity.ok().body(new SuccessResponse(result)); + } + + + } + + @GetMapping(value = "/profile/{cstmrSno}") + @ApiOperation(value = "로그인한 회원의 정보") + @Tag(name = "JWT 토큰 이용", description = "JWT 토큰 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity proflie(@PathVariable Integer cstmrSno) throws Exception{ + + JwtProfileRsModel result = service.profile(cstmrSno); + if(result == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.DATA_NOTFOUNT)); + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + } + + + @PostMapping(value = "/refresh") + @Tag(name = "JWT 토큰 이용", description = "JWT 토큰 관련 API") +// public ResponseEntity refresh(@RequestParam("cstmrSno") int cstmrSno , @RequestParam("refreshToken") String refreshToken) throws Exception{ + public ResponseEntity refresh(@RequestBody Map body) throws Exception{ + + + //입력값 검증 + if(body.get("cstmrSno") == null || body.get("refreshToken") == null || !(body.get("cstmrSno") instanceof Integer)) { + + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + int cstmrSno = (int)body.get("cstmrSno"); + String refreshToken = (String)body.get("refreshToken"); + + + + JwtRsModel result = service.findRefreshtoken(cstmrSno, refreshToken); +// JwtRsModel result = null; + + if(result ==null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.DATA_NOTFOUNT)); + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + } + + @GetMapping(value = "/logout/{cstmrSno}") + @ApiOperation(value = "로그아웃 한 회원의 정보") + @Tag(name = "JWT 토큰 이용", description = "JWT 토큰 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity logout(@PathVariable Integer cstmrSno) throws Exception{ + +// if(cstmrSno == null || !(body.get("cstmrSno") instanceof Integer)) { +// return ResponseEntity.status(HttpStatus.OK) +// .body(new ErrorResponse(RSErrorCode.ER_PARAM)); +// } +// int cstmrSno = (int)body.get("cstmrSno"); + + + PtyCstmrBas bas = service.logoutProcess(cstmrSno); + + if(bas == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.DATA_NOTFOUNT)); + } + + return ResponseEntity.ok().body(new SuccessResponse(RSErrorCode.SUCCESS)); + } + + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/filter/JwtAuthenticationEntryPoint.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/filter/JwtAuthenticationEntryPoint.java new file mode 100644 index 00000000..815b81bd --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/filter/JwtAuthenticationEntryPoint.java @@ -0,0 +1,25 @@ +package com.palnet.biz.api.acnt.jwt.filter; + +import java.io.IOException; +import java.io.Serializable; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +//허가되지 않은 사용자라면, 접근 불가 메세지를 띄워 리소스 정보획득을 못하게 막아줍니다. +@Component +public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable { + + private static final long serialVersionUID = -7858869558953243875L; + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, + AuthenticationException authException) throws IOException { + + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/filter/JwtRequestFilter.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/filter/JwtRequestFilter.java new file mode 100644 index 00000000..e74300a3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/filter/JwtRequestFilter.java @@ -0,0 +1,96 @@ +package com.palnet.biz.api.acnt.jwt.filter; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import com.palnet.biz.api.acnt.jwt.service.JwtUserDetailsService; +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; + +import io.jsonwebtoken.ExpiredJwtException; +import lombok.extern.log4j.Log4j2; + +//프론트엔드에서 매순간 request를 요청 할 때마다 이 필터를 먼저 거침 +@Component +@Log4j2 +public class JwtRequestFilter extends OncePerRequestFilter { + + @Autowired + private JwtUserDetailsService jwtUserDetailsService; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + @Value("${spring.jwt.prefix}") + private String JWT_PREFIX; + + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException { + +// logger.info("access request uri :: " + request.getRequestURI()); +// logger.info("access remote host :: " + request.getRemoteHost()); + + final String requestTokenHeader = request.getHeader("Authorization"); + + String username = null; + String jwtToken = null; + // JWT Token is in the form "Bearer token". Remove Bearer word and get + // only the Token +// log.debug("=============================================================================="); +// log.debug(requestTokenHeader); +// log.debug("=============================================================================="); + + if (requestTokenHeader != null && requestTokenHeader.startsWith(JWT_PREFIX)) { + jwtToken = requestTokenHeader.substring(7); + try { + username = jwtTokenUtil.getUsernameFromToken(jwtToken); + } catch (IllegalArgumentException e) { + log.warn("Unable to get JWT Token"); + } catch (ExpiredJwtException e) { + log.warn("JWT Token has expired"); + } + } else { +// logger.debug(">>>" + requestTokenHeader); +// logger.warn("JWT Token is Error "); +// logger.warn("Request URI : "+ request.getRequestURI()); + } +// log.debug(">>>>>>>>>>" + username); + + // Once we get the token validate it. + if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { + + + UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username); + + // if token is valid configure Spring Security to manually set + // authentication + if (jwtTokenUtil.validateToken(jwtToken, userDetails)) { + + UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities()); + usernamePasswordAuthenticationToken + .setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + // After setting the Authentication in the context, we specify + // that the current user is authenticated. So it passes the + // Spring Security Configurations successfully. + SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); + } + } + chain.doFilter(request, response); + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtGroupModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtGroupModel.java new file mode 100644 index 00000000..cb5c5f7a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtGroupModel.java @@ -0,0 +1,9 @@ +package com.palnet.biz.api.acnt.jwt.model; + +import lombok.Data; + +@Data +public class JwtGroupModel { + private String groupId; + private String groupAuthCd; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtProfileRsModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtProfileRsModel.java new file mode 100644 index 00000000..cf902cef --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtProfileRsModel.java @@ -0,0 +1,19 @@ +package com.palnet.biz.api.acnt.jwt.model; + +import lombok.Data; + +@Data +public class JwtProfileRsModel { + private int cstmrSno; + + private String authId; + + private String siteCode; + + private String userId; + + private String memberName; + + private String trmnlId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtRqModel.java new file mode 100644 index 00000000..7c40b46a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtRqModel.java @@ -0,0 +1,20 @@ +package com.palnet.biz.api.acnt.jwt.model; + +import java.io.Serializable; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class JwtRqModel implements Serializable { + + private static final long serialVersionUID = 5926468583005150707L; + + private String userId; + private String userPswd; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtRsModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtRsModel.java new file mode 100644 index 00000000..d4fb3fe7 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtRsModel.java @@ -0,0 +1,21 @@ +package com.palnet.biz.api.acnt.jwt.model; + +import java.io.Serializable; + +import lombok.Data; + +@Data +public class JwtRsModel implements Serializable { + + private String accessToken ; + + private String refreshToken; + + private String userId; + + private Integer cstmrSno; + + private String auth; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtUserModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtUserModel.java new file mode 100644 index 00000000..570b4fd1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/model/JwtUserModel.java @@ -0,0 +1,98 @@ +package com.palnet.biz.api.acnt.jwt.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import javax.persistence.*; +import java.util.*; + +@Entity +@Data +@NoArgsConstructor +@AllArgsConstructor +public class JwtUserModel implements UserDetails { + + @Id + @GeneratedValue(strategy= GenerationType.IDENTITY) + @Column(name = "CSTMR_SNO", unique = true) + private Integer cstmrSno; + + @Column(name = "USER_ID", unique = true) + private String userId; + + @Column(name = "USER_PSWD") + private String userPswd; + + @Column(name = "SITE_CODE") + private String siteCode; + + @Column(name = "AUTH_ID") + private String auth; + + @Column(name = "CSTMR_STATUS_CD") + private String cstmrStatusCd; + + @Transient + private List group; + + + // 사용자의 권한을 콜렉션 형태로 반환 + // 단, 클래스 자료형은 GrantedAuthority를 구현해야함 + @Override + public Collection getAuthorities() { + Set roles = new HashSet<>(); + for (String role : auth.split(",")) { + roles.add(new SimpleGrantedAuthority(role)); + } + return roles; + } + + // 사용자의 id를 반환 (unique한 값) + @Override + public String getUsername() { + return userId; + } + + // 사용자의 password를 반환 + @Override + public String getPassword() { + return userPswd; + } + + // 계정 만료 여부 반환 + @Override + public boolean isAccountNonExpired() { + // 만료되었는지 확인하는 로직 + return true; // true -> 만료되지 않았음 + } + + // 계정 잠금 여부 반환 + @Override + public boolean isAccountNonLocked() { + // 계정 잠금되었는지 확인하는 로직 + if(cstmrStatusCd.equals("A")) + return true; + else + return false; +// return true; // true -> 잠금되지 않았음 + } + + // 패스워드의 만료 여부 반환 + @Override + public boolean isCredentialsNonExpired() { + // 패스워드가 만료되었는지 확인하는 로직 + return true; // true -> 만료되지 않았음 + } + + // 계정 사용 가능 여부 반환 + @Override + public boolean isEnabled() { + // 계정이 사용 가능한지 확인하는 로직 + return true; // true -> 사용 가능 + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/service/JwtService.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/service/JwtService.java new file mode 100644 index 00000000..66e280f4 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/service/JwtService.java @@ -0,0 +1,237 @@ +package com.palnet.biz.api.acnt.jwt.service; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.acnt.cstmr.service.AcntCstmrService; +import com.palnet.biz.api.acnt.jwt.model.JwtProfileRsModel; +import com.palnet.biz.api.acnt.jwt.model.JwtRqModel; +import com.palnet.biz.api.acnt.jwt.model.JwtRsModel; +import com.palnet.biz.api.acnt.jwt.model.JwtUserModel; +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.PtyCstmrBas; +import com.palnet.biz.jpa.entity.PtyCstmrConectHist; +import com.palnet.biz.jpa.repository.pty.PtyCstmrBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrConectHistRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrQueryRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.DateUtils; +import com.palnet.comn.utils.EncryptUtils; +import com.palnet.comn.utils.HttpUtils; + +import lombok.extern.log4j.Log4j2; + +@Service +@Log4j2 +public class JwtService { + @Autowired + private PtyCstmrBasRepository ptyCstmrBasRepository; + + @Autowired + private PtyCstmrConectHistRepository ptyCstmrConectHistRepository; + + @Autowired + private JwtUserDetailsService userDetailsService; + + @Autowired + private PtyCstmrQueryRepository query ; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + /** + * 로그인 처리 + * @param rq + * @return + */ + public Map loginProcess(JwtRqModel rq) throws Exception{ + + int loginError = 1; // -100 : 아이디/비밀번호가 없습니다 , -101 : 계정정보를 찾을수 없습니다 , -102 : 비밀번호가 잘못 되었습니다 , -103 : 계정을 사용할수 없습니다. + + Map resultMap = new HashMap(); + + //입력값 검증 처리 + if(StringUtils.isEmpty(rq.getUserId()) || StringUtils.isEmpty(rq.getUserPswd())) { + loginError = -100; + } + + JwtUserModel userDetails = (JwtUserModel)userDetailsService + .loadUserByUsername(rq.getUserId()); + + + //계정이 없는경우 + if(userDetails == null) { + loginError = -101; + }else{ + String password = EncryptUtils.sha256Encrypt(rq.getUserPswd()); + + //비밀번호 검증 처리 + if (!userDetails.getPassword().equals(password)) { + loginError = -102; + + } + + //계정 검증로직 + if(!userDetails.isAccountNonLocked() || !userDetails.isAccountNonExpired() || !userDetails.isEnabled() || !userDetails.isCredentialsNonExpired()) { + loginError = -103; + + } + } + + + if(loginError < 0) { + + String errorMessage = ""; + if(loginError == -100) { + errorMessage = "Please parameter Check"; + }else if(loginError == -101) { + errorMessage = "Account not found"; + + }else if(loginError == -102) { + errorMessage = "Password does not match"; + }else if(loginError == -103) { + errorMessage = "Account is unavailable"; + } + //실패 이력 저장 + //cstmrSno , String loginYn , String errorCode + if(userDetails != null) { + this.historySave(userDetails.getCstmrSno(), "N", loginError+""); + } + + resultMap.put("loginError", loginError); + resultMap.put("errorMessage", errorMessage); + + return resultMap; + + }else { + + String accessToken = jwtTokenUtil.generateToken(userDetails); + String refreshToken = jwtTokenUtil.generateRefreshToken(userDetails); + + JwtRsModel result = new JwtRsModel(); + result.setAccessToken(accessToken); + result.setRefreshToken(refreshToken); + result.setAuth(userDetails.getAuth()); + result.setUserId(userDetails.getUserId()); + result.setCstmrSno(userDetails.getCstmrSno()); + //토큰 저장 처리 + log.debug("========= refresh>>>>" + refreshToken); + this.refreshTokenSave(userDetails.getCstmrSno(), refreshToken); + + //성공이력 저장 + this.historySave(userDetails.getCstmrSno(), "Y", loginError+""); + + resultMap.put("loginError", loginError); + resultMap.put("errorMessage", ""); + resultMap.put("result", result); + + return resultMap; + } + + } + + public PtyCstmrBas logoutProcess(int cstmrSno) throws Exception{ + + Optional optional = ptyCstmrBasRepository.findById(cstmrSno); + if (optional.isPresent()) { + PtyCstmrBas entity = optional.get(); + entity.setRfrshToken(""); + return ptyCstmrBasRepository.save(entity); + }else { + return null; + } + + } + + + /** + * 로그인 이력 저장 + * @param cstmrSno + * @param loginYn + * @param errorCode + * @return + * @throws Exception + */ + public PtyCstmrConectHist historySave(int cstmrSno , String loginYn , String errorCode) throws Exception{ + String conectIp = HttpUtils.getRequestIp(); + + PtyCstmrConectHist entity = new PtyCstmrConectHist(); + entity.setCstmrSno(cstmrSno); + entity.setConectSucesYn(loginYn); + entity.setConectErrorCd(errorCode); + entity.setConectIp(conectIp); + entity.setConectDt(DateUtils.nowDate()); + return ptyCstmrConectHistRepository.save(entity); + } + + /** + * refresh Token 저장 처리 + * @param cstmrSno + * @param refreshToken + * @return + * @throws Exception + */ + public PtyCstmrBas refreshTokenSave(int cstmrSno , String refreshToken) throws Exception{ + + Optional optional = ptyCstmrBasRepository.findById(cstmrSno); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + PtyCstmrBas entity = optional.get(); + entity.setRfrshToken(refreshToken); + + return ptyCstmrBasRepository.save(entity); + } + + /** + * 프로필 조회 + * @param cstmrSno + * @return + * @throws Exception + */ + public JwtProfileRsModel profile(int cstmrSno) throws Exception{ + JwtProfileRsModel model = query.findUserProfile(cstmrSno); +// model.setMemberName(EncryptUtils.decrypt(model.getMemberName())); + + return model; + } + + /** + * token 만료시 refresh 토큰으로 재검색 + * @param cstmrSno + * @param refreshToken + * @return + */ + public JwtRsModel findRefreshtoken(int cstmrSno , String refreshToken) { + JwtUserModel userDetails = query.findRefreshtoken(cstmrSno, refreshToken); + + if(userDetails == null) { + return null; + } + + String accessToken = jwtTokenUtil.generateToken(userDetails); + + JwtRsModel result = new JwtRsModel(); + result.setAccessToken(accessToken); + result.setRefreshToken(refreshToken); + result.setAuth(userDetails.getAuth()); + result.setUserId(userDetails.getUserId()); + result.setCstmrSno(userDetails.getCstmrSno()); + + return result; + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/service/JwtUserDetailsService.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/service/JwtUserDetailsService.java new file mode 100644 index 00000000..b7cc08a3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/service/JwtUserDetailsService.java @@ -0,0 +1,41 @@ +package com.palnet.biz.api.acnt.jwt.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.acnt.jwt.model.JwtUserModel; +import com.palnet.biz.jpa.repository.pty.PtyCstmrBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrQueryRepository; +import com.palnet.comn.utils.JsonUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Service +@RequiredArgsConstructor +@Log4j2 +public class JwtUserDetailsService implements UserDetailsService{ + + @Autowired + private PtyCstmrQueryRepository query ; + + @Autowired + private PtyCstmrBasRepository repository; + + + + @Override + public JwtUserModel loadUserByUsername(String username){ + + JwtUserModel model = query.findUserPassword(username); +// log.debug("jwtUser>>>>" + JsonUtils.toJson(model)); + if(model == null) { + return null; + }else { + return model; + } + + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/utils/JwtTokenUtil.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/utils/JwtTokenUtil.java new file mode 100644 index 00000000..3a6019df --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/jwt/utils/JwtTokenUtil.java @@ -0,0 +1,166 @@ +package com.palnet.biz.api.acnt.jwt.utils; + +import com.palnet.biz.api.acnt.jwt.model.JwtGroupModel; +import com.palnet.biz.api.acnt.jwt.model.JwtUserModel; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.io.Serializable; +import java.util.*; +import java.util.function.Function; + +@Component +@Log4j2 +public class JwtTokenUtil implements Serializable { + + private static final long serialVersionUID = -2550185165626007488L; + + public static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60; // 5시간 +// public static final long JWT_TOKEN_VALIDITY = 10; // 10초 + public static final long JWT_REFRESH_TOKEN_VALIDTY = 21* 24 * 60 * 60; //21일 + + + @Value("${spring.jwt.secret}") + private String secret; + @Value("${spring.jwt.prefix}") + private String JWT_PREFIX; + + //retrieve username from jwt token + // jwt token으로부터 username을 획득한다. + public String getUsernameFromToken(String token) { + return getClaimFromToken(token, Claims::getSubject); + } + + //retrieve expiration date from jwt token + // jwt token으로부터 만료일자를 알려준다. + public Date getExpirationDateFromToken(String token) { + return getClaimFromToken(token, Claims::getExpiration); + } + + public T getClaimFromToken(String token, Function claimsResolver) { + final Claims claims = getAllClaimsFromToken(token); + return claimsResolver.apply(claims); + } + //for retrieveing any information from token we will need the secret key + private Claims getAllClaimsFromToken(String token) { + return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } + + //check if the token has expired + // 토큰이 만료되었는지 확인한다. + private Boolean isTokenExpired(String token) { + final Date expiration = getExpirationDateFromToken(token); +// log.debug(">>>" + expiration); + return expiration.before(new Date()); + } + + //generate token for user + // 유저를 위한 토큰을 발급해준다. + public String generateToken(JwtUserModel userDetails) { + Map claims = new HashMap<>(); + claims.put("userId", userDetails.getUserId()); + claims.put("cstmrSno", userDetails.getCstmrSno()); + claims.put("auth", userDetails.getAuth()); + claims.put("group", userDetails.getGroup()); + return doGenerateToken(claims, userDetails.getUsername()); + } + + + public String generateRefreshToken(JwtUserModel userDetails) { + Map claims = new HashMap<>(); + claims.put("userId", userDetails.getUserId()); + claims.put("cstmrSno", userDetails.getCstmrSno()); + return doGenerateRefreshToken(claims, userDetails.getUsername()); + } + + + //while creating the token - + //1. Define claims of the token, like Issuer, Expiration, Subject, and the ID + //2. Sign the JWT using the HS512 algorithm and secret key. + //3. According to JWS Compact Serialization(https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-3.1) + // compaction of the JWT to a URL-safe string + private String doGenerateToken(Map claims, String subject) { + + return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + } + + private String doGenerateRefreshToken(Map claims , String subject) { + return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + JWT_REFRESH_TOKEN_VALIDTY * 1000)) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + } + + //validate token + public Boolean validateToken(String token, UserDetails userDetails) { + final String username = getUsernameFromToken(token); + return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); + } + + public String getUserIdByToken() { + HttpServletRequest rq = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String token = rq.getHeader("Authorization"); + + if(token == null || "".equals(token)) return null; + + token = token.substring(JWT_PREFIX.length()).trim(); + String userId = getUsernameFromToken(token); + + return userId; + } + public Integer getCstmrSnoByToken() { + HttpServletRequest rq = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String token = rq.getHeader("Authorization"); + + if(token == null || "".equals(token)) return null; + + token = token.substring(JWT_PREFIX.length()).trim(); + Claims payload = getAllClaimsFromToken(token); + Integer cstmrSno = payload.get("cstmrSno",Integer.class); + + return cstmrSno; + } + + public List getGroupAuthByToken() { + HttpServletRequest rq = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String token = rq.getHeader("Authorization"); + + if(token == null || "".equals(token)) return null; + + token = token.substring(JWT_PREFIX.length()).trim(); + Claims payload = getAllClaimsFromToken(token); + List groupList = payload.get("group", ArrayList.class); + List r = new ArrayList<>(); + + if(groupList!=null) { + for(LinkedHashMap map : groupList){ + JwtGroupModel model = new JwtGroupModel(); + model.setGroupId(map.get("groupId")); + model.setGroupAuthCd(map.get("groupAuthCd")); + r.add(model); + } + } + return r; + } + + public String getUserAuthByToken() { + HttpServletRequest rq = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String token = rq.getHeader("Authorization"); + + if(token == null || "".equals(token)) return null; + + token = token.substring(JWT_PREFIX.length()).trim(); + Claims payload = getAllClaimsFromToken(token); + + return payload.get("auth", String.class); + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/controller/AcntTermsController.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/controller/AcntTermsController.java new file mode 100644 index 00000000..11a30aa2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/controller/AcntTermsController.java @@ -0,0 +1,74 @@ +package com.palnet.biz.api.acnt.terms.controller; + +import java.util.List; + +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.acnt.terms.model.AcntTermsRqModel; +import com.palnet.biz.api.acnt.terms.model.AcntTermsRsModel; +import com.palnet.biz.api.acnt.terms.service.AcntTermsService; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRqModel; +import com.palnet.biz.api.anls.hstry.service.AnlsHstryService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.api.ctr.cntrl.service.CtrCntrlService; +import com.palnet.biz.sample.entity.SampleEntity; +import com.palnet.biz.sample.service.SampleService; +import com.palnet.comn.model.GPHistoryModel; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/acnt/terms", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "약관 기본", description = "약관 관련 API") +public class AcntTermsController { + + @Autowired + private final AcntTermsService service; + + + + @GetMapping(value = "/list") + @Tag(name = "약관 기본", description = "약관 관련 API") + @ApiOperation(value = "약관 기본 정보") + public ResponseEntity list(AcntTermsRqModel rq) { + List result = null; + + log.debug("RQ>>>>>>>>" , rq.toString()); + + try { + result = service.list(rq); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRqModel.java new file mode 100644 index 00000000..ab5b360a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRqModel.java @@ -0,0 +1,11 @@ +package com.palnet.biz.api.acnt.terms.model; + +import lombok.Data; + +@Data +public class AcntTermsRqModel{ + + private String siteCd; + + private String langDivCd; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRsModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRsModel.java new file mode 100644 index 00000000..6d3fee22 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRsModel.java @@ -0,0 +1,26 @@ +package com.palnet.biz.api.acnt.terms.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class AcntTermsRsModel{ + + private int termsSno ; + + private String siteCd; + + private Date estbshDate; + + private String termsCtgryCd; + + private String langDivCd; + + private String termsTitleNm; + + private String termsCn; + + private String simpleCn; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/service/AcntTermsService.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/service/AcntTermsService.java new file mode 100644 index 00000000..fc41e412 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/service/AcntTermsService.java @@ -0,0 +1,35 @@ +package com.palnet.biz.api.acnt.terms.service; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.acnt.terms.model.AcntTermsRqModel; +import com.palnet.biz.api.acnt.terms.model.AcntTermsRsModel; +import com.palnet.biz.jpa.repository.pty.PtyTermsQueryRepository; + +@Service +public class AcntTermsService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + +// @Autowired +// private CtrCntrlBasRepository ctrCntrlBasRepository; + + @Autowired + private PtyTermsQueryRepository query; + + + + public List list(AcntTermsRqModel rq){ + + List resultList = query.list(rq); + + return resultList; + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/controller/AnlsHstryController.java b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/controller/AnlsHstryController.java new file mode 100644 index 00000000..c44b708d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/controller/AnlsHstryController.java @@ -0,0 +1,112 @@ +package com.palnet.biz.api.anls.hstry.controller; + +import java.util.List; + +import com.palnet.biz.api.comn.model.ComnPagingRs; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryGroupModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRqModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRsModel; +import com.palnet.biz.api.anls.hstry.service.AnlsHstryService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.comn.code.RSErrorCode; +import com.palnet.comn.utils.JsonUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/anls/hstry", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "비행 이력 현황", description = "비행 이력 현황 관련 API") +public class AnlsHstryController { + + @Autowired + private final AnlsHstryService service; + + + @GetMapping(value = "/list") + @ApiOperation(value = "비행 현황 목록 출력") + @Tag(name = "비행 이력 현황", description = "비행 이력 현황 관련 API") + public ResponseEntity list(AnlsHstryGroupModel rq) { + List rs = null; + ComnPagingRs response; + + //입력값 검증 + if(rq.getStDate() == null || !(rq.getStDate().length() == 10) || rq.getEndDate() ==null || !(rq.getEndDate().length() == 10) ) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + response = service.list(rq); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(response)); + + } + + @GetMapping(value = "/detail/{id}") + @ApiOperation(value = "비행 현황 상세") + @Tag(name = "비행 이력 현황", description = "비행 이력 현황 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity detail(@PathVariable String id) { + AnlsHstryModel result = null; + + try { + result = service.detail(id); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + @GetMapping(value = "/log/{id}") + @ApiOperation(value = "비행 이력 데이터") + @Tag(name = "비행 이력 현황", description = "비행 이력 현황 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity log(@PathVariable String id) { + List result = null; + try { + result = service.hstryList(id); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryDetailModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryDetailModel.java new file mode 100644 index 00000000..785fddba --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryDetailModel.java @@ -0,0 +1,47 @@ +package com.palnet.biz.api.anls.hstry.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class AnlsHstryDetailModel{ + + private int hstrySno; + + private String cntrlId; + + private String idntfNum; + + private String trmnlId; + + private String mssgTypeCd; + + private String statusCd; + + private Double lat; + + private Double lon; + + private Double speed; + + private String speedType; + + private Double heading; + + private Double elev; + + private String elevType; + + private Double mvDstnc; + + private Double bttrLvl; + + private Double bttrVltg; + + private Date trmnlRcvDt; + + private Date srvrRcvDt; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryGroupModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryGroupModel.java new file mode 100644 index 00000000..c4540037 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryGroupModel.java @@ -0,0 +1,21 @@ +package com.palnet.biz.api.anls.hstry.model; + +import com.palnet.biz.api.comn.model.ComnPagingModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class AnlsHstryGroupModel extends ComnPagingModel { + + private String stDate; + + private String endDate; + + private String search1; + + private String searchType1; + + private String groupId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryModel.java new file mode 100644 index 00000000..2c2bc80f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryModel.java @@ -0,0 +1,79 @@ +package com.palnet.biz.api.anls.hstry.model; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Id; + +import com.palnet.comn.utils.DateUtils; + +import io.netty.util.internal.StringUtil; +import lombok.Data; + +@Data +public class AnlsHstryModel{ + + private String cntrlId; + + private String idntfNum; + + private String statusCd; + + private String objectTypeCd; + + private Date flghtStDt; + + private Date flghtEndDt; + + private Date cntrlStDt; + + private Date cntrlEndDt; + + private Double ttlTime= 0.0; + + private String ttlTimeType; + + private Double ttlDstnc= 0.0; + + private String ttlDstncType; + + private Double avrgSpeed = 0.0; + + private String avrgSpeedType; + + private Double bttrCnsmptn= 0.0; + + private String endTypeCd; + + private String actnType; + + private String area1 = ""; + + private String area2 = ""; + + private String area3 = ""; + + private String zipCd = ""; + + private String landNm = ""; + + private String landNum = ""; + + private String areaType = ""; + + private String areaNm = ""; + + private String stArea = ""; + + private String endArea = ""; + + private Date createDt; + + private Date updateDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryRqModel.java new file mode 100644 index 00000000..5d37e0cd --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryRqModel.java @@ -0,0 +1,12 @@ +package com.palnet.biz.api.anls.hstry.model; + +import com.palnet.biz.api.comn.model.ComnRqModel; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class AnlsHstryRqModel extends ComnRqModel{ + private String cntrlId; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryRsModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryRsModel.java new file mode 100644 index 00000000..2a75d88f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/model/AnlsHstryRsModel.java @@ -0,0 +1,83 @@ +package com.palnet.biz.api.anls.hstry.model; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Id; + +import com.palnet.comn.utils.DateUtils; + +import io.netty.util.internal.StringUtil; +import lombok.Data; + +@Data +public class AnlsHstryRsModel{ + + private String cntrlId; + + private String idntfNum; + + private String statusCd; + + private String objectTypeCd; + + private Date flghtStDt; + + private Date flghtEndDt; + + private Date cntrlStDt; + + private Date cntrlEndDt; + + private Double ttlTime= 0.0; + + private String ttlTimeType; + + private Double ttlDstnc= 0.0; + + private String ttlDstncType; + + private Double avrgSpeed = 0.0; + + private String avrgSpeedType; + + private Double bttrCnsmptn= 0.0; + + private String endTypeCd; + + private String actnType; + + private String area1 = ""; + + private String area2 = ""; + + private String area3 = ""; + + private String zipCd = ""; + + private String landNm = ""; + + private String landNum = ""; + + private String areaType = ""; + + private String areaNm = ""; + + private String stArea = ""; + + private String endArea = ""; + + private String groupId = ""; + + private int cstmrSno; + + private Date createDt; + + private Date updateDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/service/AnlsHstryService.java b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/service/AnlsHstryService.java new file mode 100644 index 00000000..e8441835 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/hstry/service/AnlsHstryService.java @@ -0,0 +1,154 @@ +package com.palnet.biz.api.anls.hstry.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import com.palnet.biz.api.comn.model.ComnPagingRs; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.PathVariable; + +import com.palnet.biz.api.acnt.jwt.model.JwtGroupModel; +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryGroupModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; +import com.palnet.biz.jpa.entity.ComIdntfBas; +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.FltPlanBas; +import com.palnet.biz.jpa.entity.FltPlanPilot; +import com.palnet.biz.jpa.repository.com.ComArcrftBasRepository; +import com.palnet.biz.jpa.repository.com.ComIdntBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlHstryAreaRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlQueryRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanBasRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanPilotRepository; +import com.palnet.biz.jpa.repository.pty.PtyCstmrGroupRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; + +@Service +public class AnlsHstryService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private CtrCntrlBasRepository ctrCntrlBasRepository; + + @Autowired + private PtyCstmrGroupRepository ptyCstmrGroupRepository; + + @Autowired + private ComArcrftBasRepository comArcrftBasRepository; + + @Autowired + private ComIdntBasRepository comIdntBasRepository; + + @Autowired + private CtrCntrlHstryAreaRepository ctrCntrlHstryAreaRepository; + + @Autowired + private FltPlanBasRepository fltPlanBasRepository; + + @Autowired + private FltPlanPilotRepository fltPlanPilotRepository; + + @Autowired + private CtrCntrlQueryRepository query; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + //비행이력현황 list + public ComnPagingRs list(AnlsHstryGroupModel rq){ + Integer cstmrSno = jwtTokenUtil.getCstmrSnoByToken(); + List groupAuthList = jwtTokenUtil.getGroupAuthByToken(); + List adminAuth = new ArrayList<>(); + String groupAuth = null; + String appAuth = jwtTokenUtil.getUserAuthByToken(); + PageImplresultList; + + ComnPagingRs response = new ComnPagingRs<>(); + Pageable pageable = PageRequest.of(rq.getPage()-1, rq.getRecord()); + + if("USER".equals(appAuth) || "ROLE_USER".equals(appAuth)) { + for(JwtGroupModel list : groupAuthList) { + if(list.getGroupId().equals(rq.getGroupId())) { + groupAuth = list.getGroupAuthCd(); + } + } + } + if("NORMAL".equals(groupAuth)) { + for (JwtGroupModel list : groupAuthList) { + if("MASTER".equals(list.getGroupAuthCd()) || "LEADER".equals(list.getGroupAuthCd())) { + adminAuth.add(list); + } + } + List idntfList = comIdntBasRepository.findIdntfNumber(cstmrSno); + List basResult = fltPlanBasRepository.findByPlanSno(cstmrSno); + List pilotList = fltPlanPilotRepository.findByPlanSno(cstmrSno); + + List pilotResult = new ArrayList<>(); + + for(FltPlanPilot list : pilotList) { + pilotResult = fltPlanBasRepository.findBasList(list.getPlanSno()); + } + resultList = query.cntrlBasNormalHstryList(rq, pageable, idntfList, basResult, pilotResult); + + long total = query.cntrlBasNormalHstryCount(rq, idntfList, basResult, pilotResult); + + long totalPage = total % rq.getRecord() > 0 ? total/rq.getRecord() + 1 : total/rq.getRecord(); + response.setItems(resultList.getContent()); + response.setTotal(total); + response.setTotalPage(totalPage); + response.setPage(rq.getPage()); + + return response; + } + + PageImpl result = query.listCntrlBasRs(rq, pageable); + + long total = query.countCntrlBasRs(rq, cstmrSno); + long totalPage = total % rq.getRecord() > 0 ? (total/rq.getRecord()) + 1 : total/rq.getRecord(); + response.setItems(result.getContent()); + response.setTotal(total); + response.setTotalPage(totalPage); + response.setPage(rq.getPage()); + + return response; + } + + public AnlsHstryModel detail(String cntrlId) throws Exception{ + + AnlsHstryModel model = new AnlsHstryModel(); + + Optional optional = ctrCntrlBasRepository.findById(cntrlId); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + CtrCntrlBas entity = optional.get(); + + BeanUtils.copyProperties(entity , model); + + + return model; + + } + + public List hstryList(@PathVariable String id) { + + List result = query.listCntrlHstryPage(id); + + return result; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/controller/AnlsSmltController.java b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/controller/AnlsSmltController.java new file mode 100644 index 00000000..fd74a684 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/controller/AnlsSmltController.java @@ -0,0 +1,160 @@ +package com.palnet.biz.api.anls.smlt.controller; + +import java.util.List; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRqModel; +import com.palnet.biz.api.anls.smlt.model.AnlsSmltDetailModel; +import com.palnet.biz.api.anls.smlt.model.AnlsSmltStcsModel; +import com.palnet.biz.api.anls.smlt.service.AnlsSmltService; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.comn.code.RSErrorCode; +import com.palnet.comn.utils.JsonUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/anls/smlt", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "비행 시뮬레이션", description = "비행 이력 시뮬레이션 관련 API") +public class AnlsSmltController { + + @Autowired + private final AnlsSmltService service; + + /** + * 비행 현황 목록 + * @param rq + * @return + */ + @GetMapping(value = "/list") + @ApiOperation(value = "비행 현황 목록") + @Tag(name = "비행 시뮬레이션", description = "비행 이력 시뮬레이션 관련 API") + public ResponseEntity list(AnlsHstryRqModel rq) { + ComnPagingRs result = null; + + log.debug("JSON>>>>>>>>" , JsonUtils.toJson(rq)); + log.debug("Param" + rq.getStDate() + "::" + rq.getEndDate()); + + //입력값 검증 + if(rq.getStDate() == null || !(rq.getStDate().length() == 10) || rq.getEndDate() ==null || !(rq.getEndDate().length() == 10) ) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.list(rq); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + + } + + + /** + * 비행 이력 데이터 조회 + * @param rq + * @return + */ + @GetMapping(value = "/hist/{id}") + @ApiOperation(value = "비행 이력 데이터 조회") + @Tag(name = "비행 시뮬레이션", description = "비행 이력 시뮬레이션 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity histList(@PathVariable String id) { + List result = null; + + try { +// result = service.list(rq); + result = service.histList(id); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + /** + * 통계 데이터 조회 + * @param rq + * @return + */ + @GetMapping(value = "/stcs/{id}") + @ApiOperation(value = "통계 데이터 조회") + @Tag(name = "비행 시뮬레이션", description = "비행 이력 시뮬레이션 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity stcsList(@PathVariable String id) { + List result = null; + + + try { + result = service.stcsList(id); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + /** + * 비행 상세정보 조회 + * @param id + * @return + */ + @GetMapping(value = "/detail/{id}") + @ApiOperation(value = "비행 상세정보 조회") + @Tag(name = "비행 시뮬레이션", description = "비행 이력 시뮬레이션 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity detail(@PathVariable String id) { + AnlsSmltDetailModel result = null; + + try { + result = service.detail(id); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltDetailModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltDetailModel.java new file mode 100644 index 00000000..b16b58b2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltDetailModel.java @@ -0,0 +1,60 @@ +package com.palnet.biz.api.anls.smlt.model; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Id; + +import com.palnet.comn.utils.DateUtils; + +import io.netty.util.internal.StringUtil; +import lombok.Data; + +@Data +public class AnlsSmltDetailModel{ + + private String cntrlId; + + private String idntfNum; + + private Date flghtStDt; + + private Date flghtEndDt; + + private Date cntrlStDt; + + private Date cntrlEndDt; + + private Double ttlTime= 0.0; + + private String ttlTimeType; + + private Double ttlDstnc= 0.0; + + private String ttlDstncType; + + private Double avrgSpeed = 0.0; + + private String avrgSpeedType; + + private Double bttrCnsmptn= 0.0; + + private String stArea = ""; + + private String endArea = ""; + + private String arcrftTypeCd = ""; + + private String prdctNum = ""; + + private String arcrftModelNm = ""; + + private String imageUrl = ""; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltHistModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltHistModel.java new file mode 100644 index 00000000..1afa8a91 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltHistModel.java @@ -0,0 +1,46 @@ +package com.palnet.biz.api.anls.smlt.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class AnlsSmltHistModel{ + + private int hstrySno; + + private String cntrlId; + + private String trmnlId; + + private String mssgTypeCd; + + private String statusCd; + + private double lat; + + private double lon; + + private double speed; + + private String speedType; + + private double heading; + + private double elev; + + private String elevType; + + private double mvDstnc; + + private String mvDstncType; + + private double bttrLvl; + + private double bttrVltg; + + private Date trmnlRcvDt; + + private Date srvrRcvDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltRqModel.java new file mode 100644 index 00000000..850de188 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltRqModel.java @@ -0,0 +1,12 @@ +package com.palnet.biz.api.anls.smlt.model; + +import com.palnet.biz.api.comn.model.ComnRqModel; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class AnlsSmltRqModel extends ComnRqModel{ + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltStcsModel.java b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltStcsModel.java new file mode 100644 index 00000000..2b59a523 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/model/AnlsSmltStcsModel.java @@ -0,0 +1,28 @@ +package com.palnet.biz.api.anls.smlt.model; + +import lombok.Data; + +@Data +public class AnlsSmltStcsModel{ + + private String dateCd; + + private String timeCd; + + private Double avrgSpeed; + + private String speedType; + + private Double avrgElev; + + private String elevType; + + private Double avrgMvDstnc; + + private String mvDstncType; + + private Double minBttrLvl; + + private Double maxBttrLvl; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/service/AnlsSmltService.java b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/service/AnlsSmltService.java new file mode 100644 index 00000000..ce8950e7 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/anls/smlt/service/AnlsSmltService.java @@ -0,0 +1,227 @@ +package com.palnet.biz.api.anls.smlt.service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.acnt.jwt.model.JwtGroupModel; +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRqModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRsModel; +import com.palnet.biz.api.anls.smlt.model.AnlsSmltDetailModel; +import com.palnet.biz.api.anls.smlt.model.AnlsSmltStcsModel; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.jpa.entity.ComIdntfBas; +import com.palnet.biz.jpa.entity.CtrCntrlHstryArea; +import com.palnet.biz.jpa.entity.FltPlanBas; +import com.palnet.biz.jpa.entity.FltPlanPilot; +import com.palnet.biz.jpa.repository.com.ComIdntBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlQueryRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanBasRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanPilotRepository; +import com.palnet.comn.utils.DateUtils; +import com.palnet.comn.utils.NumberUtils; + +@Service +public class AnlsSmltService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private CtrCntrlBasRepository ctrCntrlBasRepository; + + @Autowired + private CtrCntrlQueryRepository query; + + @Autowired + private ComIdntBasRepository comIdntBasRepository; + + @Autowired + private FltPlanBasRepository fltPlanBasRepository; + + @Autowired + private FltPlanPilotRepository fltPlanPilotRepository; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + + /** + * 비행 현황 목록 + * @param rq + * @return + */ + public ComnPagingRs list(AnlsHstryRqModel rq){ + String appAuth = jwtTokenUtil.getUserAuthByToken(); + List groupAuth = jwtTokenUtil.getGroupAuthByToken(); + List adminAuth = new ArrayList<>(); + Integer cstmrSno = jwtTokenUtil.getCstmrSnoByToken(); + ComnPagingRs response = new ComnPagingRs<>(); + Pageable pageable = PageRequest.of(rq.getPage()-1, rq.getRecord()); + + PageImpl result; + ListresultList = new ArrayList<>(); + + if("SUPER".equals(appAuth)||"ADMIN".equals(appAuth)) {// App 권한이 수퍼 / 어드민일 경우 목록 전부 표출 + long total = resultList.size(); + long totalPage = total % rq.getRecord() > 0 ? (total/rq.getRecord()) + 1 : total/rq.getRecord(); + + result = query.listCntrlBas(rq, pageable); + + response.setItems(result.getContent()); + response.setTotal(total); + response.setTotalPage(totalPage); + response.setPage(rq.getPage()); + return response; + } + + if("USER".equals(appAuth) || "ROLE_USER".equals(appAuth)) { + for (JwtGroupModel list : groupAuth) { + if("MASTER".equals(list.getGroupAuthCd()) || "LEADER".equals(list.getGroupAuthCd())) { + adminAuth.add(list); + } + } + } + + List idntfList = comIdntBasRepository.findIdntfNumber(cstmrSno); + List basResult = fltPlanBasRepository.findByPlanSno(cstmrSno); + List pilotList = fltPlanPilotRepository.findByPlanSno(cstmrSno); + + List pilotResult = new ArrayList<>(); + + for(FltPlanPilot list : pilotList) { + pilotResult = fltPlanBasRepository.findBasList(list.getPlanSno()); + } + result = query.cntrlBasNormalSmltList(rq, pageable, adminAuth, idntfList, basResult, pilotResult); // App 권한은 user이지만 group 권한이 LEADER / MASTER인 그룹이 있는 경우 해당 비행 이력 목록 표출 + // group 권한이 Normal인 경우 본인이 작성한 비행계획서의 이력 / 본인이 조종사인 기체 이력/ 본인이 등록한 기체 이력 표출 + + long total = query.cntrlBasNormalSmltCount(rq, adminAuth, idntfList, basResult, pilotResult); + + long totalPage = total % rq.getRecord() > 0 ? total/rq.getRecord() + 1 : total/rq.getRecord(); + response.setItems(result.getContent()); + response.setTotal(total); + response.setTotalPage(totalPage); + response.setPage(rq.getPage()); + + return response; + + } + + /** + * + * @param rq비행 이력 데이터 조회 + * @return + */ + public List histList(String id){ + + List resultList = query.listCntrlHstry(id); + + //정렬 순서 뒤집기 처리 + Collections.reverse(resultList); + + return resultList; + } + + + /** + * 통계 데이터 조회 + * @param rq + * @return + */ + public List stcsList(String id){ + + List result = query.anlsSmltStcs(id); + + + //통계 데이터 가공 처리 + //소수점 자리 1자리로 컷트 + for(AnlsSmltStcsModel model : result) { + + model.setAvrgElev(NumberUtils.formatZero2(model.getAvrgElev())); + model.setAvrgMvDstnc(NumberUtils.formatZero2(model.getAvrgMvDstnc())); + model.setAvrgSpeed(NumberUtils.formatZero2(model.getAvrgSpeed())); + } + + return result; + } + + + + /** + * 비행 상세정보 조회 + * @param cntrlId + * @return + * @throws Exception + */ + public AnlsSmltDetailModel detail(String cntrlId) throws Exception{ + + AnlsSmltDetailModel result = new AnlsSmltDetailModel(); + + + result = query.anlsSmltDetail(cntrlId); + +// Optional optional = ctrCntrlBasRepository.findById(cntrlId); +// +// if (!optional.isPresent()) { +// throw new CustomException(ErrorCode.DATA_NOTFIND); +// } +// +// CtrCntrlBas entity = optional.get(); +// +// BeanUtils.copyProperties(entity , result); + + + List areaList = query.detailArea(cntrlId); + + + for(CtrCntrlHstryArea area : areaList) { + if(area != null) { + String areaNm = ""; + if(!StringUtils.isEmpty(area.getArea1())) { + areaNm = areaNm + " " + area.getArea1(); + } + + if(!StringUtils.isEmpty(area.getArea2())) { + areaNm = areaNm + " " + area.getArea2(); + } + + if(!StringUtils.isEmpty(area.getArea3())) { + areaNm = areaNm + " " + area.getArea3(); + } + + if(!StringUtils.isEmpty(area.getLandNm())) { + areaNm = areaNm + " " + area.getLandNm(); + } + + if(!StringUtils.isEmpty(area.getLandNum())) { + areaNm = areaNm + " " + area.getLandNum(); + } + + if(area.getActnType().equals("01")) { + result.setStArea(areaNm); + }else if(area.getActnType().equals("99")) { + result.setEndArea(areaNm); + } + } + + } + return result; + + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/dron/controller/BasDronController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/controller/BasDronController.java new file mode 100644 index 00000000..c16b0a80 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/controller/BasDronController.java @@ -0,0 +1,311 @@ +package com.palnet.biz.api.bas.dron.controller; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.bas.dron.model.BasDronModel; +import com.palnet.biz.api.bas.dron.model.BasDronRqModel; +import com.palnet.biz.api.bas.dron.model.BasIdntfModel; +import com.palnet.biz.api.bas.dron.model.BasIdntfRqModel; +import com.palnet.biz.api.bas.dron.service.BasDronService; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.comn.code.RSErrorCode; +import com.palnet.comn.exception.CustomException; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/bas/dron", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "드론 컨트롤러", description = "드론 관련 API") +public class BasDronController { + + @Autowired + private final BasDronService service; + + + /** + * 목록 조회 + * @param rq + * @return + */ + @GetMapping(value = "/list") + @ApiOperation(value = "드론 목록 조회") + @Tag(name = "드론 컨트롤러", description = "드론 관련 API") + public ResponseEntity list(BasDronRqModel rq) { + ComnPagingRs result = null; + + //입력값 검증 + if(StringUtils.isEmpty(rq.getGroupId())) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.list(rq); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + + } + + + /** + * 식별정보 조회 + * @param rq + * @return + */ + @GetMapping(value = "/idntf/list/{id}") + @ApiOperation(value = "식별정보 조회") + @Tag(name = "드론 컨트롤러", description = "드론 관련 API") + @ApiImplicitParam(name = "id",value = "기체일련번호", dataTypeClass = Integer.class) + public ResponseEntity mylist(@PathVariable Integer id) { + List result = null; + + //입력값 검증 + if(StringUtils.isEmpty(id)) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.listIdntf(id); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + /** + * 상세 조회 + * @param id + * @return + */ + @GetMapping(value = "/detail/{id}") + @ApiOperation(value = "드론 상세 조회") + @Tag(name = "드론 컨트롤러", description = "드론 관련 API") + @ApiImplicitParam(name = "id",value = "기체일련번호", dataTypeClass = Integer.class) + public ResponseEntity detail(@PathVariable Integer id) { + BasDronModel result = null; + + try { + //입력값 검증 + if(StringUtils.isEmpty(id)) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + + result = service.detail(id); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + /** + * 생성 + * @return + */ + @PostMapping(value = "/create") + @ApiOperation(value = "드론정보 생성") + @Tag(name = "드론 컨트롤러", description = "드론 관련 API") + public ResponseEntity create(@RequestBody BasDronModel rq) { + Map resultMap = new HashMap(); + + try { + boolean result = service.create(rq); + + resultMap.put("result", result); + + }catch(CustomException e2) { + log.error("IGNORE : {}", e2); + resultMap.put("result", false); + resultMap.put("errorCode", e2.getErrorCode()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + }catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + /** + * 생성 + * @return + */ + @PostMapping(value = "/idntf/create") + @ApiOperation(value = "식별장치 생성") + @Tag(name = "드론 컨트롤러", description = "드론 관련 API") + public ResponseEntity createIdntf(@RequestBody BasIdntfRqModel rq) { + Map resultMap = new HashMap(); + + try { +// boolean result = service.create(rq); + boolean result = service.createIdntf(rq); + + resultMap.put("result", result); + + }catch(CustomException e2) { + log.error("IGNORE : {}", e2); + resultMap.put("result", false); + resultMap.put("errorCode", e2.getErrorCode()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } + catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + /** + * 수정 + * @return + */ + @PutMapping(value = "/update") + @ApiOperation(value = "드론정보 수정") + @Tag(name = "드론 컨트롤러", description = "드론 관련 API") + public ResponseEntity update(@RequestBody BasDronModel rq) { + Map resultMap = new HashMap(); + + try { + boolean result = service.update(rq); + + resultMap.put("result", result); + + } + catch(CustomException e2) { + log.error("IGNORE : {}", e2); + resultMap.put("result", false); + resultMap.put("errorCode", e2.getErrorCode()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + }catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + /** + * 삭제 + * @param id + * @return + */ + @DeleteMapping(value = "/delete/{id}") + @ApiOperation(value = "드론정보 삭제") + @Tag(name = "드론 컨트롤러", description = "드론 관련 API") + @ApiImplicitParam(name = "id",value = "기체일련번호", dataTypeClass = Integer.class) + public ResponseEntity delete(@PathVariable Integer id) { + Map resultMap = new HashMap(); + + try { + + //입력값 검증 + if(StringUtils.isEmpty(id)) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + boolean result = service.delete(id); + + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + /** + * 식별장치 삭제 + * @param id + * @return + */ + @DeleteMapping(value = "/idntf/delete/{id}") + @ApiOperation(value = "식별장치 삭제") + @Tag(name = "드론 컨트롤러", description = "드론 관련 API") + @ApiImplicitParam(name = "id",value = "식별번호", dataTypeClass = String.class) + public ResponseEntity deleteIdntf(@PathVariable String id) { + Map resultMap = new HashMap(); + + try { + + //입력값 검증 + if(StringUtils.isEmpty(id)) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + boolean result = service.deleteIdntf(id); + + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasDronModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasDronModel.java new file mode 100644 index 00000000..09a1098c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasDronModel.java @@ -0,0 +1,62 @@ +package com.palnet.biz.api.bas.dron.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BasDronModel { + + private String groupNm; + + private String groupId; + + private int arcrftSno; + + private double arcrftHght; + + private double arcrftLngth; + + private String arcrftModelNm; + + private String arcrftTypeCd; + + private double arcrftWdth; + + private double arcrftWght; + + private String cameraYn; + + private Date createDt; + + private String createUserId; + + private String insrncYn; + + private String prdctCmpnNm; + + private Date prdctDate; + + private String prdctNum; + + private double takeoffWght; + + private Date updateDt; + + private String updateUserId; + + private String imageUrl; + + private String wghtTypeCd; + + //식별 번호 정보 + private String idntfNum; + + private String newIdntfNum; //변경된 식별 정보 + + private String idntfTypeCd; + + private String ownerNm; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasDronRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasDronRqModel.java new file mode 100644 index 00000000..5d3c2892 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasDronRqModel.java @@ -0,0 +1,23 @@ +package com.palnet.biz.api.bas.dron.model; + +import com.palnet.biz.api.comn.model.ComnPagingModel; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class BasDronRqModel extends ComnPagingModel { + + private String groupId; + + private String arcrftModelNm; + + private String arcrftTypeCd; + + private String idntfNum; + + private String ownerNm; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasIdntfModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasIdntfModel.java new file mode 100644 index 00000000..aed922a4 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasIdntfModel.java @@ -0,0 +1,31 @@ +package com.palnet.biz.api.bas.dron.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BasIdntfModel { + + //식별 번호 정보 + private String id; + private String idntfNum; + private String isSave; + + private int arcrftSno; + + private String idntfTypeCd; + + private String ownerNm; + + private String hpno; + + private Date updateDt; + + private Date createDt; + + private int cstmrSno; + + private String groupId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasIdntfRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasIdntfRqModel.java new file mode 100644 index 00000000..9d2cffab --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasIdntfRqModel.java @@ -0,0 +1,14 @@ +package com.palnet.biz.api.bas.dron.model; + +import java.util.List; + +import lombok.Data; + +@Data +public class BasIdntfRqModel { + + private List data; + + private int arcrftSno; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasOwnerModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasOwnerModel.java new file mode 100644 index 00000000..7276cf5a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/model/BasOwnerModel.java @@ -0,0 +1,30 @@ +package com.palnet.biz.api.bas.dron.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BasOwnerModel { + + private int ownerSno; + + private int arcrftSno; + + private String ownerNm; + + private String hpno; + + private String telno; + + private String useYn; + + private Date createDt; + + private String createUserId; + + private Date updateDt; + + private String updateUserId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/dron/service/BasDronService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/service/BasDronService.java new file mode 100644 index 00000000..cc78c9c6 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/dron/service/BasDronService.java @@ -0,0 +1,428 @@ +package com.palnet.biz.api.bas.dron.service; + +import java.util.List; +import java.util.Optional; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRsModel; +import com.palnet.biz.api.bas.dron.model.BasDronModel; +import com.palnet.biz.api.bas.dron.model.BasDronRqModel; +import com.palnet.biz.api.bas.dron.model.BasIdntfModel; +import com.palnet.biz.api.bas.dron.model.BasIdntfRqModel; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.jpa.entity.ComArcrftBas; +import com.palnet.biz.jpa.entity.ComIdntfBas; +import com.palnet.biz.jpa.repository.com.ComArcrftBasRepository; +import com.palnet.biz.jpa.repository.com.ComIdntBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyDronQueryRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.DateUtils; +import com.palnet.comn.utils.EncryptUtils; + +import lombok.extern.log4j.Log4j2; + +@Service +@Log4j2 +public class BasDronService { + + @Autowired + private PtyDronQueryRepository query; + + @Autowired + private ComArcrftBasRepository comArcrftBasRepository; + + @Autowired + private ComIdntBasRepository comIdntBasRepository; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + /** + * 드론 목록 + * @param rq + * @return + */ + public ComnPagingRs list(BasDronRqModel rq){ + + ComnPagingRs response = new ComnPagingRs<>(); + + Pageable pageable = PageRequest.of(rq.getPage()-1, rq.getRecord()); + + PageImpl result = query.list(rq, pageable); + + long total = query.listCount(rq); + + long totalPage = total % rq.getRecord() > 0 ? (total/rq.getRecord()) + 1 : total/rq.getRecord(); + + response.setItems(result.getContent()); + response.setTotal(total); + response.setPage(rq.getPage()); + response.setTotalPage(totalPage); + + return response; + + } + + /** + * 식별장치 목록 + * @param arcrftSno + * @return + */ + public List listIdntf(int arcrftSno){ + + List resultList = query.idntfList(arcrftSno); + + for(BasIdntfModel model : resultList){ + if(model.getHpno() != null && !model.getHpno().isEmpty()){ + model.setHpno(EncryptUtils.decrypt(model.getHpno())); + } + } + + return resultList; + } + + /** + * 상세 조회 + * @param cntrlId + * @return + * @throws Exception + */ + public BasDronModel detail(int arcrftSno) throws Exception{ + + BasDronModel model = query.detail(arcrftSno); + + if (model == null ) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + return model; + + } + + /** + * 생성 + * @param + * @return + * @throws Exception + */ + @Transactional + public boolean create(BasDronModel rq) throws Exception{ + + // 사전 체크 , 동일한 ID 존재 여부 확인 + if(!query.isNotPrdctNum(rq.getPrdctNum() , 0)) { + throw new CustomException(ErrorCode.DATA_DUPLICATE); + } + + // 민감정보 암호화 처리 +// if(!StringUtils.isEmpty(rq.getHpno())) { +// rq.setHpno(EncryptUtils.encrypt(rq.getHpno())); +// } +// if(!StringUtils.isEmpty(rq.getOwnerNm())) { +// rq.setOwnerNm(EncryptUtils.encrypt(rq.getOwnerNm())); +// } +// if(!StringUtils.isEmpty(rq.getTelno())) { +// rq.setTelno(EncryptUtils.encrypt(rq.getTelno())); +// } + + + + //1. 드론 기본 정보 등록 + ComArcrftBas comArcrftBas = this.insertComArcrftBas(rq); + if(comArcrftBas == null) { + throw new CustomException(ErrorCode.DB_ERROR); + } + + log.debug("===========================>" + comArcrftBas.getArcrftSno()); + rq.setArcrftSno(comArcrftBas.getArcrftSno()); // KEY 넣기 + + //2. 드론 운영자 정보 등록 +// ComArcrftOwner comArcrftOwner = this.insertComArcrftOwner(rq); +// if(comArcrftOwner == null) { +// throw new CustomException(ErrorCode.DB_ERROR); +// } + +// //3. 드론 식별 정보 등록 +// ComIdntfBas comIdntfBas = this.insertComIdntfBas(rq); +// if(comIdntfBas == null) { +// throw new CustomException(ErrorCode.DB_ERROR); +// } + + //4. 드론 그룹에 연결 등록 +// PtyGroupArcrft ptyGroupArcrft = this.insertPtyGroupArcrft(rq); +// if(ptyGroupArcrft == null) { +// throw new CustomException(ErrorCode.DB_ERROR); +// } + + return true; + + } + + /** + * 식밸장치 생성 + * @param + * @return + * @throws Exception + */ + @Transactional + public boolean createIdntf(BasIdntfRqModel rq) throws Exception{ + + if( rq == null && rq.getData().size() == 0) + throw new CustomException(ErrorCode.DATA_NOTFIND); + + + for(BasIdntfModel model : rq.getData() ) { + Optional optional = comIdntBasRepository.findById(model.getIdntfNum()); + String hpno = EncryptUtils.encrypt(model.getHpno()); + if (optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_DUPLICATE); + } + + int cstmrSno = jwtTokenUtil.getCstmrSnoByToken(); + ComIdntfBas entity = new ComIdntfBas(); + + BeanUtils.copyProperties(model , entity); + + entity.setHpno(hpno); + entity.setArcrftSno(rq.getArcrftSno()); + entity.setCreateDt(DateUtils.nowDate()); + entity.setUpdateDt(DateUtils.nowDate()); + entity.setCstmrSno(cstmrSno); + log.debug(entity.toString()); + + if( comIdntBasRepository.save(entity) == null ) return false; + + } + return true; + + } + + public boolean deleteIdntf(String idntfNum) { + Optional optional = comIdntBasRepository.findById(idntfNum); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + ComIdntfBas entity = optional.get(); + comIdntBasRepository.delete(entity); + return true; + + } + + public ComArcrftBas insertComArcrftBas(BasDronModel model) throws Exception{ + + + ComArcrftBas basEntity = new ComArcrftBas(); + + BeanUtils.copyProperties(model , basEntity); + + basEntity.setCreateDt(DateUtils.nowDate()); + basEntity.setUpdateDt(DateUtils.nowDate()); + basEntity.setUseYn("Y"); + + log.debug(basEntity.toString()); + + return comArcrftBasRepository.save(basEntity); + + } + + public ComIdntfBas insertComIdntfBas(BasDronModel model) throws Exception{ + ComIdntfBas entity = new ComIdntfBas(); + + BeanUtils.copyProperties(model , entity); + entity.setCreateDt(DateUtils.nowDate()); + entity.setUpdateDt(DateUtils.nowDate()); + log.debug(entity.toString()); + + return comIdntBasRepository.save(entity); + } + +// public PtyGroupArcrft insertPtyGroupArcrft(BasDronModel model) throws Exception{ +// PtyGroupArcrft entity = new PtyGroupArcrft(); +// BeanUtils.copyProperties(model , entity); +// entity.setCreateDt(DateUtils.nowDate()); +// entity.setUpdateDt(DateUtils.nowDate()); +// entity.setUseYn("Y"); +// log.debug(entity.toString()); +// +// return ptyGroupArcrftRepository.save(entity); +// +// } + + + /** + * 수정 + * @param + * @return + * @throws Exception + */ + @Transactional + public boolean update(BasDronModel rq) throws Exception{ + + // 사전 체크 , 동일한 ID 존재 여부 확인 + if(!query.isNotPrdctNum(rq.getPrdctNum() , rq.getArcrftSno())) { + throw new CustomException(ErrorCode.DATA_DUPLICATE); + } + + //1. 기체 정보 수정 + ComArcrftBas comArcrftBas = this.updateComArcrftBas(rq); + if(comArcrftBas == null) { + throw new CustomException(ErrorCode.DB_ERROR); + } + + //2-1. 식별장치 수정 필요 여부 체크 newIdnfnum -> idnftNum 비교후 다르면 +// if(!rq.getNewIdntfNum().equals(rq.getIdntfNum())) { +// //2-2 식별번호 중복 체크 +// if(!query.isNotIdntNum(rq.getNewIdntfNum())) { +// throw new CustomException(ErrorCode.DATA_DUPLICATE); +// } +// +// //2-3식별정보 수정 +// ComIdntfBas comIdntfBas = this.updateComIdntfBas(rq); +// +// if(comIdntfBas == null) { +// throw new CustomException(ErrorCode.DB_ERROR); +// } +// } + + + //민감 정보 암호화 처리 + // 민감정보 암호화 처리 +// if(!StringUtils.isEmpty(rq.getHpno())) { +// rq.setHpno(EncryptUtils.encrypt(rq.getHpno())); +// } +// if(!StringUtils.isEmpty(rq.getOwnerNm())) { +// rq.setOwnerNm(EncryptUtils.encrypt(rq.getOwnerNm())); +// } +// if(!StringUtils.isEmpty(rq.getTelno())) { +// rq.setTelno(EncryptUtils.encrypt(rq.getTelno())); +// } + + + //3. 운영자 정보 수정 +// ComArcrftOwner comArcrftOwner = this.updateComArcrftOwner(rq); + +// if(comArcrftOwner == null) { +// throw new CustomException(ErrorCode.DB_ERROR); +// } + + return true; + } + + + public ComArcrftBas updateComArcrftBas(BasDronModel model) throws Exception{ + + + Optional optional = comArcrftBasRepository.findById(model.getArcrftSno()); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + ComArcrftBas entity = optional.get(); + + entity.setArcrftHght(model.getArcrftHght()); + entity.setArcrftLngth(model.getArcrftLngth()); + entity.setArcrftModelNm(model.getArcrftModelNm()); + entity.setArcrftTypeCd(model.getArcrftTypeCd()); + entity.setArcrftWdth(model.getArcrftWdth()); + entity.setArcrftWght(model.getArcrftWght()); + entity.setCameraYn(model.getCameraYn()); + entity.setImageUrl(model.getImageUrl()); + entity.setInsrncYn(model.getInsrncYn()); + entity.setPrdctCmpnNm(model.getPrdctCmpnNm()); + entity.setPrdctDate(model.getPrdctDate()); + entity.setPrdctNum(model.getPrdctNum()); + entity.setTakeoffWght(model.getTakeoffWght()); + entity.setUpdateUserId(model.getUpdateUserId()); + entity.setUpdateDt(DateUtils.nowDate()); + + return comArcrftBasRepository.save(entity); + + + } + +// public ComArcrftOwner updateComArcrftOwner(BasDronModel model) throws Exception{ +// +// +// Optional optional = comArcrftOwnerRepository.findById(model.getOwnerSno()); +// if (!optional.isPresent()) { +// throw new CustomException(ErrorCode.DATA_NOTFIND); +// } +// +// ComArcrftOwner entity = optional.get(); +// entity.setUpdateDt(DateUtils.nowDate()); +// entity.setUpdateUserId(model.getUpdateUserId()); +//// entity.setOwnerNm(model.getOwnerNm()); +//// entity.setHpno(model.getHpno()); +// entity.setTelno(model.getTelno()); +// +// log.debug(entity.toString()); +// +// return comArcrftOwnerRepository.save(entity); +// +// } + + + public ComIdntfBas updateComIdntfBas(BasDronModel model) throws Exception{ + + Optional optional = comIdntBasRepository.findById(model.getIdntfNum()); + + if (optional.isPresent()) { + ComIdntfBas entity = optional.get(); + comIdntBasRepository.delete(entity); + } + + model.setIdntfNum(model.getNewIdntfNum()); + + return this.insertComIdntfBas(model); + } + + + /** + * 삭제 + * @param + * @return + * @throws Exception + */ + @Transactional + public boolean delete(int arcrftSno) throws Exception{ + + try { + //1. 기체 정보 사용여부 N 으로 체크 + Optional optional = comArcrftBasRepository.findById(arcrftSno); + if (optional.isPresent()) { + ComArcrftBas comArcrftBas = optional.get(); + comArcrftBas.setUseYn("N"); + comArcrftBasRepository.save(comArcrftBas); + } + + //2. 식별 정보 삭제 처리 + comIdntBasRepository.deleteByArcrftSno(arcrftSno); + + //3. 기체 소유자정보 사용여부 N 처리 +// comArcrftOwnerRepository.deleteByArcrftSno(arcrftSno); + + //4. 그룹기체 정보 사용여부 N 처리 +// ptyGroupArcrftRepository.deleteByArcrftSno(arcrftSno); + + return true; + }catch(Exception e) { + log.error("IGNORE : {}", e); + throw new CustomException(ErrorCode.DB_ERROR); + } + + + + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/controller/BasFlightController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/controller/BasFlightController.java new file mode 100644 index 00000000..52dcde1a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/controller/BasFlightController.java @@ -0,0 +1,400 @@ +package com.palnet.biz.api.bas.flight.controller; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.proj4j.CRSFactory; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.bas.flight.model.BasFlightAprovRq; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanArcrftModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanListRq; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanPilotModel; +import com.palnet.biz.api.bas.flight.model.BasFlightScheduleRs; +import com.palnet.biz.api.bas.flight.model.BasFlightWeatherModel; +import com.palnet.biz.api.bas.flight.service.BasFlightService; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.scheduler.ctr.service.CtrTrnsLctnService; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.AreaUtils; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequestMapping(value = "/api/bas/flight", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "비행계획서", description = "비행계획서 관련 API") +public class BasFlightController { + + private final BasFlightService basFlightService; + private final Environment env; + private final CtrTrnsLctnService ctrTrnsLctnService; + private final AreaUtils utils; + + @Autowired + public BasFlightController(BasFlightService basFlightService, Environment env, CtrTrnsLctnService ctrTrnsLctnService, AreaUtils AreaUtils) { + this.basFlightService = basFlightService; + this.env = env; + this.ctrTrnsLctnService = ctrTrnsLctnService; + this.utils = AreaUtils; + } + + @GetMapping("/area") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity findAirSpace() throws IOException, ParseException { + // 1. file read + Resource resource = new ClassPathResource("air/airgeo.json"); + InputStream jsonInputStream = resource.getInputStream(); + InputStreamReader inputStreamReader = new InputStreamReader(jsonInputStream, "UTF-8"); + BufferedReader reader = new BufferedReader(inputStreamReader); + + // 2. json parsing + JSONParser jsonParser = new JSONParser(); + JSONObject jsonObject = (JSONObject) jsonParser.parse(reader); + + // 3. body return + String type = (String) jsonObject.get("type"); + Object airArea = jsonObject; + List features = (List) jsonObject.get("features"); + + log.info("type is name : {}", type); + log.info("features size : {}", features.size()); + + return ResponseEntity.ok().body(airArea); + } + + // 비행계획서 조회 + @GetMapping(value = "/plan/list") + @ApiOperation(value = "비행계획서 조회") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity findPlanList(BasFlightPlanListRq rq) { + ComnPagingRs result = null; + // System.out.println(rq); + try { + result = basFlightService.listPlan(rq); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + } + + // 비행계획서 상세 조회 + @GetMapping(value = "/plan/detail/{planSno}") + @ApiOperation(value = "비행계획서 상세 조회") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + @ApiImplicitParam(name = "planSno",value = "비행계획서일련번호", dataTypeClass = Integer.class) + public ResponseEntity detailPlan(@PathVariable("planSno") Integer planSno) { + BasFlightPlanModel result = null; + try { + result = basFlightService.detailPlan(planSno); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + } + + // 비행계획서 등록 + @PostMapping(value = "/plan/create") + @ApiOperation(value = "비행계획서 등록") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity createPlan(@RequestBody BasFlightPlanModel rq) { + Map resultMap = new HashMap(); + try { + log.info(">>> rq : {}", rq); + boolean result = basFlightService.createPlan(rq); + resultMap.put("result", result); + log.info(">>> resultMap : " , resultMap); + + } catch (CustomException e) { + log.error("IGNORE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + } + + // 비행계획서 수정 + @PutMapping(value = "/plan/update") + @ApiOperation(value = "비행계획서 수정") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity updatePlan(@RequestBody BasFlightPlanModel rq) { + Map resultMap = new HashMap(); + try { + boolean result = basFlightService.updatePlan(rq); + resultMap.put("result", result); + + } catch (CustomException e) { + log.error("IGNORE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + } + + // 비행계획서 삭제 + @DeleteMapping(value = "/plan/delete/{planSno}") + @ApiOperation(value = "비행계획서 삭제") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + @ApiImplicitParam(name = "planSno",value = "비행계획서일련번호", dataTypeClass = Integer.class) + public ResponseEntity deletePlan(@PathVariable("planSno") Integer planSno) { + Map resultMap = new HashMap(); + try { + boolean result = basFlightService.deletePlan(planSno); + resultMap.put("result", result); + + } catch (CustomException e) { + log.error("IGNORE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + } + + // 그룹 조종사 조회 + @GetMapping(value = "/plan/pilot/{groupId}") + @ApiOperation(value = "그룹의 조종사 조회") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + @ApiImplicitParam(name = "groupId",value = "그룹ID", dataTypeClass = String.class) + public ResponseEntity findPilot(@PathVariable("groupId") String groupId) { + List result = null; + try { + result = basFlightService.listPilotByGroup(groupId); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + + } + // 그룹 기체 조회 + @GetMapping(value = "/plan/arcrft/{groupId}") + @ApiOperation(value = "그룹의 기체 조회") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + @ApiImplicitParam(name = "groupId",value = "그룹ID", dataTypeClass = String.class) + public ResponseEntity findArcrft(@PathVariable("groupId") String groupId) { + List result = null; + try { + result = basFlightService.listArcrftByGroup(groupId); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + + } + + // 비행 구역 버퍼 존 생성 + @PostMapping("/plan/area/buffer") + @ApiOperation(value = "비행 구역 버퍼 존 생성") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity findBuffer(@RequestBody List rq) { + List rs = null; + try { + rs = basFlightService.getBuffer(rq); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + + return ResponseEntity.ok().body(new SuccessResponse<>(rs)); + } + + @GetMapping("/plan/api/weather") + @ApiOperation(value = "비행계획서 날씨") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity restApiGetWeather(BasFlightWeatherModel rq){ + JSONObject jsonObject = null; + + try { + jsonObject = basFlightService.getWeather(rq); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + + + return ResponseEntity.ok().body(new SuccessResponse<>(jsonObject)); + } + // 비행계획서 리스트(승인) + @GetMapping(value = "/aprv/list") + @ApiOperation(value = "비행계획서 리스트(승인)") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity findAprvList(BasFlightPlanListRq rq) { + ComnPagingRs result = null; + try { + result = basFlightService.aprvList(rq); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + } + // 비행계획서 승인/미승인 + @PutMapping(value = "/aprv/proc") + @ApiOperation(value = "비행 계획서 승인/미승인") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity updateAprvProc(@RequestBody BasFlightAprovRq rq) { + Map resultMap = new HashMap(); + try { + int result = basFlightService.aprovePlan(rq); + resultMap.put("result", result); + + } catch (CustomException e) { + log.error("IGNORE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + + } + + @PostMapping("/airspace/contains") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity checkAirspaceContains(@RequestBody List rq) { + Map resultMap = new HashMap(); + try { + boolean result = basFlightService.checkAirspaceContains(rq); + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); + + } + + //지역 검색 + @GetMapping("/plan/area/search") + @ApiOperation(value = "지역 검색") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity searchArea(String query) throws ParseException { + String text = null; + try { + text = URLEncoder.encode(query, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("검색어 인코딩 실패", e); + } + + String apiURL = env.getProperty("api.naver.search-url") + "?query=" + text + "&display=5"; + Map requestHeaders = new HashMap<>(); + requestHeaders.put("X-Naver-Client-Id", env.getProperty("api.naver.client-id")); + requestHeaders.put("X-Naver-Client-Secret", env.getProperty("api.naver.client-secret-key")); + String responseBody = basFlightService.searchArea(apiURL, requestHeaders); + + JSONParser parser = new JSONParser(); + Object obj = parser.parse(responseBody); + + return ResponseEntity.ok().body(new SuccessResponse<>(obj)); + } + + @GetMapping("/schedule") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity findSchedule(@RequestParam("searchDate") String searchDate) { + List response; + + try { + + response = basFlightService.findSchecdule(searchDate); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(response)); + } + + //test + @GetMapping("/test") + public void createCircleTest(@RequestParam double getX, @RequestParam double getY, @RequestParam double buffer) { + + + Coordinate circleCoord = new Coordinate(getY, getX); + + List coordList = utils.createCircle(circleCoord, buffer); + for(Coordinate a : coordList) { + System.out.println("["+a.getX() + ", " + a.getY()+"],"); + } + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightAprovRq.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightAprovRq.java new file mode 100644 index 00000000..b640bcff --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightAprovRq.java @@ -0,0 +1,11 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class BasFlightAprovRq { + private List planSnoList; + private String aprvlYn; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanArcrftModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanArcrftModel.java new file mode 100644 index 00000000..a7609893 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanArcrftModel.java @@ -0,0 +1,36 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.Date; + +@Data +public class BasFlightPlanArcrftModel { + private Integer planArcrftSno; + private Integer planSno; + private Integer arcrftSno; + private String idntfNum; + private String groupNm; + private String prdctNum; + private String arcrftTypeCd; + private String arcrftModelNm; + private String prdctCmpnNm; + private Date prdctDate; + private double arcrftLngth; + private double arcrftWdth; + private double arcrftHght; + private double arcrftWght; + private String wghtTypeCd; + private String imageUrl; + private double takeoffWght; + private String useYn; + private String cameraYn; + private String insrncYn; + private String ownerNm; + private String createUserId; + private Date createDt; + private String updateUserId; + private Date updateDt; + private String docState = "R"; + private String idntfTypeCd; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaBufferModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaBufferModel.java new file mode 100644 index 00000000..f2a57f3e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaBufferModel.java @@ -0,0 +1,15 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class BasFlightPlanAreaBufferModel { + + + private Integer bufferZone; // 반경 + private List coordList; // 기초 좌표 + private List bufferCoordList; // 버퍼 좌표 + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordModel.java new file mode 100644 index 00000000..ecba6fc2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordModel.java @@ -0,0 +1,16 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.Date; + +@Data +public class BasFlightPlanAreaCoordModel { + private Integer planAreaCoordSno; + private Integer planAreaSno; + private double lat; + private double lon; + private String createUserId; + private Date createDt; + private String docState = "R"; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordQueryList.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordQueryList.java new file mode 100644 index 00000000..1ff24985 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordQueryList.java @@ -0,0 +1,16 @@ +package com.palnet.biz.api.bas.flight.model; + +import java.util.List; + +import org.locationtech.jts.geom.Coordinate; + +import lombok.Data; + +@Data +public class BasFlightPlanAreaCoordQueryList { + + private Integer planAreaCoordSno; + private Integer planAreaSno; + private List queryCoordList; + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordRq.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordRq.java new file mode 100644 index 00000000..fd7b9312 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaCoordRq.java @@ -0,0 +1,14 @@ +package com.palnet.biz.api.bas.flight.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BasFlightPlanAreaCoordRq { + private Integer planAreaSno; + private Integer bufferZone; + private String areaType; + private String idntfNum; + private Integer cnt; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaModel.java new file mode 100644 index 00000000..57e05b76 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanAreaModel.java @@ -0,0 +1,23 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class BasFlightPlanAreaModel { + private Integer planAreaSno; + private Integer planSno; + private String areaType; + private String fltMethod; + private Integer bufferZone; + private String fltElev; + private String createUserId; + private Date createDt; + private String updateUserId; + private Date updateDt; + private String docState = "R"; + private List coordList; + private List bufferCoordList; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanListRq.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanListRq.java new file mode 100644 index 00000000..ea979197 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanListRq.java @@ -0,0 +1,20 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.Date; + +import com.palnet.biz.api.comn.model.ComnPagingModel; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class BasFlightPlanListRq extends ComnPagingModel { + + private String groupId; + private Integer cstmrSno; + private Date schFltStDt; + private Date schFltEndDt; + private String aprvlYn; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanModel.java new file mode 100644 index 00000000..ad5c8eb1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanModel.java @@ -0,0 +1,34 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class BasFlightPlanModel { + private Integer planSno; + private String groupId; + private Integer cstmrSno; + private String idntfNum; + private String memberName; + private String email; + private String hpno; + private String clncd; + private String addr; + private String addrDtlCn; + private String zip; + private Date schFltStDt; + private Date schFltEndDt; + private String fltPurpose; + private String aprvlYn; + private String delYn; + private String createUserId; + private Date createDt; + private String updateUserId; + private Date updateDt; + private String docState = "R"; + private List areaList; + private List pilotList; + private List arcrftList; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanPilotModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanPilotModel.java new file mode 100644 index 00000000..71ee5e6f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanPilotModel.java @@ -0,0 +1,27 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.Date; + +@Data +public class BasFlightPlanPilotModel { + private Integer planPilotSno; + private Integer planSno; + private Integer cstmrSno; + private String groupNm; + private String memberName; + private String email; + private String hpno; + private String clncd; + private String addr; + private String addrDtlCn; + private String zip; + private String qlfcNo; + private String carrer; + private String createUserId; + private Date createDt; + private String updateUserId; + private Date updateDt; + private String docState = "R"; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightScheduleRs.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightScheduleRs.java new file mode 100644 index 00000000..e9a950a7 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightScheduleRs.java @@ -0,0 +1,25 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +import java.util.Date; + +@Data +public class BasFlightScheduleRs { + + private String groupId; + private String groupNm; + private String ownerNm; + private String idntfNum; + private String startAddress; + private String endAddress; + private Date schFltStDt; + private Date schFltEndDt; + private String cntrlId; + private Date cntrlStDt; + private Date cntrlEndDt; + + // BEFORE (B) : 비행 전, FLYING (F) : 비행 중, SUCCESS (S) : 비행 완료 + private String statusCd; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightWeatherModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightWeatherModel.java new file mode 100644 index 00000000..70d38056 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightWeatherModel.java @@ -0,0 +1,18 @@ +package com.palnet.biz.api.bas.flight.model; + +import lombok.Data; + +@Data +public class BasFlightWeatherModel { + private String serviceKey; + private String numOfRows; + private String pageNo; + private String dataType; + private String base_date; + private String base_time; + private String nx; + private String ny; + private double nx2; + private double ny2; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightMapper.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightMapper.java new file mode 100644 index 00000000..ffd856e1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightMapper.java @@ -0,0 +1,102 @@ +package com.palnet.biz.api.bas.flight.service; + +import com.palnet.biz.api.bas.flight.model.*; +import com.palnet.biz.jpa.entity.*; +import org.mapstruct.*; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface BasFlightMapper { + BasFlightMapper mapper = Mappers.getMapper(BasFlightMapper.class); + + // to entity + @Named("toPlanEntity") + FltPlanBas modelToEntity(BasFlightPlanModel model); + + @Named("toAreaEntity") + FltPlanArea modelToEntity(BasFlightPlanAreaModel model); + + @Named("toCoordEntity") + FltPlanAreaCoord modelToEntity(BasFlightPlanAreaCoordModel model); + + @Named("toPilotEntity") + FltPlanPilot modelToEntity(BasFlightPlanPilotModel model); + + @Named("toArcrftEntity") + FltPlanArcrft modelToEntity(BasFlightPlanArcrftModel model); + + // to entity merge + @Named("toPlanEntityForMergeModel") + void updateEntityByModel(@MappingTarget FltPlanBas entity, BasFlightPlanModel model); + @Named("toAreaEntityForMergeModel") + void updateEntityByModel(@MappingTarget FltPlanArea entity, BasFlightPlanAreaModel model); + @Named("toCoordEntityForMergeModel") + void updateEntityByModel(@MappingTarget FltPlanAreaCoord entity, BasFlightPlanAreaCoordModel model); + @Named("toPilotEntityForMergeModel") + void updateEntityByModel(@MappingTarget FltPlanPilot entity, BasFlightPlanPilotModel model); + @Named("toArcrftEntityForMergeModel") + void updateEntityByModel(@MappingTarget FltPlanArcrft entity, BasFlightPlanArcrftModel model); + + + // to model + @Named("toPlanModel") + BasFlightPlanModel entityToModel(FltPlanBas entity); + + @Named("toAreaModel") + BasFlightPlanAreaModel entityToModel(FltPlanArea entity); + + + @Named("toCoordModel") + BasFlightPlanAreaCoordModel entityToModel(FltPlanAreaCoord entity); + + @Named("toPilotModel") + BasFlightPlanPilotModel entityToModel(FltPlanPilot entity); + + @Named("toArcrftModel") + BasFlightPlanArcrftModel entityToModel(FltPlanArcrft entity); + + @Named("comArcrftBasToArcrftModel") + BasFlightPlanArcrftModel entityToModel(ComArcrftBas entity); + + + // to entity - list + @Named("toPlanEntity") + List modelToEntityPlanList(List model); + + @Named("toAreaEntity") + List modelToEntityAreaList(List model); + + @Named("toCoordEntity") + List modelToEntityCoordList(List model); + + @Named("toPilotEntity") + List modelToEntityPilotList(List model); + + @Named("toArcrftEntity") + List modelToEntityArcrftList(List model); + + + // to model - list + @Named("toPlanModel") + List entityToModelPlanList(List entity); + + @Named("toAreaModel") + List entityToModeArealList(List entity); + + @Named("toCoordModel") + List entityToModelCoordList(List entity); + + @Named("toPilotModel") + List entityToModelPilotList(List entity); + + @Named("toArcrftModel") + List entityToModelArcrftList(List entity); + + @Named("comArcrftBasToArcrftModel") + List comArcrftEntityToModelArcrftList(List entity); + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java new file mode 100644 index 00000000..2012de75 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java @@ -0,0 +1,725 @@ +package com.palnet.biz.api.bas.flight.service; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.locationtech.jts.geom.Coordinate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.palnet.biz.api.acnt.jwt.model.JwtGroupModel; +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.bas.flight.model.BasFlightAprovRq; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanArcrftModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaCoordModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaCoordRq; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanListRq; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanPilotModel; +import com.palnet.biz.api.bas.flight.model.BasFlightScheduleRs; +import com.palnet.biz.api.bas.flight.model.BasFlightWeatherModel; +import com.palnet.biz.api.bas.group.model.BasGroupJoinModel; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.jpa.entity.FltPlanArcrft; +import com.palnet.biz.jpa.entity.FltPlanArea; +import com.palnet.biz.jpa.entity.FltPlanAreaCoord; +import com.palnet.biz.jpa.entity.FltPlanBas; +import com.palnet.biz.jpa.entity.FltPlanPilot; +import com.palnet.biz.jpa.repository.flt.FltPlanArcrftRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanAreaCoordRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanAreaRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanBasRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanPilotRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanQueryRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupQueryRepository; +import com.palnet.biz.scheduler.ctr.model.CtrTrnsLctnModel; +import com.palnet.biz.scheduler.ctr.service.CtrTrnsLctnService; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.AreaUtils; +import com.palnet.comn.utils.EncryptUtils; + +import lombok.extern.log4j.Log4j2; + + +@Log4j2 +@Service +@Transactional(readOnly = true) +public class BasFlightService { + + @Autowired + private CtrTrnsLctnService ctrTrnsLctnService; + + private final FltPlanBasRepository fltPlanBasRepository; + private final FltPlanArcrftRepository fltPlanArcrftRepository; + private final FltPlanAreaRepository fltPlanAreaRepository; + private final FltPlanAreaCoordRepository fltPlanAreaCoordRepository; + private final FltPlanPilotRepository fltPlanPilotRepository; + private final FltPlanQueryRepository fltPlanQueryRepository; + private final PtyGroupQueryRepository ptyPlanQueryRepository; + private final JwtTokenUtil jwtTokenUtil; + private final AreaUtils areaUtils; + + public BasFlightService(FltPlanBasRepository fltPlanBasRepository, + FltPlanArcrftRepository fltPlanArcrftRepository, + FltPlanAreaRepository fltPlanAreaRepository, + FltPlanAreaCoordRepository fltPlanAreaCoordRepository, + FltPlanPilotRepository fltPlanPilotRepository, + FltPlanQueryRepository fltPlanQueryRepository, + PtyGroupQueryRepository ptyPlanQueryRepository, + JwtTokenUtil jwtTokenUtil, + AreaUtils areaUtils) { + this.fltPlanBasRepository = fltPlanBasRepository; + this.fltPlanArcrftRepository = fltPlanArcrftRepository; + this.fltPlanAreaRepository = fltPlanAreaRepository; + this.fltPlanAreaCoordRepository = fltPlanAreaCoordRepository; + this.fltPlanPilotRepository = fltPlanPilotRepository; + this.fltPlanQueryRepository = fltPlanQueryRepository; + this.ptyPlanQueryRepository = ptyPlanQueryRepository; + this.jwtTokenUtil = jwtTokenUtil; + this.areaUtils = areaUtils; + } + + // 비행계획서 조회 + public ComnPagingRs listPlan(BasFlightPlanListRq rq) { + List groupList = ptyPlanQueryRepository.joinList(rq.getCstmrSno()); + String userAccount = null; + String masterAccount = null; + String appAuth = jwtTokenUtil.getUserAuthByToken(); + + ComnPagingRs response = new ComnPagingRs<>(); + + Pageable pageable = PageRequest.of(rq.getPage()-1, rq.getRecord()); + if(groupList.size() > 0) { + for (BasGroupJoinModel list : groupList) { + if (list.getGroupId().equals(rq.getGroupId())) { + userAccount = list.getGroupAuthCd(); + } + } + } + if (appAuth.equals("SUPER") || appAuth.equals("ADMIN")) { + masterAccount = "ADMIN"; + } else if (userAccount.equals("MASTER") || userAccount.equals("LEADER")) { + masterAccount = "ADMIN"; + } else { + masterAccount = "NORMAL"; + } + PageImpl result = fltPlanQueryRepository.listPlan(rq, masterAccount, pageable); + + long total = fltPlanQueryRepository.listPlanCount(rq, masterAccount); + + long totalPage = total % rq.getRecord() > 0 ? (total/rq.getRecord()) + 1 : total/rq.getRecord(); + + response.setItems(result.getContent()); + response.setTotal(total); + response.setPage(rq.getPage()); + response.setTotalPage(totalPage); + + return response; + } + + // 비행계획서 상세 조회 + public BasFlightPlanModel detailPlan(Integer planSno) { + BasFlightPlanModel rs = new BasFlightPlanModel(); + // 비행계획서 + FltPlanBas planEntity = fltPlanBasRepository.findByPlanSnoAndDelYnNot(planSno, "Y").orElse(null); + if(planEntity != null){ + rs = BasFlightMapper.mapper.entityToModel(planEntity); + // 버퍼영역 + List areaEntityList = fltPlanAreaRepository.findByPlanSnoOrderByPlanAreaSnoAsc(planSno); + if (areaEntityList != null && !areaEntityList.isEmpty()) { + List area = new ArrayList<>(); + for (FltPlanArea areaEntity : areaEntityList) { + BasFlightPlanAreaModel areaModel = BasFlightMapper.mapper.entityToModel(areaEntity); + List coordEntityList = fltPlanAreaCoordRepository.findByPlanAreaSnoOrderByPlanAreaCoordSnoAsc(areaEntity.getPlanAreaSno()); + if (coordEntityList != null && !coordEntityList.isEmpty()) { + areaModel.setCoordList(BasFlightMapper.mapper.entityToModelCoordList(coordEntityList)); + + // Line인 경우 BufferList 생성 + if("LINE".equals(areaEntity.getAreaType())) { + List convertCoordinates = areaUtils.convertCoordinates(areaModel.getCoordList()); + List bufferList = areaUtils.buffer(convertCoordinates, areaModel.getBufferZone()); + List bufferCoordList = areaUtils.convertModel(bufferList); + + areaModel.setBufferCoordList(bufferCoordList); + } + } + area.add(areaModel); + } + rs.setAreaList(area); + } + // 조종사 + List pilotList = fltPlanPilotRepository.findByPlanSnoOrderByPlanPilotSnoAsc(planSno); + if (pilotList != null && !pilotList.isEmpty()) { + rs.setPilotList(BasFlightMapper.mapper.entityToModelPilotList(pilotList)); + } + // 기체 + List arcrft = fltPlanArcrftRepository.findByPlanSnoOrderByPlanArcrftSnoAsc(planSno); + if (arcrft != null && !arcrft.isEmpty()) { + rs.setArcrftList(BasFlightMapper.mapper.entityToModelArcrftList(arcrft)); + } + } + return rs; + } + + public void planValid(BasFlightPlanModel rq) { + boolean isEqualsFltElev = false; + List rqAreaList = rq.getAreaList(); + String rqFltElev = rqAreaList.get(0).getFltElev(); + + List effectivePlanList = fltPlanQueryRepository.CoordCheck(rq); + + List effectivePlanArea = new ArrayList<>(); + for(BasFlightPlanModel plan : effectivePlanList) { + effectivePlanArea.addAll(plan.getAreaList()); + } + for(BasFlightPlanAreaModel area : effectivePlanArea) { + if(rqFltElev.equals(area.getFltElev())) isEqualsFltElev = true; + } + List effectivePlanCount = fltPlanQueryRepository.CoordCount(rq); + for(BasFlightPlanModel i : effectivePlanList) { + if(rq.getPlanSno().equals(i.getPlanSno()))return; + } + if(effectivePlanList != null && !effectivePlanList.isEmpty()) { + for(BasFlightPlanModel plan : effectivePlanList) { + // 1. 구역 조회 + List areaList = fltPlanAreaRepository.findByPlanSnoOrderByPlanAreaSnoAsc(plan.getPlanSno()); + + // 2. 좌표 조회 -> 영역 포함 여부 확인 + for(FltPlanArea area : areaList) { + List coordList = fltPlanAreaCoordRepository.findByPlanAreaSnoOrderByPlanAreaCoordSnoAsc(area.getPlanAreaSno()); + + if(coordList != null && !coordList.isEmpty()) { + List coordListMapping = BasFlightMapper.mapper.entityToModelCoordList(coordList); + + // 2-1 영역 좌표 -> jts model로 mapping + List effectiveCoordList = areaUtils.convertCoordinates(coordListMapping); + List effectiveCoordBufferList = new ArrayList<>(); + + // Query에서 조회한 좌표로 버퍼좌표 생성 + if("LINE".equals(area.getAreaType())){ + List trans = areaUtils.transform(effectiveCoordList, "EPSG:4326", "EPSG:5181"); + List bufferList = areaUtils.buffer(trans, area.getBufferZone()); + effectiveCoordBufferList = areaUtils.transform(bufferList, "EPSG:5181", "EPSG:4326"); + } + if("POLYGON".equals(area.getAreaType())) { + effectiveCoordBufferList.addAll(effectiveCoordList); + } + if("CIRCLE".equals(area.getAreaType())) { + effectiveCoordBufferList = areaUtils.createCircle(effectiveCoordList.get(0), area.getBufferZone()); + } + + // 유효한 비행구역 검증하기. + for(BasFlightPlanAreaModel rqArea : rq.getAreaList()) { + boolean overlapCheck = false; + boolean overlapCheck2 = false; + boolean containCheck = false; + boolean containCheck2 = false; + List rqCoord = new ArrayList<>(); + List rqCoordBufferList = new ArrayList<>(); + + //rq로 들어온 좌표로 버퍼좌표 생성 + for(BasFlightPlanAreaCoordModel coord : rqArea.getCoordList()) { + Coordinate coords = new Coordinate(coord.getLon(), coord.getLat()); + rqCoord.add(coords); + } + if("LINE".equals(rqArea.getAreaType())){ + List trans = areaUtils.transform(rqCoord, "EPSG:4326", "EPSG:5181"); + List bufferList = areaUtils.buffer(trans, rqArea.getBufferZone()); + rqCoordBufferList = areaUtils.transform(bufferList, "EPSG:5181", "EPSG:4326"); + }else if( "POLYGON".equals(rqArea.getAreaType())) { + rqCoordBufferList.addAll(rqCoord); + }else if("CIRCLE".equals(rqArea.getAreaType())) { + rqCoordBufferList = areaUtils.createCircle(rqCoord.get(0), rqArea.getBufferZone()); + } + //검증 + + overlapCheck = areaUtils.overlaps(rqCoordBufferList, effectiveCoordBufferList); + overlapCheck2 = areaUtils.overlaps(effectiveCoordBufferList, rqCoordBufferList); + if((overlapCheck || overlapCheck2) && isEqualsFltElev) { + throw new CustomException(ErrorCode.PLAN_DATA_DUPLICATE); + } + for(Coordinate coord : effectiveCoordBufferList) { + containCheck = areaUtils.contains(rqCoordBufferList, coord); + if(containCheck && isEqualsFltElev) { + throw new CustomException(ErrorCode.PLAN_DATA_DUPLICATE); + } + } + for(Coordinate coord : rqCoordBufferList) { + containCheck2 = areaUtils.contains(effectiveCoordBufferList , coord); + if(containCheck2 && isEqualsFltElev) { + throw new CustomException(ErrorCode.PLAN_DATA_DUPLICATE); + } + } + } + } + } + + // 3. 중복 기체 확인 + for(BasFlightPlanAreaCoordRq idntfNum : effectivePlanCount) { + for(BasFlightPlanArcrftModel rqArcrft : rq.getArcrftList()) { + if(rqArcrft.getIdntfNum().equals(idntfNum.getIdntfNum())) { + throw new CustomException(ErrorCode.ARCRFT_DATA_DUPLICATE); + } + } + } + + } + } + } + + // 비행계획서 등록 + @Transactional + public boolean createPlan(BasFlightPlanModel rq) { + + // 비행계획서 유효성 검사. + this.planValid(rq); + + // 비행계획서 + String userId = jwtTokenUtil.getUserIdByToken(); + FltPlanBas basEntity = BasFlightMapper.mapper.modelToEntity(rq); + basEntity.setDelYn("N"); + basEntity.setAprvlYn("N"); + basEntity.setCreateUserId(userId); + basEntity.setUpdateUserId(userId); + FltPlanBas rBasEntity = fltPlanBasRepository.save(basEntity); + Integer planSno = rBasEntity.getPlanSno(); + // 비행구역 + List areaModelList = rq.getAreaList(); + if (areaModelList != null && !areaModelList.isEmpty()) { + for (BasFlightPlanAreaModel areaModel : areaModelList) { + FltPlanArea areaEntity = BasFlightMapper.mapper.modelToEntity(areaModel); + areaEntity.setPlanSno(planSno); + areaEntity.setCreateUserId(userId); + areaEntity.setUpdateUserId(userId); + FltPlanArea rAreaEntity = fltPlanAreaRepository.save(areaEntity); + Integer planAreaSno = rAreaEntity.getPlanAreaSno(); + List coordModelList = areaModel.getCoordList(); + if (coordModelList != null && !coordModelList.isEmpty()) { + for (BasFlightPlanAreaCoordModel coordModel : coordModelList) { + FltPlanAreaCoord coordEntity = BasFlightMapper.mapper.modelToEntity(coordModel); + coordEntity.setPlanAreaSno(planAreaSno); + coordEntity.setCreateUserId(userId); + fltPlanAreaCoordRepository.save(coordEntity); + } + } + } + } + + // 조종사 + List pilotModelList = rq.getPilotList(); + if (pilotModelList != null && !pilotModelList.isEmpty()) { + for (BasFlightPlanPilotModel pilotModel : pilotModelList) { + FltPlanPilot pilotEntity = BasFlightMapper.mapper.modelToEntity(pilotModel); + pilotEntity.setPlanSno(planSno); + pilotEntity.setCreateUserId(userId); + pilotEntity.setUpdateUserId(userId); + fltPlanPilotRepository.save(pilotEntity); + } + } + + + // 기체 + List arcrftModelList = rq.getArcrftList(); + if (arcrftModelList != null && !arcrftModelList.isEmpty()) { + for (BasFlightPlanArcrftModel arcrftModel : arcrftModelList) { + FltPlanArcrft arcrftEntity = BasFlightMapper.mapper.modelToEntity(arcrftModel); + arcrftEntity.setPlanSno(planSno); + arcrftEntity.setCreateUserId(userId); + arcrftEntity.setUpdateUserId(userId); + fltPlanArcrftRepository.save(arcrftEntity); + } + } + return true; + } + + // 비행계획서 수정 + @Transactional + public boolean updatePlan(BasFlightPlanModel rq) { + + // 비행계획서 유효성 검사. + this.planValid(rq); + + if (rq != null && rq.getPlanSno() != null) { + String userId = jwtTokenUtil.getUserIdByToken(); + Integer planSno = rq.getPlanSno(); + // 비행계획서 + FltPlanBas planEntity = fltPlanBasRepository.findById(planSno).orElseThrow(); + BasFlightMapper.mapper.updateEntityByModel(planEntity, rq); + planEntity.setUpdateUserId(userId); + fltPlanBasRepository.save(planEntity); + + // 비행구역 + List areaModelList = rq.getAreaList(); + if (areaModelList != null && !areaModelList.isEmpty()) { + List areaEntityList = fltPlanAreaRepository.findByPlanSnoOrderByPlanAreaSnoAsc(planSno); + for (BasFlightPlanAreaModel areaModel : areaModelList) { + //FltPlanArea areaEntity = fltPlanAreaRepository.findById(areaModel.getPlanAreaSno()).orElse(null); + FltPlanArea areaEntity = areaEntityList.stream().filter(fltPlanArea -> fltPlanArea.getPlanAreaSno().equals(areaModel.getPlanAreaSno())).findFirst().orElse(null); + if (areaEntity == null) { + areaEntity = BasFlightMapper.mapper.modelToEntity(areaModel); + areaEntity.setCreateUserId(userId); + } else { + BasFlightMapper.mapper.updateEntityByModel(areaEntity, areaModel); + } + areaEntity.setUpdateUserId(userId); + fltPlanAreaRepository.save(areaEntity); + + + List coordsModelList = areaModel.getCoordList(); + if (coordsModelList != null && !coordsModelList.isEmpty()) { + Integer areaSno = areaModel.getPlanAreaSno(); + List coordEntityList = fltPlanAreaCoordRepository.findByPlanAreaSnoOrderByPlanAreaCoordSnoAsc(areaSno); + for (BasFlightPlanAreaCoordModel coordModel : coordsModelList) { + FltPlanAreaCoord coordEntity = coordEntityList.stream().filter(fltPlanAreaCoord -> fltPlanAreaCoord.getPlanAreaCoordSno().equals(coordModel.getPlanAreaCoordSno())).findFirst().orElse(null); + if (coordEntity == null) { + coordEntity = BasFlightMapper.mapper.modelToEntity(coordModel); + coordEntity.setCreateUserId(userId); + } else { + BasFlightMapper.mapper.updateEntityByModel(coordEntity, coordModel); + } + fltPlanAreaCoordRepository.save(coordEntity); + } + List deleteCoordEntity = coordEntityList.stream().filter(fltPlanAreaCoord -> { + for (BasFlightPlanAreaCoordModel coordModel : coordsModelList) { + if (coordModel.getPlanAreaCoordSno() == fltPlanAreaCoord.getPlanAreaCoordSno()) + return false; + } + return true; + }).collect(Collectors.toList()); + fltPlanAreaCoordRepository.deleteAll(deleteCoordEntity); + } + + + } + + List deleteAreaEntity = areaEntityList.stream().filter(fltPlanArea -> { + for (BasFlightPlanAreaModel areaModel : areaModelList) { + if (areaModel.getPlanAreaSno() == fltPlanArea.getPlanAreaSno()) + return false; + } + return true; + }).collect(Collectors.toList()); + fltPlanAreaRepository.deleteAll(deleteAreaEntity); + + + } + + // 조종사 + List pilotModelList = rq.getPilotList(); + if(pilotModelList != null && !pilotModelList.isEmpty()){ + List pilotEntityList = fltPlanPilotRepository.findByPlanSnoOrderByPlanPilotSnoAsc(planSno); + for(BasFlightPlanPilotModel pilotModel : pilotModelList){ + FltPlanPilot pilotEntity = pilotEntityList.stream().filter(fltPlanPilot -> fltPlanPilot.getPlanPilotSno().equals(pilotModel.getPlanPilotSno())).findFirst().orElse(null); + if(pilotEntity == null){ + pilotEntity = BasFlightMapper.mapper.modelToEntity(pilotModel); + pilotEntity.setUpdateUserId(userId); + pilotEntity.setCreateUserId(userId); + + }else { + BasFlightMapper.mapper.updateEntityByModel(pilotEntity, pilotModel); + } + fltPlanPilotRepository.save(pilotEntity); + } + List deletePilotEntity = pilotEntityList.stream().filter(fltPlanPilot -> { + for (BasFlightPlanPilotModel pilotModel : pilotModelList) { + if (pilotModel.getPlanPilotSno() == fltPlanPilot.getPlanPilotSno()) + return false; + } + return true; + }).collect(Collectors.toList()); + fltPlanPilotRepository.deleteAll(deletePilotEntity); + } + + // 기체 + List arcrftModelList = rq.getArcrftList(); + if(arcrftModelList != null && !arcrftModelList.isEmpty()){ + List arcrftEntityList = fltPlanArcrftRepository.findByPlanSnoOrderByPlanArcrftSnoAsc(planSno); + for(BasFlightPlanArcrftModel arcrftModel : arcrftModelList){ + FltPlanArcrft arcrftEntity = arcrftEntityList.stream().filter(fltPlanArcrft -> fltPlanArcrft.getPlanArcrftSno().equals(arcrftModel.getPlanArcrftSno())).findFirst().orElse(null); + if(arcrftEntity == null){ + arcrftEntity = BasFlightMapper.mapper.modelToEntity(arcrftModel); + arcrftEntity.setUpdateUserId(userId); + arcrftEntity.setCreateUserId(userId); + }else { + BasFlightMapper.mapper.updateEntityByModel(arcrftEntity, arcrftModel); + } + fltPlanArcrftRepository.save(arcrftEntity); + } + List deleteArcrftEntity = arcrftEntityList.stream().filter(fltPlanArcrft -> { + for (BasFlightPlanArcrftModel arcrftModel : arcrftModelList) { + if (arcrftModel.getPlanArcrftSno() == fltPlanArcrft.getPlanArcrftSno()) + return false; + } + return true; + }).collect(Collectors.toList()); + fltPlanArcrftRepository.deleteAll(deleteArcrftEntity); + } + } + return true; + } + + // 비행계획서 삭제 + @Transactional + public boolean deletePlan(Integer planSno) { + FltPlanBas planEntity = fltPlanBasRepository.findById(planSno).orElseThrow(); + planEntity.setDelYn("Y"); + fltPlanBasRepository.save(planEntity); + return true; + } + + + + // 그룹 조종사 조회 + public List listPilotByGroup(String groupId) { + List pilotList = fltPlanQueryRepository.listPilot(groupId); + + /* 개인정보 복호화 처리 */ + for(BasFlightPlanPilotModel model : pilotList) { + if(!StringUtils.isEmpty(model.getHpno())) { + model.setHpno(EncryptUtils.decrypt(model.getHpno())); + } + + if(!StringUtils.isEmpty(model.getMemberName())) { +// model.setMemberName(EncryptUtils.decrypt(model.getMemberName())); + } + + if(!StringUtils.isEmpty(model.getEmail())) { + model.setEmail(EncryptUtils.decrypt(model.getEmail())); + } + } + + return pilotList; + } + + // 그룹 기체 조회 + public List listArcrftByGroup(String groupId) { + List arcrftModels = fltPlanQueryRepository.listArcrft(groupId); + +// List arcrftEntityList = comArcrftBasRepository.findByGroupIdOrderByArcrftSnoAsc(groupId); +// List arcrftModelList = BasFlightMapper.mapper.comArcrftEntityToModelArcrftList(arcrftEntityList); + return arcrftModels; + } + + // 비행 구역 buffer zone + public List getBuffer(List rq) { + + for(BasFlightPlanAreaModel area : rq) { + + if("LINE".equals(area.getAreaType())) { + List convertCoordinates = areaUtils.convertCoordinates(area.getCoordList()); // 객체 타입 변환 + List transCoordList = areaUtils.transform(convertCoordinates, "EPSG:4326", "EPSG:5181"); + + List bufferList = areaUtils.buffer(transCoordList, area.getBufferZone()); // buffer 영역 생성 + + List transBufferList = areaUtils.transform(bufferList, "EPSG:5181", "EPSG:4326"); // buffer 영역 좌표계 변환 + List bufferCoordList = areaUtils.convertModel(transBufferList); + + area.setBufferCoordList(bufferCoordList); + } + } + + return rq; + } + + // 비행계획서 리스트(승인) + public ComnPagingRs aprvList(BasFlightPlanListRq rq) { + String appAuth = jwtTokenUtil.getUserAuthByToken(); + + ComnPagingRs response = new ComnPagingRs<>(); + + Pageable pageable = PageRequest.of(rq.getPage()-1, rq.getRecord()); + + List groupAuthList = jwtTokenUtil.getGroupAuthByToken(); + + List groupIdList = new ArrayList<>(); + + String userAccount = null; + String masterAccount = null; + if(groupAuthList.size() > 0) { + for (JwtGroupModel list : groupAuthList) { + if (list.getGroupId().equals(rq.getGroupId())) { + userAccount = list.getGroupAuthCd(); + } + } + } + if (appAuth.equals("SUPER") || appAuth.equals("ADMIN")) { + masterAccount = "ADMIN"; + } else if (userAccount.equals("MASTER") || userAccount.equals("LEADER")) { + masterAccount = "ADMIN"; + } else { + masterAccount = "NORMAL"; + } + PageImpl result = fltPlanQueryRepository.aprvList(rq, masterAccount, pageable); + + long total = fltPlanQueryRepository.aprvCount(rq, masterAccount); + + long totalPage = total % rq.getRecord() > 0 ? (total/rq.getRecord()) + 1 : total/rq.getRecord(); + + response.setItems(result.getContent()); + response.setTotal(total); + response.setPage(rq.getPage()); + response.setTotalPage(totalPage); + + return response; + } + // 비행계획서 승인/미승인 + @Transactional + public int aprovePlan(BasFlightAprovRq rq) { + int cnt = fltPlanBasRepository.updateAprvlYnByPlanSnoIn(rq.getPlanSnoList(), rq.getAprvlYn()); + return cnt; + } + + public boolean checkAirspaceContains(List rq) { + boolean result = false; + + for(BasFlightPlanAreaModel area : rq) { + List coordinates = areaUtils.convertCoordinates(area.getCoordList()); + if("LINE".equals(area.getAreaType())) { + List transCoordList = areaUtils.transform(coordinates, "EPSG:4326", "EPSG:5181"); + List buffer = areaUtils.buffer(transCoordList, area.getBufferZone()); + List transBufferList = areaUtils.transform(buffer, "EPSG:5181", "EPSG:4326"); + result = areaUtils.overlaps(transBufferList); + } + + if("POLYGON".equals(area.getAreaType())) { + result = areaUtils.overlaps(coordinates); + } + + if("CIRCLE".equals(area.getAreaType())) { + List circle = areaUtils.createCircle(coordinates.get(0), area.getBufferZone()); + result = areaUtils.overlaps(circle); + } + } + + + return result; + } + + + //지역 검색 + public String searchArea(String apiUrl, Map requestHeaders) { + HttpURLConnection con = connect(apiUrl); + try { + con.setRequestMethod("GET"); + for(Map.Entry header :requestHeaders.entrySet()) { + con.setRequestProperty(header.getKey(), header.getValue()); + } + + int responseCode = con.getResponseCode(); + if(responseCode == HttpURLConnection.HTTP_OK) { + return readBody(con.getInputStream()); + } else { + return readBody(con.getErrorStream()); + } + } catch (IOException e) { + throw new RuntimeException("API 요청과 응답 실패", e); + } finally { + con.disconnect(); + } + } + + public HttpURLConnection connect(String apiUrl) { + try { + URL url = new URL(apiUrl); + return (HttpURLConnection)url.openConnection(); + } catch (MalformedURLException e) { + throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e); + } catch (IOException e) { + throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e); + } + } + + public String readBody(InputStream body) { + InputStreamReader streamReader = new InputStreamReader(body); + + try(BufferedReader lineReader = new BufferedReader(streamReader)) { + StringBuilder responseBody = new StringBuilder(); + + String line; + while ((line = lineReader.readLine()) != null) { + responseBody.append(line); + } + + return responseBody.toString(); + } catch (IOException e) { + throw new RuntimeException("API 응답을 읽는데 실패했습니다.", e); + } + } + + public List findSchecdule(String searchDate) { + + List schedule = fltPlanQueryRepository.findSchedule(searchDate); + + return schedule; + } + public JSONObject getWeather(BasFlightWeatherModel rq) throws IOException, ParseException { + StringBuilder urlBuilder = new StringBuilder("http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst"); + urlBuilder.append("?" + URLEncoder.encode("serviceKey","UTF-8") + "=r6RMUsk3Vtama7D6uq7MiWV9dTC9MwfIIr4%2F45y0uVNw6BaYbgpKmL%2BLUDFVTfIYUmEe4K%2FaniEjdV9mg5t82Q%3D%3D"); + urlBuilder.append("&" + URLEncoder.encode("pageNo","UTF-8") + "=" + URLEncoder.encode(rq.getPageNo(),"UTF-8")); + urlBuilder.append("&" + URLEncoder.encode("numOfRows","UTF-8") + "=" + URLEncoder.encode(rq.getNumOfRows(), "UTF-8")); /*한 페이지 결과 수*/ + urlBuilder.append("&" + URLEncoder.encode("dataType","UTF-8") + "=" + URLEncoder.encode("JSON", "UTF-8")); /*요청자료형식(XML/JSON) Default: XML*/ + urlBuilder.append("&" + URLEncoder.encode("base_date","UTF-8") + "=" + URLEncoder.encode(rq.getBase_date(), "UTF-8")); /*'21년 6월 28일 발표*/ + urlBuilder.append("&" + URLEncoder.encode("base_time","UTF-8") + "=" + URLEncoder.encode(rq.getBase_time(), "UTF-8")); /*06시 발표(정시단위) */ + urlBuilder.append("&" + URLEncoder.encode("nx","UTF-8") + "=" + URLEncoder.encode(rq.getNx(), "UTF-8")); /*예보지점의 X 좌표값*/ + urlBuilder.append("&" + URLEncoder.encode("ny","UTF-8") + "=" + URLEncoder.encode(rq.getNy(), "UTF-8")); /*예보지점의 Y 좌표값*/ + URL url = new URL(urlBuilder.toString()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setRequestProperty("Content-type", "application/json"); + log.info("Response code: " + conn.getResponseCode()); + BufferedReader rd; + if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) { + rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + } else { + rd = new BufferedReader(new InputStreamReader(conn.getErrorStream())); + } + StringBuilder sb = new StringBuilder(); + String line; + + while ((line = rd.readLine()) != null) { + sb.append(line); + + } + CtrTrnsLctnModel weatherResult = ctrTrnsLctnService.convertLatlonToAddress(rq.getNx2(),rq.getNy2()); + log.info("weatherResult >>>> : {}", weatherResult); + + + String str = sb.toString(); + JSONParser parser = new JSONParser(); + JSONObject jsonObject = (JSONObject) parser.parse(str); + if(weatherResult != null) { + jsonObject.put("area1",weatherResult.getArea1()); + jsonObject.put("area2",weatherResult.getArea2()); + jsonObject.put("area3",weatherResult.getArea3()); + jsonObject.put("landNm",weatherResult.getLandNm()); + jsonObject.put("landNum",weatherResult.getLandNum()); + } + + + rd.close(); + conn.disconnect(); + log.info(sb.toString()); + + return jsonObject; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupAprvController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupAprvController.java new file mode 100644 index 00000000..1848c94d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupAprvController.java @@ -0,0 +1,105 @@ +package com.palnet.biz.api.bas.group.controller; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.bas.group.model.BasGroupAprvModel; +import com.palnet.biz.api.bas.group.model.BasGroupAprvRqModel; +import com.palnet.biz.api.bas.group.service.BasGroupAprvService; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.comn.code.RSErrorCode; + +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/bas/group/aprv", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "그룹 승인 컨트롤러", description = "그룹 가입 승인 관련 API") +public class BasGroupAprvController { + + @Autowired + private final BasGroupAprvService service; + + /** + * 승인요청 조회 + * @param rq + * @return + */ + @GetMapping(value = "/list") + @ApiOperation(value = "승인요청 조회") + @Tag(name = "그룹 승인 컨트롤러", description = "그룹 가입 승인 관련 API") + public ResponseEntity list(BasGroupAprvRqModel rq) { + ComnPagingRs result = null; +// log.debug(">>>>" + rq.toString()); + + if(StringUtils.isEmpty(rq.getCstmrSno())) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.mylist(rq); + + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + + } + + /** + * 승인처리 / 승인취소 처리 + * @return + */ + @PutMapping(value = "/update") + @ApiOperation(value = "승인처리 / 승인취소 처리") + @Tag(name = "그룹 승인 컨트롤러", description = "그룹 가입 승인 관련 API") + public ResponseEntity update(@RequestBody BasGroupAprvModel rq) { + Map resultMap = new HashMap(); + + if(StringUtils.isEmpty(rq.getCstmrGroupSno())) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + boolean result = service.update(rq); + + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupController.java new file mode 100644 index 00000000..076ffb31 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupController.java @@ -0,0 +1,308 @@ +package com.palnet.biz.api.bas.group.controller; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.bas.group.model.BasGroupJoinModel; +import com.palnet.biz.api.bas.group.model.BasGroupModel; +import com.palnet.biz.api.bas.group.model.BasGroupRqModel; +import com.palnet.biz.api.bas.group.service.BasGroupService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.comn.code.RSErrorCode; +import com.palnet.comn.exception.CustomException; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/bas/group", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") +public class BasGroupController { + + @Autowired + private final BasGroupService service; + + @GetMapping(value = "/createid") + @ApiOperation(value = "그룹코드 생성") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + public ResponseEntity createid() { + Map resultMap = new HashMap(); + + try { + String result = service.createid(); + + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + /** + * 나의 그룹 목록 조회 + * @param rq + * @return + */ + @GetMapping(value = "/mylist") + @ApiOperation(value = "나의 그룹 목록 조회") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity mylist(Integer cstmrSno) { + List result = null; + + log.debug("Param : " + cstmrSno); + + //입력값 검증 + if(StringUtils.isEmpty(cstmrSno)) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.mylist(cstmrSno); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + /** + * 나의 그룹 - 참여 그룹 목록 조회 + * @param rq + * @return + */ + @GetMapping(value = "/joinlist") + @ApiOperation(value = "나의 그룹 - 참여 그룹 목록 조회") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity joinList(Integer cstmrSno) { + List result = null; + + + //입력값 검증 + if(StringUtils.isEmpty(cstmrSno)) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.joinList(cstmrSno); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + /** + * 그룹 목록 조회 + * @param rq + * @return + */ + @GetMapping(value = "/grouplist") + @ApiOperation(value = "그룹 목록 조회") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity grouplist(Integer cstmrSno) { + List result = null; + + + //입력값 검증 + if(StringUtils.isEmpty(cstmrSno)) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.groupList(cstmrSno); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + /** + * 전체 그룹 목록 조회 + * @param rq + * @return + */ + @GetMapping(value = "/list") + @ApiOperation(value = "전체 그룹 목록 조회") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + public ResponseEntity list(BasGroupRqModel rq) { + List result = null; + + try { + result = service.list(rq); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + /** + * 그룹 상세 조회 + * @param id + * @return + */ + @GetMapping(value = "/detail/{id}") + @ApiOperation(value = "그룹 상세 조회") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + @ApiImplicitParam(name = "id",value = "그룹ID", dataTypeClass = String.class) + public ResponseEntity detail(@PathVariable String id) { + BasGroupModel result = null; + + try { + result = service.detail(id); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + /** + * 그룹 생성 + * @return + * @throws Exception + */ + @PostMapping(value = "/create") + @ApiOperation(value = "그룹 생성") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + public ResponseEntity create(@RequestBody BasGroupModel rq) throws Exception { + Map resultMap = new HashMap(); + + try { + boolean result = service.create(rq); + + resultMap.put("result", result); + + } catch (CustomException e) { + log.error("IGNORE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + /** + * 그룹 수정 + * @return + * @throws Exception + */ + @PutMapping(value = "/update") + @ApiOperation(value = "그룹 수정") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + public ResponseEntity update(@RequestBody BasGroupModel rq) throws Exception { + Map resultMap = new HashMap(); + + try { + boolean result = service.update(rq); + + resultMap.put("result", result); + +// } catch (Exception e) { +// log.error("IGNORE : {}", e); +// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) +// .body(new ErrorResponse("Server Error", "-1")); +// +// } + } catch (CustomException e) { + log.error("IGNORE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + /** + * 그룹 삭제 + * @param id + * @return + */ + @DeleteMapping(value = "/delete/{id}") + @ApiOperation(value = "그룹 삭제") + @Tag(name = "그룹 컨트롤러", description = "그룹 관련 API") + @ApiImplicitParam(name = "id",value = "그룹ID", dataTypeClass = String.class) + public ResponseEntity delete(@PathVariable String id) { + Map resultMap = new HashMap(); + + try { + boolean result = service.delete(id); + + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupJoinController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupJoinController.java new file mode 100644 index 00000000..102db384 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupJoinController.java @@ -0,0 +1,117 @@ +package com.palnet.biz.api.bas.group.controller; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.bas.group.model.BasGroupJoinModel; +import com.palnet.biz.api.bas.group.model.BasGroupJoinRqModel; +import com.palnet.biz.api.bas.group.service.BasGroupJoinService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.comn.code.RSErrorCode; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/bas/group/join", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "그룹 참여 컨트롤러", description = "그룹 참여 관련 API") +public class BasGroupJoinController { + + @Autowired + private final BasGroupJoinService service; + + + @GetMapping(value = "/list") + @ApiOperation(value = "참여한 그룹 목록 조회") + @Tag(name = "그룹 참여 컨트롤러", description = "그룹 참여 관련 API") + public ResponseEntity list(BasGroupJoinRqModel rq) { + List result = null; + + if(StringUtils.isEmpty(rq.getCstmrSno())) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.joinFullList(rq); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + @PostMapping(value = "/create") + @ApiOperation(value = "그룹 가입 요청") + @Tag(name = "그룹 참여 컨트롤러", description = "그룹 참여 관련 API") + public ResponseEntity create(@RequestBody BasGroupJoinModel rq) { + Map resultMap = new HashMap(); + + try { + boolean result = service.create(rq); + + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + @PutMapping(value = "/update") + @ApiOperation(value = "그룹 가입 승인/미승인") + @Tag(name = "그룹 참여 컨트롤러", description = "그룹 참여 관련 API") + public ResponseEntity update(@RequestBody BasGroupJoinModel rq) { + Map resultMap = new HashMap(); + + if(StringUtils.isEmpty(rq.getCstmrGroupSno())) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + boolean result = service.update(rq); + + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupUserController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupUserController.java new file mode 100644 index 00000000..998fdffa --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/controller/BasGroupUserController.java @@ -0,0 +1,113 @@ +package com.palnet.biz.api.bas.group.controller; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.bas.group.model.BasGroupUserListModel; +import com.palnet.biz.api.bas.group.model.BasGroupUserModel; +import com.palnet.biz.api.bas.group.service.BasGroupUserService; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.comn.code.RSErrorCode; +import com.palnet.comn.exception.CustomException; + +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/bas/group/user", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "그룹 사용자 컨트롤러", description = "그룹 사용자 관련 API") +public class BasGroupUserController { + + @Autowired + private final BasGroupUserService service; + + + @GetMapping(value = "/list") + @ApiOperation(value = "그룹 사용자 조회") + @Tag(name = "그룹 사용자 컨트롤러", description = "그룹 사용자 관련 API") + public ResponseEntity list(BasGroupUserListModel rq) { + ComnPagingRs result = null; + + if(StringUtils.isEmpty(rq.getCstmrSno())) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.list(rq); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + + } + + + @PutMapping(value = "/update") + @ApiOperation(value = "그룹 사용자 권한 수정") + @Tag(name = "그룹 사용자 컨트롤러", description = "그룹 사용자 관련 API") + public ResponseEntity update(@RequestBody BasGroupUserModel rq) { + Map resultMap = new HashMap(); + + try { + boolean result = service.update(rq); + + resultMap.put("result", result); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + + } + + @PutMapping(value = "/delegate") + @ApiOperation(value = "MASTER 권한 위임") + @Tag(name = "그룹 사용자 컨트롤러", description = "그룹 사용자 관련 API") + public ResponseEntity delegate(@RequestBody List rq) { + Map resultMap = new HashMap(); + + try { + boolean result = service.delegate(rq); + resultMap.put("result", result); + } catch (CustomException e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse(e.getMessage(), e.getErrorCode())); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupAprvModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupAprvModel.java new file mode 100644 index 00000000..69c2356f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupAprvModel.java @@ -0,0 +1,39 @@ +package com.palnet.biz.api.bas.group.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BasGroupAprvModel { + + private Integer cstmrGroupSno; + + private String groupId; + + private String groupNm; + + private String groupTypeCd; + + private Integer cstmrSno; + + private String aprvlYn; + + private String joinYn; + + private String memberName; + + private String userId; + + private Date aprvlDt; + + private Date joinDt; + + private String groupAuthCd; + + private String aprvlUserId; + + private String trmnlId; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupAprvRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupAprvRqModel.java new file mode 100644 index 00000000..da8212d5 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupAprvRqModel.java @@ -0,0 +1,22 @@ +package com.palnet.biz.api.bas.group.model; + +import com.palnet.biz.api.comn.model.ComnRqModel; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class BasGroupAprvRqModel extends ComnRqModel { + + private String groupNm; + + private String memberName; + + private String aprvYn; + + private Integer cstmrSno; + + private String groupId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupJoinModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupJoinModel.java new file mode 100644 index 00000000..f6edc3fe --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupJoinModel.java @@ -0,0 +1,38 @@ +package com.palnet.biz.api.bas.group.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BasGroupJoinModel { + + private Integer cstmrGroupSno; + + private String groupId; + + private String groupNm; + + private String groupTypeCd; + + private Integer cstmrSno; + + private String aprvlYn = "N"; + + private String joinYn = "N"; + + private Date joinDt; + + private Date aprvlDt; + + private String groupAuthCd; + + private Date createDt; + + private Date updateDt; + + private String myGroupAuthCd; + + private String trmnlId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupJoinRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupJoinRqModel.java new file mode 100644 index 00000000..866fa7ca --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupJoinRqModel.java @@ -0,0 +1,18 @@ +package com.palnet.biz.api.bas.group.model; + +import com.palnet.biz.api.comn.model.ComnRqModel; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class BasGroupJoinRqModel extends ComnRqModel{ + + private String groupNm; + + private String groupId; + + private Integer cstmrSno; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupModel.java new file mode 100644 index 00000000..6630a14d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupModel.java @@ -0,0 +1,24 @@ +package com.palnet.biz.api.bas.group.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BasGroupModel { + + private String groupId; + + private String groupNm; + + private String groupTypeCd; + + private int cstmrSno; + + private Date createDt; + + private Date updateDt; + + private String trmnlId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupRqModel.java new file mode 100644 index 00000000..11b35e4b --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupRqModel.java @@ -0,0 +1,16 @@ +package com.palnet.biz.api.bas.group.model; + +import com.palnet.biz.api.comn.model.ComnRqModel; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class BasGroupRqModel extends ComnRqModel{ + + private String groupNm; + + private String groupId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserListModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserListModel.java new file mode 100644 index 00000000..27474a42 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserListModel.java @@ -0,0 +1,17 @@ +package com.palnet.biz.api.bas.group.model; + +import com.palnet.biz.api.comn.model.ComnPagingModel; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class BasGroupUserListModel extends ComnPagingModel{ + + private String memberName; + + private String groupId; + + private int cstmrSno; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserModel.java new file mode 100644 index 00000000..d285bfa2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserModel.java @@ -0,0 +1,32 @@ +package com.palnet.biz.api.bas.group.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BasGroupUserModel { + + private Integer cstmrGroupSno; + + private String groupId; + + private String groupNm; + + private String groupTypeCd; + + private Integer cstmrSno; + + private String memberName; + + private String userId; + + private Date aprvlDt; + + private Date joinDt; + + private String joinYn; + + private String groupAuthCd; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserRqModel.java new file mode 100644 index 00000000..732d8c75 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/model/BasGroupUserRqModel.java @@ -0,0 +1,21 @@ +package com.palnet.biz.api.bas.group.model; + +import com.palnet.biz.api.comn.model.ComnRqModel; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class BasGroupUserRqModel extends ComnRqModel{ + + private String groupNm; + + private String memberName; + + private String groupAuthCd; + + private Integer cstmrSno; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupAprvService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupAprvService.java new file mode 100644 index 00000000..f83dfa11 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupAprvService.java @@ -0,0 +1,97 @@ +package com.palnet.biz.api.bas.group.service; + +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.bas.group.model.BasGroupAprvModel; +import com.palnet.biz.api.bas.group.model.BasGroupAprvRqModel; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.jpa.entity.PtyCstmrGroup; +import com.palnet.biz.jpa.repository.pty.PtyCstmrGroupRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupQueryRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.DateUtils; + +@Service +public class BasGroupAprvService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private PtyGroupQueryRepository query; + + @Autowired + private PtyCstmrGroupRepository ptyCstmrGroupRepository; + + + /** + * 승인요청 조회 + * @param rq + * @return + */ + public ComnPagingRs mylist(BasGroupAprvRqModel rq){ + + ComnPagingRs response = new ComnPagingRs<>(); + + Pageable pageable = PageRequest.of(rq.getPage()-1, rq.getRecord()); + + PageImpl result = query.aprvList(rq, pageable); + + long total = query.aprvCount(rq, pageable); + + long totalPage = total % rq.getRecord() > 0 ? (total/rq.getRecord()) + 1 : total/rq.getRecord(); + + response.setItems(result.getContent()); + response.setTotal(total); + response.setPage(rq.getPage()); + response.setTotalPage(totalPage); + + return response; + + } + + + /** + * Y : 가입 , N : 탈퇴 , B : 블럭처리 , A: 가입신청 , C : 가입신청 취소 + * 승인처리 / 승인취소 처리 + * @param + * @return + * @throws Exception + */ + public boolean update(BasGroupAprvModel rq) throws Exception{ + + Optional optional = ptyCstmrGroupRepository.findById(rq.getCstmrGroupSno()); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + PtyCstmrGroup entity = optional.get(); + if(rq.getAprvlYn().equals("Y")){ + entity.setAprvlDt(DateUtils.nowDate()); + entity.setAprvlUserId(rq.getAprvlUserId()); + + entity.setGroupAuthCd(rq.getGroupAuthCd()); + entity.setTrmnlId(rq.getTrmnlId()); + } else { + entity.setGroupAuthCd(""); + entity.setTrmnlId(""); + } + entity.setAprvlYn(rq.getAprvlYn()); + + if(ptyCstmrGroupRepository.save(entity) == null) + throw new CustomException(ErrorCode.FAIL); + return true; + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupJoinService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupJoinService.java new file mode 100644 index 00000000..c8fd5576 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupJoinService.java @@ -0,0 +1,122 @@ +package com.palnet.biz.api.bas.group.service; + +import java.util.List; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.bas.group.model.BasGroupJoinModel; +import com.palnet.biz.api.bas.group.model.BasGroupJoinRqModel; +import com.palnet.biz.api.bas.group.model.BasGroupModel; +import com.palnet.biz.jpa.entity.PtyCstmrGroup; +import com.palnet.biz.jpa.entity.PtyGroupBas; +import com.palnet.biz.jpa.repository.pty.PtyCstmrGroupRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupQueryRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.DateUtils; + +@Service +public class BasGroupJoinService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private PtyGroupQueryRepository query; + + @Autowired + private PtyGroupBasRepository ptyGroupBasRepository; + + @Autowired + private PtyCstmrGroupRepository ptyCstmrGroupRepository; + + + /** + * 참여할 목록 조회 + * @param rq + * @return + */ + public List joinFullList(BasGroupJoinRqModel rq){ + + List resultList = query.joinFullList(rq); + + return resultList; + } + + + /** + * 가입요청 처리 + * @param + * @return + * @throws Exception + */ + public boolean create(BasGroupJoinModel rq) throws Exception{ + + boolean isNotJoin = query.isNotJoin(rq.getCstmrSno(), rq.getGroupId()); + + if(!isNotJoin) { + throw new CustomException(ErrorCode.DATA_DUPLICATE); + } + + boolean isReJoin = query.isReJoin(rq.getCstmrSno(), rq.getGroupId()); + //참여 정보 입력 하기 + if(!isReJoin) { + PtyCstmrGroup entity2 = new PtyCstmrGroup(); + entity2.setGroupId(rq.getGroupId()); + entity2.setGroupAuthCd(rq.getGroupAuthCd()); //생성한 사람은 최고 권한 부여 (MASTER , LEADER, NORMAL) 로 구분 하여 사용 + entity2.setCstmrSno(rq.getCstmrSno()); + entity2.setJoinYn("Y"); + entity2.setJoinDt(DateUtils.nowDate()); + entity2.setAprvlYn("N"); + if(ptyCstmrGroupRepository.save(entity2) == null) + throw new CustomException(ErrorCode.FAIL); + }else { + PtyCstmrGroup entity = ptyCstmrGroupRepository.findRejoinUser(rq.getGroupId(), rq.getCstmrSno()); + entity.setJoinYn("Y"); + entity.setJoinDt(DateUtils.nowDate()); + ptyCstmrGroupRepository.updateWithdrwDt(rq.getGroupId(), rq.getCstmrSno()); + if(ptyCstmrGroupRepository.save(entity) == null) + throw new CustomException(ErrorCode.FAIL); + } + return true; + + } + + /** + * Y : 가입 , N : 탈퇴 , B : 블럭처리 , A: 가입신청 , C : 가입신청 취소 + * 가입취소 / 탈퇴 처리 + * @param + * @return + * @throws Exception + */ + public boolean update(BasGroupJoinModel rq) throws Exception{ + + Optional optional = ptyCstmrGroupRepository.findById(rq.getCstmrGroupSno()); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + PtyCstmrGroup entity = optional.get(); + + if(rq.getJoinYn().equals("N")) { + entity.setAprvlYn("N"); + entity.setAprvlUserId(""); + entity.setGroupAuthCd(""); + entity.setWthdrwDt(DateUtils.nowDate()); + } + + entity.setJoinYn(rq.getJoinYn()); + + if(ptyCstmrGroupRepository.save(entity) == null) + throw new CustomException(ErrorCode.FAIL); + return true; + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupService.java new file mode 100644 index 00000000..7135f6f2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupService.java @@ -0,0 +1,248 @@ +package com.palnet.biz.api.bas.group.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.bas.group.model.BasGroupJoinModel; +import com.palnet.biz.api.bas.group.model.BasGroupModel; +import com.palnet.biz.api.bas.group.model.BasGroupRqModel; +import com.palnet.biz.jpa.entity.PtyCstmrGroup; +import com.palnet.biz.jpa.entity.PtyGroupBas; +import com.palnet.biz.jpa.repository.pty.PtyCstmrGroupRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupQueryRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.palnet.comn.utils.DateUtils; + +@Service +public class BasGroupService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private PtyGroupQueryRepository query; + + @Autowired + private PtyGroupBasRepository ptyGroupBasRepository; + + @Autowired + private PtyCstmrGroupRepository ptyCstmrGroupRepository; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + + public String createid() { + + String groupId = ""; + + while(true) { + groupId = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase().substring(0, 6); + Optional optional = ptyGroupBasRepository.findById(groupId); + if(!optional.isPresent()) { + break; + } + } + + return groupId; + } + + /** + * 나의 그룹 목록 + * @param cstmrSno + * @return + */ + public List mylist(int cstmrSno){ + + + List resultList = query.mylist(cstmrSno); + + return resultList; + } + + /** + * 그룹 목록 + * @param cstmrSno + * @return + */ + public List groupList(int cstmrSno){ + + String appAuth = jwtTokenUtil.getUserAuthByToken(); + List resultList = new ArrayList<>(); + if("SUPER".equals(appAuth)||"ADMIN".equals(appAuth)) { + resultList = query.groupAdminList(cstmrSno); + } else { + resultList = query.groupUserList(cstmrSno); + } + + return resultList; + } + + /** + * 나의 그룹 - 참여 그룹 목록 + * @param cstmrSno + * @return + */ + public List joinList(int cstmrSno){ + + List resultList = query.joinList(cstmrSno); + + return resultList; + } + + /** + * 전체 그룹 목록 + * @param rq + * @return + */ + public List list(BasGroupRqModel rq){ + + + List resultList = query.list(rq); + + return resultList; + } + + /** + * 그룹 상세 조회 + * @param groupId + * @return + * @throws Exception + */ + public BasGroupModel detail(String groupId) throws Exception{ + + BasGroupModel model = new BasGroupModel(); + + Optional optional = ptyGroupBasRepository.findById(groupId); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + PtyGroupBas entity = optional.get(); + + BeanUtils.copyProperties(entity , model); + + + return model; + + } + + /** + * 그룹 생성 + * @param rq + * @return + * @throws Exception + */ + public boolean create(BasGroupModel rq) throws Exception{ + + Optional optional = ptyGroupBasRepository.findById(rq.getGroupId()); + List groupNm = ptyGroupBasRepository.findByGroupNm(rq.getGroupNm()); + for(PtyGroupBas name : groupNm) { + if(rq.getGroupNm().equals(name.getGroupNm())) { + throw new CustomException(ErrorCode.DATA_DUPLICATE); + } + } + if (optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_DUPLICATE); + } + + PtyGroupBas entity = new PtyGroupBas(); + BeanUtils.copyProperties(rq , entity); + entity.setUpdateDt(DateUtils.nowDate()); + entity.setUseYn("Y"); + entity.setCreateDt(DateUtils.nowDate()); + entity.setTrmnlId(rq.getTrmnlId()); + + //참여 정보 입력 하기 + PtyCstmrGroup entity2 = new PtyCstmrGroup(); + entity2.setGroupId(rq.getGroupId()); +// entity2.setGroupAuthCd("CREATER"); //생성한 사람은 최고 권한 부여 (CREATER , ADMIN , USER) 로 구분 하여 사용 + entity2.setGroupAuthCd("MASTER"); //생성한 사람은 최고 권한 부여 (MASTER , LEADER, NORMAL) 로 구분 하여 사용 + entity2.setAprvlYn("Y"); //자동 승인 처리 함 + entity2.setAprvlDt(DateUtils.nowDate()); + entity2.setCstmrSno(rq.getCstmrSno()); + entity2.setJoinYn("Y"); + entity2.setJoinDt(DateUtils.nowDate()); + entity2.setTrmnlId(rq.getTrmnlId()); + + if( ptyGroupBasRepository.save(entity) == null) + throw new CustomException(ErrorCode.FAIL); + + if(ptyCstmrGroupRepository.save(entity2) == null) + throw new CustomException(ErrorCode.FAIL); + + return true; + + } + + /** + * 그룹 수정 + * @param rq + * @return + * @throws Exception + */ + public boolean update(BasGroupModel rq) throws Exception{ + + Optional optional = ptyGroupBasRepository.findById(rq.getGroupId()); + List groupNm = ptyGroupBasRepository.findByGroupNm(rq.getGroupNm()); + for(PtyGroupBas name : groupNm) { + if(rq.getGroupNm().equals(name.getGroupNm())) { + throw new CustomException(ErrorCode.DATA_DUPLICATE); + } + } + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + PtyGroupBas entity = optional.get(); + entity.setGroupNm(rq.getGroupNm()); + entity.setGroupTypeCd(rq.getGroupTypeCd()); + entity.setUpdateDt(DateUtils.nowDate()); + + if(ptyGroupBasRepository.save(entity) == null) + throw new CustomException(ErrorCode.FAIL); + + return true; + + + + } + + /** + * 그룹 삭제 + * @param groupId + * @return + * @throws Exception + */ + public boolean delete(String groupId) throws Exception{ + + Optional optional = ptyGroupBasRepository.findById(groupId); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + PtyGroupBas entity = optional.get(); + entity.setUseYn("N"); + entity.setUpdateDt(DateUtils.nowDate()); + + if(ptyGroupBasRepository.save(entity) == null) + throw new CustomException(ErrorCode.FAIL); + + return true; + + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupUserService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupUserService.java new file mode 100644 index 00000000..3cc8da81 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/group/service/BasGroupUserService.java @@ -0,0 +1,120 @@ +package com.palnet.biz.api.bas.group.service; + +import java.util.List; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRsModel; +import com.palnet.biz.api.bas.group.model.BasGroupUserListModel; +import com.palnet.biz.api.bas.group.model.BasGroupUserModel; +import com.palnet.biz.api.comn.model.ComnPagingRs; +import com.palnet.biz.jpa.entity.PtyCstmrGroup; +import com.palnet.biz.jpa.repository.pty.PtyCstmrGroupRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupBasRepository; +import com.palnet.biz.jpa.repository.pty.PtyGroupQueryRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; + +@Service +public class BasGroupUserService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private PtyGroupQueryRepository query; + + @Autowired + private PtyGroupBasRepository ptyGroupBasRepository; + + @Autowired + private PtyCstmrGroupRepository ptyCstmrGroupRepository; + + + + + /** + * 그룹 사용자 조회 + * @param rq + * @return + */ + public ComnPagingRs list(BasGroupUserListModel rq){ + + ComnPagingRs response = new ComnPagingRs<>(); + + Pageable pageable = PageRequest.of(rq.getPage()-1, rq.getRecord()); + + PageImpl result = query.userList(rq, pageable); + + long total = query.userCount(rq, pageable); + + long totalPage = total % rq.getRecord() > 0 ? (total/rq.getRecord()) + 1 : total/rq.getRecord(); + + response.setItems(result.getContent()); + response.setTotal(total); + response.setPage(rq.getPage()); + response.setTotalPage(totalPage); + + return response; + } + + + + /** + * 그룹사용자 권한수정 / 블럭 처리 + * @param + * @return + * @throws Exception + */ + public boolean update(BasGroupUserModel rq) throws Exception{ + + Optional optional = ptyCstmrGroupRepository.findById(rq.getCstmrGroupSno()); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + + PtyCstmrGroup entity = optional.get(); + + entity.setGroupAuthCd(rq.getGroupAuthCd()); + entity.setJoinYn(rq.getJoinYn()); + + if(ptyCstmrGroupRepository.save(entity) == null) + throw new CustomException(ErrorCode.FAIL); + return true; + + } + + public boolean delegate(List rq) throws Exception{ + + for(BasGroupUserModel model : rq) { + BasGroupUserModel userInfo = new BasGroupUserModel(); + + userInfo.setCstmrGroupSno(model.getCstmrGroupSno()); + userInfo.setGroupAuthCd(model.getGroupAuthCd()); + userInfo.setJoinYn(model.getJoinYn()); + + Optional optional = ptyCstmrGroupRepository.findById(userInfo.getCstmrGroupSno()); + + if (!optional.isPresent()) { + throw new CustomException(ErrorCode.DATA_NOTFIND); + } + PtyCstmrGroup entity = optional.get(); + + entity.setGroupAuthCd(model.getGroupAuthCd()); + entity.setJoinYn(model.getJoinYn()); + + if(ptyCstmrGroupRepository.save(entity) == null) + throw new CustomException(ErrorCode.FAIL); + } + return true; + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnPagingModel.java b/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnPagingModel.java new file mode 100644 index 00000000..d90ba5e8 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnPagingModel.java @@ -0,0 +1,13 @@ +package com.palnet.biz.api.comn.model; + +import lombok.Data; + +@Data +public class ComnPagingModel { + + private int record = 10; // 데이터 표출 수 + private int page = 0; // 현재 페이지 + private int stIdx = 0; // 시작 위치 + private int endIdx = 0; // 끝 위치 + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnPagingRs.java b/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnPagingRs.java new file mode 100644 index 00000000..adcbb2dd --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnPagingRs.java @@ -0,0 +1,16 @@ +package com.palnet.biz.api.comn.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class ComnPagingRs { + + private long total; // 전체 리스트 수 + private long totalPage; // 전체 페이지 수 + private long page; // 현재 페이지 + + private List items; // 현재 페이지 데이터 + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnRqModel.java new file mode 100644 index 00000000..8fa5074f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/model/ComnRqModel.java @@ -0,0 +1,17 @@ +package com.palnet.biz.api.comn.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class ComnRqModel extends ComnPagingModel { + private String stDate; + + private String endDate; + + private String search1; + + private String searchType1; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/model/ControlGpsDataContext.java b/pav-server/src/main/java/com/palnet/biz/api/comn/model/ControlGpsDataContext.java new file mode 100644 index 00000000..52c193a3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/model/ControlGpsDataContext.java @@ -0,0 +1,33 @@ +package com.palnet.biz.api.comn.model; + +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class ControlGpsDataContext { + + private Map idntfKey; + + public ControlGpsDataContext() { + this.idntfKey = new ConcurrentHashMap<>(); + } + + public void putIdntfKey(String key, String value) { + idntfKey.put(key, value); + } + + public void removeIdntfKey(String key) { + idntfKey.remove(key); + } + + public String getIndtfKey(String key) { + return idntfKey.get(key); + } + + public Map getAllKeys() { + return idntfKey; + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/response/BasicResponse.java b/pav-server/src/main/java/com/palnet/biz/api/comn/response/BasicResponse.java new file mode 100644 index 00000000..adaa03f0 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/response/BasicResponse.java @@ -0,0 +1,5 @@ +package com.palnet.biz.api.comn.response; + +public abstract class BasicResponse { + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/response/ErrorResponse.java b/pav-server/src/main/java/com/palnet/biz/api/comn/response/ErrorResponse.java new file mode 100644 index 00000000..a25d69b3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/response/ErrorResponse.java @@ -0,0 +1,29 @@ +package com.palnet.biz.api.comn.response; + +import com.palnet.comn.code.RSErrorCode; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class ErrorResponse extends BasicResponse{ + + private String errorMessage; + private String errorCode; + + public ErrorResponse(String errorMessage) { + this.errorMessage = errorMessage; + this.errorCode = "404"; + } + + public ErrorResponse(RSErrorCode code) { + this.errorMessage = code.message(); + this.errorCode = code.code(); + } + public ErrorResponse(String errorMessage, String errorCode) { + this.errorMessage = errorMessage; + this.errorCode = errorCode; + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/response/SuccessResponse.java b/pav-server/src/main/java/com/palnet/biz/api/comn/response/SuccessResponse.java new file mode 100644 index 00000000..d68740d5 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/response/SuccessResponse.java @@ -0,0 +1,25 @@ +package com.palnet.biz.api.comn.response; + +import java.util.List; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +public class SuccessResponse extends BasicResponse { + + private int count; + private T data; + + public SuccessResponse(T data) { + this.data = data; + if(data instanceof List) { + this.count = ((List)data).size(); + } else { + this.count = 1; + } + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/CtrCntrlController.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/CtrCntrlController.java new file mode 100644 index 00000000..1f971991 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/CtrCntrlController.java @@ -0,0 +1,299 @@ +package com.palnet.biz.api.ctr.cntrl.controller; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.text.SimpleDateFormat; +import java.time.LocalTime; +import java.util.*; + +import com.palnet.biz.api.ctr.cntrl.model.*; +import com.palnet.biz.scheduler.ctr.model.CtrTrnsLctnModel; +import com.palnet.biz.scheduler.ctr.service.CtrTrnsLctnService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.locationtech.jts.geom.Coordinate; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import com.palnet.biz.api.bas.flight.model.BasFlightPlanModel; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.api.ctr.cntrl.service.CtrCntrlService; +import com.palnet.comn.model.GPHistoryModel; + +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequestMapping(value = "/api/ctr/cntrl", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") +public class CtrCntrlController { + + private final CtrCntrlService service; + + public CtrCntrlController(CtrCntrlService service) { + this.service = service; + } + + /** + * TODO 드론 관제 이력 목록 (Socket 분리 전) + * + * @param id - 관제 ID + * @return + */ + @GetMapping(value = "/history/{id}") + @ApiOperation(value = "TODO 드론 관제 이력 목록 (Socket 분리 전)") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity historyList(@PathVariable String id) { + List result = null; + + try { + result = service.getListHistory(id); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + } + + /** + * TODO 드론 관제 상세 정보 + * + * @param id - 관제 ID + * @return + */ + @GetMapping(value = "/detail/{id}") + @ApiOperation(value = "TODO 드론 관제 상세 정보") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity detail(@PathVariable String id) { + CtrCntrlDtlModel result = null; + + try { + result = service.getDetail(id); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + } + + /** + * TODO 드론 관제 '실시간' 이력 목록 + * + * @param id - 관제 ID + * @return + */ + @GetMapping(value = "/history/list/{id}") + @ApiOperation(value = "TODO 드론 관제 '실시간' 이력 목록") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity history(@PathVariable String id) { + List history; + + try { + history = service.getHistory(id); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body(new SuccessResponse<>(history)); + } + + @GetMapping("/api/weather") + @ApiOperation(value = "드론 관제 날씨") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + public ResponseEntity restApiGetWeather(CtrCntrlWeatherModel rq) throws IOException, ParseException { + JSONObject jsonObject = null; + try { + jsonObject = service.getWeather(rq); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body(new SuccessResponse<>(jsonObject)); + } + /** + * TODO 비행 관제 사용자 권한 정보 + * + * @param cstmrSno + * @return + */ + @GetMapping("/group") + @ApiOperation(value = "TODO 비행 관제 사용자 권한 정보") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity findGroupAuthInfo(int cstmrSno) { + List list; + + try { + list = service.getGroupAuthInfo(); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + + return ResponseEntity.ok().body(new SuccessResponse(list)); + } + + /** + * TODO 비행 관제 사용자 비행 계획서 정보 + * + * @param idntfNum + * @return + */ + @GetMapping("/flight_plan/{idntfNum}") + @ApiOperation(value = "TODO 비행 관제 사용자 비행 계획서 정보") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + @ApiImplicitParam(name = "idtfNum",value = "식별번호", dataTypeClass = String.class) + public ResponseEntity findFlightPlan(@PathVariable("idntfNum") String idntfNum) { + List list; + + try { + list = service.getFlightPlan(idntfNum); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + + return ResponseEntity.ok().body(new SuccessResponse(list)); + } + + /** + * TODO 드론 운행 시작 후 알람 목록 + * + * @param id - 관제 ID + * @return + */ + @GetMapping(value = "/warn/detail/{id}") + @ApiOperation(value = "TODO 드론 운행 시작 후 알람 목록") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + @ApiImplicitParam(name = "id",value = "관제ID", dataTypeClass = String.class) + public ResponseEntity warnDetail(@PathVariable String id){ + List warnLog; + + try { + warnLog = service.getWarnLog(id); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body(new SuccessResponse(warnLog)); + } + + /** + * TODO 기체 별 최신 비정상 로그 및 비정상 로그 전체 개수 + * + * @param id + * @return + */ + @PostMapping(value = "/arcrft/warn/list") + @ApiOperation(value = "TODO 기체 별 최신 비정상 로그 및 비정상 로그 전체 개수") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + public ResponseEntity arcrftWarnList(@RequestBody CtrCntrlArcrftWarnRqModel rq){ +// public ResponseEntity arcrftWarnList(@RequestParam("id") String id){ + List arcrftWarnList; + Map result = new HashMap<>(); + + try { + arcrftWarnList = service.getArcrftWarnList(rq.getCntrlId()); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body(new SuccessResponse(arcrftWarnList)); + } + + /** + * TODO 비행 관제 구역 비정상 상황 체크 + * + * @param rq + * @return + */ + @PostMapping("/contains") + @ApiOperation(value = "TODO 비행 관제 구역 비정상 상황 체크") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + public ResponseEntity checkPlanContains(@RequestBody CtrCntrlPlanContainsRq rq) { + CtrCntrlPlanContainsRs rs; + + try { + rs = service.checkPlanContains(rq); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + + return ResponseEntity.ok().body(new SuccessResponse(rs)); + } + + /** + * TODO 실시간 Control ID 발급 + * + * @param id + * @return + */ + @GetMapping("/id/{id}") + @ApiOperation(value = "TODO 실시간 Control ID 발급") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + public ResponseEntity getId(@PathVariable String id) { + Map result; + try { + result = service.getId(id); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + } + + /** + * TODO 비행 관제 기체의 비정상 상황 확인 + * + * @param id + * @param lat + * @param lon + * @return + */ + @GetMapping("/warn/{id}/{lat}/{lon}") + @ApiOperation(value = "TODO 비행 관제 기체의 비정상 상황 확인") + @Tag(name = "드론 관제 시스템", description = "드론 관제 관련 API") + public ResponseEntity checkWarring(@PathVariable String id, + @PathVariable Double lat, + @PathVariable Double lon) { + Map result; + try { + result = service.checkWarring(id, lat, lon); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/PingController.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/PingController.java new file mode 100644 index 00000000..ed25e2f1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/PingController.java @@ -0,0 +1,13 @@ +package com.palnet.biz.api.ctr.cntrl.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class PingController { + + @GetMapping("/ping") + public String ping(){ + return "SUCCESS"; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/SocketReceiverController.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/SocketReceiverController.java new file mode 100644 index 00000000..21d9e3f5 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/controller/SocketReceiverController.java @@ -0,0 +1,57 @@ +package com.palnet.biz.api.ctr.cntrl.controller; + +import com.palnet.biz.api.ctr.cntrl.service.SocketReceiverService; +import com.palnet.comn.model.GPModel; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +/** + * packageName : com.palnet.biz.api.ctr.cntrl.controller + * fileName : SocketReciverController + * author : dhji + * date : 2023-08-29(029) + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2023-08-29(029) dhji 최초 생성 + */ +@Slf4j +@RequiredArgsConstructor +@RestController +@RequestMapping("/api/server") +public class SocketReceiverController { + + private final SocketReceiverService socketReceiverService; + @PostMapping("/receiver") + public ResponseEntity receiver(@RequestBody GPModel model) { + System.out.println("socket message : " + model); + socketReceiverService.insert(model); + return ResponseEntity.ok().build(); + } + + @PostMapping("/receiver/async") + public Callable asyncReceiver(@RequestBody GPModel model) { + return () -> { + log.info("websocket message : {}", model); + socketReceiverService.insert(model); + return "OK"; + }; + } + + @PostMapping("/receiver/all") + public ResponseEntity receiver(@RequestBody Map> models) { +// System.out.println("socket message : " + models); + socketReceiverService.insertAll(models); + return ResponseEntity.ok().build(); + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlArcrftWarnModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlArcrftWarnModel.java new file mode 100644 index 00000000..329c8814 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlArcrftWarnModel.java @@ -0,0 +1,21 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import lombok.Data; + +import java.util.Date; + +@Data +public class CtrCntrlArcrftWarnModel { + + private String cntrlId; + private String warnType; + private String idntfNum; + private Date occurDt; + private Date createDt; + private String createUserId; + + private Integer warnCount; + + private boolean controlWarnCd = false; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlArcrftWarnRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlArcrftWarnRqModel.java new file mode 100644 index 00000000..fe2d5b74 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlArcrftWarnRqModel.java @@ -0,0 +1,8 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import lombok.Data; + +@Data +public class CtrCntrlArcrftWarnRqModel { + private String cntrlId; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlDtlModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlDtlModel.java new file mode 100644 index 00000000..d2206287 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlDtlModel.java @@ -0,0 +1,31 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class CtrCntrlDtlModel { + +private String messageTypeCd; + + private String cntrlId; + private Date cntrlStDt; + private Date cntrlEndDt; + private int arcrftSno; + private String prdctNum; + private String arcrftTypeCd; + private String arcrftModelNm; + private String prdctCmpnNm; + private String wghtTypeCd; + private String imageUrl; + private String cameraYn; + private String insrncYn; + private String ownerNm; + private String hpno; + private String telno; + + private String stAreaNm; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlEndModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlEndModel.java new file mode 100644 index 00000000..b26cbc6e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlEndModel.java @@ -0,0 +1,21 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class CtrCntrlEndModel { + + private String cntrlId; + + private Date cntrlStdt; + + private Date cntrlEndDt; + + private String statusCd; + + private Date srvrRcvDt; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlGroupArcrftModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlGroupArcrftModel.java new file mode 100644 index 00000000..cdeb2ebb --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlGroupArcrftModel.java @@ -0,0 +1,23 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import lombok.Data; + +import java.util.Date; + +@Data +public class CtrCntrlGroupArcrftModel { + + private String idntfNum; + private Integer arcrftSno; + private String groupId; + private String idntfTypeCd; + private String ownerNm; + private String hpno; + private String prdctNum; + private String arcrftTypeCd; + private String arcrftModelNm; + private String prdctCmpnNm; + private Date createDt; + private Date updateDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlGroupModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlGroupModel.java new file mode 100644 index 00000000..be071c61 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlGroupModel.java @@ -0,0 +1,18 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class CtrCntrlGroupModel { + + private Integer cstmrSno; + private String userId; + private String authId; + private String groupId; + private String groupNm; + private String groupAuthCd; + + private List arcrftList; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlModel.java new file mode 100644 index 00000000..fe9b5300 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlModel.java @@ -0,0 +1,123 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import com.palnet.comn.utils.DateUtils; + +import io.netty.util.internal.StringUtil; +import lombok.Data; + +@Data +public class CtrCntrlModel implements Comparable{ + + private String messageTypeCd; + + private String controlId; + + private String objectTypeCd; + + private String objectId; + + private Double lat; + + private Double lng; + + private String elevType; + + private Double elev; + + private String speedType; + + private Double speed; + + private Double betteryLevel; + + private Double betteryVoltage; + + private String takeOffPositon; + + private String dronStatus; + + private Double heading; + + private String terminalRcvDt; + + private String serverRcvDt; + + private String controlStartDt; + + private Double moveDistance; + + private String moveDistanceType; + + // 환경센서 필드 + private Double sensorCo; + private Double sensorSo2; + private Double sensorNo2; + private Double sensorO3; + private Double sensorDust; + + private List> lastHistory; + + @Override + public int compareTo(CtrCntrlModel o) { + + if(!StringUtil.isNullOrEmpty(o.getControlStartDt()) && !StringUtil.isNullOrEmpty(controlStartDt)) { + long targetStartDt = Long.parseLong(o.getControlStartDt()); + long startDt = Long.parseLong(controlStartDt); + + if(startDt == targetStartDt) { + return 0; + }else if(startDt > targetStartDt) { + return 1; + }else if(startDt < targetStartDt) { + return -1; + } + } + + return 0; + + } + + public static void main(String [] args) { + List list = new ArrayList(); + + try { + for(int i = 0 ; i < 5 ; i++) { + Thread.sleep(1000); + // System.out.println(">>>" + DateUtils.getCurrentTime()); + CtrCntrlModel model = new CtrCntrlModel(); + model.setControlStartDt(DateUtils.getCurrentTime()); + list.add(model); + } + + list.sort(Comparator.naturalOrder()); + + // System.out.println("오름차순 정렬"); + for(CtrCntrlModel data :list) { + + // System.out.println(data.getControlStartDt()); + } + + + list.sort(Comparator.reverseOrder()); + // System.out.println("내림차순 정렬"); + for(CtrCntrlModel data :list) { + + // System.out.println(data.getControlStartDt()); + } + }catch(Exception e) { + e.printStackTrace(); + } + + + + + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlPlanContainsRq.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlPlanContainsRq.java new file mode 100644 index 00000000..19462de9 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlPlanContainsRq.java @@ -0,0 +1,18 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaCoordModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanModel; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class CtrCntrlPlanContainsRq { + + private String idntfNum; // 드론 식별번호. + private double lat; // 드론 위도 좌표 + private double lon; // 드론 경도 좌표 + + private List planList; // 비행계획서 +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlPlanContainsRs.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlPlanContainsRs.java new file mode 100644 index 00000000..d3014d09 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlPlanContainsRs.java @@ -0,0 +1,12 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import lombok.Data; + +@Data +public class CtrCntrlPlanContainsRs { + + private boolean warning = false; + private String idntfNum; + private String planSno; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlSocketContainsRq.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlSocketContainsRq.java new file mode 100644 index 00000000..e8915e55 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlSocketContainsRq.java @@ -0,0 +1,21 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import java.util.List; + +import com.palnet.biz.jpa.entity.FltPlanAreaCoord; + +import lombok.Data; + +@Data +public class CtrCntrlSocketContainsRq { + + private String idntfNum; // 드론 식별번호. + private double lat; // 드론 위도 좌표 + private double lon; // 드론 경도 좌표 + + private String areaType; // FlightPlanArea 비행타입 + private int bufferZone; // FlightPlanArea bufferZone + + private List coordList; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlSocketDataModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlSocketDataModel.java new file mode 100644 index 00000000..c6a1d6ee --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlSocketDataModel.java @@ -0,0 +1,12 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import lombok.Data; + +@Data +public class CtrCntrlSocketDataModel { + + private int planSno; + private String areaType; + private int bufferZone; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlWarnLogModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlWarnLogModel.java new file mode 100644 index 00000000..91cfa411 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlWarnLogModel.java @@ -0,0 +1,18 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import lombok.Data; +import java.util.Date; +import java.util.List; + +import com.palnet.biz.jpa.entity.CtrCntrlWarnLog; + +@Data +public class CtrCntrlWarnLogModel { + private Integer warnLogSno; + private String idntfNum; + private String warnType; + private String cntrlId; + private Date createDt; +// private List list; +// private Integer count; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlWeatherModel.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlWeatherModel.java new file mode 100644 index 00000000..43c7cbd7 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/model/CtrCntrlWeatherModel.java @@ -0,0 +1,21 @@ +package com.palnet.biz.api.ctr.cntrl.model; + +import lombok.Data; + +@Data +public class CtrCntrlWeatherModel { + private double nx; + private double ny; + private String Snx; + private String Sny; + private Integer hstryAreaSno; + private String area1; + private String area2; + private String area3; + private String zipCd; + private String landNm; + private String landNum; + private String areaType; + private String areaNm; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/service/CtrCntrlService.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/service/CtrCntrlService.java new file mode 100644 index 00000000..0c8bb319 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/service/CtrCntrlService.java @@ -0,0 +1,822 @@ +package com.palnet.biz.api.ctr.cntrl.service; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.text.SimpleDateFormat; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.locationtech.jts.geom.Coordinate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanArcrftModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaCoordModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanModel; +import com.palnet.biz.api.bas.flight.service.BasFlightMapper; +import com.palnet.biz.api.comn.model.ControlGpsDataContext; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlArcrftWarnModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlDtlModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlGroupArcrftModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlGroupModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlPlanContainsRq; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlPlanContainsRs; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlSocketContainsRq; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlSocketDataModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlWarnLogModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlWeatherModel; +import com.palnet.biz.jpa.entity.ComArcrftBas; +import com.palnet.biz.jpa.entity.ComIdntfBas; +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.CtrCntrlHstry; +import com.palnet.biz.jpa.entity.CtrCntrlHstryArea; +import com.palnet.biz.jpa.entity.CtrCntrlWarnLog; +import com.palnet.biz.jpa.entity.FltPlanArcrft; +import com.palnet.biz.jpa.entity.FltPlanArea; +import com.palnet.biz.jpa.entity.FltPlanAreaCoord; +import com.palnet.biz.jpa.entity.FltPlanBas; +import com.palnet.biz.jpa.repository.com.ComArcrftBasRepository; +import com.palnet.biz.jpa.repository.com.ComIdntBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlHstryRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlQueryRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlWarnLogRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanArcrftRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanAreaCoordRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanAreaRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanBasRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanCtrCntrlRelRepository; +import com.palnet.biz.scheduler.ctr.model.CtrTrnsLctnModel; +import com.palnet.biz.scheduler.ctr.service.CtrSchedulerService; +import com.palnet.biz.scheduler.ctr.service.CtrTrnsLctnService; +import com.palnet.comn.model.GPHistoryModel; +import com.palnet.comn.utils.AreaUtils; +import com.palnet.comn.utils.DateUtils; +import com.palnet.comn.utils.EncryptUtils; + +import lombok.extern.log4j.Log4j2; + +@Service +@Log4j2 +public class CtrCntrlService { + + @Autowired + private JwtTokenUtil jwtTokenUtil; + @Autowired + private CtrTrnsLctnService ctrTrnsLctnService; + @Autowired + private FltPlanCtrCntrlRelRepository relRepository; + + private final CtrCntrlQueryRepository query; + private final CtrCntrlBasRepository cntrlBasRepository; + private final CtrCntrlHstryRepository cntrlHstryRepository; + private final CtrCntrlWarnLogRepository warnLogRepository; + private final ComIdntBasRepository idntfRepository; + private final ComArcrftBasRepository arcrftRepository; + private final FltPlanBasRepository planBasRepository; + private final FltPlanArcrftRepository planArcrftRepository; + private final FltPlanAreaRepository planAreaRepository; + private final FltPlanAreaCoordRepository planCoordRepository; + private final AreaUtils areaUtils; + private final ControlGpsDataContext shareContext; + + public CtrCntrlService(CtrCntrlQueryRepository query, + CtrCntrlBasRepository cntrlBasRepository, + CtrCntrlHstryRepository cntrlHstryRepository, + CtrCntrlWarnLogRepository warnLogRepository, + ComIdntBasRepository idntfRepository, + ComArcrftBasRepository arcrftRepository, + FltPlanBasRepository planBasRepository, + FltPlanArcrftRepository planArcrftRepository, + FltPlanAreaRepository planAreaRepository, + FltPlanAreaCoordRepository planCoordRepository, + AreaUtils areaUtils, + ControlGpsDataContext shareContext) { + this.query = query; + this.cntrlBasRepository = cntrlBasRepository; + this.cntrlHstryRepository = cntrlHstryRepository; + this.warnLogRepository = warnLogRepository; + this.idntfRepository = idntfRepository; + this.arcrftRepository = arcrftRepository; + this.planBasRepository = planBasRepository; + this.planArcrftRepository = planArcrftRepository; + this.planAreaRepository = planAreaRepository; + this.planCoordRepository = planCoordRepository; + this.areaUtils = areaUtils; + this.shareContext = shareContext; + } + + + public List getListHistory(String objectId) { + List filterList = new ArrayList(); + +// if(cic.getHistoryData(objectId).size() > 0) { +// resultList = cic.getHistoryData(objectId); +// +// //위경도 좌표 가 정상적인 값만 표출 +// for(GPHistoryModel model : resultList) { +// if(model.getLat() > 0 && model.getLng() > 0 ) { +// filterList.add(model); +// } +// } +// } + + return filterList; + + } + + /** + * TODO 관제 상세 조회 + * + * @param controlId + * @return + */ + public CtrCntrlDtlModel getDetail(String controlId) { + + CtrCntrlDtlModel result; + + result = query.detailCntrl(controlId); + + List areaList = query.detailArea(controlId); + String stAreaNm = ""; + + if (result.getHpno() == null || result.getHpno().isEmpty()) { + } else { + result.setHpno(EncryptUtils.decrypt(result.getHpno())); + } + + for (CtrCntrlHstryArea data : areaList) { + if (data.getActnType().equals("01")) { + if (!StringUtils.isEmpty(data.getArea1())) { + stAreaNm = stAreaNm + " " + data.getArea1(); + } + + if (!StringUtils.isEmpty(data.getArea2())) { + stAreaNm = stAreaNm + " " + data.getArea2(); + } + + if (!StringUtils.isEmpty(data.getArea3())) { + stAreaNm = stAreaNm + " " + data.getArea3(); + } + + if (!StringUtils.isEmpty(data.getLandNm())) { + stAreaNm = stAreaNm + " " + data.getLandNm(); + } + + if (!StringUtils.isEmpty(data.getLandNum())) { + stAreaNm = stAreaNm + " " + data.getLandNum(); + } + } + } + + + result.setStAreaNm(stAreaNm); + + return result; + } + + /** + * TODO 관제 이력 조회 + * + * @param controlId + * @return + */ + public List getHistory(String controlId) { + return query.getDroneHistory(controlId); + } + + /** + * TODO 그룹의 기체 정보 조회 + * + * @param cstmrSno + * @return + */ + + public List getGroupAuthInfo() { + + List list = query.findByGroupInfo(); + List arcrftList = new ArrayList<>(); + if (list.size() > 0) { + for (CtrCntrlGroupModel lists : list) { + List groupArcrft = query.findByGroupArcrft(lists.getGroupId()); + arcrftList.addAll(groupArcrft); + } + } + return arcrftList; + } + + /** + * TODO 비정상 상황 이력 조회 + * + * @param controlId + * @return + */ + public List getWarnLog(String controlId) { + List logs = warnLogRepository.findAllByCntrlId(controlId); + List warnLog = new ArrayList<>(); + + for (CtrCntrlWarnLog log : logs) { + CtrCntrlWarnLogModel model = new CtrCntrlWarnLogModel(); + + model.setCntrlId(log.getCntrlId()); + model.setCreateDt(log.getCreateDt()); + model.setWarnLogSno(log.getWarnLogSno()); + model.setWarnType(log.getWarnType()); + model.setIdntfNum(log.getIdntfNum()); + + warnLog.add(model); + } + + return warnLog; + } + + + /** + * TODO 비행계획서에 등록 된 기체 별 최신 비정상 로그 및 비정상 로그 전체 개수 + * + * @param id + * @return + */ + @Transactional + public List getArcrftWarnList(String id) { + + List result = new ArrayList<>(); + + if ("".equals(id) || id == null) return null; + + String[] ids = id.indexOf(",") > -1 ? id.split(",") : new String[]{id}; // 식별번호(cntrlId)가 여러개일 경우 콤마 구분자로 나눠 배열에 저장 + + for (String cntrlId : ids) { + CtrCntrlArcrftWarnModel model = new CtrCntrlArcrftWarnModel(); + + String idntfNum = cntrlBasRepository.getIdntfNum(cntrlId); //이미 Socket에서 payload의 trim에 따라 cntrlBas에 식별번호가 PA로 시작하는 데이터가 insert 되어 있음. 이 데이터 중 매개변수로 들어온 id와 일치하는 cntrlBas의 식별번호를 가져옴 + CtrCntrlHstry hisControl = query.getWarnHstryList(cntrlId); // repo method 이름을 왜 이렇게 지었는지는 모르겠으나.. cntrlBas에 insert될 때 같이 insert되는 cntrlHstry 데이터 중 가장 마지막에 찍힌 hstry 로그를 가져옴 + + int planSno = relRepository.getPlanSno(idntfNum).orElse(0); // cntrlBas insert될때 같이 insert된 mapping 테이블에서 식별번호로 planSno 가져옴 + if(query.checkPlanSno(planSno) < 1) continue; + + FltPlanArea planAreaData = query.getPlanData(planSno); // planSno에 맞는 비헹계획서의 비행계획경로정보 가져옴 + + List coordList = planCoordRepository.getCoordinate(planAreaData.getPlanAreaSno()); // 비행계획서에 등록한 경로의 좌표 전부를 가져옴 + + CtrCntrlSocketContainsRq containsRq = new CtrCntrlSocketContainsRq(); + if (idntfNum != null) { + containsRq.setIdntfNum(idntfNum); + model.setIdntfNum(idntfNum); + model.setCntrlId(cntrlId); + } + + if (planAreaData != null) { + containsRq.setLat(hisControl.getLat()); + containsRq.setLon(hisControl.getLon()); + } + + if (hisControl != null) { + containsRq.setAreaType(planAreaData.getAreaType()); + containsRq.setBufferZone(planAreaData.getBufferZone()); + } + + if (coordList != null) { + containsRq.setCoordList(coordList); + } + + CtrCntrlPlanContainsRs ctrCntrlPlanContainsRs = this.checkSocketContains(containsRq); // 위의 정보를 기반으로 만들어진 비행계획서 경로와 rq의 좌표를 비교해서 정상 비행 여부 확인 + model.setControlWarnCd(ctrCntrlPlanContainsRs.isWarning()); + + if (model.isControlWarnCd()) { // 정상 비행이 아니라면 warning log 생성 + CtrCntrlWarnLog log = new CtrCntrlWarnLog(); + log.setCntrlId(cntrlId); + log.setIdntfNum(idntfNum); + log.setOccurDt(hisControl.getSrvrRcvDt()); + log.setLat(hisControl.getLat()); + log.setLon(hisControl.getLon()); + log.setElev(hisControl.getElev()); + log.setCreateDt(DateUtils.nowDate()); + log.setWarnType("PLAN"); + warnLogRepository.save(log); + } + CtrCntrlWarnLog warnLog = warnLogRepository.findFirstByCntrlIdOrderByOccurDtDesc(cntrlId); // 가장 마지막에 쌓인 warnLog 가져옴 + Integer warnCount = warnLogRepository.countByCntrlId(cntrlId); // warnLog 누적 카운트 가져옴 + + if (warnLog != null) { // front에 표출할 warnLog 정보 set + model.setWarnType(warnLog.getWarnType()); + model.setOccurDt(warnLog.getOccurDt()); + model.setCreateDt(warnLog.getCreateDt()); + model.setCreateUserId(warnLog.getCreateUserId()); + } + model.setWarnCount(warnCount); + + result.add(model); + } + return result; + } + + /** + * TODO 식별 번호에 해당되는 비행구역 조회 + * + * @param idntfNum + * @return + */ + public List getFlightPlan(String idntfNum) { + List rs = new ArrayList<>(); + + Date fltNowDt = DateUtils.nowDate(); + + // 기체 식별 정보 조회 + ComIdntfBas idntfBas = idntfRepository.findById(idntfNum).orElse(null); + + if (idntfBas != null) { + ComArcrftBas arcrftBas = arcrftRepository.findById(idntfBas.getArcrftSno()).orElse(null); + + if (arcrftBas != null) { + // 비행 계획 기체 조회 + List arcrftList = planArcrftRepository. + findByIdntfNumAndArcrftSnoOrderByPlanArcrftSnoAsc(idntfNum, arcrftBas.getArcrftSno()); + + if (arcrftList != null && !arcrftList.isEmpty()) { + arcrftList.forEach(arcrft -> { + FltPlanBas plan = planBasRepository. + findByGroupFlightPlan(arcrft.getPlanSno(), "Y", fltNowDt).orElse(null); + ListarcrftMappingList = new ArrayList<>(); + BasFlightPlanArcrftModel arcrftMapping = BasFlightMapper.mapper.entityToModel(arcrftBas); + arcrftMapping.setIdntfNum(idntfNum); + arcrftMappingList.add(arcrftMapping); + if (plan != null) { + BasFlightPlanModel planMapping = BasFlightMapper.mapper.entityToModel(plan); + + // 비행 계획서 구역 조회 + List areaList = planAreaRepository.findByPlanSnoOrderByPlanAreaSnoAsc(plan.getPlanSno()); + + if (areaList != null && !areaList.isEmpty()) { + List areaMappingList = new ArrayList<>(); + + areaList.forEach(area -> { + BasFlightPlanAreaModel areaMapping = BasFlightMapper.mapper.entityToModel(area); + + // 비행 구역 좌표 조회 + List coordList = + planCoordRepository.findByPlanAreaSnoOrderByPlanAreaCoordSnoAsc(area.getPlanAreaSno()); + + if (coordList != null && !coordList.isEmpty()) { + // 좌표 리스트 model mapping + List coordListMapping = + BasFlightMapper.mapper.entityToModelCoordList(coordList); + + // 구역 정보에 좌표 저장 + areaMapping.setCoordList(coordListMapping); + + // Buffer 영역 생성 저장 + if ("LINE".equals(area.getAreaType())) { + List convertCoordinates = areaUtils.convertCoordinates(areaMapping.getCoordList()); + List transCoordList = areaUtils.transform(convertCoordinates, "EPSG:4326", "EPSG:5181"); + + List bufferList = areaUtils.buffer(transCoordList, areaMapping.getBufferZone()); + List transBufferList = areaUtils.transform(bufferList, "EPSG:5181", "EPSG:4326"); // buffer 영역 좌표계 변환 + + List bufferCoordList = areaUtils.convertModel(transBufferList); + + areaMapping.setBufferCoordList(bufferCoordList); + } + } + areaMappingList.add(areaMapping); + }); + + // 비행 계획서에 구역 목록 저장 + planMapping.setAreaList(areaMappingList); + planMapping.setArcrftList(arcrftMappingList); + + } + + rs.add(planMapping); + } + }); + } + } + } + + return rs; + } + + /** + * TODO 비행 관제 비정상 상황 판별 + * + * @param rq + * @return + */ + public CtrCntrlPlanContainsRs checkPlanContains(CtrCntrlPlanContainsRq rq) { + CtrCntrlPlanContainsRs rs = new CtrCntrlPlanContainsRs(); + + int countSuccess = 0; + + if (rq.getIdntfNum() != null) { + for (BasFlightPlanModel plan : rq.getPlanList()) { + for (BasFlightPlanAreaModel area : plan.getAreaList()) { + List planArea = areaUtils.convertCoordinates(area.getCoordList()); + + // 드론 위치 + Coordinate targetCoord = new Coordinate(rq.getLon(), rq.getLat()); + + /** + * 1. 비행 구역에 벗어나면 모든 경우의 수는 비정상 상황으로 판단 + * 2. 비정상 상황 TYPE(비행구역, 공역)에 따라 구분 (미적용) + */ + boolean areaContains = true; +// boolean airspaceContains = false; + if ("LINE".equals(area.getAreaType())) { + List transPlanArea = areaUtils.transform(planArea, "EPSG:4326", "EPSG:5181"); + + List planBuffer = areaUtils.buffer(transPlanArea, area.getBufferZone()); + List transPlanBuffer = areaUtils.transform(planBuffer, "EPSG:5181", "EPSG:4326"); + + areaContains = areaUtils.contains(transPlanBuffer, targetCoord); +// log.info("LINE CONTAINS : {}", areaContains); + } + + if ("POLYGON".equals(area.getAreaType())) { + planArea.add(planArea.get(0)); + areaContains = areaUtils.contains(planArea, targetCoord); + } + + if ("CIRCLE".equals(area.getAreaType())) { + List circle = areaUtils.createCircle(planArea.get(0), area.getBufferZone()); + areaContains = areaUtils.contains(circle, targetCoord); + + } + + if (areaContains) countSuccess++; + } + } + } + + // 1개라도 + if (countSuccess > 0) { + rs.setWarning(false); + } else { + rs.setWarning(true); + } + + rs.setIdntfNum(rq.getIdntfNum()); + + return rs; + } + + /** + * TODO 임시)warnList 최적화 + * + * @param rq + * @return + */ + public CtrCntrlPlanContainsRs checkSocketContains(CtrCntrlSocketContainsRq rq) { + CtrCntrlPlanContainsRs rs = new CtrCntrlPlanContainsRs(); + + int countSuccess = 0; + + if (rq.getIdntfNum() != null) { + List planArea = new ArrayList<>(); + for(FltPlanAreaCoord coord : rq.getCoordList()) { + Coordinate coordinate = new Coordinate(coord.getLon(), coord.getLat()); + + planArea.add(coordinate); + } + // 드론 위치 + Coordinate targetCoord = new Coordinate(rq.getLon(), rq.getLat()); + + /** + * 1. 비행 구역에 벗어나면 모든 경우의 수는 비정상 상황으로 판단 + * 2. 비정상 상황 TYPE(비행구역, 공역)에 따라 구분 (미적용) + */ + boolean areaContains = true; + switch(rq.getAreaType()) { + case "LINE" : + List transPlanArea = areaUtils.transform(planArea, "EPSG:4326", "EPSG:5181"); + List planBuffer = areaUtils.buffer(transPlanArea, rq.getBufferZone()); + List transPlanBuffer = areaUtils.transform(planBuffer, "EPSG:5181", "EPSG:4326"); + + areaContains = areaUtils.contains(transPlanBuffer, targetCoord); + break; + + case "POLYGON" : + planArea.add(planArea.get(0)); + areaContains = areaUtils.contains(planArea, targetCoord); + break; + + case "CIRCLE" : + List circle = areaUtils.createCircle(planArea.get(0), rq.getBufferZone()); + areaContains = areaUtils.contains(circle, targetCoord); + break; + } + + if (areaContains) countSuccess++; + } + + // 1개라도 + if (countSuccess > 0) { + rs.setWarning(false); + } else { + rs.setWarning(true); + } + + rs.setIdntfNum(rq.getIdntfNum()); + + return rs; + } + + + /** + * TODO 비행 이력 Control-Id 발급 + * + * @param id + * @return + */ + public Map getId(String id) { + Map result = new HashMap<>(); + + + /* 식별번호의 가장 최근 이력 불러오기 */ + CtrCntrlBas latestControl = cntrlBasRepository.findFirstByIdntfNumOrderByCreateDtDesc(id).orElse(null); + + boolean isControl = false; + + if (latestControl != null) { + CtrCntrlHstry latestHistory = cntrlHstryRepository.findFirstByCntrlIdOrderBySrvrRcvDtDesc(latestControl.getCntrlId()).orElse(null); + + if (latestHistory != null) { + long diffMinute = DateUtils.diffMinute(latestHistory.getSrvrRcvDt(), new Date()); +// log.info("DIFF MINUTE : {}", diffMinute); + + if ("01".equals(latestControl.getEndTypeCd()) || diffMinute > 5) { + isControl = false; + } + if (!"01".equals(latestControl.getEndTypeCd()) && diffMinute < 5) { + isControl = true; + } + } else { + isControl = false; + } + + } else { + isControl = false; + } + + if (isControl) { + result.put("controlId", latestControl.getCntrlId()); + result.put("typeCd", "02"); + result.put("areaTrnsYn", "E"); + } else { + String controlID = UUID.randomUUID().toString(); + result.put("controlId", controlID); + result.put("typeCd", "01"); + result.put("areaTrnsYn", "N"); + + // 기체 식별번호의 관제 ID 저장 (single ton) + shareContext.putIdntfKey(id, controlID); + } + + return result; + } + + public Map checkWarring(String id, Double lat, Double lon) { + Map result = new HashMap<>(); + + List planList = this.getFlightPlan(id); + + result.put("controlWarnCd", "N"); + if (planList != null && !planList.isEmpty()) { + CtrCntrlPlanContainsRq containsRq = new CtrCntrlPlanContainsRq(); + containsRq.setIdntfNum(id); + containsRq.setLat(lat); + containsRq.setLon(lon); + containsRq.setPlanList(planList); + + CtrCntrlPlanContainsRs ctrCntrlPlanContainsRs = this.checkPlanContains(containsRq); + result.put("controlWarnCd", ctrCntrlPlanContainsRs.isWarning() ? "Y" : "N"); + } + + return result; + } + + public JSONObject getWeather(CtrCntrlWeatherModel rq) throws IOException, ParseException { + + StringBuilder urlBuilder = new StringBuilder("http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst"); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + Calendar c1 = Calendar.getInstance(); + String strToday = sdf.format(c1.getTime()); + // 현재 시간 + LocalTime now = LocalTime.now(); + + // 현재시간 출력 + + // 시, 분, 초 구하기 + int hour = now.getHour(); + int minute = now.getMinute(); + int length = (int)(Math.log10(minute)+1); + int hourlength = (int)(Math.log10(hour)+1); + String strminute = Integer.toString(minute); + String strhour = Integer.toString(hour); + String basetime = null; + + if(length<=1){ + strminute = 0+Integer.toString(minute); + }if(hourlength<=1){ + strhour = 0+Integer.toString(hour); + } + // 시, 분, 초 출력 + if ((Integer.parseInt(strhour) >= 2 && Integer.parseInt(strminute )> 9) && Integer.parseInt(strhour) <= 5) { + basetime = "0200"; + } + else if ((Integer.parseInt(strhour) >= 5 && Integer.parseInt(strminute ) > 9) && Integer.parseInt(strhour) < 8) { + basetime = "0500"; + } + else if (Integer.parseInt(strhour) <= 8 && Integer.parseInt(strminute ) < 10) { + basetime = "0500"; + } + else if ((Integer.parseInt(strhour) >= 8 && Integer.parseInt(strminute ) > 9) && Integer.parseInt(strhour) < 11) { + basetime = "0800"; + } + else if (Integer.parseInt(strhour) <= 11 && Integer.parseInt(strminute ) < 10) { + basetime = "0800"; + } + else if ((Integer.parseInt(strhour) >= 11 && Integer.parseInt(strminute ) > 9) && Integer.parseInt(strhour) < 14) { + basetime = "1100"; + } + else if (Integer.parseInt(strhour) <= 14 && Integer.parseInt(strminute ) < 10) { + basetime = "1100"; + } + else if ((Integer.parseInt(strhour) >= 14 && Integer.parseInt(strminute ) > 9) && Integer.parseInt(strhour) < 17) { + basetime = "1400"; + } + else if (Integer.parseInt(strhour) <= 17 && Integer.parseInt(strminute ) < 10) { + basetime = "1400"; + } + else if ((Integer.parseInt(strhour) >= 17 && Integer.parseInt(strminute ) > 9) && Integer.parseInt(strhour) < 20) { + basetime = "1700"; + } + else if (Integer.parseInt(strhour) <= 20 && Integer.parseInt(strminute ) < 10) { + basetime = "1700"; + } + else if ((Integer.parseInt(strhour) >= 20 && Integer.parseInt(strminute ) > 9) && Integer.parseInt(strhour) < 23) { + basetime = "2000"; + } + else if (Integer.parseInt(strhour) <= 23 && Integer.parseInt(strminute ) < 10) { + basetime = "2000"; + } + else + basetime = "2300"; + + + List coordList = new ArrayList<>(); + Coordinate coord = new Coordinate(); + Coordinate returnCoord = new Coordinate(); + coord.setX(rq.getNx()); + coord.setY(rq.getNy()); + returnCoord = this.wheather(coord); + + double nx = returnCoord.getX(); + double ny = returnCoord.getY(); + String Snx = String.format("%.0f",nx); + String Sny = String.format("%.0f",ny); + + urlBuilder.append("?" + URLEncoder.encode("serviceKey","UTF-8") + "=r6RMUsk3Vtama7D6uq7MiWV9dTC9MwfIIr4%2F45y0uVNw6BaYbgpKmL%2BLUDFVTfIYUmEe4K%2FaniEjdV9mg5t82Q%3D%3D"); + urlBuilder.append("&" + URLEncoder.encode("pageNo","UTF-8") + "=" + URLEncoder.encode("1","UTF-8")); + urlBuilder.append("&" + URLEncoder.encode("numOfRows","UTF-8") + "=" + URLEncoder.encode("14", "UTF-8")); /*한 페이지 결과 수*/ + urlBuilder.append("&" + URLEncoder.encode("dataType","UTF-8") + "=" + URLEncoder.encode("JSON", "UTF-8")); /*요청자료형식(XML/JSON) Default: XML*/ + urlBuilder.append("&" + URLEncoder.encode("base_date","UTF-8") + "=" + URLEncoder.encode(strToday, "UTF-8")); /*'21년 6월 28일 발표*/ + urlBuilder.append("&" + URLEncoder.encode("base_time","UTF-8") + "=" + URLEncoder.encode(basetime, "UTF-8")); /*06시 발표(정시단위) */ + urlBuilder.append("&" + URLEncoder.encode("nx","UTF-8") + "=" + URLEncoder.encode(Snx, "UTF-8")); /*예보지점의 X 좌표값*/ + urlBuilder.append("&" + URLEncoder.encode("ny","UTF-8") + "=" + URLEncoder.encode(Sny, "UTF-8")); /*예보지점의 Y 좌표값*/ + URL url = new URL(urlBuilder.toString()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setRequestProperty("Content-type", "application/json"); + log.info("Response code: " + conn.getResponseCode()); + BufferedReader rd; + if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) { + rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + } else { + rd = new BufferedReader(new InputStreamReader(conn.getErrorStream())); + } + StringBuilder sb = new StringBuilder(); + String line; + while ((line = rd.readLine()) != null) { + sb.append(line); + } + CtrTrnsLctnModel weatherResult = ctrTrnsLctnService.convertLatlonToAddress(rq.getNx(),rq.getNy()); + log.info("weatherResult >>>> : {}", weatherResult); + + String str = sb.toString(); + JSONParser parser = new JSONParser(); + JSONObject jsonObject = (JSONObject) parser.parse(str); + if(weatherResult != null) { + jsonObject.put("area1",weatherResult.getArea1()); + jsonObject.put("area2",weatherResult.getArea2()); + jsonObject.put("area3",weatherResult.getArea3()); + jsonObject.put("landNm",weatherResult.getLandNm()); + jsonObject.put("landNum",weatherResult.getLandNum()); + } + rd.close(); + conn.disconnect(); + log.info(sb.toString()); + + return jsonObject; + } + public Coordinate wheather(Coordinate coord) { + double nx; + double ny; + nx = coord.getX(); + ny = coord.getY(); + double RE = 6371.00877; // 지구 반경(km) + double GRID = 5.0; // 격자 간격(km) + double SLAT1 = 30.0; // 투영 위도1(degree) + double SLAT2 = 60.0; // 투영 위도2(degree) + double OLON = 126.0; // 기준점 경도(degree) + double OLAT = 38.0; // 기준점 위도(degree) + double XO = 43; // 기준점 X좌표(GRID) + double YO = 136; // 기1준점 Y좌표(GRID) + + // + // LCC DFS 좌표변환 ( code : "TO_GRID"(위경도->좌표, lat_X:위도, lng_Y:경도), "TO_GPS"(좌표->위경도, lat_X:x, lng_Y:y) ) + // + + double DEGRAD = Math.PI / 180.0; + double RADDEG = 180.0 / Math.PI; + + double re = RE / GRID; + double slat1 = SLAT1 * DEGRAD; + double slat2 = SLAT2 * DEGRAD; + double olon = OLON * DEGRAD; + double olat = OLAT * DEGRAD; + + double sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5); + sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn); + double sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5); + sf = Math.pow(sf, sn) * Math.cos(slat1) / sn; + double ro = Math.tan(Math.PI * 0.25 + olat * 0.5); + ro = re * sf / Math.pow(ro, sn); + + double theta; + if (true) { + nx = nx; + ny = ny; + double ra = Math.tan(Math.PI * 0.25 + (nx) * DEGRAD * 0.5); + ra = re * sf / Math.pow(ra, sn); + theta = ny * DEGRAD - olon; + if (theta > Math.PI) theta -= 2.0 * Math.PI; + if (theta < -Math.PI) theta += 2.0 * Math.PI; + theta *= sn; + nx = Math.floor(ra * Math.sin(theta) + XO + 0.5); + ny = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5); + } else { + nx = nx; + ny = ny; + double xn = nx - XO; + double yn = ro - ny + YO; + double ra = Math.sqrt(xn * xn + yn * yn); + if (sn < 0.0) { + ra = -ra; + } + + double alat = Math.pow((re * sf / ra), (1.0 / sn)); + alat = 2.0 * Math.atan(alat) - Math.PI * 0.5; + + if (Math.abs(xn) <= 0.0) { + theta = 0.0; + } else { + if (Math.abs(yn) <= 0.0) { + theta = Math.PI * 0.5; + if (xn < 0.0) { + theta = -theta; + } + } else theta = Math.atan2(xn, yn); + } + double alon = theta / sn + olon; + nx = alat * RADDEG; + ny = alon * RADDEG; + } + + Coordinate returnCoord = new Coordinate(); + returnCoord.setX(nx); + returnCoord.setY(ny); + return returnCoord; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/service/SocketReceiverService.java b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/service/SocketReceiverService.java new file mode 100644 index 00000000..78579613 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/ctr/cntrl/service/SocketReceiverService.java @@ -0,0 +1,117 @@ +package com.palnet.biz.api.ctr.cntrl.service; + +import com.palnet.biz.jpa.entity.*; +import com.palnet.biz.jpa.repository.com.ComArcrftBasRepository; +import com.palnet.biz.jpa.repository.com.ComIdntBasRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanCtrCntrlRelRepository; +import com.palnet.biz.jpa.repository.flt.FltPlanQueryRepository; +import com.palnet.biz.jpa.repository.pty.PtyDronQueryRepository; +import com.palnet.biz.jpa.service.ctr.CtrCntrlJpaService; +import com.palnet.comn.model.GPDatabaseModel; +import com.palnet.comn.model.GPModel; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StopWatch; + +import java.util.List; +import java.util.Map; + +/** + * packageName : com.palnet.biz.api.ctr.cntrl.service + * fileName : SocketReciverService + * author : dhji + * date : 2023-08-29(029) + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2023-08-29(029) dhji 최초 생성 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class SocketReceiverService { + + private final CtrCntrlJpaService ctrCntrlJpaService; + private final PtyDronQueryRepository ptyDronQueryRepository; + private final ComArcrftBasRepository arcrftBasRepository; + private final ComIdntBasRepository idntBasRepository; + private final FltPlanQueryRepository fltPlanQueryRepository; + private final FltPlanCtrCntrlRelRepository ctrCntrlRelRepository; + + @Transactional + public void insert(GPModel model) { + GPDatabaseModel dbModel = new GPDatabaseModel(); + BeanUtils.copyProperties(model, dbModel); + + if ("01".equals(model.getTypeCd())) { + String prodNumber = ptyDronQueryRepository.findIdntfNumByProdNumber(model.getObjectId()); + dbModel.setProdNumber(prodNumber); + + // 비행 이력 생성 + CtrCntrlBas ctrCntrlBas = ctrCntrlJpaService.insertCtrCntrlBas(dbModel); + + // 비행 이력, 비행 계획서 mapping + if ("PA".equals(model.getObjectId().substring(0, 2))) { + FltPlanCtrCntrlRel fltPlanCtrCntrlRel = new FltPlanCtrCntrlRel(); + + // 1. 식별 번호의 소유자 정보 저장. + ComIdntfBas idntfBas = idntBasRepository.findById(model.getObjectId()).orElse(null); + + // 1-1. 식별 번호의 모델 정보 조회 + ComArcrftBas arcrftBas = arcrftBasRepository.findById(idntfBas.getArcrftSno()).orElse(null); + + if (idntfBas != null && arcrftBas != null) { + fltPlanCtrCntrlRel.setCntrlId(ctrCntrlBas.getCntrlId()); + fltPlanCtrCntrlRel.setIdntfNum(ctrCntrlBas.getIdntfNum()); + fltPlanCtrCntrlRel.setIdntfCstmrSno(idntfBas.getCstmrSno()); + fltPlanCtrCntrlRel.setGroupId(arcrftBas.getGroupId()); + } + + // 2. 해당 되는 비행계획서 정보 저장. + List planArcrft = + fltPlanQueryRepository.findByFlightPlanArcrft(ctrCntrlBas.getIdntfNum(), dbModel.getServerRcvDt()); + + if (!planArcrft.isEmpty()) { + for (FltPlanBas plan : planArcrft) { + fltPlanCtrCntrlRel.setPlanSno(plan.getPlanSno()); + } + } + + // 3. mapping 정보 주입. + if (!fltPlanCtrCntrlRel.getCntrlId().isEmpty()) { + ctrCntrlRelRepository.save(fltPlanCtrCntrlRel); + } + } + } + + // Drone인 경우에만 history 생성 + CtrCntrlHstry ctrCntrlHstry = ctrCntrlJpaService.insertCtrCntrlHstry(dbModel); + + if ("01".equals(model.getTypeCd()) || "99".equals(model.getTypeCd())) { + ctrCntrlJpaService.insertCtrCntrlHstryArea(dbModel, ctrCntrlHstry.getHstrySno()); + } + + } + + @Transactional + public void insertAll(Map> models) { + // TODO 일괄 처리 필요 + log.info(">>> models :: {}", models.size()); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + for (String key : models.keySet()) { + List list = models.get(key); + log.info(">>> models size :: {}", list.size()); + for (GPModel model : list) { + log.info(">> model: {}", model); + this.insert(model); + } + } + stopWatch.stop(); + log.info(">>> insertAll time : {}", stopWatch.getTotalTimeSeconds()); + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/main/dash/controller/MainDashController.java b/pav-server/src/main/java/com/palnet/biz/api/main/dash/controller/MainDashController.java new file mode 100644 index 00000000..dca97cce --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/main/dash/controller/MainDashController.java @@ -0,0 +1,173 @@ +package com.palnet.biz.api.main.dash.controller; + +import java.util.List; +import java.util.Map; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRqModel; +import com.palnet.biz.api.anls.smlt.model.AnlsSmltDetailModel; +import com.palnet.biz.api.anls.smlt.model.AnlsSmltStcsModel; +import com.palnet.biz.api.anls.smlt.service.AnlsSmltService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.api.main.dash.model.MainDashListModel; +import com.palnet.biz.api.main.dash.model.MainDashStcsModel; +import com.palnet.biz.api.main.dash.service.MainDashService; +import com.palnet.comn.code.RSErrorCode; +import com.palnet.comn.utils.JsonUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/main/dash", produces = {MediaType.APPLICATION_JSON_VALUE}) +@Tag(name = "메인화면 컨트롤러", description = "메인화면 관련 API") +public class MainDashController { + + @Autowired + private final MainDashService service; + + /** + * @param rq + * @return + */ + @GetMapping(value = "/stcs/day") + @ApiOperation(value = "일 별 비행횟수 통계") + @Tag(name = "메인화면 컨트롤러", description = "메인화면 관련 API") + @ApiImplicitParam(name = "yyyymm",value = "날짜", dataTypeClass = String.class) + public ResponseEntity stcsDay(String yyyymm) { + List result = null; + +// log.debug(yyyymm); + + //입력값 검증 + if(yyyymm == null || !(yyyymm.length() == 7) ) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + + result = service.mainDashStcsDay(yyyymm); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + /** + * @param rq + * @return + */ + @GetMapping(value = "/stcs/area") + @ApiOperation(value = "TOP5 지역 별 비행횟수 통계") + @Tag(name = "메인화면 컨트롤러", description = "메인화면 관련 API") + @ApiImplicitParam(name = "yyyymm",value = "날짜", dataTypeClass = String.class) + public ResponseEntity stcsArea(String yyyymm) { + List result = null; + +// log.debug(yyyymm); + + if(yyyymm == null || !(yyyymm.length() == 7) ) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.mainDashStcsArea(yyyymm); + + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + /** + * @param rq + * @return + */ + @GetMapping(value = "/group/list") + @ApiOperation(value = "본인이 생성한 그룹 정보") + @Tag(name = "메인화면 컨트롤러", description = "메인화면 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity groupList(Integer cstmrSno) { + List result = null; + + //입력값 검증 + if(cstmrSno == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.mainDashGroupList(cstmrSno); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + @GetMapping(value = "/arcrft/list") + @ApiOperation(value = "기체 정보 리스트") + @Tag(name = "메인화면 컨트롤러", description = "메인화면 관련 API") + @ApiImplicitParam(name = "cstmrSno",value = "고객일련번호", dataTypeClass = Integer.class) + public ResponseEntity arcrftList(Integer cstmrSno) { + List result = null; + + //입력값 검증 + if(cstmrSno == null) { + return ResponseEntity.status(HttpStatus.OK) + .body(new ErrorResponse(RSErrorCode.ER_PARAM)); + } + + try { + result = service.mainDashDronList(cstmrSno); + + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse(result)); + + } + + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/main/dash/model/MainDashListModel.java b/pav-server/src/main/java/com/palnet/biz/api/main/dash/model/MainDashListModel.java new file mode 100644 index 00000000..e8176961 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/main/dash/model/MainDashListModel.java @@ -0,0 +1,18 @@ +package com.palnet.biz.api.main.dash.model; + +import java.util.Date; + +import lombok.Data; + +@Data +public class MainDashListModel { + + private String arcrftModelNm = ""; + + private String prdctNum = ""; + + private Date createDt; + + private String groupNm =""; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/main/dash/model/MainDashStcsModel.java b/pav-server/src/main/java/com/palnet/biz/api/main/dash/model/MainDashStcsModel.java new file mode 100644 index 00000000..c300d8c1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/main/dash/model/MainDashStcsModel.java @@ -0,0 +1,13 @@ +package com.palnet.biz.api.main.dash.model; + +import lombok.Data; + +@Data +public class MainDashStcsModel { + + private String typeCd = ""; + + private long count = 0 ; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/main/dash/service/MainDashService.java b/pav-server/src/main/java/com/palnet/biz/api/main/dash/service/MainDashService.java new file mode 100644 index 00000000..9783c4cc --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/main/dash/service/MainDashService.java @@ -0,0 +1,101 @@ +package com.palnet.biz.api.main.dash.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.palnet.biz.api.bas.group.model.BasGroupModel; +import com.palnet.biz.jpa.repository.pty.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.main.dash.model.MainDashListModel; +import com.palnet.biz.api.main.dash.model.MainDashStcsModel; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlQueryRepository; + +@Service +public class MainDashService { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private CtrCntrlBasRepository ctrCntrlBasRepository; + + @Autowired + private PtyDronQueryRepository ptyDronQueryRepository; + + @Autowired + private PtyGroupQueryRepository ptyGroupQueryRepository; + + @Autowired + private CtrCntrlQueryRepository query; + + + + + /** + * 일별 비행횟수 통계 + * @param rq + * @return + */ + public List mainDashStcsDay(String yyyymm){ + + List resultList = query.mainDashStcsDay(yyyymm); + + return resultList; + } + + /** + * Top5 지역별 비행횟수 통계 + * @param rq + * @return + */ + public List mainDashStcsArea(String yyyymm){ + + List resultList = query.mainDashStcsArea(yyyymm); + + + return resultList; + } + + /** + * TOP3 가입 그룹 리스트 표출 + */ + public List mainDashGroupList(int cstmrSno){ + + List queryList = ptyGroupQueryRepository.groupTop3(cstmrSno); + List resultList = new ArrayList(); + + for(BasGroupModel model : queryList) { + + Map data = new HashMap(); + data.put("groupId", model.getGroupId()); + data.put("groupNm", model.getGroupNm()); + data.put("createDt", model.getCreateDt()); + resultList.add(data); + } + resultList = resultList.stream().sorted((o2, o1) -> o1.get("createDt").toString().compareTo(o2.get("createDt").toString())).collect(Collectors.toList()); + + + return resultList; + + } + + + /** + * Top3 기체 정보 리스트 표출 + */ + public List mainDashDronList(int cstmrSno){ + List resultList = ptyDronQueryRepository.dronTop3(cstmrSno); + return resultList; + } + + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/config/DatabaseJpaConfig.java b/pav-server/src/main/java/com/palnet/biz/config/DatabaseJpaConfig.java new file mode 100644 index 00000000..d7ed1233 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/config/DatabaseJpaConfig.java @@ -0,0 +1,68 @@ +package com.palnet.biz.config; + +import java.util.Map; +import java.util.Objects; + +import javax.sql.DataSource; + +import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; +import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.zaxxer.hikari.HikariDataSource; + +@Configuration +@EnableJpaRepositories(entityManagerFactoryRef = "controlJpaEntityManagerFactory", transactionManagerRef = "controlJpaTransactionManager", basePackages = { + "com.palnet" }) +@EnableTransactionManagement +public class DatabaseJpaConfig { + + private final JpaProperties jpaProperties; + private final HibernateProperties hibernateProperties; + + public DatabaseJpaConfig(JpaProperties jpaProperties, HibernateProperties hibernateProperties) { + this.jpaProperties = jpaProperties; + this.hibernateProperties = hibernateProperties; + } + + @Bean(name = "dataSource") + @Primary + @ConfigurationProperties(prefix = "spring.datasource.control") + public DataSource dataSource() { + return DataSourceBuilder + .create() + .type(HikariDataSource.class) + .build(); + } + + @Bean(name = "controlJpaEntityManagerFactory") + @Primary + public LocalContainerEntityManagerFactoryBean ndcJpaEntityManagerFactory(EntityManagerFactoryBuilder builder) { + Map prop = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), + new HibernateSettings()); + return builder.dataSource(dataSource()) + .properties(prop) + .packages("com.palnet") + .persistenceUnit("biz") + .build(); + + } + + @Bean(name = "controlJpaTransactionManager") + @Primary + public PlatformTransactionManager ndcJpaTransactionManager(EntityManagerFactoryBuilder builder) { + return new JpaTransactionManager(Objects.requireNonNull(ndcJpaEntityManagerFactory(builder).getObject())); + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/config/DateTimeConfig.java b/pav-server/src/main/java/com/palnet/biz/config/DateTimeConfig.java new file mode 100644 index 00000000..dc4ad6ab --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/config/DateTimeConfig.java @@ -0,0 +1,68 @@ +package com.palnet.biz.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.format.Formatter; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Locale; + +@Configuration +public class DateTimeConfig { + + private static final String DATE_FORMAT = "yyyy-MM-dd"; + private static final String TIME_FORMAT = "HH:mm:ss"; + private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + +// @Bean +// public Formatter localDateFormatter() { +// return new Formatter() { +// @Override +// public LocalDate parse(String text, Locale locale) { +// return LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyyMMdd", locale)); +// } +// +// @Override +// public String print(LocalDate object, Locale locale) { +// return DateTimeFormatter.ISO_DATE.format(object); +// } +// }; +// } +// +// +// @Bean +// public Formatter localDateTimeFormatter() { +// return new Formatter() { +// @Override +// public LocalDateTime parse(String text, Locale locale) { +// return LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyyMMddHHmmss", locale)); +// } +// +// @Override +// public String print(LocalDateTime object, Locale locale) { +// return DateTimeFormatter.ISO_DATE_TIME.format(object); +// } +// }; +// } + + @Bean + public Formatter DateFormatter() { + return new Formatter() { + @Override + public Date parse(String text, Locale locale) throws ParseException { + SimpleDateFormat dt = new SimpleDateFormat(DATE_TIME_FORMAT, locale); + return dt.parse(text); + } + + @Override + public String print(Date object, Locale locale) { + return new SimpleDateFormat(DATE_TIME_FORMAT).format(object); + } + }; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/config/JsonConfig.java b/pav-server/src/main/java/com/palnet/biz/config/JsonConfig.java new file mode 100644 index 00000000..2a671197 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/config/JsonConfig.java @@ -0,0 +1,56 @@ +package com.palnet.biz.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.time.format.DateTimeFormatter; +import java.util.TimeZone; + +@Configuration +public class JsonConfig { + + private static final String dateFormat = "yyyy-MM-dd"; + private static final String timeFormat = "HH:mm:ss"; + private static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + + /* + */ + @Bean + @Primary + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return builder -> { + builder.timeZone(TimeZone.getTimeZone("Asia/Seoul")); + + builder.simpleDateFormat(dateTimeFormat); + builder.serializers(new LocalTimeSerializer(DateTimeFormatter.ofPattern(timeFormat))); + builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat))); + builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))); + builder.serializationInclusion(JsonInclude.Include.NON_NULL); + builder.serializationInclusion(JsonInclude.Include.NON_EMPTY); + + builder.deserializers(new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timeFormat))); + builder.deserializers(new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat))); + builder.deserializers(new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat))); + + builder.featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + builder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + builder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + builder.featuresToDisable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES); + }; + } + +} + diff --git a/pav-server/src/main/java/com/palnet/biz/config/QuerydslConfiguration.java b/pav-server/src/main/java/com/palnet/biz/config/QuerydslConfiguration.java new file mode 100644 index 00000000..9fe89d8c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/config/QuerydslConfiguration.java @@ -0,0 +1,19 @@ +package com.palnet.biz.config; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +@Configuration +public class QuerydslConfiguration { + @PersistenceContext + private EntityManager entityManager; + + @Bean + public JPAQueryFactory jpaQueryFactory() { + return new JPAQueryFactory(entityManager); + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/config/SwaggerConfig.java b/pav-server/src/main/java/com/palnet/biz/config/SwaggerConfig.java new file mode 100644 index 00000000..6a77d90c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/config/SwaggerConfig.java @@ -0,0 +1,71 @@ +package com.palnet.biz.config; + +import io.swagger.v3.oas.models.parameters.Parameter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +@Configuration +//@EnableSwagger2 +public class SwaggerConfig { + + + @Bean + public Docket api() { + return new Docket(DocumentationType.OAS_30) // open api spec 3.0 + .apiInfo(new ApiInfoBuilder().version("1.0").title("PAV").build()) + .forCodeGeneration(true).securitySchemes(Arrays.asList(apiKey())) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build() + .apiInfo(apiInfo()) + .directModelSubstitute(Date.class, String.class) + .directModelSubstitute(LocalDate.class, String.class) + .directModelSubstitute(LocalDateTime.class, String.class) + .securityContexts(Arrays.asList(securityContext())) + .securitySchemes(Arrays.asList(apiKey())); + } + + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("PAV API") + .description("----") + .version("1.0") + .build(); + } + + //ApiKey 정의 + private ApiKey apiKey() { + return new ApiKey("Authorization", "Authorization", "header"); + } + + //JWT SecurityContext 구성 + private SecurityContext securityContext() { + return SecurityContext.builder().securityReferences(defaultAuth()).build(); + } + + private List defaultAuth() { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEveryThing"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + return Arrays.asList(new SecurityReference("Authorization", authorizationScopes)); + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/config/WebMvcConfig.java b/pav-server/src/main/java/com/palnet/biz/config/WebMvcConfig.java new file mode 100644 index 00000000..69325f0e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/config/WebMvcConfig.java @@ -0,0 +1,150 @@ +package com.palnet.biz.config; + +import java.time.format.DateTimeFormatter; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; +import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; +import org.springframework.http.HttpMethod; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; + +@Configuration +public class WebMvcConfig implements WebMvcConfigurer{ + + private static final String dateFormat = "yyyy-MM-dd"; + private static final String timeFormat = "HH:mm:ss"; + private static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + + /*@Autowired + AccsUUIDcheckInterceptor accsUUIDcheckInterceptor;*/ + /*@Autowired + LogincheckInterceptor logincheckInterceptor; + @Autowired + QrcodecheckInterceptor qrcodecheckInterceptor; + @Autowired + DomainCheckInterceptor domainCheckInterceptor;*/ +// +// @Override +// public void configureMessageConverters(List> converters) { +// converters.add(escapingConverter()); +// } + + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + /*registry.addResourceHandler("/web/**").addResourceLocations("/web/") + .setCacheControl(CacheControl.maxAge(10, TimeUnit.DAYS)).resourceChain(true) +// .setCacheControl(CacheControl.noStore()).resourceChain(true) + .addResolver(new VersionResourceResolver() + .addContentVersionStrategy("/**")) + .addTransformer(new AppCacheManifestTransformer());*/ + + // html 가능 하게 설정 + /*registry.addResourceHandler("/**").addResourceLocations("/web/hcws/html/");*/ + } + + @Bean + public ResourceUrlEncodingFilter resourceUrlEncodingFilter() { + return new ResourceUrlEncodingFilter(); + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + //임시로 크로스오리진 전체를 품 + registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST","PUT", "DELETE"); + + + } + +// +// @Bean +// public HttpMessageConverter escapingConverter() { +// Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); +// builder.simpleDateFormat(dateTimeFormat); +// builder.serializers(new LocalTimeSerializer(DateTimeFormatter.ofPattern(timeFormat))); +// builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat))); +// builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))); +// +// builder.deserializers(new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timeFormat))); +// builder.deserializers(new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat))); +// builder.deserializers(new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat))); +// builder.featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS); +// builder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); +// builder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); +// +// ObjectMapper objectMapper = builder.build(); +//// objectMapper.getFactory().setCharacterEscapes(new HTMLCharacterEscapes()); +// MappingJackson2HttpMessageConverter escapingConverter = new MappingJackson2HttpMessageConverter(); +// escapingConverter.setObjectMapper(objectMapper); +// +// return escapingConverter; +// } + + @Override + public void addFormatters(FormatterRegistry registry) { + // json + DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); + + registrar.setDateFormatter(DateTimeFormatter.ofPattern(dateFormat)); + registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern(dateTimeFormat)); + registrar.registerFormatters(registry); + + /* ISO 타입. + registrar.setUseIsoFormat(true); + registrar.registerFormatters(registry); + */ + } + + + @Override + public void addInterceptors(InterceptorRegistry registry) { + + //접근고유ID 체크 Interceptor + /*registry.addInterceptor(accsUUIDcheckInterceptor) + .addPathPatterns("/sendbox/") + .addPathPatterns("/sendbox/index");*/ + +// //로그인 체크 Interceptor +/* registry.addInterceptor(logincheckInterceptor) + .addPathPatterns("/front/pass/**") + .excludePathPatterns("/front/pass/check"); //추후 삭제 +// .excludePathPatterns("/front/login/certifyhp") //추후 삭제 +// .excludePathPatterns("/front/login/index"); +// +// //QRCODE 체크 Interceptor + registry.addInterceptor(qrcodecheckInterceptor) +// .addPathPatterns("/front/login/**") +// .addPathPatterns("/front/join/**") + .addPathPatterns("/front/pass/**") +// .addPathPatterns("/front/prreg/**")//추후 추가 +// .excludePathPatterns("/") +// .excludePathPatterns("/front/login/certifyhp") //추후 삭제 + .excludePathPatterns("/front/pass/list"); //추후 삭제 +// .excludePathPatterns("/front/pass/check"); //추후 삭제 +// .excludePathPatterns("/front/login/cookieDelete"); + + registry.addInterceptor(domainCheckInterceptor) + .addPathPatterns("/","/**") + .excludePathPatterns("/web/**") + .excludePathPatterns("/rest/**"); + */ + + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/config/WebSecurityConfig.java b/pav-server/src/main/java/com/palnet/biz/config/WebSecurityConfig.java new file mode 100644 index 00000000..80fe559a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/config/WebSecurityConfig.java @@ -0,0 +1,96 @@ +package com.palnet.biz.config; + + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import com.palnet.biz.api.acnt.jwt.filter.JwtAuthenticationEntryPoint; +import com.palnet.biz.api.acnt.jwt.filter.JwtRequestFilter; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; + + @Autowired + private UserDetailsService jwtUserDetailsService; + + @Autowired + private JwtRequestFilter jwtRequestFilter; + + + private final String[] PERMITTED_URL = { + "/api/acnt/**", + "/api/ctr/cntrl/id/**", + "/api/server/**", + /* swagger v2 */ + "/v2/api-docs", + "/swagger-resources", + "/swagger-resources/**", + "/configuration/ui", + "/configuration/security", + "/swagger-ui.html", + "/webjars/**", + /* swagger v3 */ + "/v3/api-docs/**", + "/swagger-ui/**" + }; + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // configure AuthenticationManager so that it knows from where to load + // user for matching credentials + // Use BCryptPasswordEncoder + auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder()); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + // We don't need CSRF for this example + httpSecurity.csrf().disable() + // dont authenticate this particular request + .authorizeRequests() + .antMatchers(HttpMethod.OPTIONS,"/api/**").permitAll() + .antMatchers(HttpMethod.GET,"/ping").permitAll() + .antMatchers("/swagger-ui/**").permitAll() + .antMatchers(PERMITTED_URL).permitAll() + // all other requests need to be authenticated + .anyRequest().authenticated().and() + // make sure we use stateless session; session won't be used to + // store user's state. + .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS); + + // Add a filter to validate the tokens with every request + httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); + } + + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComArcrftBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComArcrftBas.java new file mode 100644 index 00000000..f9ca9ae8 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComArcrftBas.java @@ -0,0 +1,92 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + + +/** + * The persistent class for the COM_ARCRFT_BAS database table. + * + */ +@Entity +@Table(name="COM_ARCRFT_BAS") +@Data +@NamedQuery(name="ComArcrftBas.findAll", query="SELECT c FROM ComArcrftBas c") +public class ComArcrftBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="ARCRFT_SNO") + private int arcrftSno; + + @Column(name="GROUP_ID") + private String groupId; + + @Column(name="ARCRFT_HGHT") + private double arcrftHght; + + @Column(name="ARCRFT_LNGTH") + private double arcrftLngth; + + @Column(name="ARCRFT_MODEL_NM") + private String arcrftModelNm; + + @Column(name="ARCRFT_TYPE_CD") + private String arcrftTypeCd; + + @Column(name="ARCRFT_WDTH") + private double arcrftWdth; + + @Column(name="ARCRFT_WGHT") + private double arcrftWght; + + @Column(name="CAMERA_YN") + private String cameraYn; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Column(name="INSRNC_YN") + private String insrncYn; + + @Column(name="PRDCT_CMPN_NM") + private String prdctCmpnNm; + + @Temporal(TemporalType.DATE) + @Column(name="PRDCT_DATE") + private Date prdctDate; + + @Column(name="PRDCT_NUM") + private String prdctNum; + + @Column(name="TAKEOFF_WGHT") + private double takeoffWght; + + @Column(name="USE_YN") + private String useYn; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + @Column(name="IMAGE_URL") + private String imageUrl; + + @Column(name="WGHT_TYPE_CD") + private String wghtTypeCd; + + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComAuthBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComAuthBas.java new file mode 100644 index 00000000..7d1980f1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComAuthBas.java @@ -0,0 +1,124 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the COM_AUTH_BAS database table. + * + */ +@Entity +@Table(name="COM_AUTH_BAS") +@NamedQuery(name="ComAuthBas.findAll", query="SELECT c FROM ComAuthBas c") +public class ComAuthBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="AUTH_ID") + private String authId; + + @Column(name="AUTH_NM") + private String authNm; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Lob + @Column(name="RM") + private String rm; + + @Column(name="SITE_CD") + private String siteCd; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + @Column(name="USE_YN") + private String useYn; + + public ComAuthBas() { + } + + public String getAuthId() { + return this.authId; + } + + public void setAuthId(String authId) { + this.authId = authId; + } + + public String getAuthNm() { + return this.authNm; + } + + public void setAuthNm(String authNm) { + this.authNm = authNm; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public String getCreateUserId() { + return this.createUserId; + } + + public void setCreateUserId(String createUserId) { + this.createUserId = createUserId; + } + + public String getRm() { + return this.rm; + } + + public void setRm(String rm) { + this.rm = rm; + } + + public String getSiteCd() { + return this.siteCd; + } + + public void setSiteCd(String siteCd) { + this.siteCd = siteCd; + } + + public Date getUpdateDt() { + return this.updateDt; + } + + public void setUpdateDt(Date updateDt) { + this.updateDt = updateDt; + } + + public String getUpdateUserId() { + return this.updateUserId; + } + + public void setUpdateUserId(String updateUserId) { + this.updateUserId = updateUserId; + } + + public String getUseYn() { + return this.useYn; + } + + public void setUseYn(String useYn) { + this.useYn = useYn; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdBas.java new file mode 100644 index 00000000..f9a409d5 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdBas.java @@ -0,0 +1,122 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the COM_CD_BAS database table. + * + */ +@Entity +@Table(name="COM_CD_BAS") +@NamedQuery(name="ComCdBas.findAll", query="SELECT c FROM ComCdBas c") +public class ComCdBas implements Serializable { + private static final long serialVersionUID = 1L; + + @EmbeddedId + private ComCdBasPK id; + + @Column(name="ADD_INFO_VALUE") + private String addInfoValue; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Column(name="SORT_ORDR") + private byte sortOrdr; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDTE_DT") + private Date updteDt; + + @Column(name="UPDTE_USER_ID") + private String updteUserId; + + @Column(name="UPPER_CD") + private String upperCd; + + @Column(name="USE_YN") + private String useYn; + + public ComCdBas() { + } + + public ComCdBasPK getId() { + return this.id; + } + + public void setId(ComCdBasPK id) { + this.id = id; + } + + public String getAddInfoValue() { + return this.addInfoValue; + } + + public void setAddInfoValue(String addInfoValue) { + this.addInfoValue = addInfoValue; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public String getCreateUserId() { + return this.createUserId; + } + + public void setCreateUserId(String createUserId) { + this.createUserId = createUserId; + } + + public byte getSortOrdr() { + return this.sortOrdr; + } + + public void setSortOrdr(byte sortOrdr) { + this.sortOrdr = sortOrdr; + } + + public Date getUpdteDt() { + return this.updteDt; + } + + public void setUpdteDt(Date updteDt) { + this.updteDt = updteDt; + } + + public String getUpdteUserId() { + return this.updteUserId; + } + + public void setUpdteUserId(String updteUserId) { + this.updteUserId = updteUserId; + } + + public String getUpperCd() { + return this.upperCd; + } + + public void setUpperCd(String upperCd) { + this.upperCd = upperCd; + } + + public String getUseYn() { + return this.useYn; + } + + public void setUseYn(String useYn) { + this.useYn = useYn; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdBasPK.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdBasPK.java new file mode 100644 index 00000000..59120448 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdBasPK.java @@ -0,0 +1,57 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; + +/** + * The primary key class for the COM_CD_BAS database table. + * + */ +@Embeddable +public class ComCdBasPK implements Serializable { + //default serial version id, required for serializable classes. + private static final long serialVersionUID = 1L; + + @Column(name="CD_ID") + private String cdId; + + @Column(name="GROUP_CD") + private String groupCd; + + public ComCdBasPK() { + } + public String getCdId() { + return this.cdId; + } + public void setCdId(String cdId) { + this.cdId = cdId; + } + public String getGroupCd() { + return this.groupCd; + } + public void setGroupCd(String groupCd) { + this.groupCd = groupCd; + } + + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof ComCdBasPK)) { + return false; + } + ComCdBasPK castOther = (ComCdBasPK)other; + return + this.cdId.equals(castOther.cdId) + && this.groupCd.equals(castOther.groupCd); + } + + public int hashCode() { + final int prime = 31; + int hash = 17; + hash = hash * prime + this.cdId.hashCode(); + hash = hash * prime + this.groupCd.hashCode(); + + return hash; + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdGroupBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdGroupBas.java new file mode 100644 index 00000000..761dfea8 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdGroupBas.java @@ -0,0 +1,113 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the COM_CD_GROUP_BAS database table. + * + */ +@Entity +@Table(name="COM_CD_GROUP_BAS") +@NamedQuery(name="ComCdGroupBas.findAll", query="SELECT c FROM ComCdGroupBas c") +public class ComCdGroupBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="GROUP_CD") + private String groupCd; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Column(name="GROUP_CD_NM") + private String groupCdNm; + + @Lob + @Column(name="RM") + private String rm; + + @Column(name="SITE_CD") + private String siteCd; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDTE_DT") + private Date updteDt; + + @Column(name="UPDTE_USER_ID") + private String updteUserId; + + public ComCdGroupBas() { + } + + public String getGroupCd() { + return this.groupCd; + } + + public void setGroupCd(String groupCd) { + this.groupCd = groupCd; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public String getCreateUserId() { + return this.createUserId; + } + + public void setCreateUserId(String createUserId) { + this.createUserId = createUserId; + } + + public String getGroupCdNm() { + return this.groupCdNm; + } + + public void setGroupCdNm(String groupCdNm) { + this.groupCdNm = groupCdNm; + } + + public String getRm() { + return this.rm; + } + + public void setRm(String rm) { + this.rm = rm; + } + + public String getSiteCd() { + return this.siteCd; + } + + public void setSiteCd(String siteCd) { + this.siteCd = siteCd; + } + + public Date getUpdteDt() { + return this.updteDt; + } + + public void setUpdteDt(Date updteDt) { + this.updteDt = updteDt; + } + + public String getUpdteUserId() { + return this.updteUserId; + } + + public void setUpdteUserId(String updteUserId) { + this.updteUserId = updteUserId; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdLangCtg.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdLangCtg.java new file mode 100644 index 00000000..94c15694 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdLangCtg.java @@ -0,0 +1,101 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the COM_CD_LANG_CTG database table. + * + */ +@Entity +@Table(name="COM_CD_LANG_CTG") +@NamedQuery(name="ComCdLangCtg.findAll", query="SELECT c FROM ComCdLangCtg c") +public class ComCdLangCtg implements Serializable { + private static final long serialVersionUID = 1L; + + @EmbeddedId + private ComCdLangCtgPK id; + + @Column(name="CD_NM") + private String cdNm; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Lob + @Column(name="RM") + private String rm; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDTE_DT") + private Date updteDt; + + @Column(name="UPDTE_USER_ID") + private String updteUserId; + + public ComCdLangCtg() { + } + + public ComCdLangCtgPK getId() { + return this.id; + } + + public void setId(ComCdLangCtgPK id) { + this.id = id; + } + + public String getCdNm() { + return this.cdNm; + } + + public void setCdNm(String cdNm) { + this.cdNm = cdNm; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public String getCreateUserId() { + return this.createUserId; + } + + public void setCreateUserId(String createUserId) { + this.createUserId = createUserId; + } + + public String getRm() { + return this.rm; + } + + public void setRm(String rm) { + this.rm = rm; + } + + public Date getUpdteDt() { + return this.updteDt; + } + + public void setUpdteDt(Date updteDt) { + this.updteDt = updteDt; + } + + public String getUpdteUserId() { + return this.updteUserId; + } + + public void setUpdteUserId(String updteUserId) { + this.updteUserId = updteUserId; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdLangCtgPK.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdLangCtgPK.java new file mode 100644 index 00000000..b49be52c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComCdLangCtgPK.java @@ -0,0 +1,68 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; + +/** + * The primary key class for the COM_CD_LANG_CTG database table. + * + */ +@Embeddable +public class ComCdLangCtgPK implements Serializable { + //default serial version id, required for serializable classes. + private static final long serialVersionUID = 1L; + + @Column(name="CD_ID") + private String cdId; + + @Column(name="GROUP_CD") + private String groupCd; + + @Column(name="LANG_DIV_CD") + private String langDivCd; + + public ComCdLangCtgPK() { + } + public String getCdId() { + return this.cdId; + } + public void setCdId(String cdId) { + this.cdId = cdId; + } + public String getGroupCd() { + return this.groupCd; + } + public void setGroupCd(String groupCd) { + this.groupCd = groupCd; + } + public String getLangDivCd() { + return this.langDivCd; + } + public void setLangDivCd(String langDivCd) { + this.langDivCd = langDivCd; + } + + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof ComCdLangCtgPK)) { + return false; + } + ComCdLangCtgPK castOther = (ComCdLangCtgPK)other; + return + this.cdId.equals(castOther.cdId) + && this.groupCd.equals(castOther.groupCd) + && this.langDivCd.equals(castOther.langDivCd); + } + + public int hashCode() { + final int prime = 31; + int hash = 17; + hash = hash * prime + this.cdId.hashCode(); + hash = hash * prime + this.groupCd.hashCode(); + hash = hash * prime + this.langDivCd.hashCode(); + + return hash; + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComIdntfBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComIdntfBas.java new file mode 100644 index 00000000..552a198f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComIdntfBas.java @@ -0,0 +1,53 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; + +import lombok.Data; + +import java.util.Date; + + +/** + * The persistent class for the COM_IDNTF_BAS database table. + * + */ +@Entity +@Table(name="COM_IDNTF_BAS") +@Data +@NamedQuery(name="ComIdntfBas.findAll", query="SELECT c FROM ComIdntfBas c") +public class ComIdntfBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="IDNTF_NUM") + private String idntfNum; + + @Column(name="ARCRFT_SNO") + private int arcrftSno; + + @Column(name="IDNTF_TYPE_CD") + private String idntfTypeCd; + + @Column(name="OWNER_NM") + private String ownerNm; + + @Column(name = "CSTMR_SNO") + private Integer cstmrSno; + + @Column(name="HPNO") + private String hpno; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + public ComIdntfBas() { + } + + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComSiteBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComSiteBas.java new file mode 100644 index 00000000..6956ba50 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComSiteBas.java @@ -0,0 +1,124 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the COM_SITE_BAS database table. + * + */ +@Entity +@Table(name="COM_SITE_BAS") +@NamedQuery(name="ComSiteBas.findAll", query="SELECT c FROM ComSiteBas c") +public class ComSiteBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="SITE_CD") + private String siteCd; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Lob + @Column(name="SITE_DESC") + private String siteDesc; + + @Column(name="SITE_NM") + private String siteNm; + + @Column(name="SITE_URL") + private String siteUrl; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + @Column(name="USE_YN") + private String useYn; + + public ComSiteBas() { + } + + public String getSiteCd() { + return this.siteCd; + } + + public void setSiteCd(String siteCd) { + this.siteCd = siteCd; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public String getCreateUserId() { + return this.createUserId; + } + + public void setCreateUserId(String createUserId) { + this.createUserId = createUserId; + } + + public String getSiteDesc() { + return this.siteDesc; + } + + public void setSiteDesc(String siteDesc) { + this.siteDesc = siteDesc; + } + + public String getSiteNm() { + return this.siteNm; + } + + public void setSiteNm(String siteNm) { + this.siteNm = siteNm; + } + + public String getSiteUrl() { + return this.siteUrl; + } + + public void setSiteUrl(String siteUrl) { + this.siteUrl = siteUrl; + } + + public Date getUpdateDt() { + return this.updateDt; + } + + public void setUpdateDt(Date updateDt) { + this.updateDt = updateDt; + } + + public String getUpdateUserId() { + return this.updateUserId; + } + + public void setUpdateUserId(String updateUserId) { + this.updateUserId = updateUserId; + } + + public String getUseYn() { + return this.useYn; + } + + public void setUseYn(String useYn) { + this.useYn = useYn; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComTrmnlBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComTrmnlBas.java new file mode 100644 index 00000000..85443d39 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComTrmnlBas.java @@ -0,0 +1,123 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the COM_TRMNL_BAS database table. + * + */ +@Entity +@Table(name="COM_TRMNL_BAS") +@NamedQuery(name="ComTrmnlBas.findAll", query="SELECT c FROM ComTrmnlBas c") +public class ComTrmnlBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="TRMNL_ID") + private String trmnlId; + + @Column(name="AUTH_KEY") + private String authKey; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Column(name="DESC_SN") + private String descSn; + + @Column(name="TRMNL_NM") + private String trmnlNm; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DATE") + private Date updateDate; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + @Column(name="USE_YN") + private String useYn; + + public ComTrmnlBas() { + } + + public String getTrmnlId() { + return this.trmnlId; + } + + public void setTrmnlId(String trmnlId) { + this.trmnlId = trmnlId; + } + + public String getAuthKey() { + return this.authKey; + } + + public void setAuthKey(String authKey) { + this.authKey = authKey; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public String getCreateUserId() { + return this.createUserId; + } + + public void setCreateUserId(String createUserId) { + this.createUserId = createUserId; + } + + public String getDescSn() { + return this.descSn; + } + + public void setDescSn(String descSn) { + this.descSn = descSn; + } + + public String getTrmnlNm() { + return this.trmnlNm; + } + + public void setTrmnlNm(String trmnlNm) { + this.trmnlNm = trmnlNm; + } + + public Date getUpdateDate() { + return this.updateDate; + } + + public void setUpdateDate(Date updateDate) { + this.updateDate = updateDate; + } + + public String getUpdateUserId() { + return this.updateUserId; + } + + public void setUpdateUserId(String updateUserId) { + this.updateUserId = updateUserId; + } + + public String getUseYn() { + return this.useYn; + } + + public void setUseYn(String useYn) { + this.useYn = useYn; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlBas.java new file mode 100644 index 00000000..60e16edc --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlBas.java @@ -0,0 +1,87 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; + +import lombok.Data; + +import java.util.Date; + + +/** + * The persistent class for the CTR_CNTRL_BAS database table. + * + */ +@Entity +@Table(name="CTR_CNTRL_BAS") +@Data +@NamedQuery(name="CtrCntrlBas.findAll", query="SELECT c FROM CtrCntrlBas c") +public class CtrCntrlBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="CNTRL_ID") + private String cntrlId; + + @Column(name="AVRG_SPEED") + private Double avrgSpeed = 0.0; + + @Column(name="AVRG_SPEED_TYPE") + private String avrgSpeedType; + + @Column(name="BTTR_CNSMPTN") + private Double bttrCnsmptn = 0.0; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CNTRL_END_DT") + private Date cntrlEndDt; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CNTRL_ST_DT") + private Date cntrlStDt; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="END_TYPE_CD") + private String endTypeCd; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="FLGHT_END_DT") + private Date flghtEndDt; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="FLGHT_ST_DT") + private Date flghtStDt; + + @Column(name="IDNTF_NUM") + private String idntfNum; + + @Column(name="OBJECT_TYPE_CD") + private String objectTypeCd; + + @Column(name="STATUS_CD") + private String statusCd; + + @Column(name="PROC_STATUS_YN") + private String procStatusYn; + + @Column(name="TTL_DSTNC") + private Double ttlDstnc = 0.0; + + @Column(name="TTL_DSTNC_TYPE") + private String ttlDstncType; + + @Column(name="TTL_TIME") + private Double ttlTime = 0.0; + + @Column(name="TTL_TIME_TYPE") + private String ttlTimeType; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlHstry.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlHstry.java new file mode 100644 index 00000000..98a86b20 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlHstry.java @@ -0,0 +1,274 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the CTR_CNTRL_HSTRY database table. + * + */ +@Entity +@Table(name="CTR_CNTRL_HSTRY") +@NamedQuery(name="CtrCntrlHstry.findAll", query="SELECT c FROM CtrCntrlHstry c") +public class CtrCntrlHstry implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="HSTRY_SNO") + private int hstrySno; + + @Column(name="BTTR_LVL") + private Double bttrLvl; + + @Column(name="BTTR_VLTG") + private Double bttrVltg; + + @Column(name="CNTRL_ID") + private String cntrlId; + + @Column(name="ELEV") + private Double elev; + + @Column(name="ELEV_TYPE") + private String elevType; + + @Column(name="HEADING") + private Double heading; + + @Column(name="LAT") + private Double lat; + + @Column(name="LON") + private Double lon; + + @Column(name="MSSG_TYPE_CD") + private String mssgTypeCd; + + @Column(name="MV_DSTNC") + private Double mvDstnc; + + @Column(name="MV_DSTNC_TYPE") + private String mvDstncType; + + @Column(name="SPEED") + private Double speed; + + @Column(name="SPEED_TYPE") + private String speedType; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="SRVR_RCV_DT") + private Date srvrRcvDt; + + @Column(name="STATUS_CD") + private String statusCd; + + @Column(name="TRMNL_ID") + private String trmnlId; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="TRMNL_RCV_DT") + private Date trmnlRcvDt; + + // 환경센서 필드 + @Column(name="SENSOR_CO") + private Double sensorCo; + @Column(name="SENSOR_SO2") + private Double sensorSo2; + @Column(name="SENSOR_NO2") + private Double sensorNo2; + @Column(name="SENSOR_O3") + private Double sensorO3; + @Column(name="SENSOR_DUST") + private Double sensorDust; + + public CtrCntrlHstry() { + } + + public int getHstrySno() { + return this.hstrySno; + } + + public void setHstrySno(int hstrySno) { + this.hstrySno = hstrySno; + } + + public double getBttrLvl() { + return this.bttrLvl; + } + + public void setBttrLvl(double bttrLvl) { + this.bttrLvl = bttrLvl; + } + + public double getBttrVltg() { + return this.bttrVltg; + } + + public void setBttrVltg(double bttrVltg) { + this.bttrVltg = bttrVltg; + } + + public String getCntrlId() { + return this.cntrlId; + } + + public void setCntrlId(String cntrlId) { + this.cntrlId = cntrlId; + } + + public double getElev() { + return this.elev; + } + + public void setElev(double elev) { + this.elev = elev; + } + + public String getElevType() { + return this.elevType; + } + + public void setElevType(String elevType) { + this.elevType = elevType; + } + + public double getHeading() { + return this.heading; + } + + public void setHeading(double heading) { + this.heading = heading; + } + + public double getLat() { + return this.lat; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public double getLon() { + return this.lon; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public String getMssgTypeCd() { + return this.mssgTypeCd; + } + + public void setMssgTypeCd(String mssgTypeCd) { + this.mssgTypeCd = mssgTypeCd; + } + + public double getMvDstnc() { + return this.mvDstnc; + } + + public void setMvDstnc(double mvDstnc) { + this.mvDstnc = mvDstnc; + } + + public String getMvDstncType() { + return this.mvDstncType; + } + + public void setMvDstncType(String mvDstncType) { + this.mvDstncType = mvDstncType; + } + + public double getSpeed() { + return this.speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + public String getSpeedType() { + return this.speedType; + } + + public void setSpeedType(String speedType) { + this.speedType = speedType; + } + + public Date getSrvrRcvDt() { + return this.srvrRcvDt; + } + + public void setSrvrRcvDt(Date srvrRcvDt) { + this.srvrRcvDt = srvrRcvDt; + } + + public String getStatusCd() { + return this.statusCd; + } + + public void setStatusCd(String statusCd) { + this.statusCd = statusCd; + } + + public String getTrmnlId() { + return this.trmnlId; + } + + public void setTrmnlId(String trmnlId) { + this.trmnlId = trmnlId; + } + + public Date getTrmnlRcvDt() { + return this.trmnlRcvDt; + } + + public void setTrmnlRcvDt(Date trmnlRcvDt) { + this.trmnlRcvDt = trmnlRcvDt; + } + + public Double getSensorCo(){ + return sensorCo; + } + + public void setSensorCo(Double sensorCo){ + this.sensorCo = sensorCo; + } + + public Double getSensorSo2(){ + return sensorSo2; + } + + public void setSensorSo2(Double sensorSo2){ + this.sensorSo2 = sensorSo2; + } + + public Double getSensorNo2(){ + return sensorNo2; + } + + public void setSensorNo2(Double sensorNo2){ + this.sensorNo2 = sensorNo2; + } + + public Double getSensorO3(){ + return sensorO3; + } + + public void setSensorO3(Double sensorO3){ + this.sensorO3 = sensorO3; + } + + public Double getSensorDust(){ + return sensorDust; + } + + public void setSensorDust(Double sensorDust){ + this.sensorDust = sensorDust; + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlHstryArea.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlHstryArea.java new file mode 100644 index 00000000..69d6403e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlHstryArea.java @@ -0,0 +1,212 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the CTR_CNTRL_HSTRY_AREA database table. + * + */ +@Entity +@Table(name="CTR_CNTRL_HSTRY_AREA") +@NamedQuery(name="CtrCntrlHstryArea.findAll", query="SELECT c FROM CtrCntrlHstryArea c") +public class CtrCntrlHstryArea implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="HSTRY_AREA_SNO") + private int hstryAreaSno; + + @Column(name="ACTN_TYPE") + private String actnType; + + @Column(name="AREA_NM") + private String areaNm; + + @Column(name="AREA_TYPE") + private String areaType; + + @Column(name="AREA1") + private String area1; + + @Column(name="AREA2") + private String area2; + + @Column(name="AREA3") + private String area3; + + @Column(name="CNTRL_ID") + private String cntrlId; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="HSTRY_SNO") + private int hstrySno; + + @Column(name="LAND_NM") + private String landNm; + + @Column(name="LAND_NUM") + private String landNum; + + @Column(name="LAT") + private double lat; + + @Column(name="LON") + private double lon; + + @Column(name="PRCS_YN") + private String prcsYn; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + @Column(name="ZIP_CD") + private String zipCd; + + public CtrCntrlHstryArea() { + } + + public int getHstryAreaSno() { + return this.hstryAreaSno; + } + + public void setHstryAreaSno(int hstryAreaSno) { + this.hstryAreaSno = hstryAreaSno; + } + + public String getActnType() { + return this.actnType; + } + + public void setActnType(String actnType) { + this.actnType = actnType; + } + + public String getAreaNm() { + return this.areaNm; + } + + public void setAreaNm(String areaNm) { + this.areaNm = areaNm; + } + + public String getAreaType() { + return this.areaType; + } + + public void setAreaType(String areaType) { + this.areaType = areaType; + } + + public String getArea1() { + return this.area1; + } + + public void setArea1(String area1) { + this.area1 = area1; + } + + public String getArea2() { + return this.area2; + } + + public void setArea2(String area2) { + this.area2 = area2; + } + + public String getArea3() { + return this.area3; + } + + public void setArea3(String area3) { + this.area3 = area3; + } + + public String getCntrlId() { + return this.cntrlId; + } + + public void setCntrlId(String cntrlId) { + this.cntrlId = cntrlId; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public int getHstrySno() { + return this.hstrySno; + } + + public void setHstrySno(int hstrySno) { + this.hstrySno = hstrySno; + } + + public String getLandNm() { + return this.landNm; + } + + public void setLandNm(String landNm) { + this.landNm = landNm; + } + + public String getLandNum() { + return this.landNum; + } + + public void setLandNum(String landNum) { + this.landNum = landNum; + } + + public double getLat() { + return this.lat; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public double getLon() { + return this.lon; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public String getPrcsYn() { + return this.prcsYn; + } + + public void setPrcsYn(String prcsYn) { + this.prcsYn = prcsYn; + } + + public Date getUpdateDt() { + return this.updateDt; + } + + public void setUpdateDt(Date updateDt) { + this.updateDt = updateDt; + } + + public String getZipCd() { + return this.zipCd; + } + + public void setZipCd(String zipCd) { + this.zipCd = zipCd; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlWarnLog.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlWarnLog.java new file mode 100644 index 00000000..afafb13b --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CtrCntrlWarnLog.java @@ -0,0 +1,45 @@ +package com.palnet.biz.jpa.entity; + +import lombok.Data; + +import javax.persistence.*; +import java.util.Date; + +@Entity +@Table(name = "CTR_CNTRL_WARN_LOG") +@Data +public class CtrCntrlWarnLog { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "WARN_LOG_SNO") + private Integer warnLogSno; + + @Column(name = "CNTRL_ID") + private String cntrlId; + + @Column(name = "WARN_TYPE") + private String warnType; + + @Column(name = "IDNTF_NUM") + private String idntfNum; + + @Column(name = "OCCUR_DT") + private Date occurDt; + + @Column(name = "LAT") + private double lat; + + @Column(name = "LON") + private double lon; + + @Column(name = "ELEV") + private double elev; + + @Column(name = "CREATE_DT") + private Date createDt; + + @Column(name = "CREATE_USER_ID") + private String createUserId; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanArcrft.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanArcrft.java new file mode 100644 index 00000000..ecfb7ce8 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanArcrft.java @@ -0,0 +1,99 @@ +package com.palnet.biz.jpa.entity; + +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import javax.persistence.*; +import java.util.Date; + +@Table(name = "FLT_PLAN_ARCRFT") +@Entity +@Getter +@Setter +public class FltPlanArcrft { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="PLAN_ARCRFT_SNO") + private Integer planArcrftSno; + + @Column(name="PLAN_SNO") + private Integer planSno; + + @Column(name="ARCRFT_SNO") + private Integer arcrftSno; + + @Column(name="IDNTF_NUM") + private String idntfNum; + + @Column(name="GROUP_NM") + private String groupNm; + + @Column(name="PRDCT_NUM") + private String prdctNum; + + @Column(name="ARCRFT_TYPE_CD") + private String arcrftTypeCd; + + @Column(name="ARCRFT_MODEL_NM") + private String arcrftModelNm; + + @Column(name="PRDCT_CMPN_NM") + private String prdctCmpnNm; + + @Column(name="PRDCT_DATE") + private Date prdctDate; + + @Column(name="ARCRFT_LNGTH") + private double arcrftLngth; + + @Column(name="ARCRFT_WDTH") + private double arcrftWdth; + + @Column(name="ARCRFT_HGHT") + private double arcrftHght; + + @Column(name="ARCRFT_WGHT") + private double arcrftWght; + + @Column(name="WGHT_TYPE_CD") + private String wghtTypeCd; + + @Column(name="IMAGE_URL") + private String imageUrl; + + @Column(name="TAKEOFF_WGHT") + private double takeoffWght; + + @Column(name="USE_YN") + private String useYn; + + @Column(name="CAMERA_YN") + private String cameraYn; + + @Column(name="INSRNC_YN") + private String insrncYn; + + @Column(name="OWNER_NM") + private String ownerNm; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @CreationTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + @UpdateTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name="update_DT") + private Date updateDt; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanArea.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanArea.java new file mode 100644 index 00000000..18943919 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanArea.java @@ -0,0 +1,54 @@ +package com.palnet.biz.jpa.entity; + +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import javax.persistence.*; +import java.util.Date; + +@Table(name = "FLT_PLAN_AREA") +@Entity +@Getter +@Setter +public class FltPlanArea { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="PLAN_AREA_SNO") + private Integer planAreaSno; + + @Column(name="PLAN_SNO") + private Integer planSno; + + @Column(name = "AREA_TYPE") + private String areaType; + + @Column(name = "FLT_METHOD") + private String fltMethod; + + @Column(name = "BUFFER_ZONE") + private Integer bufferZone; + + @Column(name = "FLT_ELEV") + private String fltElev; + + @Column(name = "CREATE_USER_ID") + private String createUserId; + + @CreationTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "CREATE_DT") + private Date createDt; + + @Column(name = "UPDATE_USER_ID") + private String updateUserId; + + @UpdateTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "UPDATE_DT") + private Date updateDt; + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanAreaCoord.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanAreaCoord.java new file mode 100644 index 00000000..836c2497 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanAreaCoord.java @@ -0,0 +1,39 @@ +package com.palnet.biz.jpa.entity; + +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; + +import javax.persistence.*; +import java.time.LocalDateTime; +import java.util.Date; + +@Table(name = "FLT_PLAN_AREA_COORD") +@Entity +@Getter +@Setter +public class FltPlanAreaCoord { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="PLAN_AREA_COORD_SNO") + private Integer planAreaCoordSno; + + @Column(name = "PLAN_AREA_SNO") + private Integer planAreaSno; + + + @Column(name = "LON") + private double lon; + + @Column(name = "LAT") + private double lat; + + @Column(name = "CREATE_USER_ID") + private String createUserId; + + @CreationTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "CREATE_DT") + private Date createDt; +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanBas.java new file mode 100644 index 00000000..d317b4ed --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanBas.java @@ -0,0 +1,83 @@ +package com.palnet.biz.jpa.entity; + +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import javax.persistence.*; +import java.time.LocalDateTime; +import java.util.Date; + +@Table(name = "FLT_PLAN_BAS") +@Entity +@Getter +@Setter +public class FltPlanBas { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "PLAN_SNO") + private Integer planSno; + + @Column(name = "GROUP_ID") + private String groupId; + + @Column(name = "CSTMR_SNO") + private Integer cstmrSno; + + @Column(name = "MEMBER_NAME") + private String memberName; + + @Column(name = "EMAIL") + private String email; + + @Column(name = "HPNO") + private String hpno; + + @Column(name = "CLNCD") + private String clncd; + + @Column(name = "ADDR") + private String addr; + + @Column(name = "ADDR_DTL_CN") + private String addrDtlCn; + + @Column(name = "zip") + private String zip; + + @Column(name = "SCH_FLT_ST_DT") + private Date schFltStDt; + + @Column(name = "SCH_FLT_END_DT") + private Date schFltEndDt; + + @Column(name = "FLT_PURPOSE") + private String fltPurpose; + + @Column(name = "APRVL_YN") + private String aprvlYn; + + @Column(name = "DEL_YN") + private String delYn; + + @Column(name = "CREATE_USER_ID") + private String createUserId; + + @CreationTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "CREATE_DT") + private Date createDt; + + @Column(name = "UPDATE_USER_ID") + private String updateUserId; + + @UpdateTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "UPDATE_DT") + private Date updateDt; + +} + + diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanCtrCntrlRel.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanCtrCntrlRel.java new file mode 100644 index 00000000..82e7cbda --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanCtrCntrlRel.java @@ -0,0 +1,30 @@ +package com.palnet.biz.jpa.entity; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; + +@Entity +@Table(name = "FLT_PLAN_CTR_CNTRL_REL") +@Getter +@Setter +public class FltPlanCtrCntrlRel { + + @Column(name = "CNTRL_ID") + @Id + private String cntrlId; + + @Column(name = "IDNTF_NUM") + private String idntfNum; + + @Column(name = "PLAN_SNO") + private Integer planSno; + + @Column(name = "GROUP_ID") + private String groupId; + + @Column(name = "IDNTF_CSTMR_SNO") + private Integer idntfCstmrSno; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanPilot.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanPilot.java new file mode 100644 index 00000000..be9d013b --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/FltPlanPilot.java @@ -0,0 +1,74 @@ +package com.palnet.biz.jpa.entity; + +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import javax.persistence.*; +import java.util.Date; + +@Table(name = "FLT_PLAN_PILOT") +@Entity +@Getter +@Setter +public class FltPlanPilot { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "PLAN_PILOT_SNO") + private Integer planPilotSno; + + @Column(name = "PLAN_SNO") + private Integer planSno; + + @Column(name = "CSTMR_SNO") + private Integer cstmrSno; + + @Column(name = "GROUP_NM") + private String groupNm; + + @Column(name = "MEMBER_NAME") + private String memberName; + + @Column(name = "EMAIL") + private String email; + + @Column(name = "HPNO") + private String hpno; + + @Column(name = "CLNCD") + private String clncd; + + @Column(name = "ADDR") + private String addr; + + @Column(name = "ADDR_DTL_CN") + private String addrDtlCn; + + @Column(name = "zip") + private String zip; + + @Column(name = "QLFC_NO") + private String qlfcNo; + + @Column(name = "CARRER") + private String carrer; + + @Column(name = "CREATE_USER_ID") + private String createUserId; + + @CreationTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "CREATE_DT") + private Date createDt; + + @Column(name = "UPDATE_USER_ID") + private String updateUserId; + + @UpdateTimestamp + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "UPDATE_DT") + private Date updateDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCrtfyhpBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCrtfyhpBas.java new file mode 100644 index 00000000..490a5cd6 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCrtfyhpBas.java @@ -0,0 +1,42 @@ +package com.palnet.biz.jpa.entity; + +import lombok.Data; +import org.hibernate.annotations.CreationTimestamp; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + + +/** + * The persistent class for the PTY_CRTFYHP_BAS database table. + * + */ +@Entity +@Table(name="PTY_CRTFYHP_BAS") +@NamedQuery(name="PtyCrtfyhpBas.findAll", query="SELECT p FROM PtyCrtfyhpBas p") +@Data +public class PtyCrtfyhpBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="CRTFYHP_SNO") + private int crtfyhpSno; + + @CreationTimestamp + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CRTFYHP_NO") + private String crtfyhpNo; + + @Column(name="CRTFYHP_YN") + private String crtfyhpYn; + + @Column(name="HPNO") + private String hpno; + + + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrBas.java new file mode 100644 index 00000000..8ab7dd89 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrBas.java @@ -0,0 +1,70 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; + +import lombok.Data; + +import java.util.Date; + + +/** + * The persistent class for the PTY_CSTMR_BAS database table. + * + */ +@Entity +@Table(name="PTY_CSTMR_BAS") +@NamedQuery(name="PtyCstmrBas.findAll", query="SELECT p FROM PtyCstmrBas p") +@Data +public class PtyCstmrBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="CSTMR_SNO") + private Integer cstmrSno; + + @Column(name="AUTH_ID") + private String authId; + + @Column(name="CSTMR_DIV_CD") + private String cstmrDivCd; + + @Column(name="CSTMR_STATUS_CD") + private String cstmrStatusCd; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CSTMR_STATUS_CNG_DT") + private Date cstmrStatusCngDt; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="JOIN_DT") + private Date joinDt; + + @Column(name="JOIN_IP") + private String joinIp; + + @Column(name="MEMBER_DIV_CD") + private String memberDivCd; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="PSWD_UPDT_DT") + private Date pswdUpdtDt; + + @Column(name="SITE_CODE") + private String siteCode; + + @Column(name="USER_ID") + private String userId; + + @Column(name="USER_PSWD") + private String userPswd; + + @Column(name="RFRSH_TOKEN") + private String rfrshToken; + + @Column(name="TRMNL_ID") + private String trmnlId; + + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrConectHist.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrConectHist.java new file mode 100644 index 00000000..5d12cf41 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrConectHist.java @@ -0,0 +1,89 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the PTY_CSTMR_CONECT_HIST database table. + * + */ +@Entity +@Table(name="PTY_CSTMR_CONECT_HIST") +@NamedQuery(name="PtyCstmrConectHist.findAll", query="SELECT p FROM PtyCstmrConectHist p") +public class PtyCstmrConectHist implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="CSTMR_CONECT_HIST_SNO") + private int cstmrConectHistSno; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CONECT_DT") + private Date conectDt; + + @Column(name="CONECT_ERROR_CD") + private String conectErrorCd; + + @Column(name="CONECT_IP") + private String conectIp; + + @Column(name="CONECT_SUCES_YN") + private String conectSucesYn; + + @Column(name="CSTMR_SNO") + private int cstmrSno; + + public PtyCstmrConectHist() { + } + + public int getCstmrConectHistSno() { + return this.cstmrConectHistSno; + } + + public void setCstmrConectHistSno(int cstmrConectHistSno) { + this.cstmrConectHistSno = cstmrConectHistSno; + } + + public Date getConectDt() { + return this.conectDt; + } + + public void setConectDt(Date conectDt) { + this.conectDt = conectDt; + } + + public String getConectErrorCd() { + return this.conectErrorCd; + } + + public void setConectErrorCd(String conectErrorCd) { + this.conectErrorCd = conectErrorCd; + } + + public String getConectIp() { + return this.conectIp; + } + + public void setConectIp(String conectIp) { + this.conectIp = conectIp; + } + + public String getConectSucesYn() { + return this.conectSucesYn; + } + + public void setConectSucesYn(String conectSucesYn) { + this.conectSucesYn = conectSucesYn; + } + + public int getCstmrSno() { + return this.cstmrSno; + } + + public void setCstmrSno(int cstmrSno) { + this.cstmrSno = cstmrSno; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrDtl.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrDtl.java new file mode 100644 index 00000000..58c8b44d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrDtl.java @@ -0,0 +1,200 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the PTY_CSTMR_DTL database table. + * + */ +@Entity +@Table(name="PTY_CSTMR_DTL") +@NamedQuery(name="PtyCstmrDtl.findAll", query="SELECT p FROM PtyCstmrDtl p") +public class PtyCstmrDtl implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="CSTMR_SNO") + private int cstmrSno; + + @Column(name="ADDR") + private String addr; + + @Column(name="ADDR_DTL_CN") + private String addrDtlCn; + + @Temporal(TemporalType.DATE) + @Column(name="BRTHDY_DATE") + private Date brthdyDate; + + @Column(name="CLNCD") + private String clncd; + + @Column(name="CNTRY_CD") + private String cntryCd; + + @Column(name="EMAIL") + private String email; + + @Column(name="GENDER_CD") + private String genderCd; + + @Column(name="HPNO") + private String hpno; + + @Column(name="IPIN_CI") + private String ipinCi; + + @Column(name="IPIN_DI") + private String ipinDi; + + @Column(name="JOIN_CRTFY_CD") + private String joinCrtfyCd; + + @Column(name="MEMBER_NAME") + private String memberName; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + @Column(name="ZIP") + private String zip; + + public PtyCstmrDtl() { + } + + public int getCstmrSno() { + return this.cstmrSno; + } + + public void setCstmrSno(int cstmrSno) { + this.cstmrSno = cstmrSno; + } + + public String getAddr() { + return this.addr; + } + + public void setAddr(String addr) { + this.addr = addr; + } + + public String getAddrDtlCn() { + return this.addrDtlCn; + } + + public void setAddrDtlCn(String addrDtlCn) { + this.addrDtlCn = addrDtlCn; + } + + public Date getBrthdyDate() { + return this.brthdyDate; + } + + public void setBrthdyDate(Date brthdyDate) { + this.brthdyDate = brthdyDate; + } + + public String getClncd() { + return this.clncd; + } + + public void setClncd(String clncd) { + this.clncd = clncd; + } + + public String getCntryCd() { + return this.cntryCd; + } + + public void setCntryCd(String cntryCd) { + this.cntryCd = cntryCd; + } + + public String getEmail() { + return this.email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getGenderCd() { + return this.genderCd; + } + + public void setGenderCd(String genderCd) { + this.genderCd = genderCd; + } + + public String getHpno() { + return this.hpno; + } + + public void setHpno(String hpno) { + this.hpno = hpno; + } + + public String getIpinCi() { + return this.ipinCi; + } + + public void setIpinCi(String ipinCi) { + this.ipinCi = ipinCi; + } + + public String getIpinDi() { + return this.ipinDi; + } + + public void setIpinDi(String ipinDi) { + this.ipinDi = ipinDi; + } + + public String getJoinCrtfyCd() { + return this.joinCrtfyCd; + } + + public void setJoinCrtfyCd(String joinCrtfyCd) { + this.joinCrtfyCd = joinCrtfyCd; + } + + public String getMemberName() { + return this.memberName; + } + + public void setMemberName(String memberName) { + this.memberName = memberName; + } + + public Date getUpdateDt() { + return this.updateDt; + } + + public void setUpdateDt(Date updateDt) { + this.updateDt = updateDt; + } + + public String getUpdateUserId() { + return this.updateUserId; + } + + public void setUpdateUserId(String updateUserId) { + this.updateUserId = updateUserId; + } + + public String getZip() { + return this.zip; + } + + public void setZip(String zip) { + this.zip = zip; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrGroup.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrGroup.java new file mode 100644 index 00000000..d68df611 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyCstmrGroup.java @@ -0,0 +1,142 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the PTY_CSTMR_GROUP database table. + * + */ +@Entity +@Table(name="PTY_CSTMR_GROUP") +@NamedQuery(name="PtyCstmrGroup.findAll", query="SELECT p FROM PtyCstmrGroup p") +public class PtyCstmrGroup implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="CSTMR_GROUP_SNO") + private int cstmrGroupSno; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="APRVL_DT") + private Date aprvlDt; + + @Column(name="APRVL_USER_ID") + private String aprvlUserId; + + @Column(name="APRVL_YN") + private String aprvlYn; + + @Column(name="CSTMR_SNO") + private int cstmrSno; + + @Column(name="GROUP_AUTH_CD") + private String groupAuthCd; + + @Column(name="GROUP_ID") + private String groupId; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="JOIN_DT") + private Date joinDt; + + @Column(name="JOIN_YN") + private String joinYn; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="WTHDRW_DT") + private Date wthdrwDt; + + @Column(name="TRMNL_ID") + private String trmnlId; + + public PtyCstmrGroup() { + } + + public int getCstmrGroupSno() { + return this.cstmrGroupSno; + } + + public void setCstmrGroupSno(int cstmrGroupSno) { + this.cstmrGroupSno = cstmrGroupSno; + } + + public Date getAprvlDt() { + return this.aprvlDt; + } + + public void setAprvlDt(Date aprvlDt) { + this.aprvlDt = aprvlDt; + } + + public String getAprvlUserId() { + return this.aprvlUserId; + } + + public void setAprvlUserId(String aprvlUserId) { + this.aprvlUserId = aprvlUserId; + } + + public String getAprvlYn() { + return this.aprvlYn; + } + + public void setAprvlYn(String aprvlYn) { + this.aprvlYn = aprvlYn; + } + + public int getCstmrSno() { + return this.cstmrSno; + } + + public void setCstmrSno(int cstmrSno) { + this.cstmrSno = cstmrSno; + } + + public String getGroupAuthCd() { + return this.groupAuthCd; + } + + public void setGroupAuthCd(String groupAuthCd) { + this.groupAuthCd = groupAuthCd; + } + + public String getGroupId() { + return this.groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public Date getJoinDt() { + return this.joinDt; + } + + public void setJoinDt(Date joinDt) { + this.joinDt = joinDt; + } + + public String getJoinYn() { + return this.joinYn; + } + + public void setJoinYn(String joinYn) { + this.joinYn = joinYn; + } + + public Date getWthdrwDt() { + return this.wthdrwDt; + } + + public void setWthdrwDt(Date wthdrwDt) { + this.wthdrwDt = wthdrwDt; + } + + public String getTrmnlId() { return this.trmnlId; } + + public void setTrmnlId(String trmnlId) { this.trmnlId = trmnlId; } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyGroupBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyGroupBas.java new file mode 100644 index 00000000..a376c867 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyGroupBas.java @@ -0,0 +1,97 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the PTY_GROUP_BAS database table. + * + */ +@Entity +@Table(name="PTY_GROUP_BAS") +@NamedQuery(name="PtyGroupBas.findAll", query="SELECT p FROM PtyGroupBas p") +public class PtyGroupBas implements Serializable { + private static final long serialVersionUID = 1L; + private String groupId; + private Date createDt; + private String groupNm; + private String groupTypeCd; + private Date updateDt; + private String useYn; + private String trmnlId; + + public PtyGroupBas() { + } + + + @Id + @Column(name="GROUP_ID") + public String getGroupId() { + return this.groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + + @Column(name="GROUP_NM") + public String getGroupNm() { + return this.groupNm; + } + + public void setGroupNm(String groupNm) { + this.groupNm = groupNm; + } + + + @Column(name="GROUP_TYPE_CD") + public String getGroupTypeCd() { + return this.groupTypeCd; + } + + public void setGroupTypeCd(String groupTypeCd) { + this.groupTypeCd = groupTypeCd; + } + + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + public Date getUpdateDt() { + return this.updateDt; + } + + public void setUpdateDt(Date updateDt) { + this.updateDt = updateDt; + } + + + @Column(name="USE_YN") + public String getUseYn() { + return this.useYn; + } + + public void setUseYn(String useYn) { + this.useYn = useYn; + } + + + @Column(name="TRMNL_ID") + public String getTrmnlId() { return this.trmnlId;} + + public void setTrmnlId(String trmnlId) { this.trmnlId = trmnlId; } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtySnsLoginRel.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtySnsLoginRel.java new file mode 100644 index 00000000..0901d27a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtySnsLoginRel.java @@ -0,0 +1,112 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the PTY_SNS_LOGIN_REL database table. + * + */ +@Entity +@Table(name="PTY_SNS_LOGIN_REL") +@NamedQuery(name="PtySnsLoginRel.findAll", query="SELECT p FROM PtySnsLoginRel p") +public class PtySnsLoginRel implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="SNS_LOGIN_SNO") + private int snsLoginSno; + + @Column(name="CSTMR_SNO") + private int cstmrSno; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="LINK_DT") + private Date linkDt; + + @Column(name="LINK_IP") + private String linkIp; + + @Column(name="LINK_YN") + private String linkYn; + + @Column(name="SNS_CD") + private String snsCd; + + @Column(name="SNS_IDNTFR_ID") + private String snsIdntfrId; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="WTHDR_DT") + private Date wthdrDt; + + public PtySnsLoginRel() { + } + + public int getSnsLoginSno() { + return this.snsLoginSno; + } + + public void setSnsLoginSno(int snsLoginSno) { + this.snsLoginSno = snsLoginSno; + } + + public int getCstmrSno() { + return this.cstmrSno; + } + + public void setCstmrSno(int cstmrSno) { + this.cstmrSno = cstmrSno; + } + + public Date getLinkDt() { + return this.linkDt; + } + + public void setLinkDt(Date linkDt) { + this.linkDt = linkDt; + } + + public String getLinkIp() { + return this.linkIp; + } + + public void setLinkIp(String linkIp) { + this.linkIp = linkIp; + } + + public String getLinkYn() { + return this.linkYn; + } + + public void setLinkYn(String linkYn) { + this.linkYn = linkYn; + } + + public String getSnsCd() { + return this.snsCd; + } + + public void setSnsCd(String snsCd) { + this.snsCd = snsCd; + } + + public String getSnsIdntfrId() { + return this.snsIdntfrId; + } + + public void setSnsIdntfrId(String snsIdntfrId) { + this.snsIdntfrId = snsIdntfrId; + } + + public Date getWthdrDt() { + return this.wthdrDt; + } + + public void setWthdrDt(Date wthdrDt) { + this.wthdrDt = wthdrDt; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsAgreeTxn.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsAgreeTxn.java new file mode 100644 index 00000000..4dce74c6 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsAgreeTxn.java @@ -0,0 +1,113 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the PTY_TERMS_AGREE_TXN database table. + * + */ +@Entity +@Table(name="PTY_TERMS_AGREE_TXN") +@NamedQuery(name="PtyTermsAgreeTxn.findAll", query="SELECT p FROM PtyTermsAgreeTxn p") +public class PtyTermsAgreeTxn implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="AGREE_SNO") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int agreeSno; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="AGREE_DT") + private Date agreeDt; + + @Column(name="AGREE_YN") + private String agreeYn; + + @Column(name="CSTMR_SNO") + private int cstmrSno; + + @Column(name="PROC_IP") + private String procIp; + + @Column(name="TERMS_SNO") + private int termsSno; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + public PtyTermsAgreeTxn() { + } + + public int getAgreeSno() { + return this.agreeSno; + } + + public void setAgreeSno(int agreeSno) { + this.agreeSno = agreeSno; + } + + public Date getAgreeDt() { + return this.agreeDt; + } + + public void setAgreeDt(Date agreeDt) { + this.agreeDt = agreeDt; + } + + public String getAgreeYn() { + return this.agreeYn; + } + + public void setAgreeYn(String agreeYn) { + this.agreeYn = agreeYn; + } + + public int getCstmrSno() { + return this.cstmrSno; + } + + public void setCstmrSno(int cstmrSno) { + this.cstmrSno = cstmrSno; + } + + public String getProcIp() { + return this.procIp; + } + + public void setProcIp(String procIp) { + this.procIp = procIp; + } + + public int getTermsSno() { + return this.termsSno; + } + + public void setTermsSno(int termsSno) { + this.termsSno = termsSno; + } + + public Date getUpdateDt() { + return this.updateDt; + } + + public void setUpdateDt(Date updateDt) { + this.updateDt = updateDt; + } + + public String getUpdateUserId() { + return this.updateUserId; + } + + public void setUpdateUserId(String updateUserId) { + this.updateUserId = updateUserId; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsBas.java new file mode 100644 index 00000000..ebf32638 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsBas.java @@ -0,0 +1,124 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the PTY_TERMS_BAS database table. + * + */ +@Entity +@Table(name="PTY_TERMS_BAS") +@NamedQuery(name="PtyTermsBas.findAll", query="SELECT p FROM PtyTermsBas p") +public class PtyTermsBas implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name="TERMS_SNO") + private int termsSno; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Temporal(TemporalType.DATE) + @Column(name="ESTBSH_DATE") + private Date estbshDate; + + @Column(name="LAST_TXN_YN") + private String lastTxnYn; + + @Column(name="SITE_CD") + private String siteCd; + + @Column(name="TERMS_CTGRY_CD") + private String termsCtgryCd; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="UPDATE_DT") + private Date updateDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + public PtyTermsBas() { + } + + public int getTermsSno() { + return this.termsSno; + } + + public void setTermsSno(int termsSno) { + this.termsSno = termsSno; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public String getCreateUserId() { + return this.createUserId; + } + + public void setCreateUserId(String createUserId) { + this.createUserId = createUserId; + } + + public Date getEstbshDate() { + return this.estbshDate; + } + + public void setEstbshDate(Date estbshDate) { + this.estbshDate = estbshDate; + } + + public String getLastTxnYn() { + return this.lastTxnYn; + } + + public void setLastTxnYn(String lastTxnYn) { + this.lastTxnYn = lastTxnYn; + } + + public String getSiteCd() { + return this.siteCd; + } + + public void setSiteCd(String siteCd) { + this.siteCd = siteCd; + } + + public String getTermsCtgryCd() { + return this.termsCtgryCd; + } + + public void setTermsCtgryCd(String termsCtgryCd) { + this.termsCtgryCd = termsCtgryCd; + } + + public Date getUpdateDt() { + return this.updateDt; + } + + public void setUpdateDt(Date updateDt) { + this.updateDt = updateDt; + } + + public String getUpdateUserId() { + return this.updateUserId; + } + + public void setUpdateUserId(String updateUserId) { + this.updateUserId = updateUserId; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsDtl.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsDtl.java new file mode 100644 index 00000000..ecd574f6 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsDtl.java @@ -0,0 +1,102 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; +import java.util.Date; + + +/** + * The persistent class for the PTY_TERMS_DTL database table. + * + */ +@Entity +@Table(name="PTY_TERMS_DTL") +@NamedQuery(name="PtyTermsDtl.findAll", query="SELECT p FROM PtyTermsDtl p") +public class PtyTermsDtl implements Serializable { + private static final long serialVersionUID = 1L; + + @EmbeddedId + private PtyTermsDtlPK id; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="CREATE_DT") + private Date createDt; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Lob + @Column(name="RM") + private String rm; + + @Lob + @Column(name="SIMPLE_CN") + private String simpleCn; + + @Lob + @Column(name="TERMS_CN") + private String termsCn; + + @Column(name="TERMS_TITLE_NM") + private String termsTitleNm; + + public PtyTermsDtl() { + } + + public PtyTermsDtlPK getId() { + return this.id; + } + + public void setId(PtyTermsDtlPK id) { + this.id = id; + } + + public Date getCreateDt() { + return this.createDt; + } + + public void setCreateDt(Date createDt) { + this.createDt = createDt; + } + + public String getCreateUserId() { + return this.createUserId; + } + + public void setCreateUserId(String createUserId) { + this.createUserId = createUserId; + } + + public String getRm() { + return this.rm; + } + + public void setRm(String rm) { + this.rm = rm; + } + + public String getSimpleCn() { + return this.simpleCn; + } + + public void setSimpleCn(String simpleCn) { + this.simpleCn = simpleCn; + } + + public String getTermsCn() { + return this.termsCn; + } + + public void setTermsCn(String termsCn) { + this.termsCn = termsCn; + } + + public String getTermsTitleNm() { + return this.termsTitleNm; + } + + public void setTermsTitleNm(String termsTitleNm) { + this.termsTitleNm = termsTitleNm; + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsDtlPK.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsDtlPK.java new file mode 100644 index 00000000..b0f81e2e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsDtlPK.java @@ -0,0 +1,57 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import javax.persistence.*; + +/** + * The primary key class for the PTY_TERMS_DTL database table. + * + */ +@Embeddable +public class PtyTermsDtlPK implements Serializable { + //default serial version id, required for serializable classes. + private static final long serialVersionUID = 1L; + + @Column(name="TERMS_SNO") + private int termsSno; + + @Column(name="LANG_DIV_CD") + private String langDivCd; + + public PtyTermsDtlPK() { + } + public int getTermsSno() { + return this.termsSno; + } + public void setTermsSno(int termsSno) { + this.termsSno = termsSno; + } + public String getLangDivCd() { + return this.langDivCd; + } + public void setLangDivCd(String langDivCd) { + this.langDivCd = langDivCd; + } + + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof PtyTermsDtlPK)) { + return false; + } + PtyTermsDtlPK castOther = (PtyTermsDtlPK)other; + return + (this.termsSno == castOther.termsSno) + && this.langDivCd.equals(castOther.langDivCd); + } + + public int hashCode() { + final int prime = 31; + int hash = 17; + hash = hash * prime + this.termsSno; + hash = hash * prime + this.langDivCd.hashCode(); + + return hash; + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/SuredataEntity.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/SuredataEntity.java new file mode 100644 index 00000000..28e62f09 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/SuredataEntity.java @@ -0,0 +1,64 @@ + +package com.palnet.biz.jpa.entity; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import javax.persistence.*; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Entity +@Table(name = "SUREData") +@Data +@EqualsAndHashCode +@NoArgsConstructor +public class SuredataEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "SEQNO") + private Integer seqno; + + @Column(name = "USERCODE") + private String usercode; + + @Column(name = "DEPTCODE") + private String deptcode; + + @Column(name = "reqname") + private String reqname; + + @Column(name = "REQPHONE") + private String reqphone; + + @Column(name = "CALLNAME") + private String callname; + + @Column(name = "CALLPHONE") + private String callphone; + + @Column(name = "SUBJECT") + private String subject; + + @Column(name = "MSG") + private String msg; + + @Column(name = "REQTIME") + private String reqtime; + + @Column(name = "RESULT") + private String result; + + @Column(name = "KIND") + private String kind; + +//// +//// @CreationTimestamp +//// @Column(name = "CREAT_DT", updatable = false) +// private LocalDateTime creatDt; + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComArcrftBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComArcrftBasRepository.java new file mode 100644 index 00000000..9745574e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComArcrftBasRepository.java @@ -0,0 +1,22 @@ +package com.palnet.biz.jpa.repository.com; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.ComArcrftBas; +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.PtyCstmrGroup; +import com.palnet.biz.jpa.entity.PtyTermsBas; + +import java.util.List; + +@Repository +public interface ComArcrftBasRepository extends JpaRepository{ + List findByGroupIdOrderByArcrftSnoAsc(String groupId); + + @Query("select c from ComArcrftBas c " + + "where c.groupId = :groupId " ) + List findArcrftSno(@Param("groupId") String groupId); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComIdntBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComIdntBasRepository.java new file mode 100644 index 00000000..f705bb79 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComIdntBasRepository.java @@ -0,0 +1,28 @@ +package com.palnet.biz.jpa.repository.com; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.ComIdntfBas; + +@Repository +public interface ComIdntBasRepository extends JpaRepository{ + + @Modifying + @Query(value = "DELETE FROM COM_IDNTF_BAS WHERE ARCRFT_SNO = :arcrftSno", nativeQuery = true) + int deleteByArcrftSno(@Param("arcrftSno") int arcrftSno); + + @Query("select c from ComIdntfBas c " + + "where c.arcrftSno = :arcrftSno " ) + List findIdntfNum(@Param("arcrftSno") int arcrftSno); + + @Query("select c from ComIdntfBas c " + + "where c.cstmrSno = :cstmrSno ") + List findIdntfNumber(@Param("cstmrSno") int cstmrSno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlBasRepository.java new file mode 100644 index 00000000..f9db9bdc --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlBasRepository.java @@ -0,0 +1,48 @@ +package com.palnet.biz.jpa.repository.ctr; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + + +@Repository +public interface CtrCntrlBasRepository extends JpaRepository{ + + @Modifying + @Transactional + @Query("update CtrCntrlBas c " + + "SET c.endTypeCd = :endTypeCd, c.cntrlEndDt = :cntrlEndDt, c.statusCd = :statusCd " + + "WHERE c.cntrlId = :cntrlId") + int updateCntrlEndType(@Param("endTypeCd") String endTypeCd, + @Param("cntrlEndDt") Date cntrlEndDt, + @Param("statusCd") String statusCd, + @Param("cntrlId") String cntrlId); + + Optional findFirstByIdntfNumOrderByCreateDtDesc(String idntfNum); + + @Query("select c from CtrCntrlBas c " + + "where c.cntrlStDt >= :cntrlStDt " + + "and c.cntrlEndDt <= :cntrlEndDt " + + "and c.cntrlId = :cntrlId " + + "and c.idntfNum like %:idntfNum% " ) + List findCntrlBas(@Param("cntrlStDt") Date cntrlStDt, @Param("cntrlEndDt") Date cntrlEndDt, @Param("cntrlId") String cntrlId, @Param("idntfNum") String idntfNum); + + @Query("select c from CtrCntrlBas c " + + "where c.cntrlStDt >= :cntrlStDt " + + "and c.cntrlEndDt <= :cntrlEndDt " + + "and c.idntfNum = :idntfNum" ) + List findCntrlId(@Param("cntrlStDt") Date cntrlStDt, @Param("cntrlEndDt") Date cntrlEndDt, @Param("idntfNum") String idntfNum); + + @Query(value = " select IDNTF_NUM from CTR_CNTRL_BAS " + + "where CNTRL_ID = :cntrlId ", nativeQuery = true ) + String getIdntfNum(@Param("cntrlId") String cntrlId); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlHstryAreaRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlHstryAreaRepository.java new file mode 100644 index 00000000..1a8f0840 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlHstryAreaRepository.java @@ -0,0 +1,19 @@ +package com.palnet.biz.jpa.repository.ctr; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlHstryArea; + +@Repository +public interface CtrCntrlHstryAreaRepository extends JpaRepository{ + + @Query("select c from CtrCntrlHstryArea c " + + "where c.cntrlId = :cntrlId") + List findHstryArea(@Param("cntrlId") String cntrlId); + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlHstryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlHstryRepository.java new file mode 100644 index 00000000..f7dfa4a7 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlHstryRepository.java @@ -0,0 +1,22 @@ +package com.palnet.biz.jpa.repository.ctr; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlHstry; + +@Repository +public interface CtrCntrlHstryRepository extends JpaRepository{ + + Optional findFirstByCntrlIdOrderBySrvrRcvDtDesc(String cntrlId); + + List findByCntrlIdOrderByHstrySno(String cntrlId); + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlQueryRepository.java new file mode 100644 index 00000000..f892a532 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlQueryRepository.java @@ -0,0 +1,1668 @@ +package com.palnet.biz.jpa.repository.ctr; + +import com.palnet.biz.api.acnt.jwt.model.JwtGroupModel; +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryGroupModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; +import com.palnet.biz.api.anls.hstry.model.AnlsHstryRqModel; +import com.palnet.biz.api.anls.smlt.model.AnlsSmltDetailModel; +import com.palnet.biz.api.anls.smlt.model.AnlsSmltStcsModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlDtlModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlEndModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlGroupArcrftModel; +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlGroupModel; +import com.palnet.biz.api.main.dash.model.MainDashStcsModel; +import com.palnet.biz.jpa.entity.*; +import com.palnet.comn.model.GPHistoryModel; +import com.palnet.comn.utils.DateUtils; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.ConstantImpl; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.core.types.dsl.StringTemplate; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +@Log4j2 +@Repository +@RequiredArgsConstructor +public class CtrCntrlQueryRepository{ + + + private final JPAQueryFactory query; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + /** + * 비행 현황 데이터 조회 + * @param rq + * @return + */ + public PageImpl listCntrlBas(AnlsHstryRqModel rq, Pageable pageable){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRel = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + QFltPlanBas qFltPlanBas = QFltPlanBas.fltPlanBas; + + BooleanBuilder builder = new BooleanBuilder(); + + builder.and(qCntrlBasEntity.statusCd.eq("99")); + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + builder.and(qCntrlBasEntity.cntrlStDt.after(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.before(endDate)); + builder.and(qCntrlBasEntity.statusCd.eq("99")); + builder.and(qFltPlanBas.aprvlYn.eq("Y")); + + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + ArrayList result = new ArrayList(); + + List queryList = query.select(Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.statusCd, + qCntrlBasEntity.objectTypeCd, + qCntrlBasEntity.flghtStDt, + qCntrlBasEntity.flghtEndDt, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlBasEntity.ttlTime, + qCntrlBasEntity.ttlTimeType, + qCntrlBasEntity.ttlDstnc, + qCntrlBasEntity.ttlDstncType, + qCntrlBasEntity.avrgSpeed, + qCntrlBasEntity.avrgSpeedType, + qCntrlBasEntity.bttrCnsmptn, + qCntrlBasEntity.endTypeCd, + qCntrlBasEntity.createDt, + qCntrlBasEntity.updateDt, + qCntrlHstryAreaEntity.actnType, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.areaNm, + qCntrlHstryAreaEntity.areaType, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum, + qCntrlHstryAreaEntity.zipCd + + + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .on(qCntrlHstryAreaEntity.actnType.eq("01")) + .leftJoin(qFltPlanCtrCntrlRel) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRel.cntrlId)) + .leftJoin(qFltPlanBas) + .on(qFltPlanCtrCntrlRel.planSno.eq(qFltPlanBas.planSno)) + .where(builder) + .orderBy(qCntrlBasEntity.cntrlStDt.asc()) + .offset(pageable.getOffset()) + .limit(5) + .fetch(); + + for(AnlsHstryModel model: queryList) { + String addr = ""; + + if(!StringUtils.isEmpty(model.getArea1())) { + addr = addr + " " + model.getArea1(); + } + + if(!StringUtils.isEmpty(model.getArea2())) { + addr = addr + " " + model.getArea2(); + } + + if(!StringUtils.isEmpty(model.getArea3())) { + addr = addr + " " + model.getArea3(); + } + + if(!StringUtils.isEmpty(model.getLandNm())) { + addr = addr + " " + model.getLandNm(); + } + + if(!StringUtils.isEmpty(model.getLandNum())) { + addr = addr + " " + model.getLandNum(); + } + model.setStArea(addr); + result.add(model); + } + + + + return new PageImpl<>(result, pageable, result.size()); + } + + public List cntrlBasAuthList(AnlsHstryRqModel rq, String groupId){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRelEntity = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + + BooleanBuilder builder = new BooleanBuilder(); + + builder.and(qCntrlBasEntity.statusCd.eq("99")); + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + builder.and(qCntrlBasEntity.cntrlStDt.after(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.before(endDate)); + builder.and(qFltPlanCtrCntrlRelEntity.groupId.eq(groupId)); + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + ArrayList result = new ArrayList(); + + List queryList = query.select(Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.statusCd, + qCntrlBasEntity.objectTypeCd, + qCntrlBasEntity.flghtStDt, + qCntrlBasEntity.flghtEndDt, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlBasEntity.ttlTime, + qCntrlBasEntity.ttlTimeType, + qCntrlBasEntity.ttlDstnc, + qCntrlBasEntity.ttlDstncType, + qCntrlBasEntity.avrgSpeed, + qCntrlBasEntity.avrgSpeedType, + qCntrlBasEntity.bttrCnsmptn, + qCntrlBasEntity.endTypeCd, + qCntrlBasEntity.createDt, + qCntrlBasEntity.updateDt, + qCntrlHstryAreaEntity.actnType, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.areaNm, + qCntrlHstryAreaEntity.areaType, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum, + qCntrlHstryAreaEntity.zipCd + + + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .on(qCntrlHstryAreaEntity.actnType.eq("01")) + .leftJoin(qFltPlanCtrCntrlRelEntity) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRelEntity.cntrlId)) + .where(builder) + .orderBy(qCntrlBasEntity.cntrlStDt.asc()) + .fetch(); + + for(AnlsHstryModel model: queryList) { + String addr = ""; + + if(!StringUtils.isEmpty(model.getArea1())) { + addr = addr + " " + model.getArea1(); + } + + if(!StringUtils.isEmpty(model.getArea2())) { + addr = addr + " " + model.getArea2(); + } + + if(!StringUtils.isEmpty(model.getArea3())) { + addr = addr + " " + model.getArea3(); + } + + if(!StringUtils.isEmpty(model.getLandNm())) { + addr = addr + " " + model.getLandNm(); + } + + if(!StringUtils.isEmpty(model.getLandNum())) { + addr = addr + " " + model.getLandNum(); + } + model.setStArea(addr); + result.add(model); + } + + + + return result; + } + public PageImpl cntrlBasNormalHstryList(AnlsHstryGroupModel rq, + Pageable pageable, + List idntfList, + List basResult, + List pilotResult){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRelEntity = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + QFltPlanBas qFltPlanBasEntity = QFltPlanBas.fltPlanBas; + + BooleanBuilder builder = new BooleanBuilder(); + BooleanBuilder idntfBuilder = new BooleanBuilder(); + BooleanBuilder basBuilder = new BooleanBuilder(); + BooleanBuilder pilotBuilder = new BooleanBuilder(); + + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + + builder.and(qFltPlanCtrCntrlRelEntity.groupId.eq(rq.getGroupId())); + builder.and(qCntrlBasEntity.cntrlStDt.after(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.before(endDate)); + builder.and(qCntrlBasEntity.statusCd.eq("99")); + builder.and(qFltPlanBasEntity.aprvlYn.eq("Y")); + + if(idntfList.size()>0) { + for(ComIdntfBas list : idntfList) { + idntfBuilder.or(qCntrlBasEntity.idntfNum.eq(list.getIdntfNum())); + } + } + if(basResult.size()>0) { + for(FltPlanBas list : basResult) { + basBuilder.or(qFltPlanCtrCntrlRelEntity.planSno.eq(list.getPlanSno())); + } + } + if(pilotResult.size()>0) { + for(FltPlanBas list : pilotResult) { + pilotBuilder.or(qFltPlanCtrCntrlRelEntity.planSno.eq(list.getPlanSno())); + } + } + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + List result = new ArrayList<>(); + + List queryList = query.select(Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.statusCd, + qCntrlBasEntity.objectTypeCd, + qCntrlBasEntity.flghtStDt, + qCntrlBasEntity.flghtEndDt, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlBasEntity.ttlTime, + qCntrlBasEntity.ttlTimeType, + qCntrlBasEntity.ttlDstnc, + qCntrlBasEntity.ttlDstncType, + qCntrlBasEntity.avrgSpeed, + qCntrlBasEntity.avrgSpeedType, + qCntrlBasEntity.bttrCnsmptn, + qCntrlBasEntity.endTypeCd, + qCntrlBasEntity.createDt, + qCntrlBasEntity.updateDt, + qCntrlHstryAreaEntity.actnType, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.areaNm, + qCntrlHstryAreaEntity.areaType, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum, + qCntrlHstryAreaEntity.zipCd + + + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .on(qCntrlHstryAreaEntity.actnType.eq("01")) + .leftJoin(qFltPlanCtrCntrlRelEntity) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRelEntity.cntrlId)) + .leftJoin(qFltPlanBasEntity) + .on(qFltPlanCtrCntrlRelEntity.planSno.eq(qFltPlanBasEntity.planSno)) + .where((builder) + .and( + (idntfBuilder) + .or(basBuilder) + .or(pilotBuilder))) + .orderBy(qCntrlBasEntity.cntrlStDt.asc()) + .groupBy(qFltPlanBasEntity.planSno) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + for(AnlsHstryModel model: queryList) { + String addr = ""; + + if(!StringUtils.isEmpty(model.getArea1())) { + addr = addr + " " + model.getArea1(); + } + + if(!StringUtils.isEmpty(model.getArea2())) { + addr = addr + " " + model.getArea2(); + } + + if(!StringUtils.isEmpty(model.getArea3())) { + addr = addr + " " + model.getArea3(); + } + + if(!StringUtils.isEmpty(model.getLandNm())) { + addr = addr + " " + model.getLandNm(); + } + + if(!StringUtils.isEmpty(model.getLandNum())) { + addr = addr + " " + model.getLandNum(); + } + model.setStArea(addr); + result.add(model); + } + + + + return new PageImpl<>(result, pageable, result.size()); + } + public PageImpl cntrlBasNormalSmltList(AnlsHstryRqModel rq, + Pageable pageable, + List adminAuth, + List idntfList, + List basResult, + List pilotResult){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRelEntity = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + QFltPlanBas qFltPlanBasEntity = QFltPlanBas.fltPlanBas; + + BooleanBuilder builder = new BooleanBuilder(); + BooleanBuilder adminBuilder = new BooleanBuilder(); + BooleanBuilder idntfBuilder = new BooleanBuilder(); + BooleanBuilder basBuilder = new BooleanBuilder(); + BooleanBuilder pilotBuilder = new BooleanBuilder(); + + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + builder.and(qCntrlBasEntity.cntrlStDt.after(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.before(endDate)); + builder.and(qFltPlanBasEntity.aprvlYn.eq("Y")); + builder.and(qCntrlBasEntity.statusCd.eq("99")); + + if(adminAuth.size()>0) { + for(JwtGroupModel list : adminAuth) { + adminBuilder.or(qFltPlanCtrCntrlRelEntity.groupId.eq(list.getGroupId())); + } + } + if(idntfList.size()>0) { + for(ComIdntfBas list : idntfList) { + idntfBuilder.or(qCntrlBasEntity.idntfNum.eq(list.getIdntfNum())); + } + } + if(basResult.size()>0) { + for(FltPlanBas list : basResult) { + basBuilder.or(qFltPlanCtrCntrlRelEntity.planSno.eq(list.getPlanSno())); + } + } + if(pilotResult.size()>0) { + for(FltPlanBas list : pilotResult) { + pilotBuilder.or(qFltPlanCtrCntrlRelEntity.planSno.eq(list.getPlanSno())); + } + } + + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + List result = new ArrayList<>(); + + List queryList = query.select(Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.statusCd, + qCntrlBasEntity.objectTypeCd, + qCntrlBasEntity.flghtStDt, + qCntrlBasEntity.flghtEndDt, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlBasEntity.ttlTime, + qCntrlBasEntity.ttlTimeType, + qCntrlBasEntity.ttlDstnc, + qCntrlBasEntity.ttlDstncType, + qCntrlBasEntity.avrgSpeed, + qCntrlBasEntity.avrgSpeedType, + qCntrlBasEntity.bttrCnsmptn, + qCntrlBasEntity.endTypeCd, + qCntrlBasEntity.createDt, + qCntrlBasEntity.updateDt, + qCntrlHstryAreaEntity.actnType, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.areaNm, + qCntrlHstryAreaEntity.areaType, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum, + qCntrlHstryAreaEntity.zipCd + + + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .on(qCntrlHstryAreaEntity.actnType.eq("01")) + .leftJoin(qFltPlanCtrCntrlRelEntity) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRelEntity.cntrlId)) + .leftJoin(qFltPlanBasEntity) + .on(qFltPlanCtrCntrlRelEntity.planSno.eq(qFltPlanBasEntity.planSno)) + .where((builder) + .and( + (idntfBuilder) + .or(adminBuilder) + .or(basBuilder) + .or(pilotBuilder))) + .orderBy(qCntrlBasEntity.cntrlStDt.asc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + + .fetch(); + + for(AnlsHstryModel model: queryList) { + String addr = ""; + + if(!StringUtils.isEmpty(model.getArea1())) { + addr = addr + " " + model.getArea1(); + } + + if(!StringUtils.isEmpty(model.getArea2())) { + addr = addr + " " + model.getArea2(); + } + + if(!StringUtils.isEmpty(model.getArea3())) { + addr = addr + " " + model.getArea3(); + } + + if(!StringUtils.isEmpty(model.getLandNm())) { + addr = addr + " " + model.getLandNm(); + } + + if(!StringUtils.isEmpty(model.getLandNum())) { + addr = addr + " " + model.getLandNum(); + } + model.setStArea(addr); + result.add(model); + } + + + + return new PageImpl<>(result, pageable, result.size()); + } + public List cntrlBasNormalList(AnlsHstryRqModel rq, String idntfNum){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + + BooleanBuilder builder = new BooleanBuilder(); + + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + builder.and(qCntrlBasEntity.cntrlStDt.after(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.before(endDate)); + + builder.and(qCntrlBasEntity.statusCd.eq("99")); + builder.and(qCntrlBasEntity.idntfNum.eq(idntfNum)); + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + ArrayList result = new ArrayList(); + + List queryList = query.select(Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.statusCd, + qCntrlBasEntity.objectTypeCd, + qCntrlBasEntity.flghtStDt, + qCntrlBasEntity.flghtEndDt, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlBasEntity.ttlTime, + qCntrlBasEntity.ttlTimeType, + qCntrlBasEntity.ttlDstnc, + qCntrlBasEntity.ttlDstncType, + qCntrlBasEntity.avrgSpeed, + qCntrlBasEntity.avrgSpeedType, + qCntrlBasEntity.bttrCnsmptn, + qCntrlBasEntity.endTypeCd, + qCntrlBasEntity.createDt, + qCntrlBasEntity.updateDt, + qCntrlHstryAreaEntity.actnType, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.areaNm, + qCntrlHstryAreaEntity.areaType, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum, + qCntrlHstryAreaEntity.zipCd + + + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .on(qCntrlHstryAreaEntity.actnType.eq("01")) + .where(builder) + .orderBy(qCntrlBasEntity.cntrlStDt.asc()) + .fetch(); + + for(AnlsHstryModel model: queryList) { + String addr = ""; + + if(!StringUtils.isEmpty(model.getArea1())) { + addr = addr + " " + model.getArea1(); + } + + if(!StringUtils.isEmpty(model.getArea2())) { + addr = addr + " " + model.getArea2(); + } + + if(!StringUtils.isEmpty(model.getArea3())) { + addr = addr + " " + model.getArea3(); + } + + if(!StringUtils.isEmpty(model.getLandNm())) { + addr = addr + " " + model.getLandNm(); + } + + if(!StringUtils.isEmpty(model.getLandNum())) { + addr = addr + " " + model.getLandNum(); + } + model.setStArea(addr); + result.add(model); + } + + + + return result; + } + + public long cntrlBasNormalHstryCount(AnlsHstryGroupModel rq, + List idntfList, + List basResult, + List pilotResult){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRelEntity = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + QFltPlanBas qFltPlanBasEntity = QFltPlanBas.fltPlanBas; + + BooleanBuilder builder = new BooleanBuilder(); + BooleanBuilder idntfBuilder = new BooleanBuilder(); + BooleanBuilder basBuilder = new BooleanBuilder(); + BooleanBuilder pilotBuilder = new BooleanBuilder(); + + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + + builder.and(qFltPlanCtrCntrlRelEntity.groupId.eq(rq.getGroupId())); + builder.and(qCntrlBasEntity.cntrlStDt.after(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.before(endDate)); + builder.and(qFltPlanBasEntity.aprvlYn.eq("Y")); + builder.and(qCntrlBasEntity.statusCd.eq("99")); + + if(idntfList.size()>0) { + for(ComIdntfBas list : idntfList) { + idntfBuilder.or(qCntrlBasEntity.idntfNum.eq(list.getIdntfNum())); + } + } + if(basResult.size()>0) { + for(FltPlanBas list : basResult) { + basBuilder.or(qFltPlanCtrCntrlRelEntity.planSno.eq(list.getPlanSno())); + } + } + if(pilotResult.size()>0) { + for(FltPlanBas list : pilotResult) { + pilotBuilder.or(qFltPlanCtrCntrlRelEntity.planSno.eq(list.getPlanSno())); + } + } + + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + + + long result = query.select(Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.statusCd, + qCntrlBasEntity.objectTypeCd, + qCntrlBasEntity.flghtStDt, + qCntrlBasEntity.flghtEndDt, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlBasEntity.ttlTime, + qCntrlBasEntity.ttlTimeType, + qCntrlBasEntity.ttlDstnc, + qCntrlBasEntity.ttlDstncType, + qCntrlBasEntity.avrgSpeed, + qCntrlBasEntity.avrgSpeedType, + qCntrlBasEntity.bttrCnsmptn, + qCntrlBasEntity.endTypeCd, + qCntrlBasEntity.createDt, + qCntrlBasEntity.updateDt, + qCntrlHstryAreaEntity.actnType, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.areaNm, + qCntrlHstryAreaEntity.areaType, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum, + qCntrlHstryAreaEntity.zipCd + + + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .on(qCntrlHstryAreaEntity.actnType.eq("01")) + .leftJoin(qFltPlanCtrCntrlRelEntity) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRelEntity.cntrlId)) + .leftJoin(qFltPlanBasEntity) + .on(qFltPlanCtrCntrlRelEntity.planSno.eq(qFltPlanBasEntity.planSno)) + .where((builder) + .and( + (idntfBuilder) + .or(basBuilder) + .or(pilotBuilder))) + .orderBy(qCntrlBasEntity.cntrlStDt.asc()) + .groupBy(qFltPlanBasEntity.planSno) + .fetchCount(); + + return result; + } + + public long cntrlBasNormalSmltCount(AnlsHstryRqModel rq, List adminAuth, List idntfList, List basResult, List pilotResult){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRelEntity = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + QFltPlanBas qFltPlanBasEntity = QFltPlanBas.fltPlanBas; + + BooleanBuilder builder = new BooleanBuilder(); + BooleanBuilder adminBuilder = new BooleanBuilder(); + BooleanBuilder idntfBuilder = new BooleanBuilder(); + BooleanBuilder basBuilder = new BooleanBuilder(); + BooleanBuilder pilotBuilder = new BooleanBuilder(); + + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + builder.and(qCntrlBasEntity.cntrlStDt.after(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.before(endDate)); + builder.and(qFltPlanBasEntity.aprvlYn.eq("Y")); + builder.and(qCntrlBasEntity.statusCd.eq("99")); + + if(adminAuth.size()>0) { + for(JwtGroupModel list : adminAuth) { + adminBuilder.or(qFltPlanCtrCntrlRelEntity.groupId.eq(list.getGroupId())); + } + } + if(idntfList.size()>0) { + for(ComIdntfBas list : idntfList) { + idntfBuilder.or(qCntrlBasEntity.idntfNum.eq(list.getIdntfNum())); + } + } + if(basResult.size()>0) { + for(FltPlanBas list : basResult) { + basBuilder.or(qFltPlanCtrCntrlRelEntity.planSno.eq(list.getPlanSno())); + } + } + if(pilotResult.size()>0) { + for(FltPlanBas list : pilotResult) { + pilotBuilder.or(qFltPlanCtrCntrlRelEntity.planSno.eq(list.getPlanSno())); + } + } + + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + + + long result = query.select(Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.statusCd, + qCntrlBasEntity.objectTypeCd, + qCntrlBasEntity.flghtStDt, + qCntrlBasEntity.flghtEndDt, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlBasEntity.ttlTime, + qCntrlBasEntity.ttlTimeType, + qCntrlBasEntity.ttlDstnc, + qCntrlBasEntity.ttlDstncType, + qCntrlBasEntity.avrgSpeed, + qCntrlBasEntity.avrgSpeedType, + qCntrlBasEntity.bttrCnsmptn, + qCntrlBasEntity.endTypeCd, + qCntrlBasEntity.createDt, + qCntrlBasEntity.updateDt, + qCntrlHstryAreaEntity.actnType, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.areaNm, + qCntrlHstryAreaEntity.areaType, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum, + qCntrlHstryAreaEntity.zipCd + + + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .on(qCntrlHstryAreaEntity.actnType.eq("01")) + .leftJoin(qFltPlanCtrCntrlRelEntity) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRelEntity.cntrlId)) + .leftJoin(qFltPlanBasEntity) + .on(qFltPlanCtrCntrlRelEntity.planSno.eq(qFltPlanBasEntity.planSno)) + .where((builder) + .and( + (idntfBuilder) + .or(basBuilder) + .or(pilotBuilder))) + .orderBy(qCntrlBasEntity.cntrlStDt.asc()) + .fetchCount(); + + return result; + } + + public List cntrlBasNormalPlanList(AnlsHstryRqModel rq, int planSno){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRelEntity = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + + BooleanBuilder builder = new BooleanBuilder(); + + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + builder.and(qCntrlBasEntity.cntrlStDt.after(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.before(endDate)); + + builder.and(qFltPlanCtrCntrlRelEntity.planSno.eq(planSno)); + builder.and(qCntrlBasEntity.statusCd.eq("99")); + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + ArrayList result = new ArrayList(); + + List queryList = query.select(Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.statusCd, + qCntrlBasEntity.objectTypeCd, + qCntrlBasEntity.flghtStDt, + qCntrlBasEntity.flghtEndDt, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlBasEntity.ttlTime, + qCntrlBasEntity.ttlTimeType, + qCntrlBasEntity.ttlDstnc, + qCntrlBasEntity.ttlDstncType, + qCntrlBasEntity.avrgSpeed, + qCntrlBasEntity.avrgSpeedType, + qCntrlBasEntity.bttrCnsmptn, + qCntrlBasEntity.endTypeCd, + qCntrlBasEntity.createDt, + qCntrlBasEntity.updateDt, + qCntrlHstryAreaEntity.actnType, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.areaNm, + qCntrlHstryAreaEntity.areaType, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum, + qCntrlHstryAreaEntity.zipCd + + + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .on(qCntrlHstryAreaEntity.actnType.eq("01")) + .leftJoin(qFltPlanCtrCntrlRelEntity) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRelEntity.cntrlId)) + .where(builder) + .orderBy(qCntrlBasEntity.cntrlStDt.asc()) + .fetch(); + + for(AnlsHstryModel model: queryList) { + String addr = ""; + + if(!StringUtils.isEmpty(model.getArea1())) { + addr = addr + " " + model.getArea1(); + } + + if(!StringUtils.isEmpty(model.getArea2())) { + addr = addr + " " + model.getArea2(); + } + + if(!StringUtils.isEmpty(model.getArea3())) { + addr = addr + " " + model.getArea3(); + } + + if(!StringUtils.isEmpty(model.getLandNm())) { + addr = addr + " " + model.getLandNm(); + } + + if(!StringUtils.isEmpty(model.getLandNum())) { + addr = addr + " " + model.getLandNum(); + } + model.setStArea(addr); + result.add(model); + } + + + + return result; + } + + @Cacheable(value = "cntrl-count") + public long countCntrlBasRs(AnlsHstryGroupModel rq, int cstmrSno) { + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRelEntity = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + QFltPlanBas qFltPlanBasEntity = QFltPlanBas.fltPlanBas; + + BooleanBuilder builder = new BooleanBuilder(); + + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + builder.and(qFltPlanCtrCntrlRelEntity.groupId.eq(rq.getGroupId())); + builder.and(qCntrlBasEntity.cntrlStDt.goe(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.loe(endDate)); + builder.and(qFltPlanBasEntity.aprvlYn.eq("Y")); + builder.and(qCntrlBasEntity.statusCd.eq("99")); + + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + long count = query + .select(qCntrlBasEntity) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .leftJoin(qFltPlanCtrCntrlRelEntity) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRelEntity.cntrlId)) + .leftJoin(qFltPlanBasEntity) + .on(qFltPlanCtrCntrlRelEntity.planSno.eq(qFltPlanBasEntity.planSno)) + .where(builder) + .orderBy(qCntrlBasEntity.cntrlStDt.desc()) + .groupBy(qCntrlBasEntity.cntrlId) + .fetchCount(); + + return count; + + } + + + + public PageImpl listCntrlBasRs(AnlsHstryGroupModel rq, Pageable pageable){ + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea qCntrlHstryAreaEntity = QCtrCntrlHstryArea.ctrCntrlHstryArea; + QFltPlanCtrCntrlRel qFltPlanCtrCntrlRelEntity = QFltPlanCtrCntrlRel.fltPlanCtrCntrlRel; + QFltPlanBas qFltPlanBasEntity = QFltPlanBas.fltPlanBas; + + BooleanBuilder builder = new BooleanBuilder(); + + Calendar end = Calendar.getInstance(); + end.setTime(DateUtils.stringToDate(rq.getEndDate())); + end.add(Calendar.DATE, 1); + Date endDate = end.getTime(); + builder.and(qFltPlanCtrCntrlRelEntity.groupId.eq(rq.getGroupId())); + builder.and(qCntrlBasEntity.cntrlStDt.goe(DateUtils.stringToDate(rq.getStDate()))); + builder.and(qCntrlBasEntity.cntrlEndDt.loe(endDate)); + builder.and(qFltPlanBasEntity.aprvlYn.eq("Y")); + builder.and(qCntrlBasEntity.statusCd.eq("99")); + + if(!StringUtils.isEmpty(rq.getSearch1())) { + builder.and(qCntrlBasEntity.idntfNum.like("%" + rq.getSearch1() + "%")); + } + + List queryList = query.select( + Projections.bean(AnlsHstryModel.class , + qCntrlBasEntity.cntrlId, + qCntrlBasEntity.idntfNum, + qCntrlBasEntity.cntrlStDt, + qCntrlBasEntity.cntrlEndDt, + qCntrlHstryAreaEntity.area1, + qCntrlHstryAreaEntity.area2, + qCntrlHstryAreaEntity.area3, + qCntrlHstryAreaEntity.landNm, + qCntrlHstryAreaEntity.landNum + )) + .from(qCntrlBasEntity) + .leftJoin(qCntrlHstryAreaEntity) + .on(qCntrlBasEntity.cntrlId.eq(qCntrlHstryAreaEntity.cntrlId)) + .leftJoin(qFltPlanCtrCntrlRelEntity) + .on(qCntrlBasEntity.cntrlId.eq(qFltPlanCtrCntrlRelEntity.cntrlId)) + .leftJoin(qFltPlanBasEntity) + .on(qFltPlanCtrCntrlRelEntity.planSno.eq(qFltPlanBasEntity.planSno)) + .where(builder) + .orderBy(qCntrlBasEntity.cntrlStDt.desc()) + .groupBy(qCntrlBasEntity.cntrlId) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + + List result = new ArrayList<>(); + + for(AnlsHstryModel model: queryList) { + String addr = ""; + + if(!StringUtils.isEmpty(model.getArea1())) { + addr = addr + " " + model.getArea1(); + } + + if(!StringUtils.isEmpty(model.getArea2())) { + addr = addr + " " + model.getArea2(); + } + + if(!StringUtils.isEmpty(model.getArea3())) { + addr = addr + " " + model.getArea3(); + } + + if(!StringUtils.isEmpty(model.getLandNm())) { + addr = addr + " " + model.getLandNm(); + } + + if(!StringUtils.isEmpty(model.getLandNum())) { + addr = addr + " " + model.getLandNum(); + } + model.setStArea(addr); + result.add(model); + } + + return new PageImpl<>(result, pageable, result.size()); + } + + /** + * 비행 이력 데이터 조회 + * @param id + * @return + */ + public List listCntrlHstryPage(String id){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstry qCtrCntrHstry = QCtrCntrlHstry.ctrCntrlHstry; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(qCtrCntrHstry.cntrlId.eq(id)); + + List result = query.select(Projections.bean(AnlsHstryDetailModel.class , + qCtrCntrHstry.cntrlId , + qCtrCntrHstry.hstrySno , + qCtrCntrHstry.trmnlId , + qCtrCntrHstry.mssgTypeCd , + qCtrCntrHstry.statusCd , + qCtrCntrHstry.lat, + qCtrCntrHstry.lon , + qCtrCntrHstry.speed , + qCtrCntrHstry.speedType , + qCtrCntrHstry.heading , + qCtrCntrHstry.elev , + qCtrCntrHstry.elevType , + qCtrCntrHstry.mvDstnc , + qCtrCntrHstry.mvDstncType , + qCtrCntrHstry.bttrLvl, + qCtrCntrHstry.bttrVltg, + qCtrCntrHstry.trmnlRcvDt , + qCtrCntrHstry.srvrRcvDt, + qCntrlBasEntity.idntfNum + )) + .from(qCntrlBasEntity) + .leftJoin(qCtrCntrHstry) + .on(qCntrlBasEntity.cntrlId.eq(qCtrCntrHstry.cntrlId)) + .where(builder) + .orderBy(qCtrCntrHstry.srvrRcvDt.asc()) + .fetch(); + + return result; + } +public List listCntrlHstry(String id){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstry qCtrCntrHstry = QCtrCntrlHstry.ctrCntrlHstry; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(qCtrCntrHstry.cntrlId.eq(id)); + + List result = query.select(Projections.bean(AnlsHstryDetailModel.class , + qCtrCntrHstry.cntrlId , + qCtrCntrHstry.hstrySno , + qCtrCntrHstry.trmnlId , + qCtrCntrHstry.mssgTypeCd , + qCtrCntrHstry.statusCd , + qCtrCntrHstry.lat, + qCtrCntrHstry.lon , + qCtrCntrHstry.speed , + qCtrCntrHstry.speedType , + qCtrCntrHstry.heading , + qCtrCntrHstry.elev , + qCtrCntrHstry.elevType , + qCtrCntrHstry.mvDstnc , + qCtrCntrHstry.mvDstncType , + qCtrCntrHstry.bttrLvl, + qCtrCntrHstry.bttrVltg, + qCtrCntrHstry.trmnlRcvDt , + qCtrCntrHstry.srvrRcvDt, + qCntrlBasEntity.idntfNum + )) + .from(qCntrlBasEntity) + .leftJoin(qCtrCntrHstry) + .on(qCntrlBasEntity.cntrlId.eq(qCtrCntrHstry.cntrlId)) + .where(builder) + .orderBy(qCtrCntrHstry.srvrRcvDt.asc()) + .fetch(); + + return result; + } + public long listCntrlHstryCount(String id){ + + QCtrCntrlBas qCntrlBasEntity = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstry qCtrCntrHstry = QCtrCntrlHstry.ctrCntrlHstry; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(qCtrCntrHstry.cntrlId.eq(id)); + + List resultList = query.select(Projections.bean(AnlsHstryDetailModel.class , + qCtrCntrHstry.cntrlId , + qCtrCntrHstry.hstrySno , + qCtrCntrHstry.trmnlId , + qCtrCntrHstry.mssgTypeCd , + qCtrCntrHstry.statusCd , + qCtrCntrHstry.lat, + qCtrCntrHstry.lon , + qCtrCntrHstry.speed , + qCtrCntrHstry.speedType , + qCtrCntrHstry.heading , + qCtrCntrHstry.elev , + qCtrCntrHstry.elevType , + qCtrCntrHstry.mvDstnc , + qCtrCntrHstry.mvDstncType , + qCtrCntrHstry.bttrLvl, + qCtrCntrHstry.bttrVltg, + qCtrCntrHstry.trmnlRcvDt , + qCtrCntrHstry.srvrRcvDt, + qCntrlBasEntity.idntfNum + )) + .from(qCntrlBasEntity) + .leftJoin(qCtrCntrHstry) + .on(qCntrlBasEntity.cntrlId.eq(qCtrCntrHstry.cntrlId)) + .where(builder) + .orderBy(qCtrCntrHstry.srvrRcvDt.asc()) + .fetch(); + long cnt = 0; + for(AnlsHstryDetailModel list : resultList) { + cnt ++; + } + return cnt; + } + + public List listCntrlHstryArea() { + QCtrCntrlHstryArea qCtrCntrHstryArea = QCtrCntrlHstryArea.ctrCntrlHstryArea; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(qCtrCntrHstryArea.prcsYn.eq("N")); + + List list = + query.select(qCtrCntrHstryArea) + .from(qCtrCntrHstryArea) + .where(builder) + .orderBy(qCtrCntrHstryArea.createDt.desc()) + .fetch(); + + return list; + + } + + public CtrCntrlHstry getWarnHstryList(String cntrlId) { + QCtrCntrlHstry qCtrCntrHstry = QCtrCntrlHstry.ctrCntrlHstry; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(qCtrCntrHstry.cntrlId.eq(cntrlId)); + + CtrCntrlHstry result = + query.select(Projections.bean(CtrCntrlHstry.class, + qCtrCntrHstry.lat, + qCtrCntrHstry.lon, + qCtrCntrHstry.srvrRcvDt, + qCtrCntrHstry.elev + )) + .from(qCtrCntrHstry) + .where(builder) + .orderBy(qCtrCntrHstry.srvrRcvDt.desc()) + .fetchFirst(); + + return result; + + } + + public FltPlanArea getPlanData(int planSno) { + QFltPlanArea qFltPlanArea = QFltPlanArea.fltPlanArea; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(qFltPlanArea.planSno.eq(planSno)); + + FltPlanArea result = + query.select(Projections.bean(FltPlanArea.class, + qFltPlanArea.planAreaSno, + qFltPlanArea.areaType, + qFltPlanArea.bufferZone + )) + .from(qFltPlanArea) + .where(builder) + .limit(1) + .fetchFirst(); + + return result; + } + + public long checkPlanSno(int planSno) { + QFltPlanBas qFltPlanBas = QFltPlanBas.fltPlanBas; + + BooleanBuilder builder = new BooleanBuilder(); + Calendar end = Calendar.getInstance(); + Date now = DateUtils.nowDate(); + end.setTime(now); + Date endDate = end.getTime(); + builder.and(qFltPlanBas.schFltStDt.loe(now)); + builder.and(qFltPlanBas.schFltEndDt.goe(now)); + + builder.and(qFltPlanBas.planSno.eq(planSno)); + + long result = + query.select(Projections.bean(FltPlanBas.class, + qFltPlanBas.planSno + )) + .from(qFltPlanBas) + .where(builder) + .fetchCount(); + + return result; + } + + /** + * 상세보기 조회 + * 관제마스터 , 드론 , 드론운영자 정보 조회 + */ + public CtrCntrlDtlModel detailCntrl(String controlId) { + QCtrCntrlBas ctr = QCtrCntrlBas.ctrCntrlBas; + QComArcrftBas bas = QComArcrftBas.comArcrftBas; + QComIdntfBas own = QComIdntfBas.comIdntfBas; + + CtrCntrlDtlModel result = query.select(Projections.bean(CtrCntrlDtlModel.class , + ctr.cntrlId , + ctr.cntrlStDt , + ctr.cntrlEndDt , + bas.arcrftSno , + bas.prdctNum , + bas.arcrftTypeCd, + bas.arcrftModelNm , + bas.prdctCmpnNm , + bas.wghtTypeCd , + bas.imageUrl , + bas.cameraYn , + bas.insrncYn , + own.ownerNm , + own.hpno + )) + .from(ctr) + .leftJoin(own) + .on(ctr.idntfNum.eq(own.idntfNum)) + .leftJoin(bas) + .on(own.arcrftSno.eq(bas.arcrftSno)) + .where(ctr.cntrlId.eq(controlId)) + + .where(bas.useYn.eq("Y")) +// .where(ctr.objectId.ne("none")) + .fetchFirst(); + + + if(result == null) return new CtrCntrlDtlModel(); + +// if(!StringUtils.isEmpty(result.getOwnerNm())) { +// result.setOwnerNm(EncryptUtils.decrypt(result.getOwnerNm())); +// } +// if(!StringUtils.isEmpty(result.getHpno())) { +// result.setHpno(EncryptUtils.decrypt(result.getHpno())); +// } +// if(!StringUtils.isEmpty(result.getTelno())) { +// result.setTelno(EncryptUtils.decrypt(result.getTelno())); +// } + return result; + + } + + /** + * 상세보기 조회 + * 지역정보 조회 + */ + public List detailArea(String controlId) { + QCtrCntrlHstryArea area = QCtrCntrlHstryArea.ctrCntrlHstryArea; + + List result = query.select(area) + .from(area) + .where(area.cntrlId.eq(controlId)) + + .fetch(); + + return result; + + } + + + /** + * 드론 정보 조회 + * + */ + public ComArcrftBas findComArcrftBasByPrdtNum(String prdtNum) { + QComArcrftBas bas = QComArcrftBas.comArcrftBas; + ComArcrftBas result = query.select(bas).from(bas).where(bas.prdctNum.eq(prdtNum)).where(bas.useYn.eq("Y")).fetchFirst(); + + return result; + + } + + /** + * 종료 처리 되지 않은 데이터 종료처리 대상 조회 + * 기준 - STAUS = 01 , 최종 수신 시간이 30분 초과 한 경우 + */ + + public List endList(){ + QCtrCntrlBas bas = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstry hst = QCtrCntrlHstry.ctrCntrlHstry; + + List result = query.select(Projections.bean(CtrCntrlEndModel.class , + hst.cntrlId, + hst.srvrRcvDt.max().as("srvrRcvDt") + )) + .from(hst) + .where(hst.cntrlId.in( + JPAExpressions + .select(bas.cntrlId) + .from(bas) + .where(bas.statusCd.eq("01")) + )) + .groupBy(hst.cntrlId) + .fetch(); + + return result; + + } + + + + + /** + * 후처리 대상자 선정을 위한 조회 쿼리 + */ + public List endProcessList(){ + QCtrCntrlBas bas = QCtrCntrlBas.ctrCntrlBas; + List result = query.select(Projections.bean(CtrCntrlEndModel.class , + bas.cntrlId + )) + .from(bas) + .where(bas.procStatusYn.eq("N")) + .orderBy(bas.cntrlStDt.asc()) + .limit(100) // 100건만 추출 + .fetch(); + return result; + + } + + + /*** + * 시뮬레이션 상세정보 조회 쿼리 + * + */ + + public AnlsSmltDetailModel anlsSmltDetail(String cntrlId){ + QCtrCntrlBas bas = QCtrCntrlBas.ctrCntrlBas; + QComArcrftBas air = QComArcrftBas.comArcrftBas; + QComIdntfBas idntf = QComIdntfBas.comIdntfBas; + + AnlsSmltDetailModel result = query.select(Projections.bean(AnlsSmltDetailModel.class , + bas.cntrlId , + bas.idntfNum , + bas.flghtStDt , + bas.flghtEndDt , + bas.cntrlStDt , + bas.cntrlEndDt , + bas.ttlTime , + bas.ttlTimeType , + bas.ttlDstnc , + bas.ttlDstncType , + bas.avrgSpeed , + bas.avrgSpeedType , + bas.bttrCnsmptn , + air.arcrftTypeCd , + air.prdctNum , + air.arcrftModelNm , + air.imageUrl + )) + .from(bas) + .leftJoin(idntf) + .on(bas.idntfNum.eq(idntf.idntfNum)) + .leftJoin(air) + .on(idntf.arcrftSno.eq(air.arcrftSno)) + .on(air.useYn.eq("Y")) + .where(bas.cntrlId.eq(cntrlId)) + .fetchFirst(); + + return result; + + + } + + + /*** + * 시뮬레이션 통계 + */ + + public List anlsSmltStcs(String cntrlId){ + + QCtrCntrlHstry hstry = QCtrCntrlHstry.ctrCntrlHstry; + + StringTemplate formattedDate = Expressions.stringTemplate( + "DATE_FORMAT({0}, {1})" + , hstry.srvrRcvDt + , ConstantImpl.create("%Y-%m-%d")); + + + StringTemplate formattedTime = Expressions.stringTemplate( + "DATE_FORMAT({0}, {1})" + , hstry.srvrRcvDt + , ConstantImpl.create("%H:%i")); + + + List result = query.select(Projections.bean(AnlsSmltStcsModel.class , + formattedTime.as("timeCd"), + formattedDate.as("dateCd"), + + hstry.speed.avg().as("avrgSpeed"), + hstry.speedType.max().as("speedType"), + hstry.elev.avg().as("avrgElev"), + hstry.elevType.max().as("elevType"), + hstry.mvDstnc.avg().as("avrgMvDstnc"), + hstry.mvDstncType.max().as("mvDstncType"), + hstry.bttrLvl.max().as("maxBttrLvl"), + hstry.bttrLvl.min().as("minBttrLvl") + + )) + .from(hstry) + .where(hstry.cntrlId.eq(cntrlId)) + .groupBy(formattedDate , formattedTime) + .fetch(); + + return result; + } + + /*** + * 대시보드 통계(지역별) + */ + + public List mainDashStcsArea(String yyyymm){ + QCtrCntrlBas bas = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstryArea area = QCtrCntrlHstryArea.ctrCntrlHstryArea; + + StringTemplate formattedDate = Expressions.stringTemplate( + "DATE_FORMAT({0}, {1})" + , bas.cntrlStDt + , ConstantImpl.create("%Y-%m")); + + + List result = query.select(Projections.bean(MainDashStcsModel.class , + area.area1.as("typeCd"), + area.count().as("count") + )) + .from(bas) + .leftJoin(area) + .on(bas.cntrlId.eq(area.cntrlId)) + .on(area.actnType.eq("01")) + .where(area.area1.isNotNull()) + .where(formattedDate.eq(yyyymm)) + .groupBy(area.area1) + .orderBy(area.count().desc()) + .limit(5) + .fetch(); + + return result; + + + } + + /*** + * 대시보드 통계(일자별) + */ + + public List mainDashStcsDay(String yyyymm){ + QCtrCntrlBas bas = QCtrCntrlBas.ctrCntrlBas; + + StringTemplate formattedDate = Expressions.stringTemplate( + "DATE_FORMAT({0}, {1})" + , bas.cntrlStDt + , ConstantImpl.create("%Y-%m")); + + StringTemplate formattedDate2 = Expressions.stringTemplate( + "DATE_FORMAT({0}, {1})" + , bas.cntrlStDt + , ConstantImpl.create("%d")); + + + List result = query.select(Projections.bean(MainDashStcsModel.class , + formattedDate2.as("typeCd"), + bas.count().as("count") + )) + .from(bas) + .where(bas.statusCd.eq("99")) + .where(formattedDate.eq(yyyymm)) + .groupBy(formattedDate2) + .fetch(); + return result; + } + + public List getDroneHistory(String controlId) { + QCtrCntrlBas bas = QCtrCntrlBas.ctrCntrlBas; + QCtrCntrlHstry hst = QCtrCntrlHstry.ctrCntrlHstry; + + + List list = query.select(Projections.bean(GPHistoryModel.class, + bas.idntfNum.as("objectId"), + hst.lat.as("lat"), + hst.lon.as("lng") + )) + .from(bas) + .leftJoin(hst) + .on(bas.cntrlId.eq(hst.cntrlId)) + .where(bas.cntrlId.eq(controlId)) + .fetch(); + return list; + + } + + @Cacheable(value = "group-auth") + public List findByGroupInfo() { + QPtyCstmrGroup pcg = QPtyCstmrGroup.ptyCstmrGroup; + QPtyGroupBas pgb = QPtyGroupBas.ptyGroupBas; + + String authId = jwtTokenUtil.getUserAuthByToken(); + Integer cstmrSno = jwtTokenUtil.getCstmrSnoByToken(); + List groupAuth = jwtTokenUtil.getGroupAuthByToken(); + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(pgb.useYn.eq("Y")); + if("ADMIN".equals(authId) || "SUPER".equals(authId)) { + builder.and(pcg.groupAuthCd.eq("MASTER")); + } + if ("USER".equals(authId) || "ROLE_USER".equals(authId)) { // 앱 권한이 노말이라면 , 본인의 그룹만 불러옴. + builder.and(pcg.aprvlYn.eq("Y")); + builder.and(pcg.cstmrSno.eq(cstmrSno)); + } + + List model = query.select(Projections.bean(CtrCntrlGroupModel.class, + pgb.groupId.as("groupId"), + pgb.groupNm.as("groupNm"), + pcg.groupAuthCd.as("groupAuthCd") + )) + .from(pgb) + .leftJoin(pcg) + .on(pcg.groupId.eq(pgb.groupId)) + .groupBy(pgb.groupId) + .where(builder) + .fetch(); + + + for(CtrCntrlGroupModel list : model) { + if(groupAuth != null) { + for(JwtGroupModel lists : groupAuth) { + if(list.getGroupId().equals(lists.getGroupId())) { + list.setGroupAuthCd(lists.getGroupAuthCd()); + break; + }else { + list.setGroupAuthCd(""); + } + } + } + } + return model; + // + +// BooleanBuilder builder = new BooleanBuilder(); +// builder.and(pcg.aprvlYn.eq("Y")); +// +// if ("USER".equals(authId) || "ROLE_USER".equals(authId)) { +// builder.and(pcg.cstmrSno.eq(cstmrSno)); +// } +// +// List models = query.select(Projections.bean(CtrCntrlGroupModel.class, +// pcg.cstmrSno.as("cstmrSno"), +// pgb.groupId.as("groupId"), +// pgb.groupNm.as("groupNm"), +// pcg.groupAuthCd.as("groupAuthCd") +// )) +// .from(pcg) +// .leftJoin(pgb) +// .on(pcg.groupId.eq(pgb.groupId)) +// .where(builder) +// .fetch(); +// +// return models; + } + + // public List findByGroupArcrft(String groupId) { + // public List findByGroupArcrft(String groupId, String groupAuthCd) { + @Cacheable(value = "group-arcrft") + public List findByGroupArcrft(String groupId) { + QComArcrftBas arcrftBas = QComArcrftBas.comArcrftBas; + QComIdntfBas idntfBas = QComIdntfBas.comIdntfBas; + String appAuth = jwtTokenUtil.getUserAuthByToken(); + int cstmrSno = jwtTokenUtil.getCstmrSnoByToken(); + String groupAuth = null; + List groupAuthList = jwtTokenUtil.getGroupAuthByToken(); + BooleanBuilder builder = new BooleanBuilder(); + builder.and(arcrftBas.groupId.eq(groupId)); + if("USER".equals(appAuth) || "ROLE_USER".equals(appAuth)) { + for(JwtGroupModel list : groupAuthList) { + if(list.getGroupId().equals(groupId)) { + groupAuth = list.getGroupAuthCd(); + } + } + if("NORMAL".equals(groupAuth)){ // 그룹권한이 노말인 경우 + builder.and(idntfBas.cstmrSno.eq(cstmrSno)); + } + } + + List arcrftList = query.select(Projections.bean(CtrCntrlGroupArcrftModel.class, +// arcrftBas.arcrftSno, +// arcrftBas.groupId, + idntfBas.idntfNum +// idntfBas.idntfTypeCd, +// idntfBas.ownerNm, +// arcrftBas.arcrftTypeCd, +// arcrftBas.arcrftModelNm, +// arcrftBas.prdctCmpnNm, +// idntfBas.createDt, +// idntfBas.updateDt + )) + .from(arcrftBas) + .leftJoin(idntfBas) + .on(arcrftBas.arcrftSno.eq(idntfBas.arcrftSno)) + .where(arcrftBas.useYn.eq("Y"), + idntfBas.idntfNum.isNotNull(), +// idntfBas.idntfNum.like("PALDRONE%")) + idntfBas.idntfNum.like("PA%")) + .where(builder) + .fetch(); + + return arcrftList; +//------------------------------------------- + + +// List arcrftList = query.select(Projections.bean(CtrCntrlGroupArcrftModel.class, +// arcrftBas.arcrftSno, +// arcrftBas.groupId, +// idntfBas.idntfNum, +// idntfBas.idntfTypeCd, +// idntfBas.ownerNm, +// idntfBas.hpno, +// arcrftBas.prdctNum, +// arcrftBas.arcrftTypeCd, +// arcrftBas.arcrftModelNm, +// arcrftBas.prdctCmpnNm, +// idntfBas.createDt, +// idntfBas.updateDt +// )) +// .from(arcrftBas) +// .leftJoin(idntfBas) +// .on(arcrftBas.arcrftSno.eq(idntfBas.arcrftSno)) +// .where(arcrftBas.useYn.eq("Y") +// .and(idntfBas.idntfNum.isNotNull()) +// .and(idntfBas.idntfNum.like("PALDRONE%"))) +// .orderBy(arcrftBas.groupId.asc(), idntfBas.createDt.asc()) +// .fetch(); +// +// return arcrftList; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlWarnLogRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlWarnLogRepository.java new file mode 100644 index 00000000..fa16a011 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/ctr/CtrCntrlWarnLogRepository.java @@ -0,0 +1,13 @@ +package com.palnet.biz.jpa.repository.ctr; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.palnet.biz.jpa.entity.CtrCntrlWarnLog; + +public interface CtrCntrlWarnLogRepository extends JpaRepository { + List findAllByCntrlId(String cntrlId); + CtrCntrlWarnLog findFirstByCntrlIdOrderByOccurDtDesc(String cntrlId); + Integer countByCntrlId(String cntrlId); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanArcrftRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanArcrftRepository.java new file mode 100644 index 00000000..fafab018 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanArcrftRepository.java @@ -0,0 +1,22 @@ +package com.palnet.biz.jpa.repository.flt; + +import com.palnet.biz.jpa.entity.FltPlanArcrft; +import com.palnet.biz.jpa.entity.FltPlanBas; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; +import java.util.Optional; + +public interface FltPlanArcrftRepository extends JpaRepository { + List findByPlanSnoOrderByPlanArcrftSnoAsc(Integer planSno); + + @Query("select f from FltPlanArcrft f " + + "where f.arcrftModelNm = :arcrftModelNm ") + List findByarcrftModelNm(String arcrftModelNm); + + + List findByIdntfNumAndArcrftSnoOrderByPlanArcrftSnoAsc(String idntfNum, Integer acrftSno); + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanAreaCoordRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanAreaCoordRepository.java new file mode 100644 index 00000000..5b8ef431 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanAreaCoordRepository.java @@ -0,0 +1,23 @@ +package com.palnet.biz.jpa.repository.flt; + +import java.util.List; + +import org.locationtech.jts.geom.Coordinate; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaCoordModel; +import com.palnet.biz.jpa.entity.FltPlanAreaCoord; + +public interface FltPlanAreaCoordRepository extends JpaRepository { + + List findByPlanAreaSnoOrderByPlanAreaCoordSnoAsc(Integer planAreaSno); + + @Query("Select lat, lon from FltPlanAreaCoord ") + Coordinate[] findCoord(); + + @Query("Select f from FltPlanAreaCoord f " + + "where planAreaSno = :planAreaSno " ) + List getCoordinate(@Param ("planAreaSno") int planAreaSno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanAreaRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanAreaRepository.java new file mode 100644 index 00000000..98098fd5 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanAreaRepository.java @@ -0,0 +1,24 @@ +package com.palnet.biz.jpa.repository.flt; + +import com.palnet.biz.jpa.entity.FltPlanArea; +import com.palnet.biz.jpa.entity.FltPlanBas; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface FltPlanAreaRepository extends JpaRepository { + List findByPlanSnoOrderByPlanAreaSnoAsc(Integer planSno); + + @Query(value = " select PLAN_AREA_SNO from FLT_PLAN_AREA " + + " where PLAN_SNO = :planSno " + + " order by PLAN_AREA_SNO desc limit 1 ", nativeQuery = true) + int getPlanAreaSno(@Param("planSno") int planSno); + + @Query(value = "select f from FltPlanArea f " + + "where f.planSno = :planSno ") + FltPlanArea getPlanAreaData(@Param("planSno") int planSno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanBasRepository.java new file mode 100644 index 00000000..5ad7619a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanBasRepository.java @@ -0,0 +1,51 @@ +package com.palnet.biz.jpa.repository.flt; + + +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlSocketDataModel; +import com.palnet.biz.jpa.entity.FltPlanBas; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +public interface FltPlanBasRepository extends JpaRepository { + @Query("select f from FltPlanBas f " + + "where ((SCH_FLT_ST_DT <= :schFltStDt and SCH_FLT_END_DT >= :schFltEndDt)" + + "or (SCH_FLT_ST_DT >= :schFltStDt and (SCH_FLT_ST_DT <= :schFltEndDt and SCH_FLT_END_DT >= :schFltEndDt ))" + + "or ((SCH_FLT_ST_DT <= :schFltStDt and SCH_FLT_END_DT >= :schFltStDt) and SCH_FLT_END_DT <= :schFltEndDt)" + + "or (SCH_FLT_ST_DT >= :schFltStDt and SCH_FLT_END_DT <= :schFltEndDt)) and DEL_YN='N'") + List findByStartEndDate(@Param("schFltStDt") Date schFltStDt,@Param("schFltEndDt") Date schFltEndDt); + + + @Query("select f from FltPlanBas f " + + "where f.planSno = :planSno " + + "and f.aprvlYn = :aprvlYn " + + "and f.schFltStDt <= :fltNowDt " + + "and :fltNowDt <= f.schFltEndDt") + Optional findByGroupFlightPlan(@Param("planSno") Integer planSno, + @Param("aprvlYn") String aprvlYn, + @Param("fltNowDt") Date fltNowDt); + + @Transactional + @Modifying + @Query("update FltPlanBas f set f.aprvlYn = :aprvlYn where f.planSno in :planSno") + int updateAprvlYnByPlanSnoIn(@Param("planSno") List planSnos, @Param("aprvlYn") String aprvlYn); + + Optional findByPlanSnoAndDelYnNot(Integer planSno, String delYn); + + @Query("Select f from FltPlanBas f " + + "where f.cstmrSno = :cstmrSno " + + "and f.aprvlYn = 'Y' " ) + List findByPlanSno(@Param("cstmrSno")int cstmrSno); + + @Query("Select f from FltPlanBas f " + + "where f.planSno = :planSno " + + "and f.aprvlYn = 'Y' " ) + List findBasList(@Param("planSno")int planSno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanCtrCntrlRelRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanCtrCntrlRelRepository.java new file mode 100644 index 00000000..f32cc5c2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanCtrCntrlRelRepository.java @@ -0,0 +1,18 @@ +package com.palnet.biz.jpa.repository.flt; + + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import com.palnet.biz.jpa.entity.FltPlanCtrCntrlRel; + +public interface FltPlanCtrCntrlRelRepository extends JpaRepository { + + @Query(value = " select PLAN_SNO from FLT_PLAN_CTR_CNTRL_REL" + + " where IDNTF_NUM = :idntfNum " + + " order by PLAN_SNO desc limit 1 ", nativeQuery = true ) + Optional getPlanSno(@Param("idntfNum") String idntfNum); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanPilotRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanPilotRepository.java new file mode 100644 index 00000000..7e24846f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanPilotRepository.java @@ -0,0 +1,17 @@ +package com.palnet.biz.jpa.repository.flt; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import com.palnet.biz.jpa.entity.FltPlanPilot; + +public interface FltPlanPilotRepository extends JpaRepository { + List findByPlanSnoOrderByPlanPilotSnoAsc(Integer planSno); + + @Query("select f from FltPlanPilot f " + + "where f.cstmrSno = :cstmrSno " ) + List findByPlanSno(@Param("cstmrSno") int cstmrSno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanQueryRepository.java new file mode 100644 index 00000000..90a4e12e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/flt/FltPlanQueryRepository.java @@ -0,0 +1,663 @@ +package com.palnet.biz.jpa.repository.flt; + +import java.util.Date; +import java.util.List; + +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; + +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.api.bas.flight.model.BasFlightPlanArcrftModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaCoordRq; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanListRq; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanModel; +import com.palnet.biz.api.bas.flight.model.BasFlightPlanPilotModel; +import com.palnet.biz.api.bas.flight.model.BasFlightScheduleRs; +import com.palnet.biz.jpa.entity.FltPlanBas; +import com.palnet.biz.jpa.entity.QComArcrftBas; +import com.palnet.biz.jpa.entity.QComIdntfBas; +import com.palnet.biz.jpa.entity.QCtrCntrlBas; +import com.palnet.biz.jpa.entity.QCtrCntrlHstryArea; +import com.palnet.biz.jpa.entity.QFltPlanArcrft; +import com.palnet.biz.jpa.entity.QFltPlanArea; +import com.palnet.biz.jpa.entity.QFltPlanAreaCoord; +import com.palnet.biz.jpa.entity.QFltPlanBas; +import com.palnet.biz.jpa.entity.QPtyCstmrDtl; +import com.palnet.biz.jpa.entity.QPtyCstmrGroup; +import com.palnet.biz.jpa.entity.QPtyGroupBas; +import com.palnet.comn.utils.DateUtils; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.group.GroupBy; +import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.CaseBuilder; +import com.querydsl.core.types.dsl.DateTemplate; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Repository +@RequiredArgsConstructor +public class FltPlanQueryRepository { + + + private final JPAQueryFactory query; + + + // 비행계획서 목록 + // TODO 현재 모두 조회 - 권한에 따른 조회 필요 + public PageImpl listPlan(BasFlightPlanListRq rq, String masterAccount, Pageable pageable) { + QFltPlanBas bas = QFltPlanBas.fltPlanBas; + QFltPlanArea area = QFltPlanArea.fltPlanArea; + + BooleanBuilder builder = new BooleanBuilder(); + + if (rq.getGroupId() != null) { + builder.and(bas.groupId.eq(rq.getGroupId())); + } + + if (rq.getCstmrSno() != null) { +// if(masterAccount.equals("USER")) { + if(masterAccount.equals("NORMAL")) { + builder.and(bas.cstmrSno.eq(rq.getCstmrSno())); + } + } + + builder.and(bas.schFltStDt.goe(rq.getSchFltStDt())); + builder.and(bas.schFltStDt.before(rq.getSchFltEndDt())); + +// if ("Y".equals(rq.getAprvlYn()) || "N".equals(rq.getAprvlYn())) { +// builder.and(bas.aprvlYn.eq(rq.getAprvlYn())); +// } + if (!"A".equals(rq.getAprvlYn())) { + builder.and(bas.aprvlYn.eq(rq.getAprvlYn())); + } + builder.and(bas.delYn.ne("Y")); + + List r = query + .from(bas) + .leftJoin(area) + .on(bas.planSno.eq(area.planSno)) + .where(builder) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .transform( + GroupBy.groupBy(bas.planSno) + .list(Projections.bean( + BasFlightPlanModel.class, + bas.planSno, + bas.groupId, + bas.cstmrSno, + bas.memberName, + bas.email, + bas.hpno, + bas.clncd, + bas.addr, + bas.addrDtlCn, + bas.zip, + bas.schFltStDt, + bas.schFltEndDt, + bas.fltPurpose, + bas.aprvlYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt, + GroupBy.list(Projections.bean( + BasFlightPlanAreaModel.class, + area.planAreaSno, + area.planSno, + area.areaType, + area.fltMethod, + area.bufferZone, + area.fltElev, + area.createUserId, + area.createDt, + area.updateUserId, + area.updateDt + ).skipNulls()).as("areaList") + )) + ); + + return new PageImpl<>(r, pageable, r.size()); + + } + public long listPlanCount(BasFlightPlanListRq rq, String masterAccount) { + QFltPlanBas bas = QFltPlanBas.fltPlanBas; + QFltPlanArea area = QFltPlanArea.fltPlanArea; + + BooleanBuilder builder = new BooleanBuilder(); + + if (rq.getGroupId() != null) { + builder.and(bas.groupId.eq(rq.getGroupId())); + } + + if (rq.getCstmrSno() != null) { +// if(masterAccount.equals("USER")) { + if(masterAccount.equals("NORMAL")) { + builder.and(bas.cstmrSno.eq(rq.getCstmrSno())); + } + } + + builder.and(bas.schFltStDt.goe(rq.getSchFltStDt())); + builder.and(bas.schFltStDt.before(rq.getSchFltEndDt())); + +// if ("Y".equals(rq.getAprvlYn()) || "N".equals(rq.getAprvlYn())) { +// builder.and(bas.aprvlYn.eq(rq.getAprvlYn())); +// } + if (!"A".equals(rq.getAprvlYn())) { + builder.and(bas.aprvlYn.eq(rq.getAprvlYn())); + } + builder.and(bas.delYn.ne("Y")); + + List r = query + .from(bas) + .leftJoin(area) + .on(bas.planSno.eq(area.planSno)) + .where(builder) + .transform( + GroupBy.groupBy(bas.planSno) + .list(Projections.bean( + BasFlightPlanModel.class, + bas.planSno, + bas.groupId, + bas.cstmrSno, + bas.memberName, + bas.email, + bas.hpno, + bas.clncd, + bas.addr, + bas.addrDtlCn, + bas.zip, + bas.schFltStDt, + bas.schFltEndDt, + bas.fltPurpose, + bas.aprvlYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt, + GroupBy.list(Projections.bean( + BasFlightPlanAreaModel.class, + area.planAreaSno, + area.planSno, + area.areaType, + area.fltMethod, + area.bufferZone, + area.fltElev, + area.createUserId, + area.createDt, + area.updateUserId, + area.updateDt + ).skipNulls()).as("areaList") + )) + ); + long cnt = 0; + for(BasFlightPlanModel list : r ) { + cnt++; + } + + return cnt; + + } + //동일 기체 등록시 비행시간 중복여부 조회 + public List arcrftCheck(BasFlightPlanModel rq, String idntfNum){ + QFltPlanArcrft arcrft = QFltPlanArcrft.fltPlanArcrft; + QFltPlanBas bas = QFltPlanBas.fltPlanBas; + + List list = query + .select(Projections.bean( + BasFlightPlanModel.class, + bas.schFltStDt, + bas.schFltEndDt, + bas.delYn + )) + .from(bas) + .leftJoin(arcrft) + .on(bas.planSno.eq(arcrft.planSno)) + .where(arcrft.idntfNum.eq(idntfNum) + .and(((bas.schFltStDt.loe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltEndDt()))) + .or((bas.schFltStDt.goe(rq.getSchFltStDt())) + .and((bas.schFltStDt.loe(rq.getSchFltEndDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltEndDt())))) + .or(((bas.schFltStDt.loe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltStDt()))) + .and(bas.schFltEndDt.loe(rq.getSchFltEndDt()))) + .or((bas.schFltStDt.goe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.loe(rq.getSchFltEndDt())))) + .and(bas.delYn.eq("N"))) + .fetch(); + return list; + + } + // 비행계획구역 설정시 같은 시간대에 구역이 중복되는지 조회 + public List CoordCheck(BasFlightPlanModel rq){ + QFltPlanArea area = QFltPlanArea.fltPlanArea; + QFltPlanBas bas = QFltPlanBas.fltPlanBas; + List list = query + .from(bas) + .leftJoin(area) + .on(bas.planSno.eq(area.planSno)) + .where((((bas.schFltStDt.loe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltEndDt()))) + .or((bas.schFltStDt.goe(rq.getSchFltStDt())) + .and((bas.schFltStDt.loe(rq.getSchFltEndDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltEndDt())))) + .or(((bas.schFltStDt.loe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltStDt()))) + .and(bas.schFltEndDt.loe(rq.getSchFltEndDt()))) + .or((bas.schFltStDt.goe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.loe(rq.getSchFltEndDt())))) + .and(bas.delYn.eq("N")) + .and(bas.groupId.eq(rq.getGroupId()))) + .transform( + GroupBy.groupBy(bas.planSno) + .list(Projections.bean( + BasFlightPlanModel.class, + bas.planSno, + bas.groupId, + bas.cstmrSno, + bas.memberName, + bas.email, + bas.hpno, + bas.clncd, + bas.addr, + bas.addrDtlCn, + bas.zip, + bas.schFltStDt, + bas.schFltEndDt, + bas.fltPurpose, + bas.aprvlYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt, + GroupBy.list(Projections.bean( + BasFlightPlanAreaModel.class, + area.planAreaSno, + area.planSno, + area.areaType, + area.fltMethod, + area.bufferZone, + area.fltElev, + area.createUserId, + area.createDt, + area.updateUserId, + area.updateDt + ).skipNulls()).as("areaList") + )) + ); + + return list; + } + //CoordCheck에 들어갈 count + public List CoordCount(BasFlightPlanModel rq){ + QFltPlanArea area = QFltPlanArea.fltPlanArea; + QFltPlanAreaCoord coord = QFltPlanAreaCoord.fltPlanAreaCoord; + QFltPlanBas bas = QFltPlanBas.fltPlanBas; + QFltPlanArcrft arcrft = QFltPlanArcrft.fltPlanArcrft; + List list = query + .select(Projections.bean( + BasFlightPlanAreaCoordRq.class, + area.bufferZone, + area.areaType, + area.planAreaSno.count().intValue().as("cnt"), + arcrft.idntfNum + )) + .from(bas) + .leftJoin(area) + .on(bas.planSno.eq(area.planSno)) + .leftJoin(arcrft) + .on(area.planSno.eq(arcrft.planSno)) + .leftJoin(coord) + .on(area.planAreaSno.eq(coord.planAreaSno)) + + .where((((bas.schFltStDt.loe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltEndDt()))) + .or((bas.schFltStDt.goe(rq.getSchFltStDt())) + .and((bas.schFltStDt.loe(rq.getSchFltEndDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltEndDt())))) + .or(((bas.schFltStDt.loe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.goe(rq.getSchFltStDt()))) + .and(bas.schFltEndDt.loe(rq.getSchFltEndDt()))) + .or((bas.schFltStDt.goe(rq.getSchFltStDt())) + .and(bas.schFltEndDt.loe(rq.getSchFltEndDt())))) + .and(bas.delYn.eq("N")) + .and(((coord.lon.goe(0.1)) + .and(coord.lat.goe(0.1))))) + .groupBy(area.planAreaSno) + .fetch(); + return list; + } + // 조종사 조회 + public List listPilot(String groupId) { +// QPtyCstmrBas bas = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl dtl = QPtyCstmrDtl.ptyCstmrDtl; + QPtyCstmrGroup group = QPtyCstmrGroup.ptyCstmrGroup; + QPtyGroupBas groupBas = QPtyGroupBas.ptyGroupBas; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(group.groupId.eq(groupId)); + + List r = query + .select(Projections.bean( + BasFlightPlanPilotModel.class, + groupBas.groupNm, + dtl.cstmrSno, + dtl.memberName, + dtl.email, + dtl.hpno, + dtl.clncd, + dtl.addr, + dtl.addrDtlCn, + dtl.zip + )) + .from(dtl) + .leftJoin(group) + .on(dtl.cstmrSno.eq(group.cstmrSno)) + .leftJoin(groupBas) + .on(group.groupId.eq(groupBas.groupId)) + .where(builder) + .fetch(); + return r; + } + + // 기체 조회 + public List listArcrft(String groupId) { + QComArcrftBas arcrft = QComArcrftBas.comArcrftBas; + QPtyGroupBas group = QPtyGroupBas.ptyGroupBas; + QComIdntfBas idntf = QComIdntfBas.comIdntfBas; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(group.groupId.eq(groupId)).and(idntf.idntfNum.isNotNull()); + + List models = query.select(Projections.bean( + BasFlightPlanArcrftModel.class, + arcrft.arcrftSno, + arcrft.arcrftModelNm, + arcrft.arcrftTypeCd, + arcrft.prdctNum, + arcrft.prdctCmpnNm, + arcrft.prdctDate, + arcrft.useYn, + arcrft.createUserId, + group.groupId, + group.groupNm, + group.groupTypeCd, + idntf.idntfNum, + idntf.ownerNm, + idntf.hpno, + idntf.idntfTypeCd + )) + .from(arcrft) + .leftJoin(group) + .on(arcrft.groupId.eq(group.groupId)) + .leftJoin(idntf) + .on(arcrft.arcrftSno.eq(idntf.arcrftSno)) + .where(builder) + .fetch(); + + return models; + } + + public PageImpl aprvList(BasFlightPlanListRq rq, String masterAccount, Pageable pageable) { + QFltPlanBas bas = QFltPlanBas.fltPlanBas; + QFltPlanArea area = QFltPlanArea.fltPlanArea; + BooleanBuilder builder = new BooleanBuilder(); +// if (userAccount.equals("CREATER") || userAccount.equals("ADMIN")) { + if(masterAccount != null) { + if (masterAccount.equals("SPUER") || masterAccount.equals("ADMIN")) { + builder.and(bas.groupId.in(rq.getGroupId())); + } else { + builder.and(bas.groupId.in(rq.getGroupId())); + builder.and(bas.cstmrSno.eq(rq.getCstmrSno())); + } + } + builder.and(bas.schFltStDt.goe(rq.getSchFltStDt())); + builder.and(bas.schFltStDt.before(rq.getSchFltEndDt())); + + if (rq.getAprvlYn() != null && !"A".equals(rq.getAprvlYn())) { + builder.and(bas.aprvlYn.eq(rq.getAprvlYn())); + } + builder.and(bas.delYn.ne("Y")); + + List r = query + .from(bas) + .leftJoin(area) + .on(bas.planSno.eq(area.planSno)) + .where(builder) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .transform( + GroupBy.groupBy(bas.planSno) + .list(Projections.bean( + BasFlightPlanModel.class, + bas.planSno, + bas.groupId, + bas.cstmrSno, + bas.memberName, + bas.email, + bas.hpno, + bas.clncd, + bas.addr, + bas.addrDtlCn, + bas.zip, + bas.schFltStDt, + bas.schFltEndDt, + bas.fltPurpose, + bas.aprvlYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt, + GroupBy.list(Projections.bean( + BasFlightPlanAreaModel.class, + area.planAreaSno, + area.planSno, + area.areaType, + area.fltMethod, + area.bufferZone, + area.fltElev, + area.createUserId, + area.createDt, + area.updateUserId, + area.updateDt + ).skipNulls()).as("areaList") + )) + ); + + return new PageImpl<>(r,pageable, r.size()); + } + public long aprvCount(BasFlightPlanListRq rq, String masterAccount) { + QFltPlanBas bas = QFltPlanBas.fltPlanBas; + QFltPlanArea area = QFltPlanArea.fltPlanArea; + + BooleanBuilder builder = new BooleanBuilder(); +// if (userAccount.equals("CREATER") || userAccount.equals("ADMIN")) { + if(masterAccount != null) { + if (masterAccount.equals("SUPER") || masterAccount.equals("ADMIN")) { + builder.and(bas.groupId.in(rq.getGroupId())); + } else { + builder.and(bas.groupId.in(rq.getGroupId())); + builder.and(bas.cstmrSno.eq(rq.getCstmrSno())); + } + } + builder.and(bas.schFltStDt.goe(rq.getSchFltStDt())); + builder.and(bas.schFltStDt.before(rq.getSchFltEndDt())); + + if (rq.getAprvlYn() != null && !"A".equals(rq.getAprvlYn())) { + builder.and(bas.aprvlYn.eq(rq.getAprvlYn())); + } + builder.and(bas.delYn.ne("Y")); + + List list = query + .from(bas) + .leftJoin(area) + .on(bas.planSno.eq(area.planSno)) + .where(builder) + .transform( + GroupBy.groupBy(bas.planSno) + .list(Projections.bean( + BasFlightPlanModel.class, + bas.planSno, + bas.groupId, + bas.cstmrSno, + bas.memberName, + bas.email, + bas.hpno, + bas.clncd, + bas.addr, + bas.addrDtlCn, + bas.zip, + bas.schFltStDt, + bas.schFltEndDt, + bas.fltPurpose, + bas.aprvlYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt, + GroupBy.list(Projections.bean( + BasFlightPlanAreaModel.class, + area.planAreaSno, + area.planSno, + area.areaType, + area.fltMethod, + area.bufferZone, + area.fltElev, + area.createUserId, + area.createDt, + area.updateUserId, + area.updateDt + ).skipNulls()).as("areaList") + )) + ); + long cnt = 0; + for(BasFlightPlanModel lis : list) { + cnt++; + } + + return cnt; + } + @Cacheable(value = "schedule") + public List findSchedule(String searchDate) { + QFltPlanBas fltPlanBas = QFltPlanBas.fltPlanBas; + QFltPlanArcrft fltPlanArcrft = QFltPlanArcrft.fltPlanArcrft; + QCtrCntrlBas cntrlBas = QCtrCntrlBas.ctrCntrlBas; + QPtyGroupBas groupBas = QPtyGroupBas.ptyGroupBas; + QCtrCntrlHstryArea cntrlHstryArea = QCtrCntrlHstryArea.ctrCntrlHstryArea; + + BooleanBuilder builder = new BooleanBuilder(); + + DateTemplate flightStartDate = Expressions.dateTemplate( + Date.class,"DATE({0})", fltPlanBas.schFltStDt); + + DateTemplate flightEndDate = Expressions.dateTemplate( + Date.class,"DATE({0})", fltPlanBas.schFltEndDt); + + builder.and(flightStartDate.loe(DateUtils.stringToDate(searchDate))) + .and(flightEndDate.goe(DateUtils.stringToDate(searchDate))) + .and(fltPlanBas.aprvlYn.eq("Y")); + + List querys = query.select( + Projections.bean( + BasFlightScheduleRs.class, + fltPlanBas.groupId, + ExpressionUtils.as( + JPAExpressions.select(groupBas.groupNm) + .from(groupBas) + .where(groupBas.groupId.eq(fltPlanBas.groupId)),"groupNm" + ), + fltPlanArcrft.ownerNm, + fltPlanArcrft.idntfNum, + ExpressionUtils.as( + JPAExpressions.select( + cntrlHstryArea.area1.concat(" ") + .concat(cntrlHstryArea.area2).concat(" ") + .concat(cntrlHstryArea.area3).concat(" ") + .concat(cntrlHstryArea.landNm).concat(" ") + .concat(cntrlHstryArea.landNum) + ) + .from(cntrlHstryArea) + .where(cntrlHstryArea.cntrlId.eq(cntrlBas.cntrlId) + .and(cntrlHstryArea.actnType.eq("01"))), + "startAddress" + ), + ExpressionUtils.as( + JPAExpressions.select( + cntrlHstryArea.area1.concat(" ") + .concat(cntrlHstryArea.area2).concat(" ") + .concat(cntrlHstryArea.area3).concat(" ") + .concat(cntrlHstryArea.landNm).concat(" ") + .concat(cntrlHstryArea.landNum) + ) + .from(cntrlHstryArea) + .where(cntrlHstryArea.cntrlId.eq(cntrlBas.cntrlId) + .and(cntrlHstryArea.actnType.eq("99"))), + "endAddress" + ), + fltPlanBas.schFltStDt, + fltPlanBas.schFltEndDt, + cntrlBas.cntrlId, + cntrlBas.cntrlStDt, + cntrlBas.cntrlEndDt, + new CaseBuilder() + .when(cntrlBas.statusCd.eq("01")).then("F") + .when(cntrlBas.statusCd.eq("99")).then("S") + .otherwise("B").as("statusCd") + ) + ) + .from(fltPlanBas) + .leftJoin(fltPlanArcrft) + .on(fltPlanBas.planSno.eq(fltPlanArcrft.planSno)) + .leftJoin(cntrlBas) + .on(fltPlanArcrft.idntfNum.eq(cntrlBas.idntfNum)) + .on(cntrlBas.cntrlStDt.goe(fltPlanBas.schFltStDt)) + .on(cntrlBas.cntrlStDt.loe(fltPlanBas.schFltEndDt)) + .where(builder) + .orderBy(fltPlanBas.schFltStDt.asc(), cntrlBas.cntrlStDt.asc()) + .fetch(); + + return querys; + } + + public List findByFlightPlanArcrft(String idntfNum, String serverReceiveDate) { + QFltPlanBas fltPlanBas = QFltPlanBas.fltPlanBas; + QFltPlanArcrft fltPlanArcrft = QFltPlanArcrft.fltPlanArcrft; + + BooleanBuilder parameter = new BooleanBuilder(); + + DateTemplate flightStartDate = Expressions.dateTemplate( + Date.class,"DATE({0})", fltPlanBas.schFltStDt); + + DateTemplate flightEndDate = Expressions.dateTemplate( + Date.class,"DATE({0})", fltPlanBas.schFltEndDt); + + parameter.and(flightStartDate.loe(DateUtils.stringToDatetime(serverReceiveDate))) + .and(flightEndDate.goe(DateUtils.stringToDatetime(serverReceiveDate))) + .and(fltPlanArcrft.idntfNum.eq(idntfNum)); + + List result = query.select(fltPlanBas) + .from(fltPlanBas) + .leftJoin(fltPlanArcrft) + .on(fltPlanBas.planSno.eq(fltPlanArcrft.planSno)) + .where(parameter) + .fetch(); + + return result; + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCrtfyhpBasQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCrtfyhpBasQueryRepository.java new file mode 100644 index 00000000..aa3f4c70 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCrtfyhpBasQueryRepository.java @@ -0,0 +1,49 @@ +package com.palnet.biz.jpa.repository.pty; + + +import com.palnet.biz.jpa.entity.PtyCrtfyhpBas; +import com.palnet.biz.jpa.entity.QPtyCrtfyhpBas; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.stereotype.Repository; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +@Log4j2 +@Repository +@RequiredArgsConstructor +public class PtyCrtfyhpBasQueryRepository { + private final JPAQueryFactory query; + + public List confirmSms(String hpno, String crtfyNo) { + QPtyCrtfyhpBas qEntity = QPtyCrtfyhpBas.ptyCrtfyhpBas; + + Date now = Calendar.getInstance().getTime(); + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.MINUTE, -5); + Date prevTime = calendar.getTime(); + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(qEntity.crtfyhpNo.eq(crtfyNo)); + + builder.and(qEntity.crtfyhpYn.eq("N")); +// builder.and(qEntity.createDt.between(LocalDateTime.now().minusMinutes(5), LocalDateTime.now())); + builder.and(qEntity.createDt.goe(prevTime)); + builder.and(qEntity.createDt.loe(now)); + + + List entity = + query.select(qEntity).from(qEntity) + .where(builder) + .orderBy(qEntity.createDt.desc()) + .fetch(); + + return entity; + + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCrtfyhpBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCrtfyhpBasRepository.java new file mode 100644 index 00000000..3247c45e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCrtfyhpBasRepository.java @@ -0,0 +1,23 @@ +package com.palnet.biz.jpa.repository.pty; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import com.palnet.biz.jpa.entity.PtyCrtfyhpBas; + +@Repository +public interface PtyCrtfyhpBasRepository extends JpaRepository{ + @Transactional + @Modifying + @Query(value = "UPDATE PTY_CRTFYHP_BAS " + + "SET CRTFYHP_YN = 'Y' " + + "WHERE CRTFYHP_YN = 'N' " + + "AND HPNO = :hpno " + ,nativeQuery = true) + void prevCrtfyhpYnBlock(@Param("hpno") String hpno); + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrBasRepository.java new file mode 100644 index 00000000..78831bfb --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrBasRepository.java @@ -0,0 +1,22 @@ +package com.palnet.biz.jpa.repository.pty; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.api.acnt.jwt.model.JwtUserModel; +import com.palnet.biz.jpa.entity.PtyCstmrBas; + +@Repository +public interface PtyCstmrBasRepository extends JpaRepository{ + Optional findByUserId(String userId); + + + @Query("select p from PtyCstmrBas p " + + "where p.cstmrSno = :cstmrSno " ) + PtyCstmrBas findByUserGroupId(@Param("cstmrSno") int cstmrSno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrConectHistRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrConectHistRepository.java new file mode 100644 index 00000000..9db4a14a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrConectHistRepository.java @@ -0,0 +1,12 @@ +package com.palnet.biz.jpa.repository.pty; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.PtyCstmrConectHist; + +@Repository +public interface PtyCstmrConectHistRepository extends JpaRepository{ + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrDtlRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrDtlRepository.java new file mode 100644 index 00000000..cb75fb18 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrDtlRepository.java @@ -0,0 +1,13 @@ +package com.palnet.biz.jpa.repository.pty; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.PtyCstmrDtl; +import com.palnet.biz.jpa.entity.PtyTermsBas; + +@Repository +public interface PtyCstmrDtlRepository extends JpaRepository{ + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrGroupRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrGroupRepository.java new file mode 100644 index 00000000..02de1f2d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrGroupRepository.java @@ -0,0 +1,44 @@ +package com.palnet.biz.jpa.repository.pty; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import com.palnet.biz.jpa.entity.PtyCstmrGroup; + +@Repository +public interface PtyCstmrGroupRepository extends JpaRepository{ + + @Query("select p from PtyCstmrGroup p " + + "where p.joinYn = 'Y' " + + "and p.groupId = :groupId " + + "and p.cstmrSno = :cstmrSno") + PtyCstmrGroup findGroupId(@Param("groupId") String groupId, @Param("cstmrSno") int cstmrSno); + + @Query("select p from PtyCstmrGroup p " + + "where p.groupId = :groupId " ) + List changeGroupJoinYn(@Param("groupId") String groupId); + + @Query("select p from PtyCstmrGroup p " + + "where p.cstmrSno = :cstmrSno " ) + List changeGroupAprvlYn(@Param("cstmrSno") int cstmrSno); + + @Query("select p from PtyCstmrGroup p " + + "where p.groupId = :groupId " + + "and p.cstmrSno = :cstmrSno") + PtyCstmrGroup findRejoinUser(@Param("groupId") String groupId, @Param("cstmrSno") int cstmrSno); + + @Transactional + @Modifying + @Query(value = "UPDATE PTY_CSTMR_GROUP " + + "SET WTHDRW_DT = null " + + "WHERE GROUP_ID = :groupId " + + "AND CSTMR_SNO = :cstmrSno " + ,nativeQuery = true ) + void updateWithdrwDt(@Param("groupId") String groupId, @Param("cstmrSno") int cstmrSno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrQueryRepository.java new file mode 100644 index 00000000..e32385bd --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyCstmrQueryRepository.java @@ -0,0 +1,281 @@ +package com.palnet.biz.jpa.repository.pty; + +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrPwModel; +import com.palnet.biz.api.acnt.cstmr.model.AcntCstmrRqModel; +import com.palnet.biz.api.acnt.cstmr.model.AnctCstmerRlModel; +import com.palnet.biz.api.acnt.jwt.model.JwtGroupModel; +import com.palnet.biz.jpa.entity.*; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.api.acnt.jwt.model.JwtProfileRsModel; +import com.palnet.biz.api.acnt.jwt.model.JwtUserModel; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +import java.util.ArrayList; +import java.util.List; + +@Log4j2 +@Repository +@RequiredArgsConstructor +public class PtyCstmrQueryRepository{ + + + private final JPAQueryFactory query; + + public boolean findCstmrByUserId(String userId){ + + boolean result = false; + + QPtyCstmrBas basEntity = QPtyCstmrBas.ptyCstmrBas; + + + BooleanBuilder builder = new BooleanBuilder(); + + builder.and(basEntity.cstmrStatusCd.eq("A")); //활성화 상태 + builder.and(basEntity.userId.eq(userId)); + + PtyCstmrBas entity = query.select(basEntity) + .from(basEntity) + .where(builder) + .fetchFirst(); + if(entity != null) { + result = true; + } + + return result; + } + public boolean certifNum(String name , String hpno) { + QPtyCstmrDtl dtl = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(dtl.hpno.eq(hpno)); + builder.and(dtl.memberName.eq(name)); + + PtyCstmrDtl entity = query.select(dtl) + .from(dtl) + .where(builder) + .fetchFirst(); + boolean result = false; + if(entity != null) { + result = true; + } + return result; + } + + public String findUserId(String name , String hpno) { + QPtyCstmrBas bas = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl dtl = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.cstmrStatusCd.eq("A")); + builder.and(dtl.hpno.eq(hpno)); + builder.and(dtl.memberName.eq(name)); + PtyCstmrBas entity = query.select(bas) + .from(bas) + .leftJoin(dtl) + .on(bas.cstmrSno.eq(dtl.cstmrSno)) + .where(builder) + .fetchFirst(); + + String userId = entity.getUserId(); + return userId; + } + public PtyCstmrBas findUserPw(String id , String hpno) { + QPtyCstmrBas bas = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl dtl = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.cstmrStatusCd.eq("A")); + builder.and(dtl.hpno.eq(hpno)); + builder.and(bas.userId.eq(id)); + PtyCstmrBas entity = query.select(bas) + .from(bas) + .leftJoin(dtl) + .on(bas.cstmrSno.eq(dtl.cstmrSno)) + .where(builder) + .fetchFirst(); + + return entity; + } + + public boolean findCstmrByHpno(String hpno) { + boolean result = false; + + QPtyCstmrBas basEntity = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl dtlEntity = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(basEntity.cstmrStatusCd.eq("A")); //활성화 상태 + builder.and(dtlEntity.hpno.eq(hpno)); + + PtyCstmrBas entity = query.select(basEntity) + .from(basEntity) + .leftJoin(dtlEntity) + .on(basEntity.cstmrSno.eq(dtlEntity.cstmrSno)) + .where(builder) + .fetchFirst(); + if(entity != null) { + result = true; + } + return result; + + } + + public JwtUserModel findUserPassword(String userId) { + QPtyCstmrBas basEntity = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrGroup groupEntity = QPtyCstmrGroup.ptyCstmrGroup; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(basEntity.userId.eq(userId)); + + PtyCstmrBas entity = query.select(basEntity) + .from(basEntity) + .where(builder) + .fetchFirst(); + + List pcgEntityList = null; + if(entity != null){ + BooleanBuilder groupBuilder = new BooleanBuilder(); + groupBuilder.and(groupEntity.cstmrSno.eq(entity.getCstmrSno()) + .and(groupEntity.joinYn.eq("Y"))); + + pcgEntityList = query.select(groupEntity) + .from(groupEntity) + .where(groupBuilder) + .fetch(); + } + + + if(entity != null) { + JwtUserModel model = new JwtUserModel(); + model.setAuth(entity.getAuthId()); + model.setUserId(entity.getUserId()); + model.setCstmrSno(entity.getCstmrSno()); + model.setCstmrStatusCd(entity.getCstmrStatusCd()); + model.setUserPswd(entity.getUserPswd()); + if(pcgEntityList != null && !pcgEntityList.isEmpty()){ + List groupModelList = new ArrayList<>(); + for(PtyCstmrGroup pcgEntity : pcgEntityList){ + JwtGroupModel groupModel = new JwtGroupModel(); + groupModel.setGroupId(pcgEntity.getGroupId()); + groupModel.setGroupAuthCd(pcgEntity.getGroupAuthCd()); + groupModelList.add(groupModel); + } + model.setGroup(groupModelList); + } + + return model; + + }else { + return null; + } + + + } + + public JwtProfileRsModel findUserProfile(int cstmrSno) { + QPtyCstmrBas basEntity = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl dtlEntity = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(basEntity.cstmrSno.eq(cstmrSno)); + + + JwtProfileRsModel model = query.select(Projections.bean(JwtProfileRsModel.class , + basEntity.cstmrSno, + basEntity.userId, + basEntity.authId, + basEntity.trmnlId, + basEntity.siteCode, + dtlEntity.memberName + )) + .from(basEntity) + .leftJoin(dtlEntity) + .on(basEntity.cstmrSno.eq(dtlEntity.cstmrSno)) + .where(builder) + .fetchFirst(); + + return model; + + } + + public JwtUserModel findRefreshtoken(int cstmrSno , String refreshToken) { + QPtyCstmrBas basEntity = QPtyCstmrBas.ptyCstmrBas; + BooleanBuilder builder = new BooleanBuilder(); + builder.and(basEntity.cstmrSno.eq(cstmrSno)); + builder.and(basEntity.rfrshToken.eq(refreshToken)); + + PtyCstmrBas entity = query.select(basEntity) + .from(basEntity) + .where(builder) + .fetchFirst(); + if(entity != null) { + JwtUserModel model = new JwtUserModel(); + model.setAuth(entity.getAuthId()); + model.setUserId(entity.getUserId()); + model.setCstmrSno(entity.getCstmrSno()); + model.setCstmrStatusCd(entity.getCstmrStatusCd()); + model.setUserPswd(entity.getUserPswd()); + + return model; + + }else { + return null; + } + } + + public List list(int cstmrSno) { + QPtyCstmrBas bas = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl dtl = QPtyCstmrDtl.ptyCstmrDtl; + + List list = query + .select(Projections.bean( + AnctCstmerRlModel.class, + dtl.memberName, + dtl.brthdyDate, + dtl.genderCd, + dtl.cntryCd, + dtl.email, + dtl.hpno, + bas.userId + )) + .from(bas) + .leftJoin(dtl) + .on(bas.cstmrSno.eq(dtl.cstmrSno)) + .where(bas.cstmrSno.eq(cstmrSno)) + .fetch(); + + return list; + } + + + + public AcntCstmrRqModel findpassword(String userId) { + QPtyCstmrBas basEntity = QPtyCstmrBas.ptyCstmrBas; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(basEntity.userId.eq(userId)); + + PtyCstmrBas entity = query.select(basEntity) + .from(basEntity) + .where(builder) + .fetchFirst(); + + if(entity != null) { + JwtUserModel model = new JwtUserModel(); + model.setCstmrSno(entity.getCstmrSno()); + model.setUserPswd(entity.getUserPswd()); + } + + return null; + } + + +} + + diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyDronQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyDronQueryRepository.java new file mode 100644 index 00000000..2e38fdee --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyDronQueryRepository.java @@ -0,0 +1,342 @@ +package com.palnet.biz.jpa.repository.pty; + + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.api.bas.dron.model.BasDronModel; +import com.palnet.biz.api.bas.dron.model.BasDronRqModel; +import com.palnet.biz.api.bas.dron.model.BasIdntfModel; +import com.palnet.biz.api.main.dash.model.MainDashListModel; +import com.palnet.biz.jpa.entity.QComArcrftBas; +import com.palnet.biz.jpa.entity.QComIdntfBas; +import com.palnet.biz.jpa.entity.QPtyCstmrGroup; +import com.palnet.biz.jpa.entity.QPtyGroupBas; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Repository +@RequiredArgsConstructor +public class PtyDronQueryRepository{ + private final JPAQueryFactory query; + + /** + * 목록 조회 + * @param rq + * @return + */ + public PageImpl list(BasDronRqModel rq, Pageable pageable){ + + QComArcrftBas bas = QComArcrftBas.comArcrftBas; + QComIdntfBas idnt = QComIdntfBas.comIdntfBas; + + + BooleanBuilder builder = new BooleanBuilder(); + + if(!StringUtils.isEmpty(rq.getArcrftModelNm())) { + builder.and(bas.arcrftModelNm.like('%' + rq.getArcrftModelNm() + '%')); + } + + if(!StringUtils.isEmpty(rq.getGroupId())) { + builder.and(bas.groupId.eq(rq.getGroupId())); + } + + if(!StringUtils.isEmpty(rq.getArcrftTypeCd())) { + builder.and(bas.arcrftTypeCd.eq(rq.getArcrftTypeCd())); + } + + builder.and(bas.useYn.eq("Y")); + + List result = + query.select(Projections.bean(BasDronModel.class , + bas.groupId, + bas.arcrftSno, + bas.arcrftHght, + bas.arcrftLngth, + bas.arcrftModelNm, + bas.arcrftTypeCd, + bas.arcrftWdth, + bas.arcrftWght, + bas.cameraYn, + bas.createDt, + bas.createUserId, + bas.insrncYn, + bas.prdctCmpnNm, + bas.prdctDate, + bas.prdctNum, + bas.takeoffWght, + bas.updateDt, + bas.updateUserId, + bas.wghtTypeCd + )).from(bas) + .where(builder) + .orderBy(bas.createDt.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + +// List result = new ArrayList(); +// +// for(BasDronModel model : queryResult) { +//// if(!StringUtils.isEmpty(model.getOwnerNm())) { +//// model.setOwnerNm(EncryptUtils.decrypt(model.getOwnerNm())); +//// } +// +// result.add(model); +// } + + return new PageImpl<>(result, pageable, result.size()); + } + public long listCount(BasDronRqModel rq){ + + QComArcrftBas bas = QComArcrftBas.comArcrftBas; + QComIdntfBas idnt = QComIdntfBas.comIdntfBas; + + + BooleanBuilder builder = new BooleanBuilder(); + + if(!StringUtils.isEmpty(rq.getArcrftModelNm())) { + builder.and(bas.arcrftModelNm.like('%' + rq.getArcrftModelNm() + '%')); + } + + if(!StringUtils.isEmpty(rq.getGroupId())) { + builder.and(bas.groupId.eq(rq.getGroupId())); + } + + if(!StringUtils.isEmpty(rq.getArcrftTypeCd())) { + builder.and(bas.arcrftTypeCd.eq(rq.getArcrftTypeCd())); + } + + builder.and(bas.useYn.eq("Y")); + + List result = + query.select(Projections.bean(BasDronModel.class , + bas.groupId, + bas.arcrftSno, + bas.arcrftHght, + bas.arcrftLngth, + bas.arcrftModelNm, + bas.arcrftTypeCd, + bas.arcrftWdth, + bas.arcrftWght, + bas.cameraYn, + bas.createDt, + bas.createUserId, + bas.insrncYn, + bas.prdctCmpnNm, + bas.prdctDate, + bas.prdctNum, + bas.takeoffWght, + bas.updateDt, + bas.updateUserId, + bas.wghtTypeCd + )).from(bas) + .where(builder) + .orderBy(bas.createDt.desc()) + .fetch(); + +// List result = new ArrayList(); +// +// for(BasDronModel model : queryResult) { +//// if(!StringUtils.isEmpty(model.getOwnerNm())) { +//// model.setOwnerNm(EncryptUtils.decrypt(model.getOwnerNm())); +//// } +// +// result.add(model); +// } + long cnt = 0; + for(BasDronModel list : result) { + cnt++; + } + return cnt; + } + /** + * 식별번호 조회 + * @param arcrftSno + * @return + */ + public List idntfList(int arcrftSno){ + + QComIdntfBas idnt = QComIdntfBas.comIdntfBas; + QComArcrftBas arcrft = QComArcrftBas.comArcrftBas; + + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(idnt.arcrftSno.eq(arcrftSno)); + + + List result = + query.select(Projections.bean(BasIdntfModel.class , + + idnt.arcrftSno, + idnt.idntfNum, + idnt.idntfTypeCd, + idnt.createDt, + idnt.updateDt, + idnt.ownerNm, + idnt.hpno, + idnt.cstmrSno, + arcrft.groupId + )).from(idnt) + .leftJoin(arcrft) + .on(idnt.arcrftSno.eq(arcrft.arcrftSno)) + .where(builder) + .orderBy(idnt.createDt.asc()) + .fetch(); + return result; + } + + + + + /** + * 상세 조회 + * @param arcrftSno + * @return + */ + public BasDronModel detail(int arcrftSno){ + + QComArcrftBas bas = QComArcrftBas.comArcrftBas; + + BasDronModel result = + query.select(Projections.bean(BasDronModel.class , + bas.groupId, + bas.arcrftSno, + bas.arcrftHght, + bas.arcrftLngth, + bas.arcrftModelNm, + bas.arcrftTypeCd, + bas.arcrftWdth, + bas.arcrftWght, + bas.cameraYn, + bas.createDt, + bas.createUserId, + bas.insrncYn, + bas.prdctCmpnNm, + bas.prdctDate, + bas.prdctNum, + bas.takeoffWght, + bas.updateDt, + bas.updateUserId, + bas.wghtTypeCd, + bas.imageUrl + )).from(bas) + .where(bas.arcrftSno.eq(arcrftSno)) + .fetchOne(); + +// if(!StringUtils.isEmpty(result.getOwnerNm())) { +// result.setOwnerNm(EncryptUtils.decrypt(result.getOwnerNm())); +// } +// if(!StringUtils.isEmpty(result.getHpno())) { +// result.setHpno(EncryptUtils.decrypt(result.getHpno())); +// } +// if(!StringUtils.isEmpty(result.getTelno())) { +// result.setTelno(EncryptUtils.decrypt(result.getTelno())); +// } + + return result; + + } + + + + /** + * 식별번호가 존해 하는지 여부체크 + * @param idntfNum + * @param + * @return + */ + public boolean isNotIdntNum(String idntfNum) { + QComIdntfBas idnt = QComIdntfBas.comIdntfBas; + BooleanBuilder builder = new BooleanBuilder(); + builder.and(idnt.idntfNum.eq(idntfNum)); + + long count = query.select(idnt.idntfNum).from(idnt).where(builder).fetchCount(); + + if(count == 0) { + return true; + }else { + return false; + } + + } + + + public boolean isNotPrdctNum(String prdctNum , int arcrftSno) { + QComArcrftBas bas = QComArcrftBas.comArcrftBas; + + long count = query.select(bas.prdctNum).from(bas).where(bas.useYn.eq("Y")).where(bas.prdctNum.eq(prdctNum).and(bas.arcrftSno.ne(arcrftSno))).fetchCount(); + + if(count == 0) { + return true; + }else { + return false; + } + } + + public String findIdntfNumByProdNumber(String idntfNum) { + QComIdntfBas idnt = QComIdntfBas.comIdntfBas; + QComArcrftBas bas = QComArcrftBas.comArcrftBas; + String prdctNum = ""; + + prdctNum = + query.select(bas.prdctNum) + .from(bas) + .where(bas.useYn.eq("Y")) + .where(bas.arcrftSno.in( + JPAExpressions + .select(idnt.arcrftSno) + .from(idnt) + .where(idnt.idntfNum.eq(idntfNum)) + )) + .fetchOne(); + + return prdctNum; + + } + + /*** + * 메인 대시보드 기체 정보 3건 표출 + */ + public List dronTop3(int cstmrSno){ + QComArcrftBas bas = QComArcrftBas.comArcrftBas; + QPtyGroupBas gBas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup group = QPtyCstmrGroup.ptyCstmrGroup; + + List result = + query.select(Projections.bean(MainDashListModel.class , + bas.arcrftModelNm, + bas.prdctNum, + bas.createDt, + gBas.groupNm + )).from(group) + .leftJoin(bas) + .on(group.groupId.eq(bas.groupId)) + .on(group.joinYn.eq("Y")) + .on(group.aprvlYn.eq("Y")) + .on(bas.useYn.eq("Y")) + .leftJoin(gBas) + .on(group.groupId.eq(gBas.groupId)) + .where(bas.useYn.eq("Y")) + .where(group.cstmrSno.eq(cstmrSno)) + .limit(3) + .orderBy(bas.createDt.desc()) + .fetch(); + + + return result; + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyGroupBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyGroupBasRepository.java new file mode 100644 index 00000000..8c5dcac1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyGroupBasRepository.java @@ -0,0 +1,22 @@ +package com.palnet.biz.jpa.repository.pty; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.PtyGroupBas; + +@Repository +public interface PtyGroupBasRepository extends JpaRepository{ + + @Query("select p from PtyGroupBas p " + + "where p.groupNm = :groupNm ") + List findByGroupNm(@Param("groupNm") String groupNm); + + @Query("select p from PtyGroupBas p " + + "where p.groupId = :groupId ") + PtyGroupBas findByGroupId(@Param("groupId") String groupId); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyGroupQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyGroupQueryRepository.java new file mode 100644 index 00000000..c2f450cc --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyGroupQueryRepository.java @@ -0,0 +1,663 @@ +package com.palnet.biz.jpa.repository.pty; + + + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.bas.group.model.BasGroupAprvModel; +import com.palnet.biz.api.bas.group.model.BasGroupAprvRqModel; +import com.palnet.biz.api.bas.group.model.BasGroupJoinModel; +import com.palnet.biz.api.bas.group.model.BasGroupJoinRqModel; +import com.palnet.biz.api.bas.group.model.BasGroupModel; +import com.palnet.biz.api.bas.group.model.BasGroupRqModel; +import com.palnet.biz.api.bas.group.model.BasGroupUserListModel; +import com.palnet.biz.api.bas.group.model.BasGroupUserModel; +import com.palnet.biz.jpa.entity.FltPlanArea; +import com.palnet.biz.jpa.entity.QPtyCstmrBas; +import com.palnet.biz.jpa.entity.QPtyCstmrDtl; +import com.palnet.biz.jpa.entity.QPtyCstmrGroup; +import com.palnet.biz.jpa.entity.QPtyGroupBas; +import com.palnet.comn.utils.EncryptUtils; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Repository +@RequiredArgsConstructor +public class PtyGroupQueryRepository{ + private final JPAQueryFactory query; + + /** + * 그룹 전체 목록 + * @param rq + * @return + */ + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + public List list(BasGroupRqModel rq){ + + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.useYn.eq("Y")); + + if(!StringUtils.isEmpty(rq.getGroupId())) { + builder.and(bas.groupId.eq(rq.getGroupId())); + } + + if(!StringUtils.isEmpty(rq.getGroupNm())) { + builder.and(bas.groupNm.like(rq.getGroupNm())); + } + + List result = + query.select(Projections.bean(BasGroupModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + bas.updateDt, + bas.createDt + )).from(bas) + .where(builder) + .orderBy(bas.createDt.desc()) + .fetch(); + + return result; + + } + + /** + * 내가 생성한 그룹 목록 + * @param cstmrSno + * @return + */ + public List mylist(int cstmrSno){ + + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.useYn.eq("Y")); + builder.and(dtl.cstmrSno.eq(cstmrSno)); +// builder.and(dtl.groupAuthCd.eq("CREATER")); + builder.and(dtl.groupAuthCd.eq("MASTER")); + + + List result = + query.select(Projections.bean(BasGroupModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + bas.updateDt, + bas.createDt + )).from(bas) + .leftJoin(dtl) + .on(bas.groupId.eq(dtl.groupId)) + .where(builder) + .orderBy(bas.createDt.desc()) + .fetch(); + + return result; + + } + + /** + * 그룹 목록 + * @param cstmrSno + * @return + */ + public List groupAdminList(int cstmrSno){ + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup group = QPtyCstmrGroup.ptyCstmrGroup; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.useYn.eq("Y")); + builder.and(group.groupAuthCd.eq("MASTER")); + + List result = query.select(Projections.bean(BasGroupJoinModel.class , + bas.groupId, + bas.groupNm, + group.groupAuthCd, + bas.createDt, + group.cstmrGroupSno + )).from(bas) + .where(builder) + .leftJoin(group) + .on(bas.groupId.eq(group.groupId)) +// .orderBy(group.joinDt.desc()) + .orderBy(bas.createDt.desc()) + .orderBy(bas.groupNm.asc()) + .groupBy(bas.groupId) + .fetch(); + + BooleanBuilder builder2 = new BooleanBuilder(); + builder2.and(bas.useYn.eq("Y")); + builder2.and(group.cstmrGroupSno.isNotNull()); + + List my = query.select(Projections.bean(BasGroupUserModel.class , + bas.groupId, + bas.groupNm, + group.cstmrGroupSno, + group.cstmrSno, + group.groupAuthCd + )).from(bas) + .where(builder2) + .leftJoin(group) + .on(bas.groupId.eq(group.groupId)) + .on(group.cstmrSno.eq(cstmrSno)) + .groupBy(bas.groupId) + .fetch(); + + + for(BasGroupJoinModel groupList: result) { + for(BasGroupUserModel myList: my) { + if(groupList.getGroupId().equals(myList.getGroupId())) { + groupList.setMyGroupAuthCd(myList.getGroupAuthCd()); + } + } + } + + + return result; + } + + public List groupUserList(int cstmrSno){ + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup group = QPtyCstmrGroup.ptyCstmrGroup; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.useYn.eq("Y")); + builder.and(group.joinYn.eq("Y")); + builder.and(group.cstmrSno.eq(cstmrSno)); + + + List result = query.select(Projections.bean(BasGroupJoinModel.class , + bas.groupId, + bas.groupNm, + bas.createDt, + group.cstmrGroupSno + )).from(bas) + .where(builder) + .leftJoin(group) + .on(bas.groupId.eq(group.groupId)) + .orderBy(bas.createDt.desc()) + .orderBy(bas.groupNm.asc()) + .groupBy(bas.groupId) + .fetch(); + + return result; + + } + /** + * 나의 그룹 - 참여 그룹 목록 + * @param cstmrSno + * @return + */ + public List joinList(int cstmrSno){ + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.useYn.eq("Y")); + builder.and(dtl.joinYn.eq("Y")); + builder.and(dtl.cstmrSno.eq(cstmrSno)); + + List result = + query.select(Projections.bean(BasGroupJoinModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + bas.trmnlId, + dtl.cstmrSno, + dtl.cstmrGroupSno, + bas.updateDt, + bas.createDt, + dtl.aprvlYn, + dtl.joinDt, + dtl.aprvlDt, + dtl.groupAuthCd + )).from(bas) + .leftJoin(dtl) + .on(bas.groupId.eq(dtl.groupId)) + .where(builder) + .orderBy(dtl.joinDt.desc()) + .orderBy(bas.createDt.desc()) + .fetch(); + + return result; + + } + + /** + * 참여할 그룹 목록 + * @param cstmrSno + * @return + */ + public List joinFullList(BasGroupJoinRqModel rq){ + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.useYn.eq("Y")); +// builder.and(dtl.cstmrSno.eq(rq.getCstmrSno())); + + if(!StringUtils.isEmpty(rq.getGroupId())) { + builder.and(bas.groupId.like("%" + rq.getGroupId() + "%")); + } + + if(!StringUtils.isEmpty(rq.getGroupNm())) { + builder.and(bas.groupNm.like("%" + rq.getGroupNm() + "%")); + } + + + List result = + query.select(Projections.bean(BasGroupJoinModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + bas.updateDt, + bas.createDt, + dtl.cstmrSno, + dtl.cstmrGroupSno, + dtl.aprvlYn, + dtl.joinYn, + dtl.joinDt, + dtl.aprvlDt, + dtl.groupAuthCd + )).from(bas) + .leftJoin(dtl) + .on(bas.groupId.eq(dtl.groupId)) + .on(dtl.cstmrSno.eq(rq.getCstmrSno())) + .on(dtl.joinYn.eq("Y")) + .where(builder) + .orderBy(dtl.joinYn.asc()) + .orderBy(dtl.joinDt.desc()) + .orderBy(bas.createDt.desc()) + + .fetch(); + + return result; + + } + + public PageImpl aprvList(BasGroupAprvRqModel rq, Pageable pageable){ + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + QPtyCstmrBas cstmr = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl cstmrDtl = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + + String appAuth = jwtTokenUtil.getUserAuthByToken(); + + if(!StringUtils.isEmpty(rq.getGroupNm())) { + builder.and(bas.groupNm.like("%" + rq.getGroupNm() + "%")); + } + + if(!StringUtils.isEmpty(rq.getMemberName())) { + builder.and(cstmrDtl.memberName.like("%" + rq.getMemberName() + "%")); + } + +// if(appAuth.equals("USER") || appAuth.equals("ROLE_USER")) { +// builder.and(bas.groupId.in( +// JPAExpressions +// .select(bas.groupId) +// .from(bas) +// .leftJoin(dtl) +// .on(bas.groupId.eq(dtl.groupId)) +// .where(bas.useYn.eq("Y")) +// .where(dtl.cstmrSno.eq(rq.getCstmrSno())) +// .where(dtl.groupAuthCd.eq("MASTER").or(dtl.groupAuthCd.eq("LEADER"))) +// +// )); +// } + if(!StringUtils.isEmpty(rq.getAprvYn())) { + builder.and(dtl.aprvlYn.eq(rq.getAprvYn())); + } + builder.and(bas.groupId.eq(rq.getGroupId())); + + builder.and(dtl.joinYn.eq("Y")); + + List queryResult = + query.select(Projections.bean(BasGroupAprvModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + dtl.cstmrGroupSno, + dtl.cstmrSno, + bas.updateDt, + bas.createDt, + dtl.aprvlYn, + dtl.joinYn, + dtl.joinDt, + dtl.aprvlDt, + dtl.groupAuthCd, + dtl.aprvlUserId, + cstmrDtl.memberName, + cstmr.userId + )).from(bas) + .join(dtl) + .on(bas.groupId.eq(dtl.groupId)) + .join(cstmr) + .on(dtl.cstmrSno.eq(cstmr.cstmrSno)) + .on(cstmr.cstmrStatusCd.eq("A")) + .join(cstmrDtl) + .on(cstmr.cstmrSno.eq(cstmrDtl.cstmrSno)) + .where(builder) + +// .where(dtl.cstmrSno.ne(rq.getCstmrSno())) +// .where(dtl.groupAuthCd.ne("CREATER")) + .where(dtl.groupAuthCd.ne("MASTER")) + .orderBy(bas.createDt.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + + return new PageImpl<>(queryResult, pageable, queryResult.size()); + } + public long aprvCount(BasGroupAprvRqModel rq, Pageable pageable){ + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + QPtyCstmrBas cstmr = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl cstmrDtl = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + + String appAuth = jwtTokenUtil.getUserAuthByToken(); + + if(!StringUtils.isEmpty(rq.getGroupNm())) { + builder.and(bas.groupNm.like("%" + rq.getGroupNm() + "%")); + } + + if(!StringUtils.isEmpty(rq.getMemberName())) { + builder.and(cstmrDtl.memberName.like("%" + rq.getMemberName() + "%")); + } + +// if(appAuth.equals("USER") || appAuth.equals("ROLE_USER")) { +// builder.and(bas.groupId.in( +// JPAExpressions +// .select(bas.groupId) +// .from(bas) +// .leftJoin(dtl) +// .on(bas.groupId.eq(dtl.groupId)) +// .where(bas.useYn.eq("Y")) +// .where(dtl.cstmrSno.eq(rq.getCstmrSno())) +// .where(dtl.groupAuthCd.eq("MASTER").or(dtl.groupAuthCd.eq("LEADER"))) +// +// )); +// } + if(!StringUtils.isEmpty(rq.getAprvYn())) { + builder.and(dtl.aprvlYn.eq(rq.getAprvYn())); + } + builder.and(bas.groupId.eq(rq.getGroupId())); + + builder.and(dtl.joinYn.eq("Y")); + + List queryResult = + query.select(Projections.bean(BasGroupAprvModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + dtl.cstmrGroupSno, + dtl.cstmrSno, + bas.updateDt, + bas.createDt, + dtl.aprvlYn, + dtl.joinYn, + dtl.joinDt, + dtl.aprvlDt, + dtl.groupAuthCd, + dtl.aprvlUserId, + cstmrDtl.memberName, + cstmr.userId + )).from(bas) + .join(dtl) + .on(bas.groupId.eq(dtl.groupId)) + .join(cstmr) + .on(dtl.cstmrSno.eq(cstmr.cstmrSno)) + .on(cstmr.cstmrStatusCd.eq("A")) + .join(cstmrDtl) + .on(cstmr.cstmrSno.eq(cstmrDtl.cstmrSno)) + .where(builder) + + .where(dtl.cstmrSno.ne(rq.getCstmrSno())) +// .where(dtl.groupAuthCd.ne("CREATER")) + .where(dtl.groupAuthCd.ne("MASTER")) + .orderBy(bas.createDt.desc()) + .fetch(); + long cnt = 0; + + for(BasGroupAprvModel list : queryResult) { + cnt++; + } + return cnt; + } + /** + * 참여 했는지 여부체크 + * @param cstmrSno + * @param groupId + * @return + */ + public boolean isNotJoin(int cstmrSno , String groupId) { + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + BooleanBuilder builder = new BooleanBuilder(); + builder.and(dtl.joinYn.eq("Y")); + builder.and(dtl.cstmrSno.eq(cstmrSno)); + builder.and(dtl.groupId.eq(groupId)); + long count = query.select(dtl.cstmrGroupSno).from(dtl).where(builder).fetchCount(); + + if(count == 0) { + return true; + }else { + return false; + } + } + + public boolean isReJoin(int cstmrSno , String groupId) { + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + BooleanBuilder builder = new BooleanBuilder(); + builder.and(dtl.cstmrSno.eq(cstmrSno)); + builder.and(dtl.groupId.eq(groupId)); + long count = query.select(dtl.cstmrGroupSno).from(dtl).where(builder).fetchCount(); + + if(count >= 1) { + return true; + }else { + return false; + } + } + + + /** + * 그룹 사용자 목록 조회 + * @param rq + * @return + */ + public PageImpl userList(BasGroupUserListModel rq, Pageable pageable){ + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + QPtyCstmrBas cstmr = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl cstmrDtl = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + + builder.and(bas.useYn.eq("Y")); + builder.and(dtl.joinYn.eq("Y")); + builder.and(dtl.aprvlYn.eq("Y")); + builder.and(bas.groupId.eq(rq.getGroupId())); +// if(appAuth.equals("USER") || appAuth.equals("ROLE_USER")) { +// builder.and(bas.groupId.in( +// JPAExpressions +// .select(bas.groupId) +// .from(bas) +// .leftJoin(dtl) +// .on(bas.groupId.eq(dtl.groupId)) +// .where(bas.useYn.eq("Y")) +// .where(dtl.cstmrSno.eq(rq.getCstmrSno())) +// .where(dtl.groupAuthCd.eq("MASTER").or(dtl.groupAuthCd.eq("LEADER"))) +// +// )); +// } +// if(!StringUtils.isEmpty(rq.getGroupNm())) { +// builder.and(bas.groupNm.like("%" + rq.getGroupNm() + "%")); +// } +// + if(!StringUtils.isEmpty(rq.getMemberName())) { + builder.and(cstmrDtl.memberName.like("%" + rq.getMemberName() + "%")); + } + + +// if(!StringUtils.isEmpty(rq.getMemberName())) { +// builder.and(dtl.aprvlYn.eq(rq.getAprvYn())); +// } +// + + List queryResult = + query.select(Projections.bean(BasGroupUserModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + bas.updateDt, + bas.createDt, + dtl.cstmrGroupSno, + dtl.cstmrSno, + dtl.joinDt, + dtl.joinYn, + dtl.aprvlDt, + dtl.groupAuthCd, + cstmrDtl.memberName, + cstmr.userId + )).from(bas) + .leftJoin(dtl) + .on(bas.groupId.eq(dtl.groupId)) + .leftJoin(cstmr) + .on(dtl.cstmrSno.eq(cstmr.cstmrSno)) + .on(cstmr.cstmrStatusCd.eq("A")) + .leftJoin(cstmrDtl) + .on(cstmr.cstmrSno.eq(cstmrDtl.cstmrSno)) + .where(builder) + .orderBy(bas.createDt.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + + + return new PageImpl<>(queryResult, pageable, queryResult.size()); + } + public long userCount(BasGroupUserListModel rq, Pageable pageable){ + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + QPtyCstmrBas cstmr = QPtyCstmrBas.ptyCstmrBas; + QPtyCstmrDtl cstmrDtl = QPtyCstmrDtl.ptyCstmrDtl; + + BooleanBuilder builder = new BooleanBuilder(); + + builder.and(bas.useYn.eq("Y")); + builder.and(dtl.joinYn.eq("Y")); + builder.and(dtl.aprvlYn.eq("Y")); + builder.and(bas.groupId.eq(rq.getGroupId())); +// if(appAuth.equals("USER") || appAuth.equals("ROLE_USER")) { +// builder.and(bas.groupId.in( +// JPAExpressions +// .select(bas.groupId) +// .from(bas) +// .leftJoin(dtl) +// .on(bas.groupId.eq(dtl.groupId)) +// .where(bas.useYn.eq("Y")) +// .where(dtl.cstmrSno.eq(rq.getCstmrSno())) +// .where(dtl.groupAuthCd.eq("MASTER").or(dtl.groupAuthCd.eq("LEADER"))) +// +// )); +// } +// if(!StringUtils.isEmpty(rq.getGroupNm())) { +// builder.and(bas.groupNm.like("%" + rq.getGroupNm() + "%")); +// } +// + if(!StringUtils.isEmpty(rq.getMemberName())) { + builder.and(cstmrDtl.memberName.like("%" + rq.getMemberName() + "%")); + } + + +// if(!StringUtils.isEmpty(rq.getMemberName())) { +// builder.and(dtl.aprvlYn.eq(rq.getAprvYn())); +// } +// + + List queryResult = + query.select(Projections.bean(BasGroupUserModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + bas.updateDt, + bas.createDt, + dtl.cstmrGroupSno, + dtl.cstmrSno, + dtl.joinDt, + dtl.joinYn, + dtl.aprvlDt, + dtl.groupAuthCd, + cstmrDtl.memberName, + cstmr.userId + )).from(bas) + .leftJoin(dtl) + .on(bas.groupId.eq(dtl.groupId)) + .leftJoin(cstmr) + .on(dtl.cstmrSno.eq(cstmr.cstmrSno)) + .on(cstmr.cstmrStatusCd.eq("A")) + .leftJoin(cstmrDtl) + .on(cstmr.cstmrSno.eq(cstmrDtl.cstmrSno)) + .where(builder) +// .offset(pageable.getOffset()) +// .limit(pageable.getPageSize()) + .orderBy(bas.createDt.desc()) + .fetch(); + long cnt = 0; + + for(BasGroupUserModel list : queryResult) { + cnt++; + } + return cnt; + } + public List groupTop3(int cstmrSno){ + + QPtyGroupBas bas = QPtyGroupBas.ptyGroupBas; + QPtyCstmrGroup dtl = QPtyCstmrGroup.ptyCstmrGroup; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.useYn.eq("Y")); + builder.and(dtl.cstmrSno.eq(cstmrSno)); + builder.and(dtl.groupAuthCd.eq("MASTER")); + + List result = + query.select(Projections.bean(BasGroupModel.class , + bas.groupId, + bas.groupNm, + bas.groupTypeCd, + bas.createDt + )).from(bas) + .leftJoin(dtl) + .on(bas.groupId.eq(dtl.groupId)) + .where(builder) + .limit(3) + .orderBy(bas.createDt.desc()) + .fetch(); + + return result; + + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtySnsLoginRelRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtySnsLoginRelRepository.java new file mode 100644 index 00000000..3f143d9d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtySnsLoginRelRepository.java @@ -0,0 +1,13 @@ +package com.palnet.biz.jpa.repository.pty; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.PtySnsLoginRel; +import com.palnet.biz.jpa.entity.PtyTermsBas; + +@Repository +public interface PtySnsLoginRelRepository extends JpaRepository{ + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsAgreeTxnRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsAgreeTxnRepository.java new file mode 100644 index 00000000..f04800fd --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsAgreeTxnRepository.java @@ -0,0 +1,12 @@ +package com.palnet.biz.jpa.repository.pty; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.PtyTermsAgreeTxn; + +@Repository +public interface PtyTermsAgreeTxnRepository extends JpaRepository{ + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsBasRepository.java new file mode 100644 index 00000000..b1f2db12 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsBasRepository.java @@ -0,0 +1,12 @@ +package com.palnet.biz.jpa.repository.pty; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.PtyTermsBas; + +@Repository +public interface PtyTermsBasRepository extends JpaRepository{ + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsDtlRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsDtlRepository.java new file mode 100644 index 00000000..d26bf3e6 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsDtlRepository.java @@ -0,0 +1,13 @@ +package com.palnet.biz.jpa.repository.pty; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.PtyTermsDtl; +import com.palnet.biz.jpa.entity.PtyTermsDtlPK; + +@Repository +public interface PtyTermsDtlRepository extends JpaRepository{ + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsQueryRepository.java new file mode 100644 index 00000000..61146401 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsQueryRepository.java @@ -0,0 +1,61 @@ +package com.palnet.biz.jpa.repository.pty; + +import java.util.List; + +import org.springframework.stereotype.Repository; + +import com.palnet.biz.api.acnt.terms.model.AcntTermsRqModel; +import com.palnet.biz.api.acnt.terms.model.AcntTermsRsModel; +import com.palnet.biz.jpa.entity.QPtyTermsBas; +import com.palnet.biz.jpa.entity.QPtyTermsDtl; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Repository +@RequiredArgsConstructor +public class PtyTermsQueryRepository{ + + + private final JPAQueryFactory query; + + public List list(AcntTermsRqModel rq){ + + QPtyTermsBas basEntity = QPtyTermsBas.ptyTermsBas; + QPtyTermsDtl dtlEntity = QPtyTermsDtl.ptyTermsDtl; + + BooleanBuilder builder = new BooleanBuilder(); + + builder.and(basEntity.lastTxnYn.eq("Y")); + builder.and(basEntity.siteCd.eq(rq.getSiteCd())); + + + List queryList = query.select(Projections.bean(AcntTermsRsModel.class , + basEntity.termsSno, + basEntity.siteCd, + basEntity.estbshDate, + basEntity.termsCtgryCd, + dtlEntity.id.langDivCd, + dtlEntity.termsTitleNm, + dtlEntity.termsCn, + dtlEntity.simpleCn + )) + .from(basEntity) + .leftJoin(dtlEntity) + .on(basEntity.termsSno.eq(dtlEntity.id.termsSno).and(dtlEntity.id.langDivCd.eq(rq.getLangDivCd()))) + .where(builder) + .orderBy(basEntity.updateDt.desc()) + .fetch(); + + return queryList; + } + + + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/SuredataRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/SuredataRepository.java new file mode 100644 index 00000000..09e16215 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/SuredataRepository.java @@ -0,0 +1,15 @@ +package com.palnet.biz.jpa.repository.pty; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.PtyCrtfyhpBas; +import com.palnet.biz.jpa.entity.PtyCstmrBas; +import com.palnet.biz.jpa.entity.PtyTermsBas; +import com.palnet.biz.jpa.entity.SuredataEntity; + +@Repository +public interface SuredataRepository extends JpaRepository{ + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/service/ctr/CtrCntrlJpaService.java b/pav-server/src/main/java/com/palnet/biz/jpa/service/ctr/CtrCntrlJpaService.java new file mode 100644 index 00000000..769c9462 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/service/ctr/CtrCntrlJpaService.java @@ -0,0 +1,170 @@ +package com.palnet.biz.jpa.service.ctr; + +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.palnet.biz.jpa.entity.CtrCntrlBas; +import com.palnet.biz.jpa.entity.CtrCntrlHstry; +import com.palnet.biz.jpa.entity.CtrCntrlHstryArea; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlHstryAreaRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlHstryRepository; +import com.palnet.biz.scheduler.ctr.model.CtrTrnsLctnModel; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.model.GPDatabaseModel; +import com.palnet.comn.utils.DateUtils; + +@Service +public class CtrCntrlJpaService { + + @Autowired + private CtrCntrlBasRepository ctrCntrlBasRepository; + + @Autowired + private CtrCntrlHstryRepository ctrCntrlHstryRepository; + + @Autowired + private CtrCntrlHstryAreaRepository ctrCntrlHstryAreaRepository; + + private Logger logger = LoggerFactory.getLogger(getClass()); + + public CtrCntrlBas insertCtrCntrlBas(GPDatabaseModel data) { + Optional optional = ctrCntrlBasRepository.findById(data.getControlId()); + if (optional.isPresent()) { + logger.debug(ErrorCode.DATA_DUPLICATE.toString()); + return null; + } + + CtrCntrlBas entity = new CtrCntrlBas(); + entity.setCntrlId(data.getControlId()); + entity.setIdntfNum(data.getObjectId()); + +// if(StringUtils.isEmpty(data.getProdNumber())) { +// entity.setObjectId("none"); +// }else { +// entity.setObjectId(data.getProdNumber()); +// } + + entity.setObjectTypeCd(data.getObjectType()); + entity.setStatusCd(data.getTypeCd()); + entity.setProcStatusYn("N"); + entity.setCntrlStDt(DateUtils.stringToDatetime(data.getControlStartDt())); + entity.setCreateDt(DateUtils.nowDate()); + entity.setUpdateDt(DateUtils.nowDate()); + + return ctrCntrlBasRepository.save(entity); + + + } + + + public CtrCntrlBas updateCtrCntrlBas(GPDatabaseModel data) { + Optional optional = ctrCntrlBasRepository.findById(data.getControlId()); + if (!optional.isPresent()) { + logger.debug(ErrorCode.DATA_NOTFIND.toString()); + return null; + } + + CtrCntrlBas entity = optional.get(); + entity.setStatusCd(data.getTypeCd()); + entity.setFlghtStDt(null); + entity.setFlghtEndDt(null); + entity.setCntrlEndDt(DateUtils.stringToDatetime(data.getControlEndDt())); + entity.setTtlTime(0.0); + entity.setTtlTimeType(null); + entity.setTtlDstnc(0.0); + entity.setTtlDstncType(null); + entity.setAvrgSpeed(0.0); + entity.setAvrgSpeedType(null); + entity.setBttrCnsmptn(0.0); + entity.setEndTypeCd(data.getEndTypeCd()); + entity.setUpdateDt(DateUtils.nowDate()); + + return ctrCntrlBasRepository.save(entity); + + } + + public CtrCntrlHstry insertCtrCntrlHstry(GPDatabaseModel data) { + CtrCntrlHstry entity = new CtrCntrlHstry(); + entity.setCntrlId(data.getControlId()); + //터미널 ID 추가 필요 + entity.setTrmnlId(data.getTerminalId()); + + //이동거리 추가 필요 + entity.setMvDstnc(data.getMoveDistance()); + entity.setMvDstncType(data.getMoveDistanceType()); + + entity.setMssgTypeCd(data.getMessageType()); + entity.setStatusCd(data.getDronStatus()); + entity.setLat(data.getLat()); + entity.setLon(data.getLng()); + entity.setSpeed(data.getSpeed()); + entity.setSpeedType(data.getSpeedType()); + entity.setHeading(data.getHeading()); + entity.setElevType(data.getElevType()); + + entity.setElev(data.getElev()); + + entity.setBttrLvl(data.getBetteryLevel()); + entity.setBttrVltg(data.getBetteryVoltage()); + entity.setTrmnlRcvDt(DateUtils.stringToDatetime(data.getTerminalRcvDt())); + entity.setSrvrRcvDt(DateUtils.stringToDatetime(data.getServerRcvDt())); + + // 환경지표 + entity.setSensorCo(data.getSensorCo()); + entity.setSensorSo2(data.getSensorSo2()); + entity.setSensorNo2(data.getSensorNo2()); + entity.setSensorO3(data.getSensorO3()); + entity.setSensorDust(data.getSensorDust()); + + + return ctrCntrlHstryRepository.save(entity); + } + + public CtrCntrlHstryArea insertCtrCntrlHstryArea(GPDatabaseModel data , int hstrySno) { + CtrCntrlHstryArea entity = new CtrCntrlHstryArea(); + + entity.setCntrlId(data.getControlId()); + entity.setActnType(data.getTypeCd()); + entity.setPrcsYn("N"); + entity.setLat(data.getLat()); + entity.setLon(data.getLng()); + entity.setHstrySno(hstrySno); + entity.setCreateDt(DateUtils.nowDate()); + entity.setUpdateDt(DateUtils.nowDate()); + + return ctrCntrlHstryAreaRepository.save(entity); + + } + + public CtrCntrlHstryArea updateCtrCntrlHstryArea(CtrTrnsLctnModel model) { + + Optional optional = ctrCntrlHstryAreaRepository.findById(model.getHstryAreaSno()); + if (!optional.isPresent()) { + logger.debug(ErrorCode.DATA_NOTFIND.toString()); + return null; + } + + CtrCntrlHstryArea entity = optional.get(); + + entity.setPrcsYn("Y"); + entity.setArea1(model.getArea1()); + entity.setArea2(model.getArea2()); + entity.setArea3(model.getArea3()); + entity.setZipCd(model.getZipCd()); + entity.setLandNm(model.getLandNm()); + entity.setLandNum(model.getLandNum()); + entity.setAreaType(model.getAreaType()); + entity.setAreaNm(model.getAreaNm()); + entity.setUpdateDt(DateUtils.nowDate()); + + return ctrCntrlHstryAreaRepository.save(entity); + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/sample/entity/SampleEntity.java b/pav-server/src/main/java/com/palnet/biz/sample/entity/SampleEntity.java new file mode 100644 index 00000000..e7ff7c98 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/sample/entity/SampleEntity.java @@ -0,0 +1,28 @@ +package com.palnet.biz.sample.entity; + +import java.time.LocalDateTime; + +import javax.persistence.*; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@Table(name="SAMPLE") +@Entity +public class SampleEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "SAMPLE_SNO") + private Integer agencySno; + /* 업체명*/ + @Column(name = "SAMPLE1") + private String sample1; + /* 주소*/ + @Column(name = "sample2") + private String sample2; + + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/sample/repository/SampleRepository.java b/pav-server/src/main/java/com/palnet/biz/sample/repository/SampleRepository.java new file mode 100644 index 00000000..c49dedd4 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/sample/repository/SampleRepository.java @@ -0,0 +1,11 @@ +package com.palnet.biz.sample.repository; + + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.sample.entity.SampleEntity; + +@Repository +public interface SampleRepository extends JpaRepository { +} diff --git a/pav-server/src/main/java/com/palnet/biz/sample/service/SampleService.java b/pav-server/src/main/java/com/palnet/biz/sample/service/SampleService.java new file mode 100644 index 00000000..7d3edebd --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/sample/service/SampleService.java @@ -0,0 +1,22 @@ +package com.palnet.biz.sample.service; + +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.palnet.biz.sample.entity.SampleEntity; +import com.palnet.biz.sample.repository.SampleRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class SampleService { + private final SampleRepository sampleRepository; + + public List find() throws Exception{ + return sampleRepository.findAll(); + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/CtrScheduler.java b/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/CtrScheduler.java new file mode 100644 index 00000000..eae95c31 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/CtrScheduler.java @@ -0,0 +1,47 @@ +package com.palnet.biz.scheduler.ctr; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.palnet.biz.scheduler.ctr.service.CtrSchedulerService; + +/** + * 데이터 정제 작업을 위한 스케줄러 + * @author kang + * + */ +@Component +public class CtrScheduler { + + @Autowired + private CtrSchedulerService service; + + private Logger logger = LoggerFactory.getLogger(getClass()); + + + /** + * TODO 비행 종료 처리 - 최신 수신 일로 부터 5분동안 데이터 수신 되지 않는 경우 종료 처리 + * + * 실행 주기 : 10초 + */ + @Scheduled(fixedDelay = 1000 * 10) + public void controlEndScheduler() { +// logger.debug("=================== {Control End Scheduler} ===================== "); + service.controlEndProcess(); + } + + /** + * TODO 비행 시작 지점 주소 변환 처리 + * + * 실행 주기 : 10초 + */ + @Scheduled(fixedDelay = 1000 * 10) + public void transferLocationScheduler() { +// logger.debug("=================== {transferLocation} ===================== "); + service.transferLocationProcess(); + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/model/CtrTrnsLctnModel.java b/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/model/CtrTrnsLctnModel.java new file mode 100644 index 00000000..10ca5f31 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/model/CtrTrnsLctnModel.java @@ -0,0 +1,19 @@ +package com.palnet.biz.scheduler.ctr.model; + +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class CtrTrnsLctnModel { + + private Integer hstryAreaSno; + private String area1; + private String area2; + private String area3; + private String zipCd; + private String landNm; + private String landNum; + private String areaType; + private String areaNm; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/service/CtrSchedulerService.java b/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/service/CtrSchedulerService.java new file mode 100644 index 00000000..43cb9779 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/service/CtrSchedulerService.java @@ -0,0 +1,89 @@ +package com.palnet.biz.scheduler.ctr.service; + +import java.util.*; + +import com.palnet.biz.jpa.repository.ctr.CtrCntrlBasRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlHstryAreaRepository; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlHstryRepository; +import com.palnet.biz.api.comn.model.ControlGpsDataContext; +import lombok.RequiredArgsConstructor; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import com.palnet.biz.jpa.entity.CtrCntrlHstry; +import com.palnet.biz.jpa.entity.CtrCntrlHstryArea; +import com.palnet.biz.jpa.repository.ctr.CtrCntrlQueryRepository; +import com.palnet.biz.jpa.service.ctr.CtrCntrlJpaService; +import com.palnet.biz.scheduler.ctr.model.CtrTrnsLctnModel; +import com.palnet.comn.utils.DateUtils; + +@Service +@RequiredArgsConstructor +public class CtrSchedulerService { + + private final CtrCntrlJpaService service; + private final CtrTrnsLctnService trnsService; + private final CtrCntrlQueryRepository ctrCntrlQueryRepository; + private final CtrCntrlHstryRepository ctrCntrlHstryRepository; + private final CtrCntrlBasRepository ctrCntrlBasRepository; + private final CtrCntrlHstryAreaRepository ctrCntrlHstryAreaRepository; + private final ControlGpsDataContext gpsDataContext; + + @Value("${gp.end.time}") + private long GP_END_TIME; + + + /** + * TODO 비행 종료 처리 - 최신 수신 일로 부터 5분동안 데이터 수신 되지 않는 경우 종료 처리 + * + */ + public void controlEndProcess() { + Map keys = gpsDataContext.getAllKeys(); + + keys.forEach((key, value) -> { + CtrCntrlHstry history = ctrCntrlHstryRepository.findFirstByCntrlIdOrderBySrvrRcvDtDesc(value).orElse(null); + + if(Objects.nonNull(history)) { + long diffMinute = DateUtils.diffMinute(history.getSrvrRcvDt(), new Date()); + + if(diffMinute > GP_END_TIME) { + ctrCntrlBasRepository.updateCntrlEndType("01", DateUtils.nowDate(), "99", history.getCntrlId()); + + /* 종료지점 주소 저장 */ + CtrCntrlHstryArea area = new CtrCntrlHstryArea(); + + area.setCntrlId(history.getCntrlId()); + area.setActnType("99"); + area.setPrcsYn("N"); + area.setLat(history.getLat()); + area.setLon(history.getLon()); + area.setHstrySno(history.getHstrySno()); + area.setCreateDt(DateUtils.nowDate()); + area.setUpdateDt(DateUtils.nowDate()); + + ctrCntrlHstryAreaRepository.save(area); + + gpsDataContext.removeIdntfKey(key); + } + } + }); + } + + public void transferLocationProcess() { + List list = ctrCntrlQueryRepository.listCntrlHstryArea(); + if(list.size() > 0) { + for(CtrCntrlHstryArea entity : list) { + + CtrTrnsLctnModel lctnModel = trnsService.convertLatlonToAddress(entity.getLat(), entity.getLon()); + + if(lctnModel == null) { + lctnModel = new CtrTrnsLctnModel(); + } + + lctnModel.setHstryAreaSno(entity.getHstryAreaSno()); + service.updateCtrCntrlHstryArea(lctnModel); + } + } + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/service/CtrTrnsLctnService.java b/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/service/CtrTrnsLctnService.java new file mode 100644 index 00000000..edb96907 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/scheduler/ctr/service/CtrTrnsLctnService.java @@ -0,0 +1,131 @@ +package com.palnet.biz.scheduler.ctr.service; + +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import com.palnet.biz.scheduler.ctr.model.CtrTrnsLctnModel; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.utils.JsonUtils; + +@Service +public class CtrTrnsLctnService { + + @Value("${naver.api.url}") + private String NAVER_API_URL; + + @Value("${naver.api.id}") + private String NAVER_API_ID; + + @Value("${naver.api.key}") + private String NAVER_API_KEY; + + private Logger logger = LoggerFactory.getLogger(getClass()); + + public CtrTrnsLctnModel convertLatlonToAddress(double lat , double lon) { + HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); + factory.setConnectTimeout(5000); //타임아웃 설정 5초 + factory.setReadTimeout(5000);//타임아웃 설정 5초 + RestTemplate restTemplate = new RestTemplate(factory); + + HttpHeaders header = new HttpHeaders(); + header.add("X-NCP-APIGW-API-KEY-ID", NAVER_API_ID); + header.add("X-NCP-APIGW-API-KEY", NAVER_API_KEY); + HttpEntity entity = new HttpEntity<>(header); + + UriComponents uri = UriComponentsBuilder.fromHttpUrl(NAVER_API_URL) + .queryParam("request", "coordsToaddr") + .queryParam("coords", lon + "," + lat) + .queryParam("sourcecrs", "epsg:4326") + .queryParam("output", "json") +// .queryParam("orders", "roadaddr") + .queryParam("orders", "addr,roadaddr") + .build(); + + ResponseEntity resultMap = restTemplate.exchange(uri.toString(), HttpMethod.GET, entity, Map.class); + + HttpStatus rsStatus = resultMap.getStatusCode(); + if(rsStatus != HttpStatus.OK){ + logger.debug("response error occurs."); + return null; + } + + Map body = resultMap.getBody(); + Map apiStatus = (Map)body.get("status"); + + logger.debug(JsonUtils.toJson(body)); + + String name = (String)apiStatus.get("name"); + if(!"ok".equals(name)){ + if(apiStatus != null){ + logger.debug("get aera api response error occurs. : {}/{}", name, apiStatus.get("message")); + }else{ + logger.debug("get aera api response error occurs."); + } +// logger.debug("{}\t/{}\t/{}\t/{}\t/{}", dto.getUserSno(), dto.getLctSno(), dto.getLat(), dto.getLon(), dto.getCreatDt()); + logger.debug(ErrorCode.FAIL.message()); + return null; +// throw new CustomException(ErrorCode.FAIL); + } + + CtrTrnsLctnModel model = new CtrTrnsLctnModel(); + + List results = (List)body.get("results"); + + // 리스트에서 도로명 타입의 검색결과가 있는지 확인 + // 있을 경우 해당 인덱스로 area 주소 반환 + int typeIndex = -1; + for(Object result : results){ + typeIndex++; + if("roadaddr".equals(((Map) result).get("name"))) break; + } + if(typeIndex < 0) { + logger.debug(ErrorCode.DATA_NO.message()); + return null; + } + Map result = (Map)results.get(typeIndex); + result.forEach((resultKey, resultValue) -> { +// log.debug(">>> resultKey / resultValue : {} / {}",resultKey, resultValue); + if("region".equals(resultKey)){ + model.setArea1(((Map)((Map)resultValue).get("area1")).get("name").toString()); + model.setArea2(((Map)((Map)resultValue).get("area2")).get("name").toString()); + model.setArea3(((Map)((Map)resultValue).get("area3")).get("name").toString()); + } + if("land".equals(resultKey)){ + String landNum = ((Map)resultValue).get("number1").toString(); + if(!"".equals(((Map)resultValue).get("number2").toString())){ + landNum += "-" + ((Map)resultValue).get("number2").toString(); + } + model.setLandNum(landNum); + if(((Map)resultValue).containsKey("name")){ + model.setLandNm(((Map)resultValue).get("name").toString()); + }else{ + model.setLandNm(""); + } + model.setZipCd(((Map)((Map)resultValue).get("addition1")).get("value").toString()); + model.setAreaType(((Map)((Map)resultValue).get("addition0")).get("type").toString()); + model.setAreaNm(((Map)((Map)resultValue).get("addition0")).get("value").toString()); + } + }); + + return model; + + } + + + + +} diff --git a/pav-server/src/main/java/com/palnet/comn/code/ErrorCode.java b/pav-server/src/main/java/com/palnet/comn/code/ErrorCode.java new file mode 100644 index 00000000..5b88bd5d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/code/ErrorCode.java @@ -0,0 +1,33 @@ +package com.palnet.comn.code; + +public enum ErrorCode { + SUCCESS("1", "성공"), + FAIL("-1" , "실패"), + INTERNAL_SERVER_ERROR("ER500", "내부 시스템 오류"), + NOT_REGIST_ERROR_CODE("ER501", "등록되지 않은 오류 코드"), + DATA_NOTFIND("DT001","데이터 를 찾을수 없습니다."), + DATA_DUPLICATE("DT002","중복 데이터가 존재합니다."), + DATA_NO("DT003", "데이터 미존재"), + DB_ERROR("DB001" , "디비 처리중 오류"), + PLAN_DATA_DUPLICATE("FT500", "이미 등록된 비행계획서의 비행구역과 비행시간이 일치합니다.\n비행시간 또는 비행구역을 수정하여 주십시오."), + ARCRFT_DATA_DUPLICATE("FT500", "해당 기체는 다른 비행계획서에서 이미 등록된 기체입니다.\n비행시간 또는 기체 정보를 확인하여 주십시오."); + + + + private final String code; + + private final String message; + + private ErrorCode(String code, String message) { + this.code = code; + this.message = message; + } + + public String code() { + return code; + } + + public String message() { + return message; + } +} diff --git a/pav-server/src/main/java/com/palnet/comn/code/Level.java b/pav-server/src/main/java/com/palnet/comn/code/Level.java new file mode 100644 index 00000000..7a9f4295 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/code/Level.java @@ -0,0 +1,24 @@ +package com.palnet.comn.code; + +public enum Level { + INFO(0), + WARN(1), + RETRY(2), + DROP(3), + RECYCLE(4), + CRITICAL(5); + + private int code; + + Level(int code) { + setLevel(code); + } + + public int getLevel() { + return code; + } + + public void setLevel(int code) { + this.code = code; + } +} diff --git a/pav-server/src/main/java/com/palnet/comn/code/MessageType.java b/pav-server/src/main/java/com/palnet/comn/code/MessageType.java new file mode 100644 index 00000000..c845f4ce --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/code/MessageType.java @@ -0,0 +1,8 @@ +package com.palnet.comn.code; + +public enum MessageType { + OPENSKY, + ADSB, + LTEM, + ETC, +} diff --git a/pav-server/src/main/java/com/palnet/comn/code/ObjectType.java b/pav-server/src/main/java/com/palnet/comn/code/ObjectType.java new file mode 100644 index 00000000..f350743b --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/code/ObjectType.java @@ -0,0 +1,9 @@ +package com.palnet.comn.code; + +public enum ObjectType { + DRON, + AIRPLANE, + CAR, + BUS, + PERSON +} diff --git a/pav-server/src/main/java/com/palnet/comn/code/RSErrorCode.java b/pav-server/src/main/java/com/palnet/comn/code/RSErrorCode.java new file mode 100644 index 00000000..2ef4d831 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/code/RSErrorCode.java @@ -0,0 +1,31 @@ +package com.palnet.comn.code; + +public enum RSErrorCode { + SUCCESS("1", "Success"), + FAIL("-1" , "Fail"), + ER_PARAM("-100" , "Please parameter Check"), + DATA_NOTFOUNT("-101" , "Data not found"), + PSWD_NOTMATCH("-102" , "Password does not match"), + ACNT_UNAVAIL("-103","Account is unavailable"), + + INTERNAL_SERVER_ERROR("-500", "Internal system error"), + DATA_DUPLICATE("-104","Duplicate data exists"); + + + private final String code; + + private final String message; + + private RSErrorCode(String code, String message) { + this.code = code; + this.message = message; + } + + public String code() { + return code; + } + + public String message() { + return message; + } +} diff --git a/pav-server/src/main/java/com/palnet/comn/code/Source.java b/pav-server/src/main/java/com/palnet/comn/code/Source.java new file mode 100644 index 00000000..7a0c51b2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/code/Source.java @@ -0,0 +1,6 @@ +package com.palnet.comn.code; + +public enum Source { + SERVER, + INTERNAL +} diff --git a/pav-server/src/main/java/com/palnet/comn/collection/AuthCollection.java b/pav-server/src/main/java/com/palnet/comn/collection/AuthCollection.java new file mode 100644 index 00000000..2a2f07fa --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/collection/AuthCollection.java @@ -0,0 +1,45 @@ +package com.palnet.comn.collection; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AuthCollection { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + private static List authkeyList = new ArrayList(); + + public void reloadAuthkey() { + // 인증키 하드코딩 처리 + authkeyList.add("1cc2e08e-0c5c-43b2-8d4d-cddd3de558e3");// 지텔인증키 + authkeyList.add("35ea4080-a3f2-4e34-8361-78db06bac6fc");// PAL 인증키 + +// authkeyList.add(null) + } + + public boolean checkAuthkey(String authKey) { + boolean result = false; +// logger.debug("authKey ::: " + authKey); + + for(String key : authkeyList) { +// logger.debug("key ::: " + key); + if(authKey.equals(key)) { + result = true; + } + } + + return result; + } + + + public static void main(String [] agrs) { + AuthCollection auth = new AuthCollection(); + auth.reloadAuthkey(); + + //System.out.println("1>>>>> " + auth.checkAuthkey("!234")); + //System.out.println("2>>>>> " + auth.checkAuthkey("1cc2e08e-0c5c-43b2-8d4d-cddd3de558e3")); + } +} diff --git a/pav-server/src/main/java/com/palnet/comn/collection/GPCollection.java b/pav-server/src/main/java/com/palnet/comn/collection/GPCollection.java new file mode 100644 index 00000000..bba71194 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/collection/GPCollection.java @@ -0,0 +1,137 @@ +package com.palnet.comn.collection; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; + +import com.palnet.comn.model.GPDatabaseModel; +import com.palnet.comn.model.GPHistoryModel; +import com.palnet.comn.model.GPModel; +import com.palnet.comn.utils.DateUtils; + +/** + * 현재 움직이는 물체/비행체에 대한 정보를 전송하기 위해 저장하는 Collection + * @author kang + * + */ +public class GPCollection { + private Logger logger = LoggerFactory.getLogger(getClass()); + + private static Map nowControl = Collections.synchronizedMap(new HashMap()); //현재 움직이는 비행체 + + + private GPDatabaseCollection gpdc = new GPDatabaseCollection(); + + + // 받은 데이터 정보를 데이터구조에 맞게 저장 한다. + // 최초에 데이터를 수신한 경우 관제 ID , 관제시작 시간을 셋팅한다. + public void putData(List paramData) { + + List historyList = null; + GPModel model = null; + for(GPModel data : paramData) { + if(!nowControl.containsKey(data.getObjectId())) { + model = new GPModel(); + model.setControlId(UUID.randomUUID().toString()); + model.setTypeCd("01"); + model.setAreaTrnsYn("N"); + model.setControlStartDt(DateUtils.getCurrentTime()); + }else { + model = nowControl.get(data.getObjectId()); + model.setTypeCd("02"); + model.setAreaTrnsYn("E"); + } + model.setObjectId(data.getObjectId()); + model.setObjectType(data.getObjectType()); + model.setMessageType(data.getMessageType()); + model.setLat(data.getLat()); + model.setLng(data.getLng()); + model.setElevType(data.getElevType()); + model.setElev(data.getElev()); + model.setSpeedType(data.getSpeedType()); + model.setSpeed(data.getSpeed()); + model.setBetteryLevel(data.getBetteryLevel()); + model.setBetteryVoltage(data.getBetteryVoltage()); + model.setDronStatus(data.getDronStatus()); + model.setHeading(data.getHeading()); + model.setTerminalRcvDt(data.getTerminalRcvDt()); + model.setServerRcvDt(data.getServerRcvDt()); + model.setServerRcvDt(DateUtils.getCurrentTime()); //서버에서 받은 시간 넣기 + model.setTerminalId(data.getTerminalId()); + model.setMoveDistance(data.getMoveDistance()); + model.setMoveDistanceType(data.getMoveDistanceType()); + + // 환경 데이터 필드 추가 + model.setSensorCo(data.getSensorCo()); + model.setSensorSo2(data.getSensorSo2()); + model.setSensorNo2(data.getSensorNo2()); + model.setSensorO3(data.getSensorO3()); + model.setSensorDust(data.getSensorDust()); + + // history 좌표 넣기 start + GPHistoryModel historyModel = new GPHistoryModel(); + historyModel.setObjectId(data.getObjectId()); + historyModel.setLat(data.getLat()); + historyModel.setLng(data.getLng()); + if(model.getPostionHistory() != null) { + historyList = model.getPostionHistory() ; + }else { + historyList = new ArrayList(); + + } + historyList.add(historyModel); + model.setPostionHistory(historyList); + // history 좌표 넣기 end + + + nowControl.put(data.getObjectId(), model); + + //Database 저장을 위해 Collection 저장을 위함 + putDatabase(model); + +// logger.debug(">>>" + model.toString()); + } + } + + //데이터를 저장하기 위한 Collection 에 저장 + public void putDatabase(GPModel model) { + GPDatabaseModel gpData = new GPDatabaseModel(); + + BeanUtils.copyProperties(model, gpData); + + gpdc.putData(gpData); + + } + + + // 현재 데이터 정보를 리턴 함 + public Map getData(){ + return nowControl; + } + + // 이력 좌표데이터 정보를 리턴함 + public List getHistoryData(String objectId){ + List result = new ArrayList(); + + if(nowControl.containsKey(objectId)) { + result= nowControl.get(objectId).getPostionHistory(); + } + return result; + + } + + + // 위치 히스토리 정보 전달 + public List getHistoryList(String objectId){ + return nowControl.get(objectId).getPostionHistory(); + + } + +} diff --git a/pav-server/src/main/java/com/palnet/comn/collection/GPDatabaseCollection.java b/pav-server/src/main/java/com/palnet/comn/collection/GPDatabaseCollection.java new file mode 100644 index 00000000..cef1270a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/collection/GPDatabaseCollection.java @@ -0,0 +1,49 @@ +package com.palnet.comn.collection; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.palnet.comn.model.GPDatabaseModel; +import com.palnet.comn.model.GPModel; + +/** + * 전송된 원시데이터를 Database 에 넣기 위해 임시 저장해두는 Collection + * @author kang + * + */ +public class GPDatabaseCollection { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + private static ConcurrentLinkedQueue dataList = new ConcurrentLinkedQueue(); + + + public void putData(GPDatabaseModel paramData) { + dataList.add(paramData); + + } + +// public void putListData(List paramDataList) { +// dataList.addAll(paramDataList); +// } + + public ConcurrentLinkedQueue getData(){ + + return dataList; + } + +// public static void main(String[] args) { +// ConcurrentLinkedQueue qe = new ConcurrentLinkedQueue(); +// +// } +// +} diff --git a/pav-server/src/main/java/com/palnet/comn/encrptn/kisa/KISA_SEED_CBC.java b/pav-server/src/main/java/com/palnet/comn/encrptn/kisa/KISA_SEED_CBC.java new file mode 100644 index 00000000..90b1ceb0 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/encrptn/kisa/KISA_SEED_CBC.java @@ -0,0 +1,1923 @@ +package com.palnet.comn.encrptn.kisa; + +public class KISA_SEED_CBC { + + + // DEFAULT : JAVA = BIG_ENDIAN + private static int ENDIAN = Common.BIG_ENDIAN; + + // S-BOX + private static final int SS0[] = + { + 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124, + 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, + 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, + 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec, + 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, + 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, + 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8, + 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, + 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, + 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4, + 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, + 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, + 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8, + 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, + 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, + 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264, + 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, + 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, + 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038, + 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, + 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, + 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4, + 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, + 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, + 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040, + 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, + 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, + 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8, + 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, + 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, + 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330, + 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298 + }; + + private static final int SS1[] = + { + 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0, + 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, + 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, + 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43, + 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, + 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, + 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3, + 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, + 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, + 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430, + 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, + 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, + 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1, + 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171, + 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, + 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0, + 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, + 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, + 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62, + 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, + 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, + 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901, + 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, + 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, + 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971, + 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, + 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, + 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1, + 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, + 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393, + 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783, + 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3 + }; + + private static final int SS2[] = + { + 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505, + 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, + 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, + 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece, + 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, + 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, + 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9, + 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, + 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, + 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5, + 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, + 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, + 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b, + 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, + 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, + 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646, + 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, + 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, + 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808, + 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, + 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, + 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4, + 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, + 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, + 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040, + 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, + 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, + 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca, + 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, + 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, + 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303, + 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a + }; + + private static final int SS3[] = + { + 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838, + 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, + 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, + 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b, + 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, + 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, + 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f, + 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, + 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, + 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434, + 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, + 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, + 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031, + 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031, + 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, + 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010, + 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, + 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, + 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e, + 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, + 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, + 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809, + 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, + 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, + 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839, + 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, + 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, + 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d, + 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, + 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013, + 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407, + 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437 + }; + + private static final int BLOCK_SIZE_SEED = 16; + private static final int BLOCK_SIZE_SEED_INT = 4; + + private static final byte GetB0(int A) { return (byte)(A & 0x0ff); } + private static final byte GetB1(int A) { return (byte)((A>>8) & 0x0ff); } + private static final byte GetB2(int A) { return (byte)((A>>16) & 0x0ff); } + private static final byte GetB3(int A) { return (byte)((A>>24) & 0x0ff); } + + // Round function F and adding output of F to L. + // L0, L1 : left input values at each round + // R0, R1 : right input values at each round + // K : round keys at each round + private static final void SeedRound(int[] T, int LR[], int L0, int L1, int R0, int R1, int[] K, int K_offset) { + T[0] = LR[R0] ^ K[K_offset+0]; + T[1] = LR[R1] ^ K[K_offset+1]; + T[1] ^= T[0]; + T[1] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ + SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + T[0] += T[1]; + T[0] = SS0[GetB0(T[0])&0x0ff] ^ SS1[GetB1(T[0])&0x0ff] ^ + SS2[GetB2(T[0])&0x0ff] ^ SS3[GetB3(T[0])&0x0ff]; + T[1] += T[0]; + T[1] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ + SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + T[0] += T[1]; + LR[L0] ^= T[0]; LR[L1] ^= T[1]; + } + + + + private static final int EndianChange(int dwS) { return ( (/*ROTL(dwS,8)*/(((dwS) << (8)) | (((dwS) >> (32-(8)))&0x000000ff)) & 0x00ff00ff) | (/*ROTL(dwS,24)*/(((dwS) << (24)) | (((dwS) >> (32-(24)))&0x00ffffff)) & 0xff00ff00) ); } + + /************************ Constants for Key schedule **************************/ + private static final int KC0 = 0x9e3779b9; + private static final int KC1 = 0x3c6ef373; + private static final int KC2 = 0x78dde6e6; + private static final int KC3 = 0xf1bbcdcc; + private static final int KC4 = 0xe3779b99; + private static final int KC5 = 0xc6ef3733; + private static final int KC6 = 0x8dde6e67; + private static final int KC7 = 0x1bbcdccf; + private static final int KC8 = 0x3779b99e; + private static final int KC9 = 0x6ef3733c; + private static final int KC10 = 0xdde6e678; + private static final int KC11 = 0xbbcdccf1; + private static final int KC12 = 0x779b99e3; + private static final int KC13 = 0xef3733c6; + private static final int KC14 = 0xde6e678d; + private static final int KC15 = 0xbcdccf1b; + + + + + private static final int ABCD_A = 0; + private static final int ABCD_B = 1; + private static final int ABCD_C = 2; + private static final int ABCD_D = 3; + + private static final void RoundKeyUpdate0(int T[], int[] K, int K_offset, int ABCD[], int KC) { + T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC; + T[1] = ABCD[ABCD_B] + KC - ABCD[ABCD_D]; + K[K_offset+0] = SS0[GetB0(T[0])&0x0ff] ^ SS1[GetB1(T[0])&0x0ff] ^ SS2[GetB2(T[0])&0x0ff] ^ SS3[GetB3(T[0])&0x0ff]; + K[K_offset+1] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + T[0] = ABCD[ABCD_A]; + ABCD[ABCD_A] = ((ABCD[ABCD_A]>>8)&0x00ffffff) ^ (ABCD[ABCD_B]<<24); + ABCD[ABCD_B] = ((ABCD[ABCD_B]>>8)&0x00ffffff) ^ (T[0]<<24); + } + + private static final void RoundKeyUpdate1(int T[], int []K, int K_offset, int ABCD[], int KC) { + T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC; + T[1] = ABCD[ABCD_B] + KC - ABCD[ABCD_D]; + K[K_offset+0] = SS0[GetB0(T[0])&0x0ff] ^ SS1[GetB1(T[0])&0x0ff] ^ SS2[GetB2(T[0])&0x0ff] ^ SS3[GetB3(T[0])&0x0ff]; + K[K_offset+1] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + T[0] = ABCD[ABCD_C]; + ABCD[ABCD_C] = (ABCD[ABCD_C]<<8) ^ ((ABCD[ABCD_D]>>24)&0x000000ff); + ABCD[ABCD_D] = (ABCD[ABCD_D]<<8) ^ ((T[0]>>24)&0x000000ff); + } + + private static void BLOCK_XOR_CBC(int[] OUT_VALUE, int out_value_offset, int[] IN_VALUE1, int in_value1_offset, int[] IN_VALUE2, int in_value2_offset) { + OUT_VALUE[out_value_offset+0] = (in_value1_offset 0) + len = (inLen/4)+1; + else + len = (inLen/4); + + data = new int[len]; + + for(i=0;i> ((i%4)*8)); + } + } else { + for(i=0;i> ((3-(i%4))*8)); + } + } + + return data; + } + + + public static int SEED_CBC_init( KISA_SEED_INFO pInfo, KISA_ENC_DEC enc, byte[] pbszUserKey, byte[] pbszIV ) { + int ABCD[] = new int[4]; // Iuput/output values at each rounds(�� ���� ��/���) + int T[] = new int[2]; // Temporary variable + int K[]; + + if( null == pInfo || + null == pbszUserKey || + null == pbszIV ) + return 0; + + K = pInfo.seed_key.key_data; // Pointer of round keys + pInfo.encrypt = enc.value; // + Common.memcpy(pInfo.ivec, pbszIV, 16, ENDIAN); + pInfo.last_block_flag = pInfo.buffer_length = 0; + + // Set up input values for Key Schedule + ABCD[ABCD_A] = Common.byte_to_int(pbszUserKey, 0*4, ENDIAN); + ABCD[ABCD_B] = Common.byte_to_int(pbszUserKey, 1*4, ENDIAN); + ABCD[ABCD_C] = Common.byte_to_int(pbszUserKey, 2*4, ENDIAN); + ABCD[ABCD_D] = Common.byte_to_int(pbszUserKey, 3*4, ENDIAN); + + // Reorder for big endian + if(Common.BIG_ENDIAN != ENDIAN) { + ABCD[ABCD_A] = EndianChange(ABCD[ABCD_A]); + ABCD[ABCD_B] = EndianChange(ABCD[ABCD_B]); + ABCD[ABCD_C] = EndianChange(ABCD[ABCD_C]); + ABCD[ABCD_D] = EndianChange(ABCD[ABCD_D]); + } + + // i-th round keys( K_i,0 and K_i,1 ) are denoted as K[2*(i-1)] and K[2*i-1], respectively + RoundKeyUpdate0(T, K, 0, ABCD, KC0 ); // K_1,0 and K_1,1 + RoundKeyUpdate1(T, K, 2, ABCD, KC1 ); // K_2,0 and K_2,1 + RoundKeyUpdate0(T, K, 4, ABCD, KC2 ); // K_3,0 and K_3,1 + RoundKeyUpdate1(T, K, 6, ABCD, KC3 ); // K_4,0 and K_4,1 + RoundKeyUpdate0(T, K, 8, ABCD, KC4 ); // K_5,0 and K_5,1 + RoundKeyUpdate1(T, K, 10, ABCD, KC5 ); // K_6,0 and K_6,1 + RoundKeyUpdate0(T, K, 12, ABCD, KC6 ); // K_7,0 and K_7,1 + RoundKeyUpdate1(T, K, 14, ABCD, KC7 ); // K_8,0 and K_8,1 + RoundKeyUpdate0(T, K, 16, ABCD, KC8 ); // K_9,0 and K_9,1 + RoundKeyUpdate1(T, K, 18, ABCD, KC9 ); // K_10,0 and K_10,1 + RoundKeyUpdate0(T, K, 20, ABCD, KC10); // K_11,0 and K_11,1 + RoundKeyUpdate1(T, K, 22, ABCD, KC11); // K_12,0 and K_12,1 + RoundKeyUpdate0(T, K, 24, ABCD, KC12); // K_13,0 and K_13,1 + RoundKeyUpdate1(T, K, 26, ABCD, KC13); // K_14,0 and K_14,1 + RoundKeyUpdate0(T, K, 28, ABCD, KC14); // K_15,0 and K_15,1 + + T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC15; + T[1] = ABCD[ABCD_B] - ABCD[ABCD_D] + KC15; + + K[30] = SS0[GetB0(T[0])&0x0ff] ^ SS1[GetB1(T[0])&0x0ff] ^ // K_16,0 + SS2[GetB2(T[0])&0x0ff] ^ SS3[GetB3(T[0])&0x0ff]; + K[31] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ // K_16,1 + SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + + return 1; + + + } + + + public static int SEED_CBC_Process( KISA_SEED_INFO pInfo, int[] in, int inLen, int[] out, int[] outLen ) { + int nCurrentCount = BLOCK_SIZE_SEED; + int[] pdwXOR = null; + int in_offset = 0; + int out_offset = 0; + int pdwXOR_offset = 0; + + if( null == pInfo || + null == in || + null == out || + 0 > inLen ) + return 0; + + + if( KISA_ENC_DEC._KISA_ENCRYPT == pInfo.encrypt ) { + pdwXOR = pInfo.ivec; + in_offset = 0; + out_offset = 0; + pdwXOR_offset = 0; + + + while( nCurrentCount <= inLen ) + { + BLOCK_XOR_CBC( out, out_offset, in, in_offset, pdwXOR, pdwXOR_offset ); + + KISA_SEED_Encrypt_Block_forCBC( out, out_offset, out, out_offset, pInfo.seed_key ); + + pdwXOR = out; + pdwXOR_offset = out_offset; + + nCurrentCount += BLOCK_SIZE_SEED; + in_offset += BLOCK_SIZE_SEED_INT; + out_offset += BLOCK_SIZE_SEED_INT; + } + + outLen[0] = nCurrentCount - BLOCK_SIZE_SEED; + pInfo.buffer_length = (inLen - outLen[0]); + + Common.memcpy( pInfo.ivec, pdwXOR, pdwXOR_offset, BLOCK_SIZE_SEED ); + Common.memcpy( pInfo.cbc_buffer, in, in_offset, pInfo.buffer_length ); + } + else { + pdwXOR = pInfo.ivec; + in_offset = 0; + out_offset = 0; + pdwXOR_offset = 0; + + while( nCurrentCount <= inLen ) + { + KISA_SEED_Decrypt_Block_forCBC( in, in_offset, out, out_offset, pInfo.seed_key ); + + BLOCK_XOR_CBC( out, out_offset, out, out_offset, pdwXOR, pdwXOR_offset ); + + pdwXOR = in; + pdwXOR_offset = in_offset; + + nCurrentCount += BLOCK_SIZE_SEED; + in_offset += BLOCK_SIZE_SEED_INT; + out_offset += BLOCK_SIZE_SEED_INT; + } + + outLen[0] = nCurrentCount - BLOCK_SIZE_SEED; + + + + Common.memcpy( pInfo.ivec, pdwXOR, pdwXOR_offset, BLOCK_SIZE_SEED ); + Common.memcpy( pInfo.cbc_last_block, out, out_offset-BLOCK_SIZE_SEED_INT, BLOCK_SIZE_SEED ); + + + } + + return 1; + + } + + + public static int SEED_CBC_Close( KISA_SEED_INFO pInfo, int[] out, int out_offset, int[] outLen ) { + int nPaddngLeng; + int i; + + outLen[0] = 0; + + if( null == out ) + return 0; + + if( KISA_ENC_DEC._KISA_ENCRYPT == pInfo.encrypt ) { + nPaddngLeng = BLOCK_SIZE_SEED - pInfo.buffer_length; + + for( i = pInfo.buffer_length; i 0 && nPaddngLeng <= BLOCK_SIZE_SEED ) + { + for(i=nPaddngLeng; i>0; i--) + { + Common.set_byte_for_int(out, out_offset-i, (byte)0x00, ENDIAN); + } + + outLen[0] = nPaddngLeng; + } + else + return 0; + + + } + return 1; + + + } + + + + + + + + public static byte[] SEED_CBC_Encrypt( byte[] pbszUserKey, byte[] pbszIV, byte[] message, int message_offset, int message_length ) { + KISA_SEED_INFO info = new KISA_SEED_INFO(); + int[] outbuf; + int[] data; + byte[] cdata; + int outlen; + int nRetOutLeng[] = new int[] { 0 }; + int nPaddingLeng[] = new int[] { 0 }; + + byte[] pbszPlainText = new byte[message_length]; + System.arraycopy(message, message_offset, pbszPlainText, 0, message_length); + int nPlainTextLen = pbszPlainText.length; + + + int nPlainTextPadding = BLOCK_SIZE_SEED - (nPlainTextLen % BLOCK_SIZE_SEED); + byte []newpbszPlainText = new byte[nPlainTextLen+nPlainTextPadding]; + Common.arraycopy(newpbszPlainText, pbszPlainText, nPlainTextLen); + + byte[] pbszCipherText = new byte[newpbszPlainText.length]; + + + SEED_CBC_init( info, KISA_ENC_DEC.KISA_ENCRYPT, pbszUserKey, pbszIV ); + + outlen = ((newpbszPlainText.length/BLOCK_SIZE_SEED) ) * BLOCK_SIZE_SEED_INT ; + outbuf = new int[outlen]; + data = chartoint32_for_SEED_CBC(newpbszPlainText, nPlainTextLen); + + SEED_CBC_Process( info, data, nPlainTextLen, outbuf, nRetOutLeng ); + SEED_CBC_Close( info, outbuf, (nRetOutLeng[0]/4), nPaddingLeng ); + + cdata = int32tochar_for_SEED_CBC(outbuf, nRetOutLeng[0]+nPaddingLeng[0]); + Common.arraycopy(pbszCipherText, cdata, nRetOutLeng[0]+nPaddingLeng[0]); + + data = null; + cdata = null; + outbuf = null; + + return pbszCipherText; + } + + + + + + + + + + + + public static byte[] SEED_CBC_Decrypt( byte[] pbszUserKey, byte[] pbszIV, byte[] message, int message_offset, int message_length ) { + KISA_SEED_INFO info = new KISA_SEED_INFO(); + int[] outbuf; + int[] data; + byte[] cdata; + int outlen; + int nRetOutLeng[] = new int[] { 0 }; + int nPaddingLeng[] = new int[] { 0 }; + + + + byte[] pbszCipherText = new byte[message_length]; + System.arraycopy(message, message_offset, pbszCipherText, 0, message_length); + int nCipherTextLen = pbszCipherText.length; + + if( (nCipherTextLen%BLOCK_SIZE_SEED) != 0 ) + { + byte result[] = null; + return result; + } + + + byte []newpbszCipherText = new byte[nCipherTextLen]; + Common.arraycopy(newpbszCipherText, pbszCipherText, nCipherTextLen); + + nCipherTextLen = newpbszCipherText.length; + + + SEED_CBC_init( info, KISA_ENC_DEC.KISA_DECRYPT, pbszUserKey, pbszIV ); + + outlen = ((nCipherTextLen/16)) *4 ; + outbuf = new int[outlen]; + data = chartoint32_for_SEED_CBC(newpbszCipherText, nCipherTextLen); + + SEED_CBC_Process( info, data, nCipherTextLen, outbuf, nRetOutLeng ); + + + if( SEED_CBC_Close( info, outbuf, (nRetOutLeng[0]), nPaddingLeng ) == 1 ) + { + cdata = int32tochar_for_SEED_CBC( outbuf, nRetOutLeng[0]-nPaddingLeng[0] ); + + byte[] pbszPlainText = new byte[nRetOutLeng[0]-nPaddingLeng[0]]; + + Common.arraycopy(pbszPlainText, cdata, nRetOutLeng[0]-nPaddingLeng[0]); + + int pdmessage_length = nRetOutLeng[0]-nPaddingLeng[0]; + byte[] result = new byte[pdmessage_length]; + System.arraycopy(pbszPlainText, 0, result, 0, pdmessage_length); + + data = null; + cdata = null; + outbuf = null; + + return result; + + } + else + { + byte result[] = null; + return result; + } + + + } + + + + + + + + + + + + public static final class KISA_ENC_DEC { + public static final int _KISA_DECRYPT = 0; + public static final int _KISA_ENCRYPT = 1; + + public int value; + + public KISA_ENC_DEC(int value ) { + this.value = value; + } + + public static final KISA_ENC_DEC KISA_ENCRYPT = new KISA_ENC_DEC(_KISA_ENCRYPT); + public static final KISA_ENC_DEC KISA_DECRYPT = new KISA_ENC_DEC(_KISA_DECRYPT); + + } + + public static final class KISA_SEED_KEY { + public int[] key_data = new int[32]; + + public void init() { + for(int i=0; i> shift_value; + return (byte)value; + } else { + int shift_value = (b_offset%4)*8; + int mask_value = 0x0ff << shift_value; + int value = (src[b_offset/4] & mask_value) >> shift_value; + return (byte)value; + } + + } + + public static byte[] get_bytes_for_ints(int[] src, int offset, int ENDIAN) { + int iLen = src.length-offset; + byte[] result = new byte[(iLen)*4]; + for(int i=0; i> 24) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+3] = (byte)((src) & 0x0ff); + } else { + dst[dst_offset] = (byte)((src) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+3] = (byte)((src >> 24) & 0x0ff); + } + + } + + public static void int_to_byte_unit_big_endian(byte[] dst, int dst_offset, int src) { + dst[dst_offset] = (byte)((src>> 24) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+3] = (byte)((src) & 0x0ff); + } + + public static int URShift(int x, int n) { + if(n == 0) + return x; + if(n >= 32) + return 0; + int v = x >> n; + int v_mask = ~(0x80000000 >> (n-1)); + return v & v_mask; + } + + public static final long INT_RANGE_MAX = (long)Math.pow(2, 32); + + public static long intToUnsigned(int x) { + if(x >= 0) + return x; + return x + INT_RANGE_MAX; + } + + //Padding : PKSC #7 + //��� : PADDING �� ����(����Ʈ����) + public static int Padding(byte[] pbData, byte[] padData, int length) { + int i; + int padvalue = 16 - (length%16); + Common.arraycopy(padData, pbData, length); + i = length; + do { + padData[i] = (byte)(padvalue); + i++; + }while((i%16) != 0); + return i; + } + + + //1��(128��Ʈ XOR) + public static void BLOCK_XOR_PROPOSAL(int[] OUT_VALUE, int out_value_offset, int[] IN_VALUE1, int in_value1_offset, int[] IN_VALUE2, int in_value2_offset) { + OUT_VALUE[out_value_offset+0] = (in_value1_offset= SHA256_DIGEST_BLOCKLEN) { + Common.arraycopy_offset(Info.szBuffer, 0, pszMessage, pszMessage_offset, SHA256_DIGEST_BLOCKLEN); + SHA256_Transform(Info.szBuffer, Info.uChainVar); + pszMessage_offset += SHA256_DIGEST_BLOCKLEN; + uDataLen -= SHA256_DIGEST_BLOCKLEN; + } + + Common.arraycopy_offset(Info.szBuffer, 0, pszMessage, pszMessage_offset, uDataLen); + } + + /** + @brief �޽��� �����̱�� ���� �����̱⸦ ������ �� ������ �޽��� ����� ������ �����Լ��� ȣ���ϴ� �Լ� + @param Info : SHA256_Init ȣ���Ͽ� �ʱ�ȭ�� ����ü(���������� ���ȴ�.) + @param pszDigest : ��ȣ�� + */ + public static void SHA256_Close( SHA256_INFO Info, byte[] pszDigest ) { + int i, Index; + + Index = Common.URShift(Info.uLowLength, 3) % SHA256_DIGEST_BLOCKLEN; + Info.szBuffer[Index++] = (byte)0x80; + + if (Index > SHA256_DIGEST_BLOCKLEN - 8) { + Common.arrayinit_offset(Info.szBuffer, Index, (byte)0, SHA256_DIGEST_BLOCKLEN - Index); + SHA256_Transform(Info.szBuffer, Info.uChainVar); + Common.arrayinit(Info.szBuffer, (byte)0, SHA256_DIGEST_BLOCKLEN - 8); + } + else { + Common.arrayinit_offset(Info.szBuffer, Index, (byte)0, SHA256_DIGEST_BLOCKLEN - Index - 8); + } + + if(ENDIAN == Common.LITTLE_ENDIAN) { + Info.uLowLength = ENDIAN_REVERSE_ULONG(Info.uLowLength); + Info.uHighLength = ENDIAN_REVERSE_ULONG(Info.uHighLength); + } + + Common.int_to_byte_unit(Info.szBuffer, ((int)(SHA256_DIGEST_BLOCKLEN / 4 - 2))*4, Info.uHighLength, ENDIAN); + Common.int_to_byte_unit(Info.szBuffer, ((int)(SHA256_DIGEST_BLOCKLEN / 4 - 1))*4, Info.uLowLength, ENDIAN); + + SHA256_Transform(Info.szBuffer, Info.uChainVar); + + for (i = 0; i < SHA256_DIGEST_VALUELEN; i += 4) + BIG_D2B((Info.uChainVar)[i / 4], pszDigest, i); + } + + /** + @brief ����� �Է� ���� �ѹ��� ó�� + @param pszMessage : ����� �Է� �� + @param pszDigest : ��ȣ�� + @remarks ���������� SHA256_Init, SHA256_Process, SHA256_Close�� ȣ���Ѵ�. + */ + public static void SHA256_Encrpyt( byte[] pszMessage, int uPlainTextLen, byte[] pszDigest ) { + SHA256_INFO info = new SHA256_INFO(); + SHA256_Init( info ); + SHA256_Process( info, pszMessage, uPlainTextLen ); + SHA256_Close( info, pszDigest ); + } + + + public static class SHA256_INFO { + public int uChainVar[] = new int[SHA256_DIGEST_VALUELEN / 4]; + public int uHighLength; + public int uLowLength; + public byte szBuffer[] = new byte[SHA256_DIGEST_BLOCKLEN]; + } + + public static class Common { + + public static final int BIG_ENDIAN = 0; + public static final int LITTLE_ENDIAN = 1; + + public static void arraycopy(byte[] dst, byte[] src, int length) { + for(int i=0; i> shift_value; + return (byte)value; + } else { + int shift_value = (b_offset%4)*8; + int mask_value = 0x0ff << shift_value; + int value = (src[b_offset/4] & mask_value) >> shift_value; + return (byte)value; + } + + } + + public static byte[] get_bytes_for_ints(int[] src, int offset, int ENDIAN) { + int iLen = src.length-offset; + byte[] result = new byte[(iLen)*4]; + for(int i=0; i> 24) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+3] = (byte)((src) & 0x0ff); + } else { + dst[dst_offset] = (byte)((src) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+3] = (byte)((src >> 24) & 0x0ff); + } + + } + + public static void int_to_byte_unit_big_endian(byte[] dst, int dst_offset, int src) { + dst[dst_offset] = (byte)((src>> 24) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+3] = (byte)((src) & 0x0ff); + } + + public static int URShift(int x, int n) { + if(n == 0) + return x; + if(n >= 32) + return 0; + int v = x >> n; + int v_mask = ~(0x80000000 >> (n-1)); + return v & v_mask; + } + + public static final long INT_RANGE_MAX = (long)Math.pow(2, 32); + + public static long intToUnsigned(int x) { + if(x >= 0) + return x; + return x + INT_RANGE_MAX; + } + } + + public static void main(String[] args) + { + byte pbData[] = {(byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, + (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F, + (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F, + (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, + (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F, + (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F}; + byte pbData1[] = {(byte)0x61}; + + byte pbCipher[] = new byte[32]; + byte pbPlain[] = new byte[16]; + +// System.out.print("[ Test SHA256 reference code ]"+"\n"); +// System.out.print("\n\n"); +// System.out.print("[ Test HASH mode ]"+"\n"); +// System.out.print("\n"); + + int Plaintext_length = 1; + + for(int k=0; k<30; k++) + { + +// System.out.print("Plaintext\t: "); +// for (int i=0; i recentPositionHistory; + + // 전체 히스토리 저장 + private List postionHistory; + + // 비정상 상황 식별 코드 + private boolean controlWarnCd; + private Instant regDt; + +} diff --git a/pav-server/src/main/java/com/palnet/comn/storage/config/StorageConfig.java b/pav-server/src/main/java/com/palnet/comn/storage/config/StorageConfig.java new file mode 100644 index 00000000..71ee696c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/storage/config/StorageConfig.java @@ -0,0 +1,31 @@ +package com.palnet.comn.storage.config; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class StorageConfig { + + @Value("${cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${cloud.aws.credentials.secretKey}") + private String accessSecret; + @Value("${cloud.aws.region.static}") + private String region; + + @Bean + public AmazonS3 s3Client() { + AWSCredentials credentials = new BasicAWSCredentials(accessKey, accessSecret); + return AmazonS3ClientBuilder.standard() + .withCredentials(new AWSStaticCredentialsProvider(credentials)) + .withRegion(region).build(); + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/comn/storage/controller/StorageController.java b/pav-server/src/main/java/com/palnet/comn/storage/controller/StorageController.java new file mode 100644 index 00000000..23934d5f --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/storage/controller/StorageController.java @@ -0,0 +1,46 @@ +package com.palnet.comn.storage.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import com.palnet.comn.storage.service.StorageService; + +@RestController +@RequestMapping("/api/file") +public class StorageController { + + @Autowired + private StorageService service; + + @PostMapping("/upload") + public ResponseEntity uploadFile(@RequestParam(value = "file") MultipartFile file) { + return new ResponseEntity<>(service.uploadFile(file), HttpStatus.OK); + } + + @GetMapping("/download/{fileName}") + public ResponseEntity downloadFile(@PathVariable String fileName) { + byte[] data = service.downloadFile(fileName); + ByteArrayResource resource = new ByteArrayResource(data); + return ResponseEntity + .ok() + .contentLength(data.length) + .header("Content-type", "application/octet-stream") + .header("Content-disposition", "attachment; filename=\"" + fileName + "\"") + .body(resource); + } + + @DeleteMapping("/delete/{fileName}") + public ResponseEntity deleteFile(@PathVariable String fileName) { + return new ResponseEntity<>(service.deleteFile(fileName), HttpStatus.OK); + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/comn/storage/service/StorageService.java b/pav-server/src/main/java/com/palnet/comn/storage/service/StorageService.java new file mode 100644 index 00000000..a364365d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/storage/service/StorageService.java @@ -0,0 +1,65 @@ +package com.palnet.comn.storage.service; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.amazonaws.services.s3.model.S3Object; +import com.amazonaws.services.s3.model.S3ObjectInputStream; +import com.amazonaws.util.IOUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +@Service +@Slf4j +public class StorageService { + + @Value("${cloud.aws.s3.bucket}") + private String bucketName; + + @Autowired + private AmazonS3 s3Client; + + public String uploadFile(MultipartFile file) { + File fileObj = convertMultiPartFileToFile(file); + String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename(); + s3Client.putObject(new PutObjectRequest(bucketName, fileName, fileObj)); + fileObj.delete(); + return fileName; + } + + + public byte[] downloadFile(String fileName) { + S3Object s3Object = s3Client.getObject(bucketName, fileName); + S3ObjectInputStream inputStream = s3Object.getObjectContent(); + try { + byte[] content = IOUtils.toByteArray(inputStream); + return content; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + public String deleteFile(String fileName) { + s3Client.deleteObject(bucketName, fileName); + return fileName + " removed ..."; + } + + + private File convertMultiPartFileToFile(MultipartFile file) { + File convertedFile = new File(file.getOriginalFilename()); + try (FileOutputStream fos = new FileOutputStream(convertedFile)) { + fos.write(file.getBytes()); + } catch (IOException e) { + log.error("Error converting multipartFile to file", e); + } + return convertedFile; + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/comn/utils/AreaUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/AreaUtils.java new file mode 100644 index 00000000..b7189c08 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/AreaUtils.java @@ -0,0 +1,335 @@ +package com.palnet.comn.utils; + +import com.palnet.biz.api.bas.flight.model.BasFlightPlanAreaCoordModel; +import lombok.extern.slf4j.Slf4j; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.locationtech.jts.geom.*; +import org.locationtech.jts.geom.impl.CoordinateArraySequence; +import org.locationtech.jts.operation.buffer.BufferOp; +import org.locationtech.jts.operation.buffer.BufferParameters; +import org.locationtech.jts.util.GeometricShapeFactory; +import org.locationtech.proj4j.BasicCoordinateTransform; +import org.locationtech.proj4j.CRSFactory; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.locationtech.proj4j.ProjCoordinate; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@Component +@Slf4j +public class AreaUtils { + + private List polygons = new ArrayList<>(); + private List points = new ArrayList<>(); + + private GeometryFactory geometryFactory = new GeometryFactory(); + + public AreaUtils() throws Exception { + this.init(); + } + + /** + * TODO 좌표계 변환 + * + * @param coordList + * @return + */ + @Cacheable(value = "coordTransform") + public List transform(List coordList, String from, String to) { + CRSFactory factory = new CRSFactory(); + + CoordinateReferenceSystem srcCRS = factory.createFromName(from); + CoordinateReferenceSystem tgtCRS = factory.createFromName(to); + + BasicCoordinateTransform transform = new BasicCoordinateTransform(srcCRS, tgtCRS); + + List result = new ArrayList<>(); + + for(Coordinate coord : coordList) { + ProjCoordinate projCoordinate = new ProjCoordinate(coord.getX(), coord.getY()); + ProjCoordinate projTrasform = transform.transform(projCoordinate, new ProjCoordinate()); + + Coordinate target = new Coordinate(projTrasform.x, projTrasform.y); + + result.add(target); + } + + return result; + } + + /** + * TODO 비행 구역 생성시 장애물 영역 포함 체크 + * + * @param targetCoordList - 비행구역 좌표 리스트 + * @return boolean - true(비정상), false(정상) + */ + public boolean overlaps(List targetCoordList) { + boolean result = false; + targetCoordList.add(targetCoordList.get(0)); + Polygon targetPolygon = geometryFactory.createPolygon(targetCoordList.toArray(new Coordinate[] {})); + + /* 공역 데이터 */ + if(polygons.size() > 0) { + for(Polygon polygon : polygons) { + Geometry overlabsGeometry = geometryFactory.createGeometry(polygon); + Geometry targetGeometry = geometryFactory.createGeometry(targetPolygon); + + boolean over = targetPolygon.overlaps(polygon); + + if(over) { + result = true; + break; + } + } + } + + return result; + } + + /** + * TODO 구역 포함 여부 + * + * @param targetCoordList - 생성 구역 + * @param effectiveCoordList - 유효한 비행 구역 + * @return boolean - true(비정상), false(정상) + */ + public boolean overlaps(List targetCoordList, List effectiveCoordList) { + targetCoordList.add(targetCoordList.get(0)); + Polygon targetPolygon = geometryFactory.createPolygon(targetCoordList.toArray(new Coordinate[] {})); + + effectiveCoordList.add(effectiveCoordList.get(0)); + Polygon effectivePolygon = geometryFactory.createPolygon(effectiveCoordList.toArray(new Coordinate[] {})); + + return targetPolygon.overlaps(effectivePolygon); + } + + /** + * TODO 드론 관제시 정상 비행 체크 (공역) + * + * @param targetCoordinate - 드론 좌표 정보 + * @return boolean - true(비정상), false(정상) + */ + public boolean contains(Coordinate targetCoordinate) { + boolean result = true; + + Point target = geometryFactory.createPoint(targetCoordinate); + + for(Polygon polygon : polygons) { + boolean contains = polygon.contains(target); + + if(contains) { + result = true; + break; + } + } + + return result; + } + + /** + * TODO 드론 관제시 정상 비행 체크 (비행 구역) + * + * @param areaCoordList - 비행 구역 좌표 리스트 + * @param targetCoordinate - 드론 좌표 정보 + * @return boolean - true(비정상), false(정상) + */ + public boolean contains(List areaCoordList, Coordinate targetCoordinate) { + boolean result = true; + areaCoordList.add(areaCoordList.get(0)); + if(targetCoordinate != null) { + Polygon plan = geometryFactory.createPolygon(areaCoordList.toArray(new Coordinate[]{})); // 비행 구역 + Point target = geometryFactory.createPoint(targetCoordinate); + + result = plan.contains(target); +// target.contains(plan); + } + + return result; + } + + /** + * TODO 비행 구역 - Buffer 영역 생성 + * + * @param coordList - 비행 구역 기초 좌표 리스트 + * @param bufferZone - 반경 + * + */ + public List buffer(List coordList, double bufferZone) { + List bufferList = new ArrayList<>(); + + LineString line = geometryFactory.createLineString(coordList.toArray(new Coordinate[] {})); + Geometry geometry = geometryFactory.createGeometry(line); + + // buffer + int nSegments = 10; + int cap = BufferParameters.CAP_SQUARE; + int join = BufferParameters.JOIN_ROUND; + + BufferParameters bufferParam = new BufferParameters(nSegments, cap, join, join); + BufferOp ops = new BufferOp(geometry, bufferParam); + +// Geometry bufTrans = ops.getResultGeometry((bufferZone/177763.63662580872)*2); + Geometry bufTrans = ops.getResultGeometry(bufferZone); + + Coordinate[] coords = bufTrans.getCoordinates(); + + bufferList.addAll(Arrays.asList(coords)); + + return bufferList; + } + + /** + * TODO 타원 생성 + * + * @param CircleCoord + * @param BufferZone + * @return + */ + public List createCircle(Coordinate CircleCoord, double BufferZone) { + GeometricShapeFactory shapeFactory = new GeometricShapeFactory(); + + double lng = CircleCoord.x; + double lat = CircleCoord.y; + double diameterInMeters = BufferZone; + + shapeFactory.setCentre(new Coordinate(lng , lat)); + shapeFactory.setHeight((diameterInMeters * 2) / 111320d); + shapeFactory.setWidth((diameterInMeters * 2) / (40075000 * Math.cos(Math.toRadians(lat)) / 360)); + shapeFactory.setNumPoints(64); + + final Polygon circle = shapeFactory.createCircle(); + circle.setSRID(4326); + + Geometry geometry = geometryFactory.createGeometry(circle); + Coordinate[] coords = geometry.getCoordinates(); + List coordList = new ArrayList<>(); + coordList.addAll(Arrays.asList(coords)); + + return coordList; + } + + /** + * TODO service model -> jts model mapping + * + * @param coordList + * @return + */ + public List convertCoordinates(List coordList) { + List coordinates = new ArrayList<>(); + + for(BasFlightPlanAreaCoordModel coord : coordList) { + Coordinate coordinate = new Coordinate(coord.getLon(), coord.getLat()); + + coordinates.add(coordinate); + } + + return coordinates; + } + + /** + * TODO jts model -> service model mapiing + * + * @param bufferList + * @return + */ + public List convertModel(List bufferList) { + List bufferCoordList = new ArrayList<>(); + + for(Coordinate buffer : bufferList) { + BasFlightPlanAreaCoordModel bufferCoord = new BasFlightPlanAreaCoordModel(); + + bufferCoord.setLat(buffer.getY()); + bufferCoord.setLon(buffer.getX()); + + bufferCoordList.add(bufferCoord); + } + + return bufferCoordList; + } + + // TODO 공역 데이터 생성 + public void init() throws Exception { + // 1. file read + ClassPathResource resource = new ClassPathResource("air/airgeo.json"); + InputStream jsonInputStream = resource.getInputStream(); + InputStreamReader inputStreamReader = new InputStreamReader(jsonInputStream, "UTF-8"); + BufferedReader reader = new BufferedReader(inputStreamReader); + + // 2. json parsing + JSONParser jsonParser = new JSONParser(); + JSONObject jsonObject = (JSONObject) jsonParser.parse(reader); + + List features = (List) jsonObject.get("features"); + + for(int i=0; i coordinates = (List) geometry.get("coordinates"); + String type = (String) geometry.get("type"); + + if("Polygon".equals(type)) { + for(JSONArray coordList : coordinates) { + List polygonPaths = new ArrayList<>(); + + for(Object coord : coordList) { + Object y = ((JSONArray) coord).get(0); + Object x = ((JSONArray) coord).get(1); + + Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y); + Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x); + + Coordinate areaCoord = new Coordinate(lon, lat); + + polygonPaths.add(areaCoord); + } + + Polygon polygon = geometryFactory.createPolygon(polygonPaths.toArray(new Coordinate[] {})); + + polygons.add(polygon); + } + } + + if("LineString".equals(type)) { + List lineStringPaths = new ArrayList<>(); + for(JSONArray coordList : coordinates) { + + Object y = coordList.get(0); + Object x = coordList.get(1); + + Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y); + Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x); + + Coordinate areaCoord = new Coordinate(lon, lat); + + lineStringPaths.add(areaCoord); + } + + Polygon polygon = geometryFactory.createPolygon(lineStringPaths.toArray(new Coordinate[] {})); + + polygons.add(polygon); + } + + if("Point".equals(type)) { + Object y = coordinates.get(0); + Object x = coordinates.get(1); + + Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y); + Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x); + + Coordinate areaCoord = new Coordinate(lon, lat); + + Point point = geometryFactory.createPoint(areaCoord); + points.add(point); + } + } + } +} diff --git a/pav-server/src/main/java/com/palnet/comn/utils/DateUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/DateUtils.java new file mode 100644 index 00000000..4eaa6608 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/DateUtils.java @@ -0,0 +1,159 @@ +package com.palnet.comn.utils; + +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DateUtils { + + public static String getCurrentTime(){ + return new SimpleDateFormat("yyyyMMddHHmmss").format(System.currentTimeMillis()); + } + + public static String stringToFormat(String str) { + Date date = stringToDatetime(str); + + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date); + } + + + public static Date stringToDatetime(String date) { + + SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + Date result = null; + try { + if(date.length() == 14) { + result = transFormat.parse(date); + } + }catch(Exception e) { + e.printStackTrace(); + } + + return result; + } + + public static Date stringToDate(String date) { + SimpleDateFormat transFormat = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat transFormat2 = new SimpleDateFormat("yyyyMMdd"); + Date result = null; + try { + if(date.length() == 10) { + result = transFormat.parse(date); + }else if(date.length() == 8) { + result = transFormat2.parse(date); + } + }catch(Exception e) { + e.printStackTrace(); + } + + return result; + } + + public static LocalDateTime stringToLocalDateTime(String date) { + + DateTimeFormatter transFormat = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + LocalDateTime localDateTime = LocalDateTime.parse(date , transFormat); + + return localDateTime; + + } + + + + public static LocalDateTime stringToLocalDate(String date) { + DateTimeFormatter transFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + DateTimeFormatter DATEFORMATTER = new DateTimeFormatterBuilder().append(transFormat) + .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) + .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) + .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) + .toFormatter(); + + + LocalDateTime localDateTime = LocalDateTime.parse(date , DATEFORMATTER); + + return localDateTime; + } + + + public static Date nowDate() { + return new Date(System.currentTimeMillis()); + } + + public static long diffSecond(Date firstDate , Date secondDate) { + + long diffDate = secondDate.getTime() - firstDate.getTime(); + long diffTime = diffDate / (1000); + + return diffTime; + + } + + public static long diffMinute(Date firstDate , Date secondDate) { + + long diffDate = secondDate.getTime() - firstDate.getTime(); + long diffTime = diffDate / (1000 * 60); + + return diffTime; + + } + + + +// public static void main(String[] args) { +// +// Date firstDate = stringToDate("20210630142014"); +// +// Date secondDate = stringToDate("20210630142914"); +// +// LocalDateTime dateTime = stringToLocalDate("2021-07-20"); +// +// System.out.println(">>>>" + dateTime); +// +// +// System.out.println("두 날짜의 차이 분: "+diffMinute(firstDate , secondDate)); +// +// System.out.println(">>>" + stringToFormat("20210630142014")); +// +// +// +// +// +//// List> list = new ArrayList>(); +//// +//// +//// for( double i= 0 ; i < 1000 ; i ++) { +//// Map position = new HashMap(); +//// position.put("lat", 11111.0); +//// position.put("lng", 11111.0); +//// position.put("date", i); +//// list.add(position); +//// } +//// +//// int limitSize = 1000; +//// if(list.size() < 1000) { +//// limitSize = list.size(); +//// } +//// +//// List> lastThreeThings = list.subList(list.size() - limitSize, list.size()); +//// +//// //뒤집기 +//// Collections.reverse(lastThreeThings); +//// +//// for(Map data : lastThreeThings) { +//// +//// +//// System.out.println(data); +//// } +// +// } +} diff --git a/pav-server/src/main/java/com/palnet/comn/utils/EncryptUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/EncryptUtils.java new file mode 100644 index 00000000..c73a8867 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/EncryptUtils.java @@ -0,0 +1,151 @@ +package com.palnet.comn.utils; + +import java.io.UnsupportedEncodingException; +import java.util.Base64; +import java.util.Base64.Decoder; +import java.util.Base64.Encoder; + +import com.palnet.comn.encrptn.kisa.KISA_SEED_CBC; +import com.palnet.comn.encrptn.kisa.KISA_SHA256; + +public class EncryptUtils { + private static String CHARSET = "utf-8"; + private static final String PBUserKey = "palnet!01234567890"; //16Byte로 설정 + private static final String DEFAULT_IV = "1234567890123456"; //16Byte로 설정 + + /* + public static byte pbUserKey[] = { (byte) 0x2c, (byte) 0x11, (byte) 0x19, (byte) 0x1d, (byte) 0x1f, (byte) 0x16, (byte) 0x12, + (byte) 0x12, (byte) 0x11, (byte) 0x19, (byte) 0x1d, (byte) 0x1f, (byte) 0x10, (byte) 0x14, (byte) 0x1b, + (byte) 0x16 }; + */ + private static byte pbUserKey[] = PBUserKey.getBytes(); + + /* + public static byte bszIV[] = { (byte) 0x27, (byte) 0x28, (byte) 0x27, (byte) 0x6d, (byte) 0x2d, (byte) 0xd5, (byte) 0x4e, + (byte) 0x29, (byte) 0x2c, (byte) 0x56, (byte) 0xf4, (byte) 0x2a, (byte) 0x65, (byte) 0x2a, (byte) 0xae, + (byte) 0x08 }; + */ + private static byte bszIV[] = DEFAULT_IV.getBytes(); + + + /*************************************** + * Main 함수 + * @param args + **************************************/ + public static void main(String[] args) { + + try { + + String plainText = "강찬구님 안녕하세요!!!!@#!@"; + + /* (1) 시작 시간 측정 */ + long startTimeLong = getCurrentTimeLong(); + /*test*/// System.out.println( "startTimeLong : " + startTimeLong ); + + /************************************* + * 암호화 + *************************************/ + String encryptData = encrypt(plainText); + // System.out.println("encrypt:" + encryptData); + + /************************************* + * 복호화 + *************************************/ + plainText = decrypt(encryptData); + // System.out.println("decrypt:" + plainText); + + + String sha256 = sha256Encrypt(plainText); + + // System.out.println("sha256:" + sha256); + + + + /* (2)종료 시간 측정 */ + long endTimeLong = getCurrentTimeLong(); + /*test*/// System.out.println( "endTimeLong : " + endTimeLong ); + + /* (3)시스템 사용기간 계산 + * - 시간 차이는 초(sec)단위로 계산되며 long 타입 변수에 저장된다. + */ + //long useTime = Math.abs( endTimeLong - startTimeLong )/1000; //절대값을 반환 - sec + //*test*/// System.out.println( " useTime : " + useTime + "(Sec)"); + long useTime = Math.abs( endTimeLong - startTimeLong ); //절대값을 반환 - 밀리세컨 + /*test*/// System.out.println( " useTime : " + useTime + "(MM)"); + + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public static String sha256Encrypt(String str) { + + byte[] bytes = str.getBytes(); + byte[] pszDigest = new byte[32]; + KISA_SHA256.SHA256_Encrpyt(bytes, bytes.length, pszDigest); + StringBuffer encrypted = new StringBuffer(); + for (int i = 0; i < 32; i++) { + encrypted.append(String.format("%02x", pszDigest[i])); + } + return encrypted.toString(); + } + + public static String encrypt(String str) { + + byte[] enc = null; + String result = ""; + try { + + //암호화 함수 호출 + enc = KISA_SEED_CBC.SEED_CBC_Encrypt(pbUserKey, bszIV, str.getBytes(CHARSET), 0, str.getBytes(CHARSET).length); + //enc = KISA_SEED_ECB.SEED_ECB_Encrypt(pbUserKey, str.getBytes(CHARSET), 0, str.getBytes(CHARSET).length); + Encoder encoder = Base64.getEncoder(); + byte[] encArray = encoder.encode(enc); + + result = new String(encArray, "utf-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + return result; + + } + + public static String decrypt(String param) { + byte[] str = param.getBytes(); + + Decoder decoder = Base64.getDecoder(); + byte[] enc = decoder.decode(str); + +// byte[] enc = Base64.decode(str); + + String result = ""; + byte[] dec = null; + + try { + //복호화 함수 호출 + dec = KISA_SEED_CBC.SEED_CBC_Decrypt(pbUserKey, bszIV, enc, 0, enc.length); + //dec = KISA_SEED_ECB.SEED_ECB_Decrypt(pbUserKey, enc, 0, enc.length); + result = new String(dec, CHARSET); + + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + return result; + } + + + /** + * - 용도 : 현재 시간을 long 타입으로 변환하며 시간 차를 구하는 함수로 사용 + * - Return Type: long + * - Argument Type : none + */ + public static long getCurrentTimeLong() { + long time; + java.util.Calendar cal = java.util.Calendar.getInstance(); + time = cal.getTimeInMillis(); + return time; + } +} diff --git a/pav-server/src/main/java/com/palnet/comn/utils/FlightUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/FlightUtils.java new file mode 100644 index 00000000..3ac42ec1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/FlightUtils.java @@ -0,0 +1,137 @@ +package com.palnet.comn.utils; + +import java.util.List; + +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.CoordinateSequence; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.LineString; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.Polygon; +import org.locationtech.jts.geom.impl.CoordinateArraySequence; +import org.locationtech.jts.operation.buffer.BufferOp; +import org.locationtech.jts.operation.buffer.BufferParameters; +import org.locationtech.jts.util.GeometricShapeFactory; +import org.locationtech.proj4j.BasicCoordinateTransform; +import org.locationtech.proj4j.CRSFactory; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.locationtech.proj4j.ProjCoordinate; + +public class FlightUtils { + //기본좌표를 받아 버퍼좌표를 생성하는 유틸 + public static Coordinate[] createBuffer(Coordinate[] lineCoords, Integer bufval) { + GeometryFactory geometryFactory = new GeometryFactory(); + LineString line = new GeometryFactory().createLineString(lineCoords); + Geometry geometry = geometryFactory.createGeometry(line); + int nSegments = 10; + int cap = BufferParameters.CAP_ROUND; + int join = BufferParameters.JOIN_ROUND; + BufferParameters bufferParam = new BufferParameters(nSegments, cap, join, join); + BufferOp ops = new BufferOp(geometry, bufferParam); + Geometry bufTrans = ops.getResultGeometry((bufval/177763.63662580872)*2); + + Geometry bufTransKaKao = ops.getResultGeometry(bufval); //KaKao 좌표로 버퍼라인 만들시 이 변수 사용 + + Coordinate[] bufferCoords = bufTrans.getCoordinates(); + + return bufferCoords; + } + //기본좌표와 반지름을 받아 원을 생성하는 유틸 + public static Coordinate[] createCircle(Coordinate circleCoords) { + GeometricShapeFactory shapeFactory = new GeometricShapeFactory(); + GeometryFactory geometryFactory = new GeometryFactory(); + double lng = circleCoords.x; + double lat = circleCoords.y; + double diameterInMeters = circleCoords.z; + shapeFactory.setCentre(new Coordinate(lng , lat)); + shapeFactory.setHeight((diameterInMeters * 2) / 111320d); + shapeFactory.setWidth((diameterInMeters * 2) / (40075000 * Math.cos(Math.toRadians(lat)) / 360)); + shapeFactory.setNumPoints(64); + final Polygon circle = shapeFactory.createEllipse(); + circle.setSRID(4326); + Geometry geometry = geometryFactory.createGeometry(circle); + Coordinate[] coords = geometry.getCoordinates(); + return coords; + + } + //생성된 버퍼좌표에서 특정 좌표가 버퍼좌표 안에 속해있는지, 혹은 아닌지를 판단하는 유틸 + public static boolean contains(Coordinate[] bufferCoords, Coordinate[] containsPoint) { + + GeometryFactory geometryFactory = new GeometryFactory(); + + CoordinateSequence coordinateSequence = new CoordinateArraySequence(containsPoint); + + LineString line = new GeometryFactory().createLineString(bufferCoords); + + Point point = new Point(coordinateSequence, geometryFactory); + + boolean contains = line.contains(point); + + return contains; + } + //생성된 버퍼좌표와 공역의 좌표가 충돌하는지를 판단하는 유틸 + public static boolean overlaps(Coordinate[] bufferCoords,Coordinate[] overlapCoords) { + + GeometryFactory geometryFactory = new GeometryFactory(); + + Polygon bufferPoly = geometryFactory.createPolygon(bufferCoords); + + Polygon overPoly = geometryFactory.createPolygon(overlapCoords); + + Geometry geoBuffer = geometryFactory.createGeometry(bufferPoly); + + Geometry geoOver = geometryFactory.createGeometry(overPoly); + + boolean overlaps = geoBuffer.overlaps(geoOver); + + return overlaps; + } + //기본 좌표(WGS84 좌표계)를 받아 kakao 좌표계로 변환해주는 유틸. 이 과정을 거쳐서 버퍼를 생성해야 버퍼라인이 균일하게 생성된다. + public static ProjCoordinate defaultTrans(Coordinate coord) { + + CRSFactory factory = new CRSFactory(); + + CoordinateReferenceSystem wgs84 = factory.createFromName("EPSG:4326"); + + CoordinateReferenceSystem kakao = factory.createFromName("EPSG:5181"); + + BasicCoordinateTransform defaultCoord = new BasicCoordinateTransform(wgs84, kakao); + + ProjCoordinate beforeCoord = new ProjCoordinate(); + + ProjCoordinate afterCoord = new ProjCoordinate(); + + beforeCoord.x = coord.getX(); + + beforeCoord.y = coord.getY(); + + ProjCoordinate result = defaultCoord.transform(beforeCoord, afterCoord); + + return result; + } + //kakao 좌표계로 변환되어 생성된 버퍼좌표를 WGS84 좌표계로 변환해준다. 이 유틸을 이용해 버퍼라인을 생성하면 균일한 모양의 도형이 나온다. + public static ProjCoordinate bufferTrans(Coordinate bufferCoords) { + + CRSFactory factory = new CRSFactory(); + + CoordinateReferenceSystem wgs84 = factory.createFromName("EPSG:4326"); + + CoordinateReferenceSystem kakao = factory.createFromName("EPSG:5181"); + + BasicCoordinateTransform defaultCoord = new BasicCoordinateTransform(kakao, wgs84); + + ProjCoordinate beforeCoord = new ProjCoordinate(); + + ProjCoordinate afterCoord = new ProjCoordinate(); + + beforeCoord.x = bufferCoords.getX(); + + beforeCoord.y = bufferCoords.getY(); + + ProjCoordinate result = defaultCoord.transform(beforeCoord, afterCoord); + + return result; + } + +} diff --git a/pav-server/src/main/java/com/palnet/comn/utils/HttpUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/HttpUtils.java new file mode 100644 index 00000000..e7e1a45c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/HttpUtils.java @@ -0,0 +1,271 @@ +package com.palnet.comn.utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.UnknownHostException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class HttpUtils { + + public static String getAthnNo(int i) { + String athnNo = RandomStringUtils.randomNumeric(i); + return athnNo; + } + + + public static void clientFileDownload(String filePath, HttpServletResponse response) { + File file = new File(filePath); + + if (file.exists()) { + + OutputStream outStream = null; + InputStream inputStream = null; + + try { + inputStream = new FileInputStream(file); + response.reset() ; + response.setContentType("image/jpeg"); + response.setHeader ("Content-Disposition", "attachment; filename=\"" + + new String(file.getName().getBytes(),"ISO8859_1")+"\"" ); + response.setHeader ("Content-Length", ""+file.length() ); + outStream = response.getOutputStream(); + byte b[] = new byte[(int)file.length()]; + int leng = 0; + + while( (leng = inputStream.read(b)) > 0 ){ + outStream.write(b,0,leng); + } + + } catch (Exception e) { + log.error("IGNORE : {}", e); + } finally { + try { + inputStream.close(); + outStream.flush(); + outStream.close(); + } catch (IOException e) { + log.error("IGNORE : {}", e); + } + } + } + } + + public static boolean checkServerAlive(String url,String port) { + boolean isAlive = false; + HttpURLConnection httpConn = null; + try { + URL hostUrl = new URL("http://"+url+":"+port+"/"); + httpConn = (HttpURLConnection) hostUrl.openConnection(); + + if (httpConn != null) { + httpConn.setInstanceFollowRedirects(false); + httpConn.setRequestMethod("HEAD"); + httpConn.connect(); + isAlive = true; + } + + } catch (java.net.ConnectException e) { + log.error("IGNORE : {}", e); + } catch (MalformedURLException e) { + log.error("IGNORE : {}", e); + } catch (IOException e) { + log.error("IGNORE : {}", e); + } finally { + if (httpConn != null) { + httpConn.disconnect(); + } + } + return isAlive; + } + + public static boolean checkPingAlive(String ip) { + boolean isAlive = false; + try { + InetAddress inet = InetAddress.getByName(ip); + + if (inet.isReachable(2000)) { + isAlive = true; + } + + } catch (UnknownHostException e) { + log.error("IGNORE : {}", e); + } catch (IOException e) { + log.error("IGNORE : {}", e); + } + return isAlive; + } + + public static boolean checkUrlAlive(String url,String port, String fullPath) { + boolean isAlive = false; + URLConnection urlConn = null; + URL hostUrl; + String fullUrl = ""; + + if (StringUtils.isEmpty(fullPath)) { + StringBuffer sb = new StringBuffer("http://"); + + if (StringUtils.isEmpty(port)) { + sb = sb.append(url); + fullUrl = sb.toString(); + } else { + sb = sb.append(url).append(":").append(port); + fullUrl = sb.toString(); + } + } else { + fullUrl = fullPath; + } + + try { + hostUrl = new URL(fullUrl); + urlConn = hostUrl.openConnection(); + urlConn.setConnectTimeout(5000); + urlConn.connect(); + isAlive = true; + } catch (MalformedURLException e) { + log.error("IGNORE : {}", e); + } catch (IOException e) { + log.error("IGNORE : {}", e); + } + + return isAlive; + } + + public static void httpPost(String url, String contentType, String body) { + PostMethod methodPost = new PostMethod(url); + RequestEntity entity = null; + + try { + entity = new StringRequestEntity(body, contentType, "UTF-8"); + } catch (UnsupportedEncodingException e) { + log.error("", e); + } + + methodPost.setRequestEntity(entity); + + executeMethod(methodPost); + } + + private static void executeMethod(HttpMethod method) { + HttpClient client = new HttpClient(); + + BufferedReader br = null; + + try { + int respCd = client.executeMethod(method); + + if (respCd == HttpStatus.SC_OK) { + br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream())); + String readLine; + while (((readLine = br.readLine()) != null)) { + log.info(readLine); + } + } else { + log.error("respCd: {}", respCd); + } + } catch (Exception e) { + log.error("", e); + } finally { + method.releaseConnection(); + + if (br != null) { + try { + br.close(); + } catch (Exception e) { + log.error("IGNORE : {}", e); + } + } + } + } + + public static String getClientIpAddr(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + return ip; + } + + + public static HttpServletRequest getCurrentRequest() { + ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + return sra.getRequest(); + } + + /** + * 클라이언트 IP 를 가져온다 + * @return 클라이언트 IP + */ + public static String getRequestIp() { + HttpServletRequest req = getCurrentRequest(); + + String[] HEADER_CLIENT_IP = { "NS-CLIENT-IP", "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"}; + for (String name : HEADER_CLIENT_IP) { + String clientIp = req.getHeader(name); + if(!StringUtils.isEmpty(clientIp) && !"unknown".equalsIgnoreCase(clientIp)) { + log.debug("{}={}", name, clientIp); + return clientIp; + } + } + + return req.getRemoteAddr(); + } + + public static String getIpFirst(String ips) { + ips = ips.replaceAll(" ", ""); + String[] ipArr = ips.split(","); + if(ipArr.length == 0) { + return null; + } + return ipArr[0]; + } + + public static String getRequestIpFirst() { + String ip = getRequestIp(); + return getIpFirst(ip); + } +} diff --git a/pav-server/src/main/java/com/palnet/comn/utils/JsonUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/JsonUtils.java new file mode 100644 index 00000000..69ec7666 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/JsonUtils.java @@ -0,0 +1,81 @@ +package com.palnet.comn.utils; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class JsonUtils { + + public static ObjectMapper getObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper; + } + + public static String toJson(Object object) { + String json = null; + + try { + json = getObjectMapper().writeValueAsString(object); + } catch (JsonProcessingException e) { + log.error("", e); + } + + return json; + } + + public static T fromJson(String val, Class clazz){ + T object = null; + + try { + object = getObjectMapper().readValue(val, clazz); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T fromJson(byte[] bytes, Class clazz){ + T object = null; + + try { + object = getObjectMapper().readValue(bytes, clazz); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T fromJson(String val, TypeReference type){ + T object = null; + + try { + object = getObjectMapper().readValue(val, type); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T bytesToJson(byte[] bytes, TypeReference type){ + T object = null; + + try { + object = getObjectMapper().readValue(bytes, type); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + +} diff --git a/pav-server/src/main/java/com/palnet/comn/utils/LocationUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/LocationUtils.java new file mode 100644 index 00000000..5e5e9e89 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/LocationUtils.java @@ -0,0 +1,68 @@ +package com.palnet.comn.utils; + +public class LocationUtils { + + + + /** + * 두 지점간의 거리 계산 + * + * @param lat1 지점 1 위도 + * @param lon1 지점 1 경도 + * @param lat2 지점 2 위도 + * @param lon2 지점 2 경도 + * @param unit 거리 표출단위 + * @return + */ + private static double distance(double lat1, double lon1, double lat2, double lon2, String unit) { + + double theta = lon1 - lon2; + double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta)); + + dist = Math.acos(dist); + dist = rad2deg(dist); + dist = dist * 60 * 1.1515; + + if (unit == "kilometer") { + dist = dist * 1.609344; + } else if(unit == "meter"){ + dist = dist * 1609.344; + } + + return (dist); + } + + + // This function converts decimal degrees to radians + private static double deg2rad(double deg) { + return (deg * Math.PI / 180.0); + } + + // This function converts radians to decimal degrees + private static double rad2deg(double rad) { + return (rad * 180 / Math.PI); + } + + + public static void main(String[] args) { + + // 마일(Mile) 단위 + double distanceMile = + distance(37.504198, 127.047967, 37.501025, 127.037701, ""); + + // 미터(Meter) 단위 + double distanceMeter = + distance(37.504198, 127.047967, 37.501025, 127.037701, "meter"); + + // 킬로미터(Kilo Meter) 단위 + double distanceKiloMeter = + distance(37.504198, 127.047967, 37.501025, 127.037701, "kilometer"); + + // System.out.println(distanceMile) ; + // System.out.println(distanceMeter) ; + // System.out.println(distanceKiloMeter) ; + + + } + +} diff --git a/pav-server/src/main/java/com/palnet/comn/utils/NumberUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/NumberUtils.java new file mode 100644 index 00000000..3c35d9c5 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/NumberUtils.java @@ -0,0 +1,16 @@ +package com.palnet.comn.utils; + + +public class NumberUtils { + public static Double formatZero2(Double object) { + + Double result = 0.0; + if(object != null) { + result = Double.parseDouble(String.format("%.2f", object)); + + } + + return result; + + } +} diff --git a/pav-server/src/main/java/com/palnet/comn/utils/StringUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/StringUtils.java new file mode 100644 index 00000000..4020b725 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/comn/utils/StringUtils.java @@ -0,0 +1,10 @@ +package com.palnet.comn.utils; + + +public class StringUtils { + public static String toStirng(Object object) { + + return object.toString().trim(); + + } +} diff --git a/pav-server/src/main/java/com/palnet/server/SocketServer.java b/pav-server/src/main/java/com/palnet/server/SocketServer.java new file mode 100644 index 00000000..993924d5 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/SocketServer.java @@ -0,0 +1,117 @@ +package com.palnet.server; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import com.palnet.server.initializer.SocketInitializer; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.AdaptiveRecvByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; + +@Component +public class SocketServer { + private Logger logger = LoggerFactory.getLogger(getClass()); + +// @Value("${netty.socket.port}") +// private int port; +// +// @Value("${netty.socket.thread.boss}") +// private int threadBoss; +// +// @Value("${netty.socket.thread.worker}") +// private int threadWorker; + + + private Channel ch; + + private EventLoopGroup bossGroup ; + private EventLoopGroup workerGroup ; + private ServerBootstrap b = new ServerBootstrap(); + +// @Autowired +// private AdsbClient client; +// + + @PostConstruct + public void postConstruct(){ +// start(); + } + + + @PreDestroy + public void preDestroy(){ + +// stop(); + } + + public void start(){ + try { + bossGroup = new NioEventLoopGroup(10); + workerGroup =new NioEventLoopGroup(); + + b.group(bossGroup , workerGroup) // bossGroup과 workerGroup은 NioEventLoopGroup의 인스턴스입니다.이 때 스레드 개수를 설정할 수 있음 각각 1, Runtime.getRuntime().availableProcessors() * 2로 설정했습니다. + .channel(NioServerSocketChannel.class) +// .handler(new LoggingHandler(LogLevel.valueOf(logBootstrap))) +// .handler(bootstrapHandler) // 채널이 활성화되면 소켓 서버와 소켓 클라이언트를 구동하게 되는 핸들러를 등록합니다. + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) + .option(ChannelOption.SO_BACKLOG, 1000) // 동시에 수용할 수 있는 소켓 연결 요청 수입니다. + +// .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(1024 , 1024 * 16 , 1024 * 1024)) + .childOption(ChannelOption.TCP_NODELAY, false) // 반응속도를 높이기 위해 Nagle 알고리즘을 비활성화 합니다 + + .childOption(ChannelOption.SO_LINGER, 0) // 소켓이 close될 때 신뢰성있는 종료를 위해 4way-handshake가 발생하고 이때 TIME_WAIT로 리소스가 낭비됩니다. 이를 방지하기 위해 0으로 설정합니다. + .childOption(ChannelOption.SO_KEEPALIVE, false) // Keep-alive를 켭니다. + .childOption(ChannelOption.SO_REUSEADDR, false) // SO_LINGER설정이 있으면 안해도 되나 혹시나병(!)으로 TIME_WAIT걸린 포트를 재사용할 수 있도록 설정합니다. + .childHandler(new SocketInitializer()); + + connection(); +// taskProcess(); +// client.start(); + + logger.warn("====== [SOCKET SERVER] Start ====== "); + }catch (Exception e) { + logger.warn("====== [SOCKET SERVER] Fail ====== "); + logger.error(e.getMessage()); + } + + } + + private void connection() { + //서버는 Listen상태로 기다려야하는데, 톰캣이 Timeout이 발생함 + //이를 방지하기 위해 Thread로 처리한다. +// new Thread(new Runnable() { +// @Override +// public void run() { +// try { +// ChannelFuture future = b.bind(port).sync(); +// future.channel().closeFuture().sync(); +// +// } catch (InterruptedException e) { +// logger.error("InterruptedException", e); +// } +// } +// }).start(); + } + + + public void stop(){ + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + logger.warn("====== [SOCKET SERVER] STOP ====== "); + + } + +} diff --git a/pav-server/src/main/java/com/palnet/server/WebServer.java b/pav-server/src/main/java/com/palnet/server/WebServer.java new file mode 100644 index 00000000..00ec80d2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/WebServer.java @@ -0,0 +1,124 @@ +package com.palnet.server; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import com.palnet.server.initializer.WebInitializer; +import com.palnet.server.task.ctr.CtrCntrlTask; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; + +@Component +public class WebServer { + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Value("${netty.websocket.port}") + private int port; + + @Value("${netty.websocket.thread.boss}") + private int threadBoss; + + @Value("${netty.websocket.thread.worker}") + private int threadWorker; + + @Value("${netty.task.controlinfoTime}") + private int controlinfoTime; + + + private Channel ch; + + private EventLoopGroup bossGroup ; + private EventLoopGroup workerGroup ; + private ServerBootstrap b = new ServerBootstrap(); + + @PostConstruct + public void postConstruct(){ +// start(); + } + + + @PreDestroy + public void preDestroy(){ + +// stop(); + } + + public void start(){ + try { + bossGroup = new NioEventLoopGroup(); + workerGroup =new NioEventLoopGroup(); + + b.group(bossGroup , workerGroup) // bossGroup과 workerGroup은 NioEventLoopGroup의 인스턴스입니다.이 때 스레드 개수를 설정할 수 있음 각각 1, Runtime.getRuntime().availableProcessors() * 2로 설정했습니다. + .channel(NioServerSocketChannel.class) +// .handler(new LoggingHandler(LogLevel.valueOf(logBootstrap))) +// .handler(bootstrapHandler) // 채널이 활성화되면 소켓 서버와 소켓 클라이언트를 구동하게 되는 핸들러를 등록합니다. + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) + .option(ChannelOption.SO_BACKLOG, 1000) // 동시에 수용할 수 있는 소켓 연결 요청 수입니다. + .childOption(ChannelOption.TCP_NODELAY, true) // 반응속도를 높이기 위해 Nagle 알고리즘을 비활성화 합니다 + .childOption(ChannelOption.SO_LINGER, 0) // 소켓이 close될 때 신뢰성있는 종료를 위해 4way-handshake가 발생하고 이때 TIME_WAIT로 리소스가 낭비됩니다. 이를 방지하기 위해 0으로 설정합니다. + .childOption(ChannelOption.SO_KEEPALIVE, true) // Keep-alive를 켭니다. + .childOption(ChannelOption.SO_REUSEADDR, true) // SO_LINGER설정이 있으면 안해도 되나 혹시나병(!)으로 TIME_WAIT걸린 포트를 재사용할 수 있도록 설정합니다. + .childHandler(new WebInitializer()); + + connection(); + taskProcess(); + + logger.warn("====== [WEBSOCKET SERVER] Start ====== "); + }catch (Exception e) { + logger.warn("====== [WEBSOCKET SERVER] Fail ====== "); + logger.error(e.getMessage()); + } + + } + + private void connection() { + //서버는 Listen상태로 기다려야하는데, 톰캣이 Timeout이 발생함 + //이를 방지하기 위해 Thread로 처리한다. + new Thread(new Runnable() { + @Override + public void run() { + try { + ChannelFuture future = b.bind(port).sync(); + future.channel().closeFuture().sync(); + + } catch (InterruptedException e) { + logger.error("InterruptedException", e); + } + } + }).start(); + } + + private void taskProcess() { + ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); + service.scheduleAtFixedRate(new CtrCntrlTask(),0,controlinfoTime,TimeUnit.MILLISECONDS); + } + + + public void stop(){ + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + logger.warn("====== [WEBSOCKET SERVER] STOP ====== "); +// ch.close().addListener(f->{ +// logger.warn("====== [WEBSOCKET SERVER] CLOSE ====== "); +// bossGroup.shutdownGracefully(); +// workerGroup.shutdownGracefully(); +// }); + } +} diff --git a/pav-server/src/main/java/com/palnet/server/codec/BigIntegerDecoder.java b/pav-server/src/main/java/com/palnet/server/codec/BigIntegerDecoder.java new file mode 100644 index 00000000..2a6508d8 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/codec/BigIntegerDecoder.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package com.palnet.server.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.CorruptedFrameException; + +import java.math.BigInteger; +import java.util.List; + +/** + * Decodes the binary representation of a {@link BigInteger} prepended + * with a magic number ('F' or 0x46) and a 32-bit integer length prefix into a + * {@link BigInteger} instance. For example, { 'F', 0, 0, 0, 1, 42 } will be + * decoded into new BigInteger("42"). + */ +public class BigIntegerDecoder extends ByteToMessageDecoder { + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { + + + + // System.out.println(">>>>>>>>>>>>>>>>>>>>>" + in.readableBytes()); + + if (in.isReadable()) { + byte[] bytes = new byte[in.readableBytes()]; + + int readerIndex = in.readerIndex(); + in.getBytes(readerIndex, bytes); + + // System.out.println(">>>" + new String(bytes)); + + } + // Wait until the length prefix is available. + + } +} diff --git a/pav-server/src/main/java/com/palnet/server/codec/SocketPayLoadDecoder.java b/pav-server/src/main/java/com/palnet/server/codec/SocketPayLoadDecoder.java new file mode 100644 index 00000000..d6936fb3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/codec/SocketPayLoadDecoder.java @@ -0,0 +1,43 @@ +package com.palnet.server.codec; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.palnet.comn.utils.JsonUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; +import io.netty.handler.codec.json.JsonObjectDecoder; + +@Sharable +public class SocketPayLoadDecoder extends MessageToMessageDecoder { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + protected void decode(ChannelHandlerContext ctx, Object msg, List out){ +// logger.info("[SocketPayLoadDecoder] Init 2 " ); + SocketPayload payload = null; + + try { + payload = JsonUtils.fromJson((String) msg, SocketPayload.class); + if(payload != null) { + out.add(payload); + + } + }catch(Exception e) { + logger.info("MSG => " + msg ); + logger.error(e.getMessage()); + + } + + + + } + + +} diff --git a/pav-server/src/main/java/com/palnet/server/codec/SocketPayLoadEncorder.java b/pav-server/src/main/java/com/palnet/server/codec/SocketPayLoadEncorder.java new file mode 100644 index 00000000..13cce854 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/codec/SocketPayLoadEncorder.java @@ -0,0 +1,38 @@ +package com.palnet.server.codec; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.palnet.comn.utils.JsonUtils; + +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; + +@Sharable +public class SocketPayLoadEncorder extends MessageToMessageEncoder { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + + @Override + protected void encode(ChannelHandlerContext ctx, SocketPayloadResponse msg, List out){ + try { + out.add(JsonUtils.toJson(msg)); +// logger.debug("[SocketPayLoadEncorder] Init 11111" ); + logger.info("=== >>>>>>>>>>>>>>" , JsonUtils.toJson(msg)); + }catch(Exception e) { + logger.info("MSG => " + msg ); + logger.error(e.getMessage()); + } + + + + } + + + + +} diff --git a/pav-server/src/main/java/com/palnet/server/codec/SocketPayload.java b/pav-server/src/main/java/com/palnet/server/codec/SocketPayload.java new file mode 100644 index 00000000..207ce0d6 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/codec/SocketPayload.java @@ -0,0 +1,23 @@ +package com.palnet.server.codec; + +import java.io.Serializable; +import java.util.List; + +import lombok.Data; + +@Data +public class SocketPayload implements Serializable{ + + private static final long serialVersionUID = 1L; + + private String authKey; + + private String terminalId; + + private String command; + + private Object body; + + + +} diff --git a/pav-server/src/main/java/com/palnet/server/codec/SocketPayloadResponse.java b/pav-server/src/main/java/com/palnet/server/codec/SocketPayloadResponse.java new file mode 100644 index 00000000..26a81454 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/codec/SocketPayloadResponse.java @@ -0,0 +1,19 @@ +package com.palnet.server.codec; + +import java.io.Serializable; +import java.util.List; + +import lombok.Data; + +@Data +public class SocketPayloadResponse implements Serializable{ + + private static final long serialVersionUID = 1L; + + private String rspCode; + + private String rspMessage; + + + +} diff --git a/pav-server/src/main/java/com/palnet/server/codec/WebPayLoadDecoder.java b/pav-server/src/main/java/com/palnet/server/codec/WebPayLoadDecoder.java new file mode 100644 index 00000000..80d1c4f5 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/codec/WebPayLoadDecoder.java @@ -0,0 +1,23 @@ +package com.palnet.server.codec; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.handler.codec.MessageToMessageDecoder; + +@Sharable +public class WebPayLoadDecoder extends MessageToMessageDecoder { + + private Logger logger = LoggerFactory.getLogger(getClass()); + @Override + protected void decode(ChannelHandlerContext ctx, String msg, List out) throws Exception { + logger.info("MSG ::" + msg); + + } + + +} diff --git a/pav-server/src/main/java/com/palnet/server/codec/WebPayLoadEncorder.java b/pav-server/src/main/java/com/palnet/server/codec/WebPayLoadEncorder.java new file mode 100644 index 00000000..fc209494 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/codec/WebPayLoadEncorder.java @@ -0,0 +1,27 @@ +package com.palnet.server.codec; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; + +@Sharable +public class WebPayLoadEncorder extends MessageToMessageEncoder { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + + @Override + protected void encode(ChannelHandlerContext ctx, String msg, List out) throws Exception { + logger.info("MSG ::" + msg); + + } + + + + +} diff --git a/pav-server/src/main/java/com/palnet/server/collection/ChannelCollection.java b/pav-server/src/main/java/com/palnet/server/collection/ChannelCollection.java new file mode 100644 index 00000000..6bf74e4e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/collection/ChannelCollection.java @@ -0,0 +1,26 @@ +package com.palnet.server.collection; + +import io.netty.channel.Channel; +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + + +public class ChannelCollection{ + + private static final long serialVersionUID = 1L; + + //접속 되어있는 모든 Channel + private static final ChannelGroup allChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + + + public void setAllChannels(Channel ch) { + allChannels.add(ch); + } + + public ChannelGroup getAllChannels() { + return allChannels; + } + + +} diff --git a/pav-server/src/main/java/com/palnet/server/command/SocketCommand.java b/pav-server/src/main/java/com/palnet/server/command/SocketCommand.java new file mode 100644 index 00000000..0280a2ba --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/command/SocketCommand.java @@ -0,0 +1,143 @@ +package com.palnet.server.command; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.palnet.comn.collection.GPCollection; +import com.palnet.comn.model.GPDatabaseModel; +import com.palnet.comn.model.GPModel; +import com.palnet.comn.utils.JsonUtils; +import com.palnet.comn.utils.StringUtils; +import com.palnet.server.codec.SocketPayload; + +public class SocketCommand { + + private Logger logger = LoggerFactory.getLogger(getClass()); + GPCollection collection = new GPCollection(); + + + public void openSkyCollectionPut(SocketPayload payload) { + + /** 전문 설정 ***/ + String messageType = "OPENSKY"; + String objectType = "FLIGHT"; + + List> resultList = new ArrayList>(); + + List dataList = new ArrayList(); + + logger.debug("BODY TYPE :: " + payload.getBody().getClass()); + + resultList = (ArrayList)payload.getBody(); + + GPModel model; + + for(LinkedHashMap obj : resultList) { + model = new GPModel(); + + model.setObjectType(objectType); + model.setMessageType(messageType); + model.setObjectId(obj.get("objectId").toString().trim()); + model.setTerminalId(obj.get("terminalId").toString().trim()); + model.setLat((Double)obj.get("lat")); + model.setLng((Double)obj.get("lng")); + model.setElev((Double)obj.get("elev")); + model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); + model.setSpeed((Double)obj.get("speed")); + model.setHeading((Double)obj.get("heading")); + model.setSpeedType((String)obj.get("speedType")); + model.setElevType((String)obj.get("elevType")); + model.setMoveDistanceType((String)obj.get("moveDistanceType")); + model.setMoveDistance((Double)obj.get("moveDistance")); + + model.setBetteryLevel((Double)obj.get("betteryLevel")); + model.setBetteryVoltage((Double)obj.get("betteryVoltage")); + model.setDronStatus((String)obj.get("dronStatus")); + + dataList.add(model); + } + +// collection.putData(dataList); +// logger.debug("SIZE :: " +collection.getData().size() ); + + + } + + + /** + * 들어온 데이터를 collection넣는 작업을 한다. + * @param payload + */ + public void sandboxCollectionPut(SocketPayload payload) { + + /** 전문 설정 ***/ + String messageType = "LTEM"; + String objectType = "DRON"; + + List> resultList = new ArrayList>(); + + List dataList = new ArrayList(); + + logger.debug("BODY TYPE :: " + payload.getBody().getClass()); + + resultList = (ArrayList)payload.getBody(); + + GPModel model; + + for(LinkedHashMap obj : resultList) { + + //위,경도 좌표가 0으로 들어오는 것은 무시 처리 + if((Double)obj.get("lat") > 0 && (Double)obj.get("lon") > 0) { + model = new GPModel(); +// logger.debug(">>>>" + obj.toString()); + model.setObjectType(objectType); + model.setMessageType(messageType); + model.setObjectId(obj.get("objectId").toString().trim()); + model.setTerminalId(payload.getTerminalId()); + if(obj.get("lat") != null) model.setLat(Double.valueOf(obj.get("lat").toString())); + if(obj.get("lon") != null) model.setLng(Double.valueOf(obj.get("lon").toString())); + if(obj.get("elev") != null) model.setElev(Double.valueOf(obj.get("elev").toString())); + model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); + if(obj.get("speed") != null) model.setSpeed(Double.valueOf(obj.get("speed").toString())); + if(obj.get("heading") != null) model.setHeading(Double.valueOf(obj.get("heading").toString())); + model.setSpeedType((String)obj.get("speedType")); + model.setElevType((String)obj.get("elevType")); + model.setMoveDistanceType((String)obj.get("moveDistanceType")); + if(obj.get("moveDistance") != null) model.setMoveDistance(Double.valueOf(obj.get("moveDistance").toString())); + + if(obj.get("betteryLevel") != null) model.setBetteryLevel(Double.valueOf(obj.get("betteryLevel").toString())); + if(obj.get("betteryVoltage") != null) model.setBetteryVoltage(Double.valueOf(obj.get("betteryVoltage").toString())); + model.setDronStatus((String)obj.get("dronStatus")); + + // 환경 데이터 필드 추가 + if(obj.get("sensorCo") != null) model.setSensorCo(Double.valueOf(obj.get("sensorCo").toString())); + if(obj.get("sensorSo2") != null) model.setSensorSo2(Double.valueOf(obj.get("sensorSo2").toString())); + if(obj.get("sensorNo2") != null) model.setSensorNo2(Double.valueOf(obj.get("sensorNo2").toString())); + if(obj.get("sensorO3") != null) model.setSensorO3(Double.valueOf(obj.get("sensorO3").toString())); + if(obj.get("sensorDust") != null) model.setSensorDust(Double.valueOf(obj.get("sensorDust").toString())); + + // TODO 환경 데이터 임의의 데이터로 수정 - 추후 제거(임시코드) +// if(model.getSensorCo() != null){ +// model.setSensorCo(TempUtils.gradualData("co")); +// model.setSensorSo2(TempUtils.gradualData("so2")); +// model.setSensorNo2(TempUtils.gradualData("no2")); +// model.setSensorO3(TempUtils.gradualData("o3")); +// model.setSensorDust(TempUtils.gradualData("dust")); +// } + dataList.add(model); + }else { + logger.info("lat , lon No data "); + } + } + +// collection.putData(dataList); +// logger.debug("SIZE :: " +collection.getData().size() ); + + } + + +} diff --git a/pav-server/src/main/java/com/palnet/server/command/TempUtils.java b/pav-server/src/main/java/com/palnet/server/command/TempUtils.java new file mode 100644 index 00000000..c96f3a1a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/command/TempUtils.java @@ -0,0 +1,81 @@ +package com.palnet.server.command; + +import lombok.Data; +import org.springframework.stereotype.Component; + +import java.util.Random; + +class SensorModel{ + static Double co = 0.0; + static Double preCo = 0.0; + static Double so2 = 0.0; + static Double preSo2 = 0.0; + static Double no2 = 0.0; + static Double preNo2 = 0.0; + static Double o3 = 0.0; + static Double preO3 = 0.0; + static Double dust = 0.0; + static Double preDust = 0.0; +} + +public class TempUtils{ + + + public static Double gradualData(String type){ + Double prev = 0.0; + Double result = 0.0; + switch(type){ + case "co": + // 일산화탄소 + prev = SensorModel.preCo; + SensorModel.preCo = SensorModel.co; + result = SensorModel.co = gradualDoubleData(SensorModel.co, prev, 0.1, 0.0, 20.0); + break; + case "so2": + // 아황산가스 + prev = SensorModel.preSo2; + SensorModel.preSo2 = SensorModel.so2; + result = SensorModel.so2 = gradualDoubleData(SensorModel.so2, prev, 0.005, 0.0, 0.2); + break; + case "no2": + // 이산화질소 + prev = SensorModel.preNo2; + SensorModel.preNo2 = SensorModel.no2; + result = SensorModel.no2 = gradualDoubleData(SensorModel.no2, prev, 0.003, 0.0, 0.3); + break; + case "o3": + // 오존 + prev = SensorModel.preO3; + SensorModel.preO3 = SensorModel.o3; + result = SensorModel.o3 = gradualDoubleData(SensorModel.o3, prev, 1.0, 0.0, 175.0); + break; + case "dust": + // 미세먼지 + prev = SensorModel.preDust; + SensorModel.preDust = SensorModel.dust; + result = SensorModel.dust = gradualDoubleData(SensorModel.dust, prev, 1.1, 0.0, 175.0); + break; + default: + result = (Math.round((new Random()).nextDouble() * 100000)) / 100.0; + break; + } + return result; + } + + public static Double gradualDoubleData(Double current, Double prev, Double diff, Double min, Double max){ + boolean isPrevAdd = current >= prev; + boolean isCurAdd = true; + if(isPrevAdd){ + isCurAdd = current + diff <= max; + }else { + isCurAdd = current - diff < min; + } + Double r = 0.0; + if(isCurAdd){ + r = current + diff; + } else { + r = current - diff; + } + return r; + } +} diff --git a/pav-server/src/main/java/com/palnet/server/handler/SocketHandler.java b/pav-server/src/main/java/com/palnet/server/handler/SocketHandler.java new file mode 100644 index 00000000..94008552 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/handler/SocketHandler.java @@ -0,0 +1,101 @@ +package com.palnet.server.handler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import com.palnet.comn.collection.AuthCollection; +import com.palnet.comn.utils.JsonUtils; +import com.palnet.server.codec.SocketPayload; +import com.palnet.server.codec.SocketPayloadResponse; +import com.palnet.server.command.SocketCommand; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +public class SocketHandler extends SimpleChannelInboundHandler { + + private Logger logger = LoggerFactory.getLogger(getClass()); + private SocketCommand command = new SocketCommand(); + + private AuthCollection auth = new AuthCollection(); + private SocketPayloadResponse res = new SocketPayloadResponse(); + + + @Override + public void channelActive(ChannelHandlerContext ctx) { + auth.reloadAuthkey(); // 채널 활성화 되면 인증키 정보를 다시 불러옴 + + logger.debug("==================== [SocketHandler channelActive ] ==================== "); + ctx.writeAndFlush("Server Connection"); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, SocketPayload payload){ + + try { + + logger.debug("==================== [SocketHandler channelRead0 ] ==================== "); + logger.debug("AUTH KEY :: ==== > " +payload.getAuthKey()); +// logger.info(auth.checkAuthkey(payload.getAuthKey().toString().trim())); + + if(StringUtils.isEmpty(payload.getAuthKey())) { + // 인증키가 없을 경우 + logger.debug("AUTH : no key " ); + res.setRspCode("-2000"); + res.setRspMessage("inValidate AuthKey"); + }else if(!auth.checkAuthkey(payload.getAuthKey().toString().trim())) { + // 인증키가 틀린 경우 + logger.debug("AUTH : error key " ); + logger.debug(payload.getAuthKey() ); +// logger.info(auth.checkAuthkey(payload.getAuthKey().toString().trim())); + res.setRspCode("-2000"); + res.setRspMessage("inValidate AuthKey"); + }else{ + logger.warn("MSG :: ==== > " + JsonUtils.toJson(payload)); + + switch(payload.getCommand().trim()) { + case "OPENSKY" : + command.openSkyCollectionPut(payload); + break; + case "SANDBOX": + command.sandboxCollectionPut(payload); + break; + default: + break; + } + + res.setRspCode("0"); + res.setRspMessage("SUCCESS"); + + } + + + }catch(Exception e) { + res.setRspCode("-9999"); + res.setRspMessage("Etc error"); + + e.printStackTrace(); + }finally { + logger.debug("res >>>" + JsonUtils.toJson(res)); + ctx.writeAndFlush(res); + } + + + } + + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.info("=========== [exceptionCaught ] ===================="); + res.setRspCode("-9999"); + res.setRspMessage("Etc error"); + ctx.writeAndFlush(res); + + cause.printStackTrace(); + ctx.close(); + } + + + +} diff --git a/pav-server/src/main/java/com/palnet/server/handler/WebCommandHandler.java b/pav-server/src/main/java/com/palnet/server/handler/WebCommandHandler.java new file mode 100644 index 00000000..7d6c217a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/handler/WebCommandHandler.java @@ -0,0 +1,21 @@ +package com.palnet.server.handler; + +import com.palnet.server.codec.SocketPayload; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +public class WebCommandHandler extends SimpleChannelInboundHandler{ + + @Override + protected void channelRead0(ChannelHandlerContext ctx, SocketPayload payload) throws Exception { + switch (payload.getCommand()) { + case "OPENSKY" : + + default: + } + + } + + +} diff --git a/pav-server/src/main/java/com/palnet/server/handler/WebHandler.java b/pav-server/src/main/java/com/palnet/server/handler/WebHandler.java new file mode 100644 index 00000000..98af4a0c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/handler/WebHandler.java @@ -0,0 +1,91 @@ +package com.palnet.server.handler; + +import java.net.SocketAddress; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.palnet.server.codec.SocketPayload; +import com.palnet.server.collection.ChannelCollection; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import io.netty.util.concurrent.GlobalEventExecutor; + +public class WebHandler extends SimpleChannelInboundHandler{ + + private Logger logger = LoggerFactory.getLogger(getClass()); + + ChannelCollection cc = new ChannelCollection(); + + + @Override + protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception { + + logger.info("==================== [ channelRead0 ] ==================== "); + + logger.info("Channel Size [" + cc.getAllChannels().size() + "]"); + + cc.getAllChannels().stream().forEach(c -> { + logger.info(":" + c); + c.writeAndFlush(new TextWebSocketFrame("test")); +// command.execute(c, data, result); + }); + + + + +// ctx.writeAndFlush(new TextWebSocketFrame("Test")); + + } + +// private class HeartBeatTask implements Runnable{ +// +// private final ChannelHandlerContext ctx; +// +// public HeartBeatTask(final ChannelHandlerContext ctx){ +// this.ctx = ctx; +// } +// +// public void run() { +// ctx.writeAndFlush(new TextWebSocketFrame("test")); +// +// // System.out.println("Client send heart beat message to server : ---> "); +// } +// +// } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// SocketAddress remoteAddress = ctx.channel().remoteAddress(); + cc.setAllChannels(ctx.channel()); +// ctx.executor().scheduleAtFixedRate(new HeartBeatTask(ctx),0,500, +// TimeUnit.MILLISECONDS); + logger.info("==================== [ channelActive ] ==================== "); + + + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + logger.info("==================== [ channelInactive ] ==================== "); + } + + + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + //2 Triggered when a connection is established with the selector of a thread in the worker thread group (channel is registered to EventLoop) + logger.info("==================== [ channelRegistered ] ==================== "); + } + + +} diff --git a/pav-server/src/main/java/com/palnet/server/initializer/SocketInitializer.java b/pav-server/src/main/java/com/palnet/server/initializer/SocketInitializer.java new file mode 100644 index 00000000..1869c465 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/initializer/SocketInitializer.java @@ -0,0 +1,70 @@ +package com.palnet.server.initializer; + +import java.util.List; + +import com.palnet.server.codec.BigIntegerDecoder; +import com.palnet.server.codec.SocketPayLoadDecoder; +import com.palnet.server.codec.SocketPayLoadEncorder; +import com.palnet.server.codec.WebPayLoadDecoder; +import com.palnet.server.codec.WebPayLoadEncorder; +import com.palnet.server.handler.WebHandler; +import com.palnet.server.handler.SocketHandler; +import com.palnet.server.handler.WebCommandHandler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.Delimiters; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; +import io.netty.handler.codec.json.JsonObjectDecoder; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.util.CharsetUtil; + +public class SocketInitializer extends ChannelInitializer{ + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + +// pipeline.addLast(new BigIntegerDecoder()) +// pipeline.addLast(new ByteToMessageDecoder() { +// +// @Override +// protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { +// out.add(in.readBytes(in.readableBytes())); +// out.add(in.readBytes(in.readableBytes())); +// +// } +// }) + + +// pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8), new StringEncoder(CharsetUtil.UTF_8)) + pipeline.addLast(new JsonObjectDecoder(655360)) +// .addLast(new DelimiterBasedFrameDecoder(1024 * 1024 , )) +// .addLast(new DelimiterBasedFrameDecoder(1024 * 1024 * 100 , Delimiters.nulDelimiter())) + .addLast(new StringDecoder(CharsetUtil.UTF_8), new StringEncoder(CharsetUtil.UTF_8)) +// .addLast(new HttpServerCodec()) +// .addLast(new HttpObjectAggregator(104857600)) +// .addLast(new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Unpooled.wrappedBuffer(new byte[]{'E', 'O', 'F', '\n'}))) + .addLast(new SocketPayLoadDecoder() , new SocketPayLoadEncorder()) + .addLast(new SocketHandler()); +// pipeline.addLast(new HttpServerCodec()) + +// pipeline.addLast(new HttpObjectAggregator(65536)) +// pipeline.addLast(new IdleStateHandler(0, 0, 180)); // [5] +// .addLast(new WebPayLoadDecoder() , new WebPayLoadEncorder()) +// .addLast(new DemoHandler()); + + } + +} diff --git a/pav-server/src/main/java/com/palnet/server/initializer/WebInitializer.java b/pav-server/src/main/java/com/palnet/server/initializer/WebInitializer.java new file mode 100644 index 00000000..3e9127f2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/initializer/WebInitializer.java @@ -0,0 +1,38 @@ +package com.palnet.server.initializer; + +import com.palnet.server.codec.WebPayLoadDecoder; +import com.palnet.server.codec.WebPayLoadEncorder; +import com.palnet.server.handler.WebHandler; +import com.palnet.server.handler.WebCommandHandler; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; +import io.netty.handler.timeout.IdleStateHandler; + +public class WebInitializer extends ChannelInitializer{ + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast(new HttpServerCodec()) + .addLast(new HttpObjectAggregator(65536)) + .addLast(new WebSocketServerCompressionHandler()) + .addLast(new WebSocketServerProtocolHandler("/ws", null, true)) + .addLast(new IdleStateHandler(0, 0, 180)) // [5] +// .addLast(idleHandler) // [6] +// .addLast(healthEndpointHandler) // [7] + .addLast(new WebPayLoadDecoder() , new WebPayLoadEncorder()) +// .addLast(new WebCommandHandler()) + .addLast(new WebHandler()); + +// .addLast(authHandler) // [9] +// .addLast(commandHandler); // [10] + + } + +} diff --git a/pav-server/src/main/java/com/palnet/server/task/ctr/CtrCntrlTask.java b/pav-server/src/main/java/com/palnet/server/task/ctr/CtrCntrlTask.java new file mode 100644 index 00000000..ff1733a3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/task/ctr/CtrCntrlTask.java @@ -0,0 +1,38 @@ +package com.palnet.server.task.ctr; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.palnet.biz.api.ctr.cntrl.service.CtrCntrlService; +import com.palnet.comn.utils.JsonUtils; +import com.palnet.server.collection.ChannelCollection; +import com.palnet.server.task.ctr.service.CtrCntrlTaskService; + +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +public class CtrCntrlTask implements Runnable{ + + private ChannelCollection cc = new ChannelCollection(); + + private Logger logger = LoggerFactory.getLogger(getClass()); + + + private CtrCntrlTaskService service = new CtrCntrlTaskService(); + + + @Override + public void run() { + try { +// logger.info("=========== [Channel Size : " + cc.getAllChannels().size() + "]"); + +// cc.getAllChannels().stream().forEach(c -> { // 접속되어 있는 모든 사용자에게 전달 처리 +// c.writeAndFlush(new TextWebSocketFrame(JsonUtils.toJson(service.getList()))); +// }); + }catch(Exception e) { + e.printStackTrace(); + } + + } + + +} diff --git a/pav-server/src/main/java/com/palnet/server/task/ctr/service/CtrCntrlTaskService.java b/pav-server/src/main/java/com/palnet/server/task/ctr/service/CtrCntrlTaskService.java new file mode 100644 index 00000000..4d4f963c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/server/task/ctr/service/CtrCntrlTaskService.java @@ -0,0 +1,117 @@ +package com.palnet.server.task.ctr.service; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.ctr.cntrl.model.CtrCntrlModel; +import com.palnet.comn.collection.GPCollection; +import com.palnet.comn.collection.GPDatabaseCollection; +import com.palnet.comn.model.GPHistoryModel; +import com.palnet.comn.model.GPModel; + +@Service +public class CtrCntrlTaskService { + + GPCollection cic = new GPCollection(); + GPDatabaseCollection gpdc = new GPDatabaseCollection(); + + + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Value("${gp.remove.time}") + private long GP_REMOVE_TIME; + + @Value("${gp.insert.count}") + private long GP_INSERT_COUNT; + + /** + * Websocket 을 통해 전달될 위치 정보를 관리 + * @return + */ + public ArrayList getList(){ + + ArrayList list = new ArrayList(); +// Map cicData = cic.getData(); +// +// CtrCntrlModel model; +// GPModel dataInfo; +// +// for(Entry data : cicData.entrySet()) { +//// List> historyList = new ArrayList>(); +// model = new CtrCntrlModel(); +//// dataInfo = new GroundPositionInfoModel(); +// dataInfo = data.getValue(); +// +// model.setObjectId(dataInfo.getObjectId()); +// model.setControlId(dataInfo.getControlId()); +// model.setControlStartDt(dataInfo.getControlStartDt()); +// model.setObjectTypeCd(dataInfo.getObjectType()); +// model.setLat(dataInfo.getLat()); +// model.setLng(dataInfo.getLng()); +// model.setElevType(dataInfo.getElevType()); +// model.setElev(dataInfo.getElev()); +// model.setSpeedType(dataInfo.getSpeedType()); +// model.setSpeed(dataInfo.getSpeed()); +// model.setBetteryLevel(dataInfo.getBetteryLevel()); +// model.setBetteryVoltage(dataInfo.getBetteryVoltage()); +// model.setDronStatus(dataInfo.getDronStatus()); +// model.setHeading(dataInfo.getHeading()); +// model.setMoveDistance(dataInfo.getMoveDistance()); +// model.setMoveDistanceType(dataInfo.getMoveDistanceType()); +// +// model.setServerRcvDt(dataInfo.getServerRcvDt()); +// +// // 환경 데이터 필드 추가 +// model.setSensorCo(dataInfo.getSensorCo()); +// model.setSensorSo2(dataInfo.getSensorSo2()); +// model.setSensorNo2(dataInfo.getSensorNo2()); +// model.setSensorO3(dataInfo.getSensorO3()); +// model.setSensorDust(dataInfo.getSensorDust()); +// +// //마지막 5개 좌표를 넣기 +//// if(dataInfo.getPostionHistory() != null) { +//// int listSize = dataInfo.getPostionHistory().size(); +//// int limitSize = 10; +//// +//// if(limitSize >= listSize) { +//// limitSize = listSize; +//// } +//// List tempHistoryList = new ArrayList(); +//// +//// tempHistoryList = dataInfo.getPostionHistory().subList(listSize - limitSize , listSize); +//// +//// +//// //뒤집기 +//// Collections.reverse(tempHistoryList); +//// +//// for(GroundPositionHistoryModel historyData : tempHistoryList) { +//// Map addDate = new HashMap(); +//// addDate.put("lat", historyData.getLat()); +//// addDate.put("lng", historyData.getLng()); +//// +//// historyList.add(addDate); +//// } +//// } +//// model.setLastHistory(historyList); +// list.add(model); +// } +// +// //=== 정렬 처리 == +// //기준 : 관제 시작일이 가장 느린순으로 상단에 올린다. +// list.sort(Comparator.reverseOrder()); + + return list; + } + + + +} diff --git a/pav-server/src/main/resources/air/airgeo.json b/pav-server/src/main/resources/air/airgeo.json new file mode 100644 index 00000000..4a9b32e7 --- /dev/null +++ b/pav-server/src/main/resources/air/airgeo.json @@ -0,0 +1,12524 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.038029813528, 37.542793], + [127.03782796105718, 37.54605084602245], + [127.03722434759435, 37.549277317206794], + [127.03622478626711, 37.55244134087174], + [127.03483890339749, 37.55551244573977], + [127.0330800457951, 37.55846105539217], + [127.03096515222015, 37.56125877310612], + [127.02851459025389, 37.56387865533063], + [127.02575196014766, 37.56629547116772], + [127.02270386753958, 37.568485945359704], + [127.01939966722774, 37.570428982442685], + [127.01587118046741, 37.572105869907375], + [127.01215238851493, 37.57350045841082], + [127.00827910536974, 37.57459931730335], + [127.00428863286584, 37.57539186397316], + [127.00021940143488, 37.575870465762556], + [126.9961106, 37.57603051347467], + [126.99200179856511, 37.575870465762556], + [126.98793256713415, 37.57539186397316], + [126.98394209463025, 37.57459931730335], + [126.98006881148505, 37.57350045841082], + [126.97635001953257, 37.572105869907375], + [126.97282153277224, 37.570428982442685], + [126.96951733246041, 37.568485945359704], + [126.96646923985233, 37.56629547116772], + [126.9637066097461, 37.56387865533063], + [126.96125604777984, 37.56125877310612], + [126.95914115420489, 37.55846105539217], + [126.9573822966025, 37.55551244573977], + [126.95599641373288, 37.55244134087174], + [126.95499685240564, 37.549277317206794], + [126.95439323894281, 37.54605084602245], + [126.95419138647199, 37.542793], + [126.95439323894281, 37.53953515397755], + [126.95499685240564, 37.53630868279321], + [126.95599641373288, 37.53314465912827], + [126.9573822966025, 37.530073554260234], + [126.95914115420489, 37.527124944607834], + [126.96125604777984, 37.52432722689389], + [126.9637066097461, 37.52170734466937], + [126.96646923985233, 37.519290528832286], + [126.96951733246041, 37.5171000546403], + [126.97282153277224, 37.51515701755732], + [126.97635001953257, 37.51348013009263], + [126.98006881148505, 37.51208554158919], + [126.98394209463025, 37.510986682696654], + [126.98793256713415, 37.51019413602685], + [126.99200179856511, 37.50971553423745], + [126.9961106, 37.509555486525336], + [127.00021940143488, 37.50971553423745], + [127.00428863286584, 37.51019413602685], + [127.00827910536974, 37.510986682696654], + [127.01215238851493, 37.51208554158919], + [127.01587118046741, 37.51348013009263], + [127.01939966722774, 37.51515701755732], + [127.02270386753958, 37.5171000546403], + [127.02575196014766, 37.519290528832286], + [127.02851459025389, 37.52170734466937], + [127.03096515222015, 37.52432722689389], + [127.0330800457951, 37.527124944607834], + [127.03483890339749, 37.530073554260234], + [127.03622478626711, 37.53314465912827], + [127.03722434759435, 37.53630868279321], + [127.03782796105718, 37.53953515397755], + [127.038029813528, 37.542793] + ] + ] + }, + "properties": { "name": "P73", "description": "서울도심 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.683323, 37.716663, 0], + [126.883354, 37.633327, 0], + [127.666669, 37.966655, 0], + [128.464535, 38.060707, 0], + [128.516672, 38.066657, 0], + [128.533337, 38.133331, 0], + [128.599993, 38.200006, 0], + [128.601066, 38.213276, 0], + [128.559503, 38.270766, 0], + [128.549998, 38.28818, 0], + [128.550683, 38.303774, 0], + [128.543802, 38.311177, 0], + [128.527866, 38.324159, 0], + [128.528777, 38.334883, 0], + [128.519066, 38.3408, 0], + [128.510833, 38.354392, 0], + [128.512767, 38.368459, 0], + [128.456851, 38.433499, 0], + [128.466955, 38.449947, 0], + [128.437266, 38.486662, 0], + [128.423793, 38.522201, 0], + [128.406567, 38.544104, 0], + [128.410929, 38.555948, 0], + [128.40333, 38.56611, 0], + [128.360025, 38.61249, 0], + [128.317379, 38.589921, 0], + [128.314819, 38.549239, 0], + [128.309665, 38.484755, 0], + [128.312063, 38.472729, 0], + [128.282547, 38.432077, 0], + [128.257141, 38.41809, 0], + [128.217014, 38.376524, 0], + [128.193283, 38.366425, 0], + [128.133382, 38.329157, 0], + [128.109897, 38.329182, 0], + [128.067997, 38.306914, 0], + [128.04693, 38.304994, 0], + [127.98762, 38.315522, 0], + [127.888554, 38.326385, 0], + [127.830734, 38.304486, 0], + [127.790909, 38.329807, 0], + [127.784729, 38.343272, 0], + [127.76619, 38.33627, 0], + [127.743181, 38.335623, 0], + [127.574924, 38.330752, 0], + [127.510757, 38.296404, 0], + [127.471619, 38.313107, 0], + [127.390513, 38.331958, 0], + [127.344004, 38.32087, 0], + [127.302704, 38.31203, 0], + [127.251892, 38.32442, 0], + [127.148895, 38.300715, 0], + [127.139421, 38.307234, 0], + [127.111749, 38.293001, 0], + [127.09124, 38.278494, 0], + [127.081604, 38.27754, 0], + [127.066498, 38.260289, 0], + [127.047958, 38.258132, 0], + [127.021866, 38.231169, 0], + [127.010193, 38.216604, 0], + [126.988443, 38.208441, 0], + [126.97792, 38.184768, 0], + [126.975861, 38.176132, 0], + [126.962002, 38.157933, 0], + [126.971309, 38.146338, 0], + [126.96697, 38.138978, 0], + [126.909256, 38.11295, 0], + [126.900035, 38.102644, 0], + [126.884537, 38.099442, 0], + [126.876984, 38.085932, 0], + [126.863479, 38.046199, 0], + [126.813126, 37.993998, 0], + [126.725922, 37.955568, 0], + [126.701889, 37.949071, 0], + [126.680603, 37.951237, 0], + [126.679916, 37.924701, 0], + [126.695277, 37.911293, 0], + [126.68747, 37.888402, 0], + [126.692963, 37.840699, 0], + [126.674423, 37.825514, 0], + [126.666305, 37.782716, 0], + [126.659317, 37.778856, 0], + [126.636048, 37.777631, 0], + [126.595297, 37.763353, 0], + [126.572113, 37.763658, 0], + [126.483209, 37.803957, 0], + [126.447144, 37.829853, 0], + [126.427231, 37.840699, 0], + [126.388361, 37.847803, 0], + [126.276856, 37.826057, 0], + [126.222014, 37.822172, 0], + [126.195145, 37.808699, 0], + [126.189652, 37.790795, 0], + [126.202011, 37.746286, 0], + [126.196518, 37.726194, 0], + [126.178665, 37.714245, 0], + [126.125794, 37.713702, 0], + [126.109314, 37.714788, 0], + [126.166675, 37.650008, 0], + [126.683323, 37.716663, 0] + ] + ] + }, + "properties": { "name": "P518", "description": "휴전선 비행금지구역", "type": "0001"} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.633339, 38.63334, 0], + [128.366674, 38.633329, 0], + [128.360025, 38.61249, 0], + [128.559503, 38.270766, 0], + [128.783334, 38.366666, 0], + [128.633339, 38.63334, 0] + ] + ] + }, + "properties": { + "name": "P518E", + "description": "휴전선 비행금지구역", + "type": "0001" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [124.14999, 38.000543, 0], + [124.633328, 37.500544, 0], + [125.833337, 37.500547, 0], + [126.166675, 37.650008, 0], + [126.178665, 37.714245, 0], + [126.109314, 37.714788, 0], + [126.074986, 37.710444, 0], + [126.033773, 37.691452, 0], + [125.676042, 37.707184, 0], + [125.631409, 37.688168, 0], + [125.474854, 37.635985, 0], + [125.297011, 37.614776, 0], + [125.142305, 37.627664, 0], + [125.004498, 37.7099, 0], + [124.93927, 37.764201, 0], + [124.909058, 37.820633, 0], + [124.752778, 38, 0], + [124.14999, 38.000543, 0] + ] + ] + }, + "properties": { "name": "P518W", "description": "휴전선 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.265991, 35.334966, 0], + [129.26417, 35.332474, 0], + [129.262622, 35.329861, 0], + [129.261017, 35.32619, 0], + [129.259987, 35.322409, 0], + [129.259366, 35.318618, 0], + [129.259472, 35.314425, 0], + [129.260146, 35.309958, 0], + [129.261019, 35.307145, 0], + [129.262562, 35.303498, 0], + [129.264278, 35.300556, 0], + [129.265823, 35.297894, 0], + [129.269627, 35.294576, 0], + [129.272106, 35.292495, 0], + [129.276123, 35.289628, 0], + [129.280734, 35.287415, 0], + [129.283934, 35.286152, 0], + [129.287257, 35.285121, 0], + [129.290678, 35.28433, 0], + [129.29417, 35.283786, 0], + [129.299126, 35.283182, 0], + [129.302902, 35.283322, 0], + [129.307194, 35.283743, 0], + [129.311762, 35.284836, 0], + [129.31512, 35.285789, 0], + [129.318363, 35.286977, 0], + [129.322643, 35.288647, 0], + [129.326076, 35.291029, 0], + [129.328995, 35.292991, 0], + [129.332041, 35.296072, 0], + [129.335003, 35.299436, 0], + [129.336719, 35.302658, 0], + [129.33876, 35.30624, 0], + [129.33973, 35.309031, 0], + [129.340761, 35.314768, 0], + [129.340496, 35.319047, 0], + [129.339989, 35.323429, 0], + [129.338608, 35.327591, 0], + [129.336496, 35.331632, 0], + [129.334763, 35.334166, 0], + [129.332765, 35.336567, 0], + [129.32951, 35.339774, 0], + [129.32642, 35.342015, 0], + [129.322464, 35.344494, 0], + [129.317493, 35.346916, 0], + [129.312881, 35.348278, 0], + [129.309458, 35.349069, 0], + [129.304447, 35.349716, 0], + [129.298867, 35.349949, 0], + [129.293632, 35.349436, 0], + [129.288357, 35.348563, 0], + [129.284997, 35.347609, 0], + [129.278646, 35.345005, 0], + [129.275703, 35.343374, 0], + [129.271831, 35.340895, 0], + [129.268072, 35.33732, 0], + [129.265991, 35.334966, 0] + ] + ] + }, + "properties": { "name": "P61A 고리", "description": "새울원전 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.15596, 35.434939, 0], + [129.1436, 35.423749, 0], + [129.128212, 35.406733, 0], + [129.116135, 35.387371, 0], + [129.105542, 35.367368, 0], + [129.09775, 35.339034, 0], + [129.095535, 35.319047, 0], + [129.095535, 35.300556, 0], + [129.100669, 35.281228, 0], + [129.105233, 35.267181, 0], + [129.111278, 35.253512, 0], + [129.118756, 35.240325, 0], + [129.127611, 35.22772, 0], + [129.137774, 35.215792, 0], + [129.149167, 35.204632, 0], + [129.161705, 35.194325, 0], + [129.175291, 35.184948, 0], + [129.189823, 35.176573, 0], + [129.205189, 35.169264, 0], + [129.221273, 35.163074, 0], + [129.237955, 35.158053, 0], + [129.255106, 35.154236, 0], + [129.272598, 35.151653, 0], + [129.290297, 35.150325, 0], + [129.308071, 35.15026, 0], + [129.325784, 35.151459, 0], + [129.343304, 35.153914, 0], + [129.360496, 35.157605, 0], + [129.377231, 35.162504, 0], + [129.393383, 35.168576, 0], + [129.408828, 35.175773, 0], + [129.42345, 35.184041, 0], + [129.437138, 35.193318, 0], + [129.449788, 35.203533, 0], + [129.461304, 35.214609, 0], + [129.471597, 35.226462, 0], + [129.480589, 35.239003, 0], + [129.488211, 35.252135, 0], + [129.494405, 35.265759, 0], + [129.499124, 35.279772, 0], + [129.503403, 35.298875, 0], + [129.504089, 35.317927, 0], + [129.502716, 35.334173, 0], + [129.501343, 35.347056, 0], + [129.496264, 35.361402, 0], + [129.490356, 35.374494, 0], + [129.48349, 35.38849, 0], + [129.476623, 35.401364, 0], + [129.462823, 35.417428, 0], + [129.451443, 35.428618, 0], + [129.438906, 35.438955, 0], + [129.425307, 35.448361, 0], + [129.410752, 35.456764, 0], + [129.395349, 35.4641, 0], + [129.379218, 35.470312, 0], + [129.362481, 35.475353, 0], + [129.345267, 35.479185, 0], + [129.327706, 35.481778, 0], + [129.309935, 35.483112, 0], + [129.292088, 35.483177, 0], + [129.26857, 35.480802, 0], + [129.256714, 35.479509, 0], + [129.239458, 35.475803, 0], + [129.222666, 35.470884, 0], + [129.206466, 35.46479, 0], + [129.190984, 35.457567, 0], + [129.176336, 35.449271, 0], + [129.166946, 35.442771, 0], + [129.15596, 35.434939, 0] + ] + ] + }, + "properties": { "name": "P61B 고리", "description": "새울원전 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.506149, 35.86457, 0], + [129.493361, 35.86564, 0], + [129.475443, 35.866814, 0], + [129.457467, 35.866716, 0], + [129.439571, 35.865346, 0], + [129.421897, 35.862715, 0], + [129.404568, 35.858843, 0], + [129.387725, 35.853759, 0], + [129.371494, 35.847502, 0], + [129.356001, 35.840121, 0], + [129.341363, 35.831671, 0], + [129.327693, 35.822218, 0], + [129.315094, 35.811833, 0], + [129.303663, 35.800596, 0], + [129.293486, 35.788593, 0], + [129.28464, 35.775915, 0], + [129.277193, 35.76266, 0], + [129.271199, 35.748928, 0], + [129.266706, 35.734824, 0], + [129.263744, 35.720456, 0], + [129.262338, 35.705933, 0], + [129.262496, 35.691366, 0], + [129.264216, 35.676866, 0], + [129.267484, 35.662542, 0], + [129.272275, 35.648504, 0], + [129.278552, 35.634859, 0], + [129.286265, 35.621709, 0], + [129.295357, 35.609156, 0], + [129.305757, 35.597293, 0], + [129.317385, 35.586212, 0], + [129.330154, 35.575995, 0], + [129.343966, 35.566721, 0], + [129.358716, 35.55846, 0], + [129.38118, 35.547871, 0], + [129.399033, 35.541725, 0], + [129.419632, 35.538373, 0], + [129.442421, 35.53424, 0], + [129.460264, 35.53307, 0], + [129.478165, 35.533168, 0], + [129.495988, 35.534532, 0], + [129.513598, 35.537152, 0], + [129.530862, 35.541009, 0], + [129.547649, 35.546074, 0], + [129.563832, 35.552307, 0], + [129.579288, 35.559662, 0], + [129.593901, 35.568083, 0], + [129.607559, 35.577507, 0], + [129.620158, 35.587862, 0], + [129.631603, 35.599069, 0], + [129.641807, 35.611043, 0], + [129.650691, 35.623695, 0], + [129.662704, 35.644463, 0], + [129.668884, 35.661202, 0], + [129.671829, 35.679087, 0], + [129.673004, 35.698013, 0], + [129.673004, 35.713068, 0], + [129.670258, 35.728677, 0], + [129.664764, 35.746512, 0], + [129.657434, 35.764732, 0], + [129.649768, 35.777904, 0], + [129.640713, 35.790485, 0], + [129.630338, 35.802376, 0], + [129.618721, 35.813487, 0], + [129.605951, 35.823734, 0], + [129.592125, 35.833037, 0], + [129.577348, 35.841327, 0], + [129.561734, 35.848539, 0], + [129.545401, 35.854618, 0], + [129.528474, 35.859518, 0], + [129.506149, 35.86457, 0] + ] + ] + }, + "properties": { "name": "P62B", "description": "월성원전 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.412133, 35.441186, 0], + [126.401471, 35.44091, 0], + [126.391259, 35.438395, 0], + [126.382196, 35.433811, 0], + [126.374899, 35.427472, 0], + [126.369865, 35.41981, 0], + [126.367943, 35.414222, 0], + [126.36724, 35.408447, 0], + [126.36851, 35.399817, 0], + [126.370867, 35.394341, 0], + [126.376491, 35.386957, 0], + [126.381466, 35.382806, 0], + [126.390388, 35.37805, 0], + [126.397048, 35.376001, 0], + [126.407599, 35.374765, 0], + [126.418183, 35.375796, 0], + [126.4249, 35.377715, 0], + [126.431107, 35.380555, 0], + [126.439054, 35.386348, 0], + [126.444892, 35.393621, 0], + [126.448224, 35.401877, 0], + [126.44882, 35.410555, 0], + [126.446641, 35.419063, 0], + [126.441833, 35.426821, 0], + [126.437322, 35.431312, 0], + [126.431922, 35.435096, 0], + [126.42252, 35.439203, 0], + [126.412133, 35.441186, 0] + ] + ] + }, + "properties": { "name": "P63A", "description": "한빛원전 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.37979, 37.066915, 0], + [129.390646, 37.067309, 0], + [129.401006, 37.06993, 0], + [129.407285, 37.072833, 0], + [129.412837, 37.076562, 0], + [129.417494, 37.081003, 0], + [129.421114, 37.086021, 0], + [129.424369, 37.094295, 0], + [129.424992, 37.100064, 0], + [129.424349, 37.105831, 0], + [129.422461, 37.111422, 0], + [129.419383, 37.116666, 0], + [129.415209, 37.121405, 0], + [129.410067, 37.125493, 0], + [129.404111, 37.128807, 0], + [129.397524, 37.131245, 0], + [129.390506, 37.132735, 0], + [129.379639, 37.133098, 0], + [129.372489, 37.132082, 0], + [129.365669, 37.130091, 0], + [129.359387, 37.127185, 0], + [129.351383, 37.121314, 0], + [129.34556, 37.11399, 0], + [129.342313, 37.105714, 0], + [129.341697, 37.099945, 0], + [129.343139, 37.09135, 0], + [129.345637, 37.085914, 0], + [129.34928, 37.080905, 0], + [129.353957, 37.076478, 0], + [129.362593, 37.071213, 0], + [129.369176, 37.068776, 0], + [129.376189, 37.067288, 0], + [129.37979, 37.066915, 0] + ] + ] + }, + "properties": { "name": "P64A", "description": "한울원전 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.395219, 36.934245, 0], + [129.431123, 36.938383, 0], + [129.46559, 36.947431, 0], + [129.481957, 36.953717, 0], + [129.512337, 36.969574, 0], + [129.52612, 36.979026, 0], + [129.538823, 36.9894, 0], + [129.55035, 37.000617, 0], + [129.56953, 37.025238, 0], + [129.577037, 37.038454, 0], + [129.583075, 37.052142, 0], + [129.590568, 37.080514, 0], + [129.591965, 37.094982, 0], + [129.59, 37.123935, 0], + [129.586652, 37.138199, 0], + [129.575348, 37.165759, 0], + [129.567477, 37.178845, 0], + [129.547591, 37.20313, 0], + [129.535727, 37.214144, 0], + [129.508608, 37.233493, 0], + [129.493559, 37.241681, 0], + [129.461056, 37.25477, 0], + [129.426183, 37.263157, 0], + [129.408189, 37.265502, 0], + [129.390005, 37.266587, 0], + [129.353629, 37.264953, 0], + [129.335715, 37.262247, 0], + [129.30112, 37.253162, 0], + [129.284704, 37.246851, 0], + [129.25426, 37.230936, 0], + [129.240465, 37.221453, 0], + [129.227764, 37.211047, 0], + [129.216254, 37.199798, 0], + [129.197144, 37.175121, 0], + [129.18969, 37.161881, 0], + [129.179263, 37.134102, 0], + [129.176367, 37.119776, 0], + [129.175319, 37.090793, 0], + [129.177172, 37.076357, 0], + [129.182739, 37.055177, 0], + [129.192026, 37.034582, 0], + [129.209262, 37.00906, 0], + [129.219897, 36.997294, 0], + [129.244798, 36.976197, 0], + [129.258874, 36.967026, 0], + [129.289743, 36.951784, 0], + [129.323445, 36.941049, 0], + [129.350281, 36.935623, 0], + [129.377066, 36.934063, 0], + [129.395219, 36.934245, 0] + ] + ] + }, + "properties": { "name": "P64B", "description": "한울원전 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.369655, 36.410003, 0], + [127.372742, 36.410093, 0], + [127.375027, 36.410554, 0], + [127.37843, 36.411538, 0], + [127.380039, 36.412205, 0], + [127.382269, 36.41327, 0], + [127.383642, 36.414445, 0], + [127.385578, 36.415913, 0], + [127.387247, 36.41776, 0], + [127.388507, 36.419578, 0], + [127.38965, 36.4218, 0], + [127.390158, 36.423729, 0], + [127.39068, 36.426117, 0], + [127.390418, 36.428081, 0], + [127.390037, 36.430226, 0], + [127.38965, 36.43178, 0], + [127.388584, 36.433688, 0], + [127.387755, 36.434983, 0], + [127.386518, 36.436475, 0], + [127.384476, 36.438452, 0], + [127.382612, 36.439721, 0], + [127.380724, 36.440964, 0], + [127.377977, 36.442034, 0], + [127.375832, 36.442621, 0], + [127.372742, 36.443242, 0], + [127.369828, 36.443392, 0], + [127.368019, 36.443335, 0], + [127.364454, 36.442841, 0], + [127.361584, 36.442138, 0], + [127.35944, 36.44119, 0], + [127.357909, 36.440412, 0], + [127.356469, 36.439531, 0], + [127.354631, 36.437995, 0], + [127.353473, 36.436855, 0], + [127.352657, 36.435854, 0], + [127.350972, 36.433815, 0], + [127.349721, 36.431084, 0], + [127.349224, 36.428672, 0], + [127.348993, 36.426766, 0], + [127.349294, 36.423866, 0], + [127.350216, 36.421052, 0], + [127.350902, 36.419704, 0], + [127.351731, 36.418409, 0], + [127.352829, 36.416586, 0], + [127.355011, 36.414941, 0], + [127.356341, 36.413953, 0], + [127.358666, 36.412442, 0], + [127.360896, 36.411597, 0], + [127.362565, 36.411034, 0], + [127.365189, 36.410369, 0], + [127.367077, 36.410093, 0], + [127.369655, 36.410003, 0] + ] + ] + }, + "properties": { "name": "P65A", "description": "한국원자력 연구원 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.381494, 36.260519, 0], + [127.407761, 36.262546, 0], + [127.434431, 36.268611, 0], + [127.457199, 36.276386, 0], + [127.482988, 36.287454, 0], + [127.502518, 36.299632, 0], + [127.523869, 36.315771, 0], + [127.535291, 36.327, 0], + [127.545458, 36.338987, 0], + [127.554292, 36.351641, 0], + [127.564316, 36.368222, 0], + [127.571869, 36.387571, 0], + [127.57511, 36.406953, 0], + [127.576483, 36.421429, 0], + [127.576282, 36.435946, 0], + [127.57451, 36.450394, 0], + [127.571178, 36.464663, 0], + [127.566311, 36.478643, 0], + [127.559945, 36.492229, 0], + [127.552127, 36.505316, 0], + [127.542918, 36.517806, 0], + [127.529297, 36.533916, 0], + [127.516251, 36.544949, 0], + [127.499771, 36.556533, 0], + [127.478787, 36.568133, 0], + [127.455139, 36.579144, 0], + [127.429481, 36.586008, 0], + [127.402267, 36.592376, 0], + [127.380295, 36.593479, 0], + [127.358, 36.592811, 0], + [127.340009, 36.591352, 0], + [127.322247, 36.588637, 0], + [127.299271, 36.583004, 0], + [127.271672, 36.573211, 0], + [127.251205, 36.563152, 0], + [127.235413, 36.551569, 0], + [127.215231, 36.537366, 0], + [127.203824, 36.526108, 0], + [127.192841, 36.51074, 0], + [127.177507, 36.488162, 0], + [127.171591, 36.474446, 0], + [127.164688, 36.453322, 0], + [127.163026, 36.431552, 0], + [127.163315, 36.412442, 0], + [127.168121, 36.391993, 0], + [127.173486, 36.374373, 0], + [127.181168, 36.354951, 0], + [127.197019, 36.335281, 0], + [127.207575, 36.323515, 0], + [127.21936, 36.312533, 0], + [127.239532, 36.296865, 0], + [127.261152, 36.285095, 0], + [127.285538, 36.274172, 0], + [127.302704, 36.269743, 0], + [127.321243, 36.26476, 0], + [127.345535, 36.2614, 0], + [127.363491, 36.260328, 0], + [127.381494, 36.260519, 0] + ] + ] + }, + "properties": { "name": "P65B", "description": "한국원자력 연구원 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.435471, 35.242254, 0], + [126.462278, 35.247083, 0], + [126.489029, 35.254591, 0], + [126.511472, 35.263993, 0], + [126.526466, 35.271886, 0], + [126.540563, 35.280813, 0], + [126.553657, 35.290709, 0], + [126.565933, 35.305039, 0], + [126.581039, 35.321288, 0], + [126.596146, 35.342015, 0], + [126.602325, 35.356016, 0], + [126.608505, 35.372255, 0], + [126.610565, 35.387371, 0], + [126.613312, 35.403043, 0], + [126.612062, 35.423548, 0], + [126.609649, 35.43798, 0], + [126.605701, 35.452185, 0], + [126.600246, 35.466057, 0], + [126.593325, 35.479487, 0], + [126.584991, 35.492375, 0], + [126.575306, 35.504622, 0], + [126.564344, 35.516134, 0], + [126.552187, 35.526823, 0], + [126.538929, 35.536608, 0], + [126.524671, 35.545414, 0], + [126.50952, 35.553173, 0], + [126.498642, 35.556809, 0], + [126.477012, 35.565322, 0], + [126.459903, 35.56962, 0], + [126.442397, 35.572685, 0], + [126.424629, 35.574496, 0], + [126.406733, 35.575037, 0], + [126.388848, 35.574305, 0], + [126.37111, 35.572305, 0], + [126.353655, 35.569053, 0], + [126.336617, 35.564573, 0], + [126.320126, 35.558901, 0], + [126.304308, 35.552078, 0], + [126.289284, 35.544158, 0], + [126.275169, 35.535201, 0], + [126.26207, 35.525276, 0], + [126.250087, 35.514458, 0], + [126.239311, 35.50283, 0], + [126.229824, 35.490481, 0], + [126.221698, 35.477505, 0], + [126.214994, 35.464002, 0], + [126.209763, 35.450074, 0], + [126.206043, 35.435827, 0], + [126.203862, 35.421371, 0], + [126.203237, 35.406814, 0], + [126.20417, 35.392269, 0], + [126.206654, 35.377845, 0], + [126.210669, 35.363652, 0], + [126.216185, 35.349799, 0], + [126.223157, 35.33639, 0], + [126.231533, 35.323527, 0], + [126.241249, 35.311308, 0], + [126.25223, 35.299825, 0], + [126.264392, 35.289166, 0], + [126.277642, 35.279411, 0], + [126.291881, 35.270635, 0], + [126.306999, 35.262903, 0], + [126.322878, 35.256276, 0], + [126.339406, 35.250801, 0], + [126.356454, 35.24652, 0], + [126.380539, 35.242815, 0], + [126.399765, 35.240572, 0], + [126.421738, 35.241133, 0], + [126.435471, 35.242254, 0] + ] + ] + }, + "properties": { "name": "P63B", "description": "한빛원전 비행금지구역", "type": "0001" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.806602, 37.665342, 0], + [126.803835, 37.631193, 0], + [126.797918, 37.617409, 0], + [126.804616, 37.591766, 0], + [126.806314, 37.568915, 0], + [126.954214, 37.448681, 0], + [127.060124, 37.447895, 0], + [127.112876, 37.542422, 0], + [127.158247, 37.57961, 0], + [127.141384, 37.615876, 0], + [127.133203, 37.640745, 0], + [127.086943, 37.675806, 0], + [127.054827, 37.693242, 0], + [127.029397, 37.701319, 0], + [126.883354, 37.633327, 0], + [126.806602, 37.665342, 0] + ] + ] + }, + "properties": { + "name": "R75", + "description": "국방부(중앙방공통제소/수방사 방공작전통제소)비행 제한구역", + "type": "0002" + } + }, + { + "type": "Feature", + "geometry": { "type": "LineString", "coordinates": [ + [127.759601, 36.449348, 152.1], + [127.756734, 36.451118, 154.85], + [127.75407, 36.453082, 167.68], + [127.751629, 36.455226, 192.58], + [127.749429, 36.457532, 221.69], + [127.747488, 36.459984, 202.52], + [127.745819, 36.462563, 171.99], + [127.744436, 36.465249, 203.55], + [127.74335, 36.468021, 209.87], + [127.742568, 36.470859, 189.05], + [127.742096, 36.473741, 178.53], + [127.741939, 36.476646, 193.8], + [127.742097, 36.47955, 230.4], + [127.742569, 36.482432, 234.84], + [127.743352, 36.48527, 279.86], + [127.74444, 36.488042, 291.94], + [127.745824, 36.490728, 233.25], + [127.747494, 36.493306, 194.28], + [127.749437, 36.495757, 176], + [127.751639, 36.498063, 193.79], + [127.754083, 36.500206, 195.66], + [127.75675, 36.502169, 196.11], + [127.75962, 36.503938, 212.39], + [127.76267, 36.505499, 248.12], + [127.765879, 36.506841, 333.2], + [127.769221, 36.507952, 518.74], + [127.77267, 36.508825, 504.89], + [127.776202, 36.509453, 505.82], + [127.779788, 36.509831, 433.91], + [127.783401, 36.509956, 377.42], + [127.787014, 36.509828, 393.93], + [127.7906, 36.509446, 407.04], + [127.79413, 36.508815, 501.18], + [127.797579, 36.507939, 404.22], + [127.800919, 36.506825, 465.77], + [127.804126, 36.50548, 376.27], + [127.807174, 36.503916, 379.23], + [127.810041, 36.502145, 365.86], + [127.812705, 36.500179, 346.64], + [127.815146, 36.498034, 368.49], + [127.817345, 36.495726, 424.47], + [127.819285, 36.493273, 410.52], + [127.820951, 36.490693, 485.16], + [127.822331, 36.488006, 406.51], + [127.823415, 36.485233, 288.69], + [127.824194, 36.482394, 217.51], + [127.824662, 36.479512, 337.61], + [127.824816, 36.476607, 467.23], + [127.824655, 36.473703, 522.65], + [127.824179, 36.470822, 359.36], + [127.823393, 36.467984, 317.61], + [127.822302, 36.465213, 311.88], + [127.820916, 36.462528, 247.76], + [127.819243, 36.459951, 199.48], + [127.817298, 36.457501, 174.99], + [127.815095, 36.455196, 163.21], + [127.812651, 36.453055, 159.95], + [127.809984, 36.451093, 147.06], + [127.807115, 36.449326, 147.6], + [127.804066, 36.447766, 149.99], + [127.800859, 36.446426, 148.67], + [127.797519, 36.445316, 165.77], + [127.794072, 36.444444, 203.2], + [127.790543, 36.443817, 243.26], + [127.78696, 36.443439, 221.37], + [127.78335, 36.443315, 249.24], + [127.779739, 36.443443, 314.82], + [127.776157, 36.443824, 268.81], + [127.77263, 36.444455, 271.6], + [127.769184, 36.445331, 240.26], + [127.765846, 36.446445, 177.85], + [127.762641, 36.447788, 162.43], + [127.759601, 36.449348, 152.1] + ] + }, + "properties": { "name": "R20", "description": "보은 반경 3.7Km 비행 제한구역", "type": "0002", "tessellate": true} + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [129.099492, 35.548315, 268.13], + [129.102252, 35.546479, 186.41], + [129.104805, 35.544453, 148.29], + [129.107132, 35.542255, 119.42], + [129.109213, 35.539899, 111.45], + [129.111035, 35.537405, 105.85], + [129.112582, 35.534792, 110.49], + [129.113844, 35.532078, 104.67], + [129.114809, 35.529286, 101.01], + [129.115472, 35.526435, 103.71], + [129.115828, 35.523548, 132.5], + [129.115872, 35.520647, 134.36], + [129.115606, 35.517754, 143.33], + [129.115031, 35.514891, 135.94], + [129.114152, 35.51208, 114.63], + [129.112975, 35.509341, 124.35], + [129.11151, 35.506697, 140.31], + [129.109767, 35.504166, 124.4], + [129.107759, 35.501769, 162.19], + [129.105503, 35.499523, 117.72], + [129.103016, 35.497446, 140.82], + [129.100315, 35.495553, 166.17], + [129.097422, 35.493859, 170.76], + [129.094359, 35.492377, 156.81], + [129.091149, 35.491118, 123.69], + [129.087817, 35.490091, 122.07], + [129.084387, 35.489304, 123.95], + [129.080887, 35.488764, 187.75], + [129.077341, 35.488474, 234.76], + [129.073779, 35.488436, 195.94], + [129.070225, 35.488652, 161.27], + [129.066709, 35.489119, 181.83], + [129.063255, 35.489833, 208.21], + [129.059892, 35.49079, 202.94], + [129.056643, 35.491982, 184.97], + [129.053534, 35.493399, 203.61], + [129.050589, 35.495032, 244.1], + [129.047829, 35.496867, 310.42], + [129.045276, 35.498892, 414.63], + [129.04295, 35.501089, 539.02], + [129.040868, 35.503444, 649.56], + [129.039045, 35.505937, 805.94], + [129.037497, 35.50855, 961.18], + [129.036233, 35.511263, 961.96], + [129.035265, 35.514055, 851.89], + [129.0346, 35.516905, 731.27], + [129.034242, 35.519791, 655.01], + [129.034195, 35.522692, 750.99], + [129.034459, 35.525585, 654.58], + [129.035031, 35.528449, 624.33], + [129.035909, 35.531261, 766.1], + [129.037084, 35.534, 857.78], + [129.038548, 35.536645, 852.75], + [129.040289, 35.539177, 938.24], + [129.042296, 35.541575, 976.14], + [129.044552, 35.543821, 952.54], + [129.04704, 35.545899, 939.22], + [129.049741, 35.547793, 834.62], + [129.052635, 35.549488, 642.33], + [129.055699, 35.550971, 522.72], + [129.058911, 35.552231, 413.08], + [129.062246, 35.553259, 344.14], + [129.065679, 35.554045, 315.6], + [129.069182, 35.554586, 263.38], + [129.07273, 35.554876, 220.55], + [129.076296, 35.554913, 202.62], + [129.079852, 35.554697, 182.8], + [129.083371, 35.554229, 174.84], + [129.086827, 35.553514, 174.24], + [129.090193, 35.552556, 143.96], + [129.093444, 35.551363, 146.97], + [129.096554, 35.549944, 191.75], + [129.099492, 35.548315, 268.13] + ] + }, + "properties": { "name": "R21", "description": "언양 반경 3.7Km 비행 제한구역", "type": "0002", "tessellate": true} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.683234, 37.216605, 0], + [128.682118, 36.917125, 0], + [129.049784, 36.917216, 0], + [129.052174, 37.217423, 0], + [128.683234, 37.216605, 0] + ] + ] + }, + "properties": { "name": "R110", "description": "필승 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.683333, 37.633333, 0], + [127.683341, 37.533289, 0], + [127.8, 37.533333, 0], + [127.782774, 37.617603, 0], + [127.732937, 37.650247, 0], + [127.683333, 37.633333, 0] + ] + ] + }, + "properties": { "name": "R10", "description": "매봉 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7, 35.15, 0], + [126.683301, 35.135438, 0], + [126.688471, 35.129529, 0], + [126.683367, 35.099909, 0], + [126.749886, 35.083009, 0], + [126.766222, 35.133185, 0], + [126.733333, 35.15, 0], + [126.7, 35.15, 0] + ] + ] + }, + "properties": { "name": "R14", "description": "평동 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [127.647392, 37.409477, 297.32], + [127.655253, 37.405761, 271.8], + [127.662676, 37.401515, 147.38], + [127.669605, 37.396771, 145.62], + [127.675985, 37.391564, 157.25], + [127.681769, 37.385936, 77.98], + [127.686913, 37.379928, 117.87], + [127.691377, 37.373586, 169.27], + [127.695128, 37.366959, 218.33], + [127.698138, 37.360098, 237.61], + [127.700383, 37.353054, 223.02], + [127.701847, 37.345881, 186.23], + [127.702519, 37.338634, 85.32], + [127.702394, 37.331368, 58.07], + [127.701473, 37.324139, 97.89], + [127.699763, 37.317001, 86.47], + [127.697278, 37.310008, 80.28], + [127.694037, 37.303214, 62.02], + [127.690065, 37.296671, 51.73], + [127.685391, 37.290428, 62.12], + [127.680052, 37.284532, 37.31], + [127.674088, 37.279029, 56.45], + [127.667545, 37.27396, 60.76], + [127.660473, 37.269363, 58.61], + [127.652925, 37.265275, 78.09], + [127.644958, 37.261724, 74.95], + [127.636634, 37.258739, 91.82], + [127.628015, 37.256343, 181.92], + [127.619167, 37.254553, 112.83], + [127.610157, 37.253382, 95.32], + [127.601054, 37.252841, 96.31], + [127.591925, 37.252932, 80.98], + [127.582841, 37.253656, 79.86], + [127.573871, 37.255006, 71.09], + [127.565082, 37.256973, 69.81], + [127.556542, 37.259541, 61.57], + [127.548315, 37.262692, 50.81], + [127.540463, 37.266401, 58.04], + [127.533046, 37.270639, 77.15], + [127.526122, 37.275376, 78.77], + [127.519741, 37.280574, 69.58], + [127.513953, 37.286195, 56.01], + [127.508802, 37.292196, 56.73], + [127.504327, 37.298531, 48.85], + [127.500563, 37.305152, 69.37], + [127.497537, 37.312008, 64.39], + [127.495275, 37.319048, 69.58], + [127.493792, 37.326218, 85.3], + [127.4931, 37.333464, 74.89], + [127.493205, 37.34073, 63.04], + [127.494106, 37.347961, 69.88], + [127.495797, 37.355102, 94.87], + [127.498265, 37.362099, 135.73], + [127.501491, 37.368898, 176.17], + [127.505451, 37.375448, 105.59], + [127.510115, 37.381698, 93.56], + [127.515448, 37.387601, 109.39], + [127.521409, 37.393112, 129.15], + [127.527952, 37.398189, 142.15], + [127.535029, 37.402793, 57.93], + [127.542585, 37.40689, 34.99], + [127.550562, 37.410447, 190.15], + [127.558899, 37.413437, 80.84], + [127.567534, 37.415839, 59.76], + [127.5764, 37.417633, 60.31], + [127.585429, 37.418806, 69.99], + [127.594553, 37.419348, 61.79], + [127.603701, 37.419256, 89.07], + [127.612805, 37.418531, 64.98], + [127.621794, 37.417178, 109.43], + [127.6306, 37.415206, 177.95], + [127.639155, 37.412633, 252.75], + [127.647392, 37.409477, 297.32] + ] + }, + "properties": { "name": "R17", "description": "여주 반경 9.26Km 비행 제한구역", "type": "0002", "tessellate": true} + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [127.251125, 36.636601, 136.79], + [127.25379, 36.634637, 102.43], + [127.256231, 36.632495, 81.92], + [127.25843, 36.63019, 49.89], + [127.26037, 36.627739, 53.59], + [127.262037, 36.625163, 76.63], + [127.263417, 36.622479, 147.17], + [127.264501, 36.61971, 141.24], + [127.265279, 36.616875, 126.76], + [127.265747, 36.613996, 90.52], + [127.2659, 36.611095, 145.43], + [127.265738, 36.608195, 114.93], + [127.265262, 36.605317, 96.67], + [127.264475, 36.602484, 98.97], + [127.263383, 36.599716, 69.82], + [127.261995, 36.597035, 42.2], + [127.260322, 36.594462, 43.01], + [127.258375, 36.592015, 75.27], + [127.256171, 36.589714, 53.21], + [127.253725, 36.587576, 73.24], + [127.251057, 36.585617, 68.78], + [127.248186, 36.583852, 60.46], + [127.245135, 36.582295, 85.54], + [127.241927, 36.580957, 74.46], + [127.238585, 36.579849, 122.01], + [127.235136, 36.578978, 71.69], + [127.231606, 36.578352, 123.92], + [127.228022, 36.577976, 82.24], + [127.22441, 36.577852, 102.55], + [127.220798, 36.577981, 143.51], + [127.217215, 36.578362, 169.25], + [127.213686, 36.578992, 187.34], + [127.210239, 36.579867, 187.35], + [127.206899, 36.58098, 223.48], + [127.203694, 36.582322, 169.42], + [127.200646, 36.583884, 156.01], + [127.197779, 36.585652, 122.4], + [127.195114, 36.587615, 125.4], + [127.192673, 36.589756, 183.21], + [127.190473, 36.59206, 251.79], + [127.188532, 36.594509, 291.27], + [127.186864, 36.597085, 248.69], + [127.185482, 36.599768, 204.47], + [127.184396, 36.602537, 178.21], + [127.183614, 36.605371, 184.48], + [127.183144, 36.60825, 197.6], + [127.182988, 36.61115, 182.64], + [127.183147, 36.61405, 189.88], + [127.183621, 36.616928, 192.34], + [127.184405, 36.619762, 185.71], + [127.185494, 36.622531, 178.33], + [127.18688, 36.625212, 148.02], + [127.188552, 36.627787, 177.68], + [127.190497, 36.630235, 234.57], + [127.192701, 36.632537, 216.73], + [127.195147, 36.634676, 209.57], + [127.197815, 36.636636, 259.45], + [127.200687, 36.638402, 262.62], + [127.203739, 36.63996, 321.47], + [127.20695, 36.641299, 209.61], + [127.210294, 36.642408, 175.27], + [127.213745, 36.643279, 106.32], + [127.217278, 36.643905, 66.86], + [127.220866, 36.644282, 95.91], + [127.224481, 36.644406, 144.65], + [127.228095, 36.644277, 117.85], + [127.231682, 36.643895, 87.54], + [127.235214, 36.643264, 103.93], + [127.238663, 36.642388, 159.87], + [127.242005, 36.641274, 152.7], + [127.245212, 36.639931, 174.67], + [127.248261, 36.638368, 143.36], + [127.251125, 36.636601, 136.79] + ] + }, + "properties": { "name": "R19", "description": "조치원 반경 3.7Km 비행 제한구역", "type": "0002", "tessellate": true} + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [127.227106, 37.336732, 115.22], + [127.224609, 37.338853, 68.07], + [127.222353, 37.341139, 90.25], + [127.220357, 37.343573, 74.78], + [127.218634, 37.346136, 75.26], + [127.217199, 37.348808, 73.78], + [127.216063, 37.351569, 83.69], + [127.215233, 37.354399, 105.98], + [127.214717, 37.357275, 108.83], + [127.214519, 37.360177, 105.33], + [127.214639, 37.36308, 146.39], + [127.215077, 37.365965, 192.35], + [127.21583, 37.368808, 185.15], + [127.216891, 37.371588, 108.15], + [127.218254, 37.374285, 86.97], + [127.219908, 37.376876, 163.17], + [127.221839, 37.379343, 135.68], + [127.224034, 37.381667, 159.11], + [127.226475, 37.38383, 151.91], + [127.229145, 37.385815, 80.68], + [127.232022, 37.387608, 62.57], + [127.235086, 37.389195, 53.1], + [127.238311, 37.390564, 47.16], + [127.241675, 37.391704, 47.68], + [127.245151, 37.392606, 46.94], + [127.248713, 37.393265, 45.57], + [127.252334, 37.393674, 38.09], + [127.255986, 37.393831, 43.32], + [127.259641, 37.393734, 77.14], + [127.263271, 37.393384, 169.46], + [127.266849, 37.392784, 223.66], + [127.270348, 37.391939, 223.75], + [127.273741, 37.390854, 156.53], + [127.277001, 37.389538, 150.35], + [127.280105, 37.388002, 136.73], + [127.283028, 37.386256, 154.64], + [127.285749, 37.384315, 75.59], + [127.288246, 37.382192, 121.41], + [127.290501, 37.379905, 131.65], + [127.292496, 37.37747, 91.48], + [127.294216, 37.374906, 119.95], + [127.295648, 37.372233, 85.52], + [127.296782, 37.369471, 86.27], + [127.297608, 37.366641, 104.17], + [127.298121, 37.363764, 179.99], + [127.298316, 37.360862, 282.72], + [127.298193, 37.357959, 182.96], + [127.297751, 37.355074, 190.2], + [127.296995, 37.352232, 310.15], + [127.295931, 37.349452, 368.69], + [127.294565, 37.346757, 395.97], + [127.29291, 37.344167, 373.02], + [127.290977, 37.341701, 282.17], + [127.288781, 37.339379, 241.54], + [127.286339, 37.337217, 300.46], + [127.283669, 37.335233, 360], + [127.280792, 37.333441, 390.09], + [127.27773, 37.331856, 373.8], + [127.274506, 37.330488, 374.17], + [127.271145, 37.329349, 377.82], + [127.267671, 37.328448, 314.8], + [127.264112, 37.32779, 264.61], + [127.260495, 37.327382, 181.28], + [127.256846, 37.327225, 119.3], + [127.253194, 37.327322, 80.18], + [127.249567, 37.327672, 75.81], + [127.245992, 37.328271, 73.26], + [127.242496, 37.329116, 70.54], + [127.239105, 37.3302, 60.3], + [127.235847, 37.331515, 81.87], + [127.232745, 37.33305, 155.27], + [127.229822, 37.334795, 182.25], + [127.227106, 37.336732, 115.22] + ] + }, + "properties": { "name": "R35", "description": "매산리 반경 3.7Km 비행 제한구역", "type": "0002", "tessellate": true} + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [128.202574, 36.34834, 432.3], + [128.19698, 36.354038, 440.03], + [128.192023, 36.360106, 357.13], + [128.18774, 36.3665, 276.11], + [128.184165, 36.373169, 169.68], + [128.181326, 36.380064, 117.19], + [128.179242, 36.387132, 102.1], + [128.177932, 36.394319, 73.25], + [128.177405, 36.40157, 57.81], + [128.177665, 36.408831, 55.49], + [128.17871, 36.416046, 58.75], + [128.180533, 36.423161, 62.5], + [128.183121, 36.43012, 52.92], + [128.186452, 36.436871, 51.19], + [128.190503, 36.443363, 52.55], + [128.195243, 36.449546, 57.49], + [128.200635, 36.455373, 62.71], + [128.20664, 36.4608, 69.35], + [128.21321, 36.465784, 58.74], + [128.220296, 36.470289, 80.77], + [128.227844, 36.474279, 71.78], + [128.235797, 36.477725, 65.47], + [128.244093, 36.4806, 58.03], + [128.25267, 36.482881, 60.74], + [128.261462, 36.484553, 58.16], + [128.270403, 36.485601, 52.41], + [128.279422, 36.486018, 90.89], + [128.288453, 36.485801, 104.27], + [128.297426, 36.484951, 77.8], + [128.306272, 36.483474, 94.57], + [128.314924, 36.481383, 100.61], + [128.323316, 36.478693, 173.12], + [128.331384, 36.475425, 155.55], + [128.339065, 36.471603, 82.79], + [128.346303, 36.467257, 134.78], + [128.353041, 36.46242, 99.65], + [128.359229, 36.457128, 79.93], + [128.364819, 36.451423, 71.1], + [128.369768, 36.445347, 69.1], + [128.37404, 36.438947, 73.68], + [128.377601, 36.432272, 69.35], + [128.380425, 36.425373, 65.57], + [128.382491, 36.418301, 58.41], + [128.383783, 36.411112, 51.66], + [128.38429, 36.403859, 47.12], + [128.384011, 36.396599, 46.08], + [128.382947, 36.389386, 44.95], + [128.381106, 36.382274, 48.76], + [128.378502, 36.375319, 54.28], + [128.375156, 36.368573, 76.85], + [128.371093, 36.362088, 79.65], + [128.366345, 36.355912, 147.71], + [128.360947, 36.350093, 245.77], + [128.35494, 36.344674, 388.88], + [128.348371, 36.339697, 344.26], + [128.341289, 36.3352, 194.13], + [128.333749, 36.331217, 145.2], + [128.325807, 36.327778, 90.24], + [128.317523, 36.324909, 59.23], + [128.308962, 36.322632, 65.57], + [128.300187, 36.320965, 78.21], + [128.291265, 36.319919, 61], + [128.282264, 36.319503, 38.37], + [128.273253, 36.31972, 74.02], + [128.264299, 36.320568, 184.28], + [128.255471, 36.322041, 322.63], + [128.246835, 36.324128, 240.96], + [128.238457, 36.326813, 345.76], + [128.230401, 36.330075, 387.82], + [128.222728, 36.33389, 159.85], + [128.215496, 36.338229, 100.01], + [128.20876, 36.343059, 210.09], + [128.202574, 36.34834, 432.3] + ] + }, + "properties": { "name": "R81", "description": "낙동 반경 9.26Km 비행 제한구역", "type": "0002", "tessellate": true} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.347694, 35.936361, 0], + [129.331028, 35.869694, 0], + [129.431028, 35.953028, 0], + [129.397722, 35.952813, 0], + [129.347694, 35.936361, 0] + ] + ] + }, + "properties": { "name": "R89", "description": "오천 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.429889, 35.926917, 0], + [129.442865, 35.892515, 0], + [129.474083, 35.894694, 0], + [129.517151, 35.886193, 0], + [129.521278, 35.890528, 0], + [129.454889, 35.92275, 0], + [129.429889, 35.926917, 0] + ] + ] + }, + "properties": { "name": "R90A", "description": "수성-A 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.442865, 35.892515, 0], + [129.461942, 35.836086, 0], + [129.495442, 35.843415, 0], + [129.517151, 35.886193, 0], + [129.473742, 35.895155, 0], + [129.442865, 35.892515, 0] + ] + ] + }, + "properties": { "name": "R90B", "description": "수성-B 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.516667, 36.333333, 0], + [126.183333, 36.216667, 0], + [126.4, 36.033333, 0], + [126.583333, 36.3, 0], + [126.516667, 36.333333, 0] + ] + ] + }, + "properties": { "name": "R97A", "description": "철매-A 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [125.95, 36.233333, 0], + [126.05, 36.2, 0], + [126.366667, 35.883333, 0], + [126.633224, 36.237074, 0], + [126.502111, 36.35625, 0], + [126.245472, 36.36875, 0], + [126.166667, 36.333333, 0], + [125.95, 36.333333, 0], + [125.95, 36.233333, 0] + ] + ] + }, + "properties": { "name": "R97B", "description": "철매-B 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [128.886577, 34.924907, 0], + [128.891234, 34.929284, 0], + [128.89634, 34.933312, 0], + [128.901856, 34.93696, 0], + [128.907738, 34.940199, 0], + [128.913943, 34.943005, 0], + [128.920423, 34.945357, 0], + [128.927129, 34.947237, 0], + [128.934009, 34.94863, 0], + [128.941012, 34.949526, 0], + [128.948083, 34.949917, 0], + [128.955169, 34.949802, 0], + [128.962216, 34.949181, 0], + [128.969169, 34.948058, 0], + [128.975977, 34.946442, 0], + [128.982586, 34.944346, 0], + [128.988947, 34.941785, 0], + [128.995012, 34.938779, 0], + [129.000733, 34.935351, 0], + [129.006067, 34.931527, 0], + [129.010974, 34.927336, 0], + [129.015416, 34.922811, 0], + [129.01936, 34.917985, 0], + [129.022775, 34.912895, 0], + [129.025636, 34.907581, 0], + [129.027922, 34.902082, 0], + [129.029613, 34.896441, 0], + [129.030699, 34.890701, 0], + [129.031171, 34.884905, 0], + [129.031024, 34.879097, 0], + [129.030262, 34.873321, 0], + [129.028889, 34.867622, 0], + [129.026916, 34.862043, 0], + [129.024358, 34.856626, 0], + [129.021235, 34.851413, 0], + [129.017571, 34.846443, 0], + [129.013393, 34.841754, 0], + [129.008733, 34.837381, 0], + [129.003628, 34.833358, 0], + [128.998115, 34.829715, 0], + [128.992237, 34.82648, 0], + [128.986038, 34.823678, 0], + [128.979566, 34.821329, 0], + [128.972869, 34.819452, 0], + [128.965999, 34.818062, 0], + [128.959007, 34.817167, 0], + [128.951947, 34.816776, 0], + [128.944873, 34.816891, 0], + [128.937837, 34.817512, 0], + [128.930894, 34.818633, 0], + [128.924096, 34.820246, 0], + [128.917495, 34.822339, 0], + [128.911141, 34.824896, 0], + [128.905083, 34.827898, 0], + [128.899365, 34.831321, 0], + [128.894032, 34.835141, 0], + [128.889125, 34.839327, 0], + [128.88468, 34.843848, 0], + [128.880732, 34.848669, 0], + [128.87731, 34.853755, 0], + [128.874442, 34.859066, 0], + [128.872148, 34.864561, 0], + [128.870446, 34.8702, 0], + [128.869349, 34.875939, 0], + [128.868866, 34.881735, 0], + [128.869001, 34.887543, 0], + [128.869752, 34.893319, 0], + [128.871115, 34.89902, 0], + [128.873078, 34.904602, 0], + [128.875627, 34.910022, 0], + [128.878743, 34.915239, 0], + [128.882402, 34.920213, 0], + [128.886577, 34.924907, 0] + ] + }, + "properties": { "name": "R100", "description": "남형제도 반경 7.4Km 비행 제한구역", "type": "0002", "tessellate": true} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.154617, 36.679506, 0], + [126.151306, 36.549556, 0], + [126.230472, 36.552333, 0], + [126.199639, 36.67675, 0], + [126.154617, 36.679506, 0] + ] + ] + }, + "properties": { "name": "R108A", "description": "안흥-A 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.154617, 36.679506, 0], + [126.124639, 36.469556, 0], + [126.250472, 36.490389, 0], + [126.199639, 36.67675, 0], + [126.154617, 36.679506, 0] + ] + ] + }, + "properties": { "name": "R108B", "description": "안흥-B 비행 제한구역", "type": "0002"} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [125.998, 36.636194, 0], + [125.713889, 35.021944, 0], + [126.052194, 34.973361, 0], + [126.297944, 36.569556, 0], + [126.17325, 36.677306, 0], + [125.998, 36.636194, 0] + ] + ] + }, + "properties": { "name": "R108C", "description": "안흥-C 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.154617, 36.679506, 0], + [126.006333, 36.38625, 0], + [126.152139, 36.36125, 0], + [126.197972, 36.67675, 0], + [126.154617, 36.679506, 0] + ] + ] + }, + "properties": { "name": "R108D", "description": "안흥-D 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.154617, 36.679506, 0], + [126.228528, 36.559556, 0], + [126.265194, 36.560111, 0], + [126.265194, 36.615944, 0], + [126.199917, 36.686472, 0], + [126.154617, 36.679506, 0] + ] + ] + }, + "properties": { "name": "R108E", "description": "안흥-E 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.154617, 36.679506, 0], + [125.943833, 36.302917, 0], + [126.009111, 36.28875, 0], + [126.197972, 36.67675, 0], + [126.154617, 36.679506, 0] + ] + ] + }, + "properties": { "name": "R108F", "description": "안흥-F 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.416667, 36.235278, 0], + [126.420833, 36.101944, 0], + [126.638056, 36.106944, 0], + [126.652222, 36.154444, 0], + [126.649444, 36.240556, 0], + [126.416667, 36.235278, 0] + ] + ] + }, + "properties": { "name": "R111", "description": "응촌 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.785278, 37.572222, 0], + [127.803333, 37.533333, 0], + [127.828333, 37.516667, 0], + [127.87, 37.530556, 0], + [127.875556, 37.559722, 0], + [127.861667, 37.572222, 0], + [127.785278, 37.572222, 0] + ] + ] + }, + "properties": { "name": "R114", "description": "비승 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [125.826484, 34.740764, 0], + [125.829562, 34.73397, 0], + [125.831907, 34.72698, 0], + [125.833502, 34.719849, 0], + [125.834335, 34.712631, 0], + [125.834399, 34.705381, 0], + [125.833694, 34.698154, 0], + [125.832226, 34.691005, 0], + [125.830007, 34.683988, 0], + [125.827052, 34.677157, 0], + [125.823385, 34.670564, 0], + [125.819034, 34.664258, 0], + [125.814032, 34.658288, 0], + [125.808417, 34.6527, 0], + [125.802232, 34.647534, 0], + [125.795525, 34.642832, 0], + [125.788345, 34.638627, 0], + [125.780748, 34.634954, 0], + [125.772791, 34.631838, 0], + [125.764536, 34.629304, 0], + [125.756043, 34.627372, 0], + [125.747379, 34.626055, 0], + [125.738608, 34.625364, 0], + [125.729798, 34.625304, 0], + [125.721014, 34.625876, 0], + [125.712324, 34.627074, 0], + [125.703794, 34.628891, 0], + [125.695489, 34.631312, 0], + [125.687471, 34.634319, 0], + [125.679801, 34.637889, 0], + [125.672538, 34.641995, 0], + [125.665737, 34.646605, 0], + [125.659449, 34.651686, 0], + [125.653722, 34.657197, 0], + [125.648601, 34.663098, 0], + [125.644124, 34.669344, 0], + [125.640325, 34.675886, 0], + [125.637233, 34.682676, 0], + [125.634872, 34.689662, 0], + [125.633261, 34.69679, 0], + [125.632411, 34.704007, 0], + [125.632329, 34.711257, 0], + [125.633016, 34.718485, 0], + [125.634467, 34.725636, 0], + [125.636671, 34.732657, 0], + [125.639612, 34.739492, 0], + [125.643267, 34.746091, 0], + [125.647609, 34.752403, 0], + [125.652604, 34.75838, 0], + [125.658216, 34.763976, 0], + [125.6644, 34.769149, 0], + [125.67111, 34.773859, 0], + [125.678296, 34.77807, 0], + [125.685901, 34.78175, 0], + [125.693869, 34.784871, 0], + [125.702138, 34.78741, 0], + [125.710646, 34.789346, 0], + [125.719327, 34.790666, 0], + [125.728115, 34.791358, 0], + [125.736943, 34.791418, 0], + [125.745744, 34.790846, 0], + [125.75445, 34.789645, 0], + [125.762996, 34.787825, 0], + [125.771315, 34.785399, 0], + [125.779345, 34.782387, 0], + [125.787024, 34.778811, 0], + [125.794293, 34.774699, 0], + [125.801098, 34.770081, 0], + [125.807386, 34.764993, 0], + [125.81311, 34.759474, 0], + [125.818226, 34.753567, 0], + [125.822694, 34.747315, 0], + [125.826484, 34.740764, 0] + ] + }, + "properties": { "name": "R117", "description": "자은도 반경 9.26Km 비행 제한구역", "type": "0002", "tessellate": true } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.520611, 37.536694, 0], + [127.470446, 37.52053, 0], + [127.470333, 37.511694, 0], + [127.52975, 37.511694, 0], + [127.520611, 37.536694, 0] + ] + ] + }, + "properties": { "name": "R1", "description": "용문 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [126.23907, 35.788827, 0], + [126.22751, 35.777749, 0], + [126.214807, 35.76753, 0], + [126.201058, 35.758246, 0], + [126.186366, 35.749969, 0], + [126.170845, 35.74276, 0], + [126.154611, 35.736674, 0], + [126.137788, 35.731757, 0], + [126.120503, 35.728047, 0], + [126.102886, 35.725572, 0], + [126.085071, 35.724349, 0], + [126.067193, 35.72439, 0], + [126.049387, 35.725692, 0], + [126.031787, 35.728247, 0], + [126.014527, 35.732035, 0], + [125.997738, 35.737027, 0], + [125.981546, 35.743186, 0], + [125.966074, 35.750464, 0], + [125.95144, 35.758808, 0], + [125.937754, 35.768153, 0], + [125.925121, 35.77843, 0], + [125.913636, 35.789559, 0], + [125.903388, 35.801457, 0], + [125.894455, 35.814034, 0], + [125.886904, 35.827193, 0], + [125.880795, 35.840836, 0], + [125.876173, 35.854858, 0], + [125.873076, 35.869154, 0], + [125.871527, 35.883614, 0], + [125.871539, 35.898128, 0], + [125.873113, 35.912586, 0], + [125.876238, 35.926878, 0], + [125.88089, 35.940894, 0], + [125.887036, 35.954529, 0], + [125.894628, 35.967678, 0], + [125.90361, 35.980241, 0], + [125.913914, 35.992121, 0], + [125.925462, 36.003229, 0], + [125.938165, 36.013478, 0], + [125.951928, 36.022792, 0], + [125.966645, 36.031098, 0], + [125.982204, 36.038334, 0], + [125.998487, 36.044443, 0], + [126.015368, 36.049379, 0], + [126.032719, 36.053104, 0], + [126.050406, 36.05559, 0], + [126.068295, 36.056817, 0], + [126.086249, 36.056777, 0], + [126.104129, 36.055469, 0], + [126.121799, 36.052903, 0], + [126.139124, 36.0491, 0], + [126.155971, 36.044088, 0], + [126.172211, 36.037906, 0], + [126.18772, 36.030601, 0], + [126.202379, 36.022228, 0], + [126.216078, 36.012853, 0], + [126.228711, 36.002546, 0], + [126.240182, 35.991387, 0.69], + [126.250404, 35.97946, 0], + [126.259299, 35.966857, 0], + [126.266801, 35.953675, 0], + [126.272853, 35.940012, 0], + [126.277409, 35.925975, 0], + [126.280435, 35.911669, 0], + [126.28191, 35.897204, 0], + [126.281823, 35.88269, 0], + [126.280175, 35.868238, 0], + [126.27698, 35.853957, 0], + [126.272262, 35.839955, 0], + [126.266059, 35.82634, 0], + [126.258419, 35.813215, 0], + [126.2494, 35.800678, 0], + [126.23907, 35.788827, 0] + ] + }, + "properties": { "name": "R105", "description": "직도 반경 18.52Km 비행 제한구역", "type": "0002", "tessellate": true } + }, + { + "type": "Feature", + "geometry": { "type": "LineString", + "coordinates": [ + [126.531181, 35.586883, 23.54], + [126.535032, 35.580315, 62.74], + [126.538164, 35.573498, 0], + [126.540553, 35.566486, 0], + [126.542181, 35.55933, 0], + [126.543037, 35.552087, 0], + [126.543113, 35.54481, 0], + [126.542409, 35.537556, 0.41], + [126.540931, 35.530379, 1.26], + [126.538691, 35.523334, 5.76], + [126.535705, 35.516475, 9.66], + [126.531996, 35.509853, 12.76], + [126.527594, 35.50352, 49.04], + [126.52253, 35.497523, 84.35], + [126.516845, 35.491908, 84.86], + [126.510581, 35.486718, 79.77], + [126.503787, 35.481991, 69.11], + [126.496513, 35.477764, 52.97], + [126.488814, 35.474069, 31.48], + [126.480751, 35.470934, 9.8], + [126.472383, 35.468382, 9.32], + [126.463774, 35.466434, 7.62], + [126.45499, 35.465103, 5.72], + [126.446097, 35.464401, 3.64], + [126.437163, 35.464331, 1.39], + [126.428256, 35.464896, 0], + [126.419442, 35.46609, 0], + [126.41079, 35.467904, 0], + [126.402364, 35.470325, 0], + [126.394228, 35.473335, 0], + [126.386445, 35.47691, 0], + [126.379074, 35.481023, 0], + [126.37217, 35.485644, 0], + [126.365785, 35.490736, 0], + [126.35997, 35.496262, 0], + [126.354767, 35.502179, 0], + [126.350217, 35.508443, 0], + [126.346355, 35.515006, 0], + [126.343209, 35.521817, 0], + [126.340804, 35.528826, 0], + [126.339158, 35.535979, 0], + [126.338284, 35.543221, 0], + [126.33819, 35.550498, 0], + [126.338875, 35.557753, 0], + [126.340335, 35.564932, 0], + [126.34256, 35.571981, 0], + [126.345531, 35.578845, 0], + [126.349227, 35.585472, 0], + [126.35362, 35.591812, 0], + [126.358677, 35.597816, 0], + [126.364358, 35.603438, 0], + [126.370622, 35.608636, 0], + [126.37742, 35.61337, 0], + [126.3847, 35.617605, 0], + [126.392407, 35.621306, 0], + [126.400482, 35.624447, 0], + [126.408864, 35.627004, 0], + [126.417488, 35.628956, 0], + [126.42629, 35.630289, 0], + [126.435201, 35.630993, 0], + [126.444154, 35.631063, 0], + [126.45308, 35.630497, 0.06], + [126.461911, 35.629301, 4.86], + [126.47058, 35.627483, 7.09], + [126.47902, 35.625057, 7.66], + [126.487168, 35.622041, 71.66], + [126.49496, 35.61846, 151.7], + [126.502339, 35.61434, 231.89], + [126.509246, 35.609712, 294.76], + [126.515631, 35.604612, 147.37], + [126.521443, 35.599078, 154.46], + [126.52664, 35.593154, 119.22], + [126.531181, 35.586883, 23.54] + ] + }, + "properties": { "name": "R104", "description": "미여도 반경 9.25Km 비행 제한구역", "type": "0002", "tessellate": true } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.444778, 37.370861, 0], + [127.412556, 37.33475, 0], + [127.428667, 37.321972, 0], + [127.473111, 37.36725, 0], + [127.444778, 37.370861, 0] + ] + ] + }, + "properties": { "name": "R122", "description": "천덕봉 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [125.302553, 34.476138, 0], + [125.294924, 34.479825, 0], + [125.287712, 34.484045, 0], + [125.280973, 34.488767, 0], + [125.274758, 34.493955, 0], + [125.269115, 34.49957, 0], + [125.264086, 34.505568, 0], + [125.25971, 34.511904, 0], + [125.25602, 34.518531, 0], + [125.253045, 34.525397, 0], + [125.250807, 34.532451, 0], + [125.249323, 34.539638, 0], + [125.248606, 34.546905, 0], + [125.248659, 34.554195, 0], + [125.249485, 34.561454, 0], + [125.251075, 34.568626, 0], + [125.253419, 34.575656, 0], + [125.256499, 34.582492, 0], + [125.260291, 34.58908, 0], + [125.264766, 34.595371, 0], + [125.269892, 34.601317, 0], + [125.275628, 34.606872, 0], + [125.281931, 34.611995, 0], + [125.288754, 34.616645, 0], + [125.296044, 34.620788, 0], + [125.303745, 34.624391, 0], + [125.3118, 34.627428, 0], + [125.320146, 34.629876, 0], + [125.32872, 34.631715, 0], + [125.337456, 34.632931, 0], + [125.346288, 34.633516, 0], + [125.355148, 34.633464, 0], + [125.36397, 34.632777, 0], + [125.372684, 34.631459, 0], + [125.381225, 34.62952, 0], + [125.389529, 34.626976, 0], + [125.39753, 34.623845, 0], + [125.405169, 34.620152, 0], + [125.412387, 34.615925, 0], + [125.419128, 34.611196, 0], + [125.425343, 34.606001, 0], + [125.430983, 34.600379, 0], + [125.436006, 34.594375, 0], + [125.440373, 34.588032, 0], + [125.444051, 34.5814, 0], + [125.447013, 34.574529, 0], + [125.449236, 34.567472, 0], + [125.450703, 34.560283, 0], + [125.451404, 34.553015, 0], + [125.451333, 34.545725, 0], + [125.45049, 34.538467, 0], + [125.448884, 34.531298, 0], + [125.446525, 34.524271, 0], + [125.443432, 34.51744, 0], + [125.439629, 34.510857, 0], + [125.435145, 34.504572, 0], + [125.430014, 34.498633, 0], + [125.424275, 34.493085, 0], + [125.417972, 34.48797, 0], + [125.411153, 34.483327, 0], + [125.40387, 34.479191, 0], + [125.396178, 34.475593, 0], + [125.388135, 34.472561, 0], + [125.379803, 34.470118, 0], + [125.371244, 34.468283, 0], + [125.362525, 34.467068, 0], + [125.35371, 34.466485, 0], + [125.344868, 34.466536, 0], + [125.336064, 34.467222, 0], + [125.327366, 34.468537, 0], + [125.31884, 34.470471, 0], + [125.31055, 34.473011, 0], + [125.302553, 34.476138, 0] + ] + }, + "properties": { "name": "R125", "description": "흑산도 반경 9.26Km 비행 제한구역", "type": "0002", "tessellate": true } + }, + { + "type": "Feature", + "geometry": { "type": "LineString", + "coordinates": [ + [127.307229, 34.903117, 467.12], + [127.308561, 34.903049, 418.61], + [127.309881, 34.902887, 364.81], + [127.311179, 34.902631, 317.22], + [127.312445, 34.902283, 283.77], + [127.313668, 34.901847, 242.02], + [127.314841, 34.901324, 203.83], + [127.315954, 34.900719, 171.78], + [127.316998, 34.900037, 154.22], + [127.317965, 34.899284, 134.34], + [127.318849, 34.898463, 114.47], + [127.319643, 34.897583, 97.68], + [127.320339, 34.89665, 84.38], + [127.320934, 34.89567, 82.68], + [127.321423, 34.894651, 74.25], + [127.321801, 34.893601, 68.15], + [127.322066, 34.892529, 62.6], + [127.322217, 34.891441, 63.12], + [127.322251, 34.890347, 54.2], + [127.322169, 34.889254, 48.12], + [127.321971, 34.888172, 46.93], + [127.321658, 34.887107, 44.62], + [127.321234, 34.88607, 42.84], + [127.320702, 34.885066, 41.63], + [127.320064, 34.884104, 56.91], + [127.319327, 34.883192, 68.21], + [127.318496, 34.882336, 60.26], + [127.317577, 34.881542, 46.99], + [127.316577, 34.880817, 40.61], + [127.315504, 34.880166, 29.14], + [127.314366, 34.879595, 26], + [127.313172, 34.879107, 32.05], + [127.31193, 34.878706, 31.52], + [127.31065, 34.878396, 27.17], + [127.309343, 34.878178, 26.76], + [127.308017, 34.878055, 30.91], + [127.306683, 34.878027, 33.22], + [127.305351, 34.878094, 36.18], + [127.304032, 34.878256, 42.11], + [127.302734, 34.878512, 45.59], + [127.301469, 34.87886, 45.2], + [127.300246, 34.879297, 45.86], + [127.299073, 34.879819, 51.32], + [127.297961, 34.880424, 71.3], + [127.296917, 34.881106, 80.51], + [127.295949, 34.881859, 82.88], + [127.295066, 34.882679, 86.18], + [127.294272, 34.88356, 86.98], + [127.293575, 34.884493, 89.69], + [127.29298, 34.885473, 97.18], + [127.292492, 34.886491, 108.37], + [127.292113, 34.887541, 122.49], + [127.291848, 34.888614, 140.83], + [127.291697, 34.889701, 148.13], + [127.291662, 34.890796, 153.32], + [127.291744, 34.891888, 166.62], + [127.291942, 34.892971, 189.18], + [127.292254, 34.894035, 207.95], + [127.292678, 34.895073, 241.76], + [127.293211, 34.896077, 268.22], + [127.293848, 34.897038, 301.51], + [127.294585, 34.897951, 334.05], + [127.295416, 34.898807, 358.06], + [127.296335, 34.899601, 383.76], + [127.297335, 34.900326, 431.58], + [127.298408, 34.900977, 467.67], + [127.299546, 34.901548, 491.02], + [127.300741, 34.902036, 495.02], + [127.301983, 34.902437, 462.27], + [127.303263, 34.902747, 453.07], + [127.304571, 34.902965, 449.07], + [127.305897, 34.903088, 461.24], + [127.307229, 34.903117, 467.12] + ] + }, + "properties": { "name": "R127", "description": "벌교 반경 1.4Km 비행 제한구역", "type": "0002", "tessellate": true } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.668611, 35.349722, 0], + [126.688889, 35.288889, 0], + [126.711111, 35.280278, 0], + [126.709167, 35.351389, 0], + [126.688611, 35.356667, 0], + [126.668611, 35.349722, 0] + ] + ] + }, + "properties": { "name": "R129", "description": "수련산 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [126.155702, 37.357252, 0], + [126.1542, 37.359899, 0], + [126.152995, 37.36264, 0], + [126.152094, 37.365453, 0], + [126.151505, 37.368319, 0], + [126.151233, 37.371214, 0], + [126.15128, 37.374117, 0], + [126.151644, 37.377006, 0], + [126.152324, 37.379859, 0], + [126.153315, 37.382653, 0], + [126.154608, 37.385369, 0], + [126.156195, 37.387984, 0], + [126.158062, 37.39048, 0], + [126.160196, 37.392837, 0], + [126.162581, 37.395037, 0], + [126.165198, 37.397063, 0], + [126.168027, 37.398901, 0], + [126.171048, 37.400535, 0], + [126.174236, 37.401954, 0], + [126.177569, 37.403147, 0], + [126.181019, 37.404104, 0], + [126.184561, 37.404819, 0], + [126.188169, 37.405286, 0], + [126.191814, 37.405501, 0], + [126.195468, 37.405463, 0], + [126.199105, 37.405172, 0], + [126.202696, 37.40463, 0], + [126.206213, 37.403841, 0], + [126.209631, 37.402812, 0], + [126.212922, 37.40155, 0], + [126.216063, 37.400065, 0], + [126.219028, 37.398368, 0], + [126.221796, 37.396472, 0], + [126.224345, 37.394392, 0], + [126.226656, 37.392143, 0], + [126.228711, 37.389742, 0], + [126.230495, 37.387208, 0], + [126.231995, 37.384561, 0], + [126.233198, 37.381819, 0], + [126.234095, 37.379005, 0], + [126.234681, 37.376139, 0], + [126.23495, 37.373243, 0], + [126.2349, 37.37034, 0], + [126.234533, 37.367452, 0], + [126.233849, 37.3646, 0], + [126.232856, 37.361806, 0], + [126.231561, 37.359091, 0], + [126.229972, 37.356477, 0], + [126.228103, 37.353982, 0], + [126.225968, 37.351626, 0], + [126.223583, 37.349428, 0], + [126.220966, 37.347402, 0], + [126.218137, 37.345566, 0], + [126.215118, 37.343933, 0], + [126.211931, 37.342515, 0], + [126.208601, 37.341323, 0], + [126.205153, 37.340366, 0], + [126.201614, 37.339652, 0], + [126.198009, 37.339186, 0], + [126.194368, 37.338971, 0], + [126.190716, 37.339009, 0], + [126.187083, 37.3393, 0], + [126.183495, 37.339841, 0], + [126.17998, 37.340629, 0], + [126.176565, 37.341657, 0], + [126.173276, 37.342918, 0], + [126.170137, 37.344402, 0], + [126.167173, 37.346098, 0], + [126.164405, 37.347993, 0], + [126.161856, 37.350072, 0], + [126.159544, 37.35232, 0], + [126.157488, 37.354719, 0], + [126.155702, 37.357252, 0] + ] + }, + "properties": { "name": "R133", "description": "초치도 반경 3.7Km 비행 제한구역", "type": "0002", "tessellate": true } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.283333, 35.119444, 0], + [129.173611, 35.019444, 0], + [129.236111, 34.972222, 0], + [129.344444, 35.073611, 0], + [129.283333, 35.119444, 0] + ] + ] + }, + "properties": { "name": "R143", "description": "부산KCG 비행 제한구역", "type": "0002" } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [126.535927, 36.324769, 13.87], + [126.53469, 36.324566, 18.99], + [126.533436, 36.324451, 25.57], + [126.532175, 36.324424, 20.81], + [126.530915, 36.324486, 24.46], + [126.529666, 36.324636, 34.33], + [126.528439, 36.324873, 54.71], + [126.527242, 36.325195, 78.83], + [126.526084, 36.3256, 90.57], + [126.524975, 36.326085, 73.06], + [126.523922, 36.326646, 51.88], + [126.522934, 36.327279, 48.32], + [126.522018, 36.327978, 64.28], + [126.521181, 36.32874, 52.17], + [126.52043, 36.329557, 32.67], + [126.51977, 36.330424, 15.49], + [126.519206, 36.331333, 0.95], + [126.518743, 36.332279, 0.09], + [126.518384, 36.333254, 0], + [126.518132, 36.334251, 0], + [126.517988, 36.335261, 0], + [126.517955, 36.336278, 0], + [126.518031, 36.337293, 0], + [126.518217, 36.338298, 0], + [126.518511, 36.339287, 0], + [126.518911, 36.340252, 0], + [126.519414, 36.341185, 0], + [126.520016, 36.342078, 0], + [126.520712, 36.342927, 0], + [126.521498, 36.343723, 0], + [126.522367, 36.344461, 0], + [126.523312, 36.345135, 0], + [126.524326, 36.34574, 0], + [126.525403, 36.346272, 0], + [126.526532, 36.346726, 0], + [126.527707, 36.347099, 0], + [126.528917, 36.347388, 0], + [126.530154, 36.347591, 0], + [126.531409, 36.347706, 0], + [126.532671, 36.347733, 0], + [126.533931, 36.347672, 0], + [126.53518, 36.347522, 0], + [126.536408, 36.347285, 0], + [126.537605, 36.346962, 0], + [126.538763, 36.346557, 0], + [126.539873, 36.346072, 0], + [126.540926, 36.345511, 0], + [126.541914, 36.344878, 0], + [126.54283, 36.344178, 0], + [126.543666, 36.343417, 0], + [126.544418, 36.342599, 0], + [126.545077, 36.341732, 1.2], + [126.545641, 36.340822, 12.43], + [126.546104, 36.339876, 19.22], + [126.546462, 36.338901, 20.55], + [126.546714, 36.337905, 22.25], + [126.546857, 36.336894, 33.19], + [126.546891, 36.335878, 59.22], + [126.546814, 36.334863, 85.51], + [126.546627, 36.333857, 101.42], + [126.546333, 36.332868, 83.18], + [126.545933, 36.331904, 65.61], + [126.545429, 36.330971, 62.52], + [126.544827, 36.330077, 54.37], + [126.544131, 36.329229, 39.56], + [126.543345, 36.328433, 32.55], + [126.542477, 36.327696, 24.8], + [126.541531, 36.327022, 20.08], + [126.540517, 36.326417, 19.8], + [126.539441, 36.325885, 12.02], + [126.538311, 36.325431, 9.27], + [126.537137, 36.325058, 10.32], + [126.535927, 36.324769, 13.87] + ] + }, + "properties": { "name": "R138", "description": "대천 반경 1.3Km 비행 제한구역", "type": "0002", "tessellate": true } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [127.417877, 36.848243, 170.18], + [127.418676, 36.847451, 186.44], + [127.419385, 36.846606, 178.38], + [127.42, 36.845715, 173.17], + [127.420515, 36.844785, 186.69], + [127.420927, 36.843822, 203.84], + [127.421232, 36.842834, 226.84], + [127.421429, 36.841828, 261.13], + [127.421515, 36.840813, 293.69], + [127.421491, 36.839796, 319.45], + [127.421356, 36.838784, 355.54], + [127.421111, 36.837785, 376.7], + [127.420758, 36.836807, 358.36], + [127.420301, 36.835858, 315.12], + [127.419741, 36.834944, 284.45], + [127.419084, 36.834072, 256.43], + [127.418335, 36.83325, 234.58], + [127.417499, 36.832483, 210.89], + [127.416583, 36.831778, 186.51], + [127.415593, 36.831138, 165.13], + [127.414538, 36.830571, 151.6], + [127.413425, 36.830079, 141.61], + [127.412262, 36.829667, 136.56], + [127.41106, 36.829337, 128.72], + [127.409825, 36.829093, 131.14], + [127.408569, 36.828935, 140.05], + [127.407301, 36.828866, 134.56], + [127.406029, 36.828885, 141.21], + [127.404765, 36.828993, 133.54], + [127.403517, 36.829189, 139.66], + [127.402296, 36.829471, 147.83], + [127.40111, 36.829838, 157.69], + [127.399968, 36.830285, 158.81], + [127.398879, 36.830811, 150.91], + [127.397852, 36.831411, 138.28], + [127.396893, 36.832079, 150.59], + [127.396012, 36.832813, 148.87], + [127.395213, 36.833605, 134.66], + [127.394504, 36.834449, 135.47], + [127.393889, 36.83534, 136.68], + [127.393374, 36.836271, 135.99], + [127.392962, 36.837233, 139.04], + [127.392656, 36.838221, 142.25], + [127.392459, 36.839227, 145.93], + [127.392373, 36.840242, 146.1], + [127.392397, 36.84126, 149.34], + [127.392532, 36.842272, 158.16], + [127.392777, 36.84327, 180.54], + [127.393129, 36.844248, 225.83], + [127.393587, 36.845198, 230.09], + [127.394146, 36.846112, 205.06], + [127.394803, 36.846983, 201.67], + [127.395553, 36.847805, 221.39], + [127.396389, 36.848572, 250.08], + [127.397305, 36.849278, 275.09], + [127.398295, 36.849917, 289.62], + [127.39935, 36.850485, 304.44], + [127.400464, 36.850976, 313.99], + [127.401627, 36.851389, 303.38], + [127.40283, 36.851718, 287.07], + [127.404065, 36.851963, 259.85], + [127.405321, 36.85212, 227.59], + [127.40659, 36.852189, 186.14], + [127.407862, 36.852169, 150.99], + [127.409126, 36.852061, 127.57], + [127.410374, 36.851865, 132.08], + [127.411596, 36.851583, 147.6], + [127.412783, 36.851216, 171.73], + [127.413925, 36.850768, 151.89], + [127.415013, 36.850242, 119.84], + [127.416041, 36.849642, 113.19], + [127.416999, 36.848973, 130.7], + [127.417877, 36.848243, 170.18] + ] + }, + "properties": { "name": "R139", "description": "진천 반경 1.3Km 비행 제한구역", "type": "0002", "tessellate": true } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.404371, 37.380504, 0], + [126.422041, 37.376657, 0], + [126.440282, 37.375304, 0], + [126.458541, 37.376486, 0], + [126.476267, 37.380167, 0], + [126.48476, 37.382913, 0], + [126.492921, 37.386235, 0], + [126.507999, 37.394508, 0], + [126.521044, 37.404733, 0], + [126.526677, 37.410483, 0], + [126.535951, 37.423041, 0], + [126.539521, 37.429753, 0], + [126.54439, 37.443789, 0], + [126.545652, 37.451006, 0], + [126.545781, 37.465564, 0], + [126.544646, 37.472794, 0], + [126.540022, 37.486882, 0], + [126.536567, 37.493633, 0], + [126.527501, 37.506291, 0], + [126.521959, 37.512101, 0], + [126.515799, 37.517506, 0], + [126.501816, 37.526938, 0], + [126.485978, 37.534299, 0], + [126.468765, 37.539364, 0], + [126.450703, 37.54198, 0], + [126.432343, 37.542066, 0], + [126.414243, 37.53962, 0], + [126.396956, 37.534716, 0], + [126.381009, 37.527505, 0], + [126.366886, 37.518205, 0], + [126.355017, 37.5071, 0], + [126.345763, 37.494528, 0], + [126.339404, 37.480872, 0], + [126.336132, 37.466547, 0], + [126.336044, 37.451989, 0], + [126.339141, 37.43764, 0], + [126.345328, 37.423935, 0], + [126.354414, 37.411291, 0], + [126.366124, 37.400092, 0], + [126.372854, 37.395142, 0], + [126.387808, 37.386729, 0], + [126.404371, 37.380504, 0] + ] + ] + }, + "properties": { "name": "인천공항", "description": "인천공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.568598160228, 38.0205107614195, 0], + [128.573821, 38.012733, 0], + [128.58518, 38.001227, 0], + [128.598898, 37.991447, 0], + [128.614559, 37.983692, 0], + [128.631689, 37.978195, 0], + [128.649767, 37.975124, 0], + [128.668247, 37.974571, 0], + [128.682992, 37.976167, 0], + [128.686568, 37.976554, 0], + [128.704176, 37.981011, 0], + [128.720537, 37.987809, 0], + [128.735156, 37.99674, 0], + [128.747588, 38.007536, 0], + [128.757456, 38.019867, 0], + [128.764459, 38.03336, 0], + [128.768383, 38.047607, 0], + [128.769106, 38.062173, 0], + [128.764166, 38.083656, 0], + [128.756998, 38.097098, 0], + [128.746971, 38.109355, 0], + [128.734387, 38.120055, 0], + [128.71963, 38.128871, 0], + [128.711574, 38.132487, 0], + [128.694414, 38.137994, 0], + [128.676297, 38.141072, 0], + [128.657775, 38.141625, 0], + [128.639414, 38.139638, 0], + [128.621771, 38.13517, 0], + [128.605386, 38.128359, 0], + [128.590758, 38.11941, 0], + [128.57833, 38.108598, 0], + [128.568481, 38.096252, 0], + [128.561509, 38.082746, 0], + [128.557624, 38.068493, 0], + [128.556944, 38.053925, 0], + [128.559485, 38.039486, 0], + [128.565171, 38.025613, 0], + [128.568598, 38.020511, 0], + [128.568598160228, 38.0205107614195, 0] + ] + ] + }, + "properties": { "name": "양양국제공항", "description": "양양국제공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.514126, 33.591465, 0], + [126.496804, 33.593516, 0], + [126.479317, 33.593028, 0], + [126.462199, 33.590016, 0], + [126.44597, 33.584571, 0], + [126.431126, 33.57686, 0], + [126.418117, 33.567116, 0], + [126.412427, 33.561573, 0], + [126.402893, 33.549355, 0], + [126.396051, 33.535943, 0], + [126.393708, 33.528915, 0], + [126.391267, 33.514483, 0], + [126.391868, 33.499918, 0], + [126.395493, 33.48566, 0], + [126.40203, 33.472144, 0], + [126.411278, 33.45978, 0], + [126.422957, 33.448942, 0], + [126.436712, 33.439959, 0], + [126.452124, 33.433104, 0], + [126.468727, 33.428584, 0], + [126.486017, 33.426537, 0], + [126.50347, 33.427024, 0], + [126.520558, 33.430031, 0], + [126.536762, 33.435466, 0], + [126.551591, 33.443165, 0], + [126.564596, 33.452895, 0], + [126.57538, 33.464358, 0], + [126.583619, 33.477211, 0], + [126.590673, 33.49823, 0], + [126.59163, 33.512782, 0], + [126.589541, 33.527252, 0], + [126.580858, 33.547844, 0], + [126.571625, 33.560221, 0], + [126.559949, 33.571074, 0], + [126.546187, 33.58007, 0], + [126.530756, 33.586937, 0], + [126.514126, 33.591465, 0] + ] + ] + }, + "properties": { "name": "제주국제공항", "description": "제주국제공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.516348, 36.797451, 0], + [127.498228, 36.798888, 0], + [127.480073, 36.797782, 0], + [127.462434, 36.794165, 0], + [127.44585, 36.788147, 0], + [127.430826, 36.779914, 0], + [127.417819, 36.769714, 0], + [127.412198, 36.763972, 0], + [127.402935, 36.751421, 0], + [127.396535, 36.737773, 0], + [127.394472, 36.730665, 0], + [127.392701, 36.716154, 0], + [127.394099, 36.701617, 0], + [127.398624, 36.687496, 0], + [127.406136, 36.674218, 0], + [127.416403, 36.662191, 0], + [127.429117, 36.651772, 0], + [127.44389, 36.643281, 0], + [127.464752, 36.634264, 0], + [127.486772, 36.632011, 0], + [127.50494, 36.631845, 0], + [127.522868, 36.634211, 0], + [127.531573, 36.636323, 0], + [127.548131, 36.642328, 0], + [127.563141, 36.650547, 0], + [127.576147, 36.660731, 0], + [127.586755, 36.672571, 0], + [127.594641, 36.685708, 0], + [127.600708, 36.703109, 0], + [127.601377, 36.714251, 0], + [127.600017, 36.728791, 0], + [127.595527, 36.74292, 0], + [127.588042, 36.756209, 0], + [127.577787, 36.768255, 0], + [127.565073, 36.778689, 0], + [127.550287, 36.787195, 0], + [127.533879, 36.793513, 0], + [127.516348, 36.797451, 0] + ] + ] + }, + "properties": { "name": "청주국제공항", "description": "청주국제공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.403553, 34.90975, 0], + [126.412208, 34.911543, 0], + [126.423111, 34.914652, 0], + [126.432381, 34.918593, 0], + [126.440964, 34.923378, 0], + [126.45089, 34.92924, 0], + [126.457297, 34.934339, 0], + [126.463138, 34.939875, 0], + [126.468369, 34.945808, 0], + [126.47295, 34.952091, 0], + [126.476846, 34.958678, 0], + [126.480027, 34.965518, 0], + [126.48247, 34.972559, 0], + [126.484154, 34.979747, 0], + [126.485068, 34.987029, 0], + [126.485204, 34.994348, 0], + [126.483879, 35.00441, 0], + [126.482506, 35.013127, 0], + [126.479759, 35.020718, 0], + [126.475983, 35.027466, 0], + [126.472893, 35.03337, 0], + [126.467056, 35.040116, 0], + [126.459362, 35.047699, 0], + [126.453134, 35.052952, 0], + [126.44637, 35.057739, 0], + [126.439121, 35.062026, 0], + [126.431443, 35.065779, 0], + [126.423394, 35.068969, 0], + [126.415035, 35.071572, 0], + [126.40643, 35.073569, 0], + [126.397645, 35.074943, 0], + [126.390839, 35.076089, 0], + [126.379803, 35.075789, 0], + [126.370883, 35.075254, 0], + [126.362054, 35.074084, 0], + [126.353383, 35.072288, 0], + [126.344937, 35.069879, 0], + [126.33419, 35.066535, 0], + [126.325607, 35.062039, 0], + [126.319427, 35.058105, 0], + [126.314654, 35.054559, 0], + [126.308247, 35.049453, 0], + [126.302408, 35.043909, 0], + [126.297183, 35.037969, 0], + [126.292611, 35.031679, 0], + [126.288726, 35.025087, 0], + [126.285558, 35.018242, 0], + [126.283132, 35.011197, 0], + [126.281464, 35.004006, 0], + [126.280568, 34.996722, 0], + [126.280451, 34.989403, 0], + [126.281113, 34.982103, 0], + [126.282548, 34.974879, 0], + [126.284746, 34.967784, 0], + [126.28769, 34.960873, 0], + [126.291357, 34.954198, 0], + [126.296768, 34.945614, 0], + [126.303291, 34.939422, 0], + [126.309471, 34.932667, 0], + [126.319381, 34.926064, 0], + [126.326624, 34.921785, 0], + [126.334294, 34.918039, 0], + [126.342332, 34.914855, 0], + [126.350677, 34.912257, 0], + [126.361656, 34.909302, 0], + [126.371612, 34.907895, 0], + [126.380539, 34.907332, 0], + [126.390495, 34.907613, 0], + [126.398392, 34.908176, 0], + [126.403553, 34.90975, 0] + ] + ] + }, + "properties": { "name": "무안국제공항", "description": "무안국제공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.812885, 35.042949, 0], + [126.826172, 35.04349, 0], + [126.839261, 35.046583, 0], + [126.847685, 35.049031, 0], + [126.855817, 35.05207, 0], + [126.863595, 35.055677, 0], + [126.87096, 35.059825, 0], + [126.877857, 35.064482, 0], + [126.884231, 35.069613, 0], + [126.890036, 35.075179, 0], + [126.895227, 35.081138, 0], + [126.899765, 35.087444, 0], + [126.903614, 35.094049, 0], + [126.906745, 35.100904, 0], + [126.909135, 35.107956, 0], + [126.910629, 35.113449, 0], + [126.911316, 35.119347, 0], + [126.911659, 35.125244, 0], + [126.911699, 35.129753, 0], + [126.910997, 35.137049, 0], + [126.909943, 35.142371, 0], + [126.908226, 35.148828, 0], + [126.906166, 35.154161, 0], + [126.903076, 35.160056, 0], + [126.900576, 35.164908, 0], + [126.896167, 35.171276, 0], + [126.891094, 35.177306, 0], + [126.885397, 35.182952, 0], + [126.879119, 35.188169, 0], + [126.872308, 35.19292, 0], + [126.865015, 35.197166, 0], + [126.853981, 35.202428, 0], + [126.846428, 35.205233, 0], + [126.840819, 35.206581, 0], + [126.832187, 35.208531, 0], + [126.823379, 35.209858, 0], + [126.814462, 35.210553, 0], + [126.803169, 35.210563, 0], + [126.796579, 35.210026, 0], + [126.787747, 35.208809, 0], + [126.779079, 35.206968, 0], + [126.770641, 35.204515, 0], + [126.762497, 35.201471, 0], + [126.754709, 35.197857, 0], + [126.747338, 35.193702, 0], + [126.740438, 35.189038, 0], + [126.734063, 35.183899, 0], + [126.728261, 35.178326, 0], + [126.723076, 35.17236, 0], + [126.718547, 35.166047, 0], + [126.71471, 35.159436, 0], + [126.711592, 35.152576, 0], + [126.709218, 35.14552, 0], + [126.707605, 35.138322, 0], + [126.706766, 35.131037, 0], + [126.706707, 35.123719, 0], + [126.707428, 35.116425, 0], + [126.708923, 35.10921, 0], + [126.71118, 35.102129, 0], + [126.714183, 35.095235, 0], + [126.717908, 35.088582, 0], + [126.722327, 35.08222, 0], + [126.727406, 35.076197, 0], + [126.733107, 35.070559, 0], + [126.739385, 35.065349, 0], + [126.746193, 35.060606, 0], + [126.75348, 35.056366, 0], + [126.76119, 35.052662, 0], + [126.769264, 35.049522, 0], + [126.777641, 35.046969, 0], + [126.783943, 35.045457, 0], + [126.795049, 35.043698, 0], + [126.803947, 35.043005, 0], + [126.812885, 35.042949, 0] + ] + ] + }, + "properties": { "name": "광주공항", "description": "광주공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.622837, 35.987045, 0], + [126.613799, 35.987213, 0], + [126.595842, 35.985636, 0], + [126.578498, 35.981558, 0], + [126.562295, 35.975102, 0], + [126.547726, 35.966465, 0], + [126.539841, 35.958, 0], + [126.529891, 35.950013, 0], + [126.521205, 35.937201, 0], + [126.515402, 35.923361, 0], + [126.512656, 35.908916, 0], + [126.513048, 35.894305, 0], + [126.515808, 35.883487, 0], + [126.519468, 35.873043, 0], + [126.527442, 35.859934, 0], + [126.538101, 35.848146, 0], + [126.546707, 35.838968, 0], + [126.558394, 35.833707, 0], + [126.574193, 35.82667, 0], + [126.591257, 35.821962, 0], + [126.60907, 35.819725, 0], + [126.618088, 35.819558, 0], + [126.636008, 35.821131, 0], + [126.65332, 35.825201, 0], + [126.6695, 35.831645, 0], + [126.67701, 35.835698, 0], + [126.690586, 35.845315, 0], + [126.701899, 35.856696, 0], + [126.710606, 35.869495, 0], + [126.716439, 35.883325, 0], + [126.719222, 35.897765, 0], + [126.718867, 35.912378, 0], + [126.715384, 35.926718, 0], + [126.708877, 35.940351, 0], + [126.699542, 35.952861, 0], + [126.687663, 35.963867, 0], + [126.673599, 35.973036, 0], + [126.65778, 35.980086, 0], + [126.64936, 35.982747, 0], + [126.640685, 35.984804, 0], + [126.622837, 35.987045, 0] + ] + ] + }, + "properties": { "name": "군산공항", "description": "군산공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.584572, 34.921971, 0], + [127.578958, 34.920043, 0], + [127.570842, 34.917006, 0], + [127.563081, 34.913401, 0], + [127.555733, 34.909254, 0], + [127.548855, 34.904597, 0], + [127.542499, 34.899466, 0], + [127.536713, 34.8939, 0], + [127.531541, 34.887941, 0], + [127.527022, 34.881635, 0], + [127.523192, 34.87503, 0], + [127.520078, 34.868176, 0], + [127.517705, 34.861125, 0], + [127.51609, 34.853932, 0], + [127.515246, 34.84665, 0], + [127.515178, 34.839336, 0], + [127.515887, 34.832044, 0], + [127.517367, 34.824831, 0], + [127.519607, 34.817752, 0], + [127.52259, 34.810859, 0], + [127.526292, 34.804206, 0], + [127.530686, 34.797843, 0], + [127.535738, 34.791819, 0], + [127.541409, 34.786179, 0], + [127.547657, 34.780966, 0], + [127.554433, 34.77622, 0], + [127.561686, 34.771976, 0], + [127.569361, 34.768267, 0], + [127.5774, 34.765122, 0], + [127.588005, 34.761076, 0], + [127.597618, 34.759384, 0], + [127.607574, 34.758538, 0], + [127.616844, 34.757692, 0], + [127.627487, 34.757974, 0], + [127.638499, 34.760298, 0], + [127.64712, 34.762128, 0], + [127.655514, 34.764568, 0], + [127.663617, 34.767599, 0], + [127.671369, 34.771198, 0], + [127.681046, 34.77546, 0], + [127.685585, 34.779988, 0], + [127.691941, 34.785111, 0], + [127.69773, 34.79067, 0], + [127.702908, 34.796622, 0], + [127.707435, 34.802921, 0], + [127.711277, 34.809521, 0], + [127.714404, 34.81637, 0], + [127.716793, 34.823417, 0], + [127.718424, 34.830608, 0], + [127.719287, 34.837888, 0], + [127.719373, 34.845202, 0], + [127.718682, 34.852495, 0], + [127.717219, 34.85971, 0], + [127.714994, 34.866793, 0], + [127.712026, 34.873691, 0], + [127.708335, 34.880349, 0], + [127.70395, 34.886718, 0], + [127.698905, 34.89275, 0], + [127.691002, 34.900856, 0], + [127.684135, 34.905361, 0], + [127.676926, 34.910429, 0], + [127.668343, 34.914652, 0], + [127.657218, 34.919488, 0], + [127.648863, 34.922052, 0], + [127.63813, 34.923941, 0], + [127.627144, 34.92563, 0], + [127.613694, 34.926106, 0], + [127.6048, 34.925531, 0], + [127.596002, 34.924322, 0], + [127.584572, 34.921971, 0] + ] + ] + }, + "properties": { "name": "여수공항", "description": "여수공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.93158, 35.098362, 0], + [128.940492, 35.098235, 0], + [128.954086, 35.099125, 0], + [128.966834, 35.101647, 0], + [128.978806, 35.105305, 0], + [128.988762, 35.109237, 0], + [128.998598, 35.11459, 0], + [129.005529, 35.119176, 0], + [129.011946, 35.124238, 0], + [129.0178, 35.129738, 0], + [129.023046, 35.135634, 0], + [129.027645, 35.141881, 0], + [129.031561, 35.148433, 0], + [129.034765, 35.155238, 0], + [129.037231, 35.162246, 0], + [129.038941, 35.169402, 0], + [129.039882, 35.176654, 0], + [129.040046, 35.183945, 0], + [129.039433, 35.191219, 0], + [129.038045, 35.198423, 0], + [129.035894, 35.2055, 0], + [129.032996, 35.212397, 0], + [129.029373, 35.219061, 0], + [129.025052, 35.225442, 0], + [129.020066, 35.23149, 0], + [129.014452, 35.237161, 0], + [129.008255, 35.242409, 0], + [129.00152, 35.247197, 0], + [128.994299, 35.251486, 0], + [128.986646, 35.255245, 0], + [128.978622, 35.258444, 0], + [128.970285, 35.261059, 0], + [128.961701, 35.26307, 0], + [128.952935, 35.264463, 0], + [128.944053, 35.265225, 0], + [128.935123, 35.265352, 0], + [128.926214, 35.264842, 0], + [128.914948, 35.263282, 0], + [128.904648, 35.260759, 0], + [128.892129, 35.256588, 0], + [128.884322, 35.253049, 0], + [128.876922, 35.248967, 0], + [128.869987, 35.244374, 0], + [128.861046, 35.237488, 0], + [128.854866, 35.231598, 0], + [128.850059, 35.224868, 0], + [128.84491, 35.217295, 0], + [128.841133, 35.210283, 0], + [128.838341, 35.20126, 0], + [128.836648, 35.194101, 0], + [128.835297, 35.184191, 0], + [128.83564, 35.176334, 0], + [128.837013, 35.166792, 0], + [128.839783, 35.158009, 0], + [128.842696, 35.151116, 0], + [128.846331, 35.144458, 0], + [128.850662, 35.138083, 0], + [128.855655, 35.132042, 0], + [128.861272, 35.126379, 0], + [128.867471, 35.121137, 0], + [128.874203, 35.116357, 0], + [128.881419, 35.112075, 0], + [128.889062, 35.108323, 0], + [128.897076, 35.10513, 0], + [128.905398, 35.10252, 0], + [128.913967, 35.100512, 0], + [128.922716, 35.099123, 0], + [128.93158, 35.098362, 0] + ] + ] + }, + "properties": { "name": "김해국제공항", "description": "김해국제공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.325885, 35.512544, 0], + [129.334653, 35.510984, 0], + [129.343554, 35.510052, 0], + [129.352522, 35.509754, 0], + [129.361487, 35.510092, 0], + [129.370382, 35.511065, 0], + [129.379139, 35.512664, 0], + [129.387692, 35.514878, 0], + [129.395976, 35.51769, 0], + [129.403928, 35.521078, 0], + [129.411488, 35.525017, 0], + [129.420662, 35.53055, 0], + [129.428215, 35.535858, 0], + [129.434395, 35.542284, 0], + [129.440575, 35.549547, 0], + [129.445038, 35.55625, 0], + [129.449071, 35.565034, 0], + [129.451757, 35.572005, 0], + [129.453686, 35.57914, 0], + [129.454843, 35.586385, 0], + [129.455219, 35.593684, 0], + [129.454812, 35.600982, 0], + [129.453623, 35.608224, 0], + [129.451663, 35.615353, 0], + [129.448945, 35.622317, 0], + [129.445491, 35.629061, 0], + [129.441326, 35.635535, 0], + [129.436481, 35.641689, 0], + [129.430995, 35.647476, 0], + [129.424908, 35.652853, 0], + [129.418266, 35.657777, 0], + [129.411121, 35.662212, 0], + [129.403526, 35.666124, 0], + [129.395541, 35.669482, 0], + [129.387224, 35.672262, 0], + [129.378641, 35.674441, 0], + [129.369856, 35.676004, 0], + [129.360936, 35.676939, 0], + [129.354057, 35.6771, 0], + [129.342966, 35.676898, 0], + [129.334053, 35.675924, 0], + [129.325279, 35.674321, 0], + [129.316711, 35.672103, 0], + [129.308413, 35.669285, 0], + [129.300451, 35.665891, 0], + [129.292883, 35.661945, 0], + [129.285768, 35.657478, 0], + [129.279161, 35.652524, 0], + [129.27311, 35.64712, 0], + [129.267663, 35.641308, 0], + [129.262861, 35.635132, 0], + [129.258741, 35.628639, 0], + [129.255332, 35.62188, 0], + [129.251747, 35.61293, 0], + [129.249344, 35.602602, 0], + [129.249254, 35.593219, 0], + [129.24968, 35.585922, 0], + [129.252091, 35.574962, 0], + [129.254494, 35.566305, 0], + [129.259065, 35.557858, 0], + [129.263241, 35.55139, 0], + [129.268093, 35.545243, 0], + [129.273584, 35.539463, 0], + [129.279673, 35.534095, 0], + [129.286313, 35.529178, 0], + [129.293453, 35.52475, 0], + [129.30104, 35.520846, 0], + [129.309014, 35.517494, 0], + [129.317317, 35.51472, 0], + [129.325885, 35.512544, 0] + ] + ] + }, + "properties": { "name": "울산공항", "description": "울산공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.995872, 35.145178, 0], + [127.992525, 35.142573, 0], + [127.987124, 35.136749, 0], + [127.982365, 35.130562, 0], + [127.978283, 35.12406, 0], + [127.974911, 35.117291, 0], + [127.972273, 35.110308, 0], + [127.97039, 35.103163, 0], + [127.969275, 35.09591, 0], + [127.968938, 35.088606, 0], + [127.969379, 35.081306, 0], + [127.970596, 35.074065, 0], + [127.97258, 35.066938, 0], + [127.975314, 35.05998, 0], + [127.978778, 35.053244, 0], + [127.982946, 35.04678, 0], + [127.987785, 35.040637, 0], + [127.993259, 35.034864, 0], + [128.000679, 35.027747, 0], + [128.009949, 35.022124, 0], + [128.018189, 35.017907, 0], + [128.025398, 35.013689, 0], + [128.033981, 35.010596, 0], + [128.045328, 35.008016, 0], + [128.054049, 35.00647, 0], + [128.062902, 35.005551, 0], + [128.071819, 35.005268, 0], + [128.080732, 35.005621, 0], + [128.089574, 35.006609, 0], + [128.098277, 35.008223, 0], + [128.106776, 35.010453, 0], + [128.115006, 35.013279, 0], + [128.122904, 35.016682, 0], + [128.130411, 35.020636, 0], + [128.137469, 35.025109, 0], + [128.144025, 35.030069, 0], + [128.150029, 35.035478, 0], + [128.155436, 35.041295, 0], + [128.160203, 35.047474, 0], + [128.162384, 35.051922, 0], + [128.166847, 35.058386, 0], + [128.168907, 35.064849, 0], + [128.171654, 35.071312, 0], + [128.172684, 35.078618, 0], + [128.17337, 35.086484, 0], + [128.173298, 35.09671, 0], + [128.172098, 35.103953, 0], + [128.170132, 35.111083, 0], + [128.166161, 35.121313, 0], + [128.159803, 35.131258, 0], + [128.152084, 35.140406, 0], + [128.143437, 35.148557, 0], + [128.132172, 35.157249, 0], + [128.122145, 35.161799, 0], + [128.114197, 35.165146, 0], + [128.099899, 35.168757, 0], + [128.088644, 35.171629, 0], + [128.079773, 35.17255, 0], + [128.068314, 35.172966, 0], + [128.053047, 35.17149, 0], + [128.038788, 35.168476, 0], + [128.024025, 35.163985, 0], + [128.012148, 35.157437, 0], + [128.005085, 35.152956, 0], + [127.995872, 35.145178, 0] + ] + ] + }, + "properties": { "name": "사천공항", "description": "사천공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.58711, 35.833938, 0], + [128.593873, 35.829119, 0], + [128.597717, 35.826721, 0], + [128.60321, 35.823102, 0], + [128.611107, 35.819762, 0], + [128.616883, 35.817763, 0], + [128.625269, 35.815107, 0], + [128.633907, 35.813053, 0], + [128.642733, 35.811617, 0], + [128.651679, 35.81081, 0], + [128.665695, 35.810853, 0], + [128.675308, 35.811688, 0], + [128.68731, 35.813916, 0], + [128.695841, 35.816247, 0], + [128.704089, 35.819172, 0], + [128.711993, 35.822668, 0], + [128.719491, 35.826709, 0], + [128.726527, 35.831264, 0], + [128.733047, 35.836298, 0], + [128.739003, 35.841773, 0], + [128.744347, 35.847649, 0], + [128.749041, 35.853879, 0], + [128.753047, 35.860417, 0], + [128.756336, 35.867213, 0], + [128.758882, 35.874215, 0], + [128.760665, 35.881371, 0], + [128.761672, 35.888625, 0], + [128.761895, 35.895922, 0], + [128.761332, 35.903208, 0], + [128.759986, 35.910426, 0], + [128.757869, 35.917522, 0], + [128.754996, 35.924441, 0], + [128.751389, 35.931131, 0], + [128.747075, 35.937541, 0], + [128.742086, 35.943622, 0], + [128.736461, 35.949327, 0], + [128.730242, 35.954614, 0], + [128.723477, 35.959441, 0], + [128.716217, 35.963772, 0], + [128.708518, 35.967574, 0], + [128.700438, 35.970818, 0], + [128.692038, 35.973479, 0], + [128.683384, 35.975537, 0], + [128.674541, 35.976976, 0], + [128.665576, 35.977785, 0], + [128.656557, 35.977958, 0], + [128.644409, 35.976895, 0], + [128.629872, 35.974671, 0], + [128.618317, 35.970782, 0], + [128.60733, 35.966058, 0], + [128.60012, 35.96328, 0], + [128.590606, 35.957292, 0], + [128.584084, 35.95225, 0], + [128.578132, 35.946767, 0], + [128.572793, 35.940884, 0], + [128.568108, 35.934647, 0], + [128.564113, 35.928103, 0], + [128.560839, 35.921302, 0], + [128.558309, 35.914295, 0], + [128.556544, 35.907137, 0], + [128.555555, 35.899881, 0], + [128.555352, 35.892583, 0], + [128.556175, 35.882374, 0], + [128.558579, 35.874307, 0], + [128.562355, 35.865961, 0], + [128.56594, 35.857391, 0], + [128.570265, 35.850988, 0], + [128.575261, 35.844914, 0], + [128.58089, 35.839217, 0], + [128.58711, 35.833938, 0] + ] + ] + }, + "properties": { "name": "대구국제공항", "description": "대구국제공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.410019, 35.904346, 0], + [129.414943, 35.903896, 0], + [129.423966, 35.903952, 0], + [129.432949, 35.904643, 0], + [129.441823, 35.905965, 0], + [129.450522, 35.907909, 0], + [129.45898, 35.910458, 0], + [129.467131, 35.913594, 0], + [129.474915, 35.917293, 0], + [129.482272, 35.921527, 0], + [129.489145, 35.926263, 0], + [129.495484, 35.931467, 0], + [129.50124, 35.937098, 0], + [129.506368, 35.943113, 0], + [129.51083, 35.949467, 0], + [129.514591, 35.956111, 0], + [129.517624, 35.962996, 0], + [129.519904, 35.970068, 0], + [129.522286, 35.981062, 0], + [129.522286, 35.989674, 0], + [129.521237, 35.999145, 0], + [129.51961, 36.006334, 0], + [129.517214, 36.013382, 0], + [129.514068, 36.020233, 0], + [129.510194, 36.026837, 0], + [129.505623, 36.033142, 0], + [129.500389, 36.039101, 0], + [129.494532, 36.044668, 0], + [129.488096, 36.049801, 0], + [129.481131, 36.05446, 0], + [129.473689, 36.05861, 0], + [129.465827, 36.06222, 0], + [129.457608, 36.065261, 0], + [129.449089, 36.067711, 0], + [129.434052, 36.07047, 0], + [129.422408, 36.071349, 0], + [129.413366, 36.071294, 0], + [129.401436, 36.070192, 0], + [129.386756, 36.067329, 0], + [129.378284, 36.064775, 0], + [129.37012, 36.061633, 0], + [129.362327, 36.057927, 0], + [129.354964, 36.053686, 0], + [129.348087, 36.048942, 0], + [129.341749, 36.043731, 0], + [129.335997, 36.038092, 0], + [129.330875, 36.03207, 0], + [129.323845, 36.022169, 0], + [129.319656, 36.01217, 0], + [129.317322, 36.001896, 0], + [129.315948, 35.993285, 0], + [129.315605, 35.98523, 0], + [129.316134, 35.976015, 0], + [129.317779, 35.968828, 0], + [129.321098, 35.959667, 0], + [129.325218, 35.950218, 0], + [129.330025, 35.944937, 0], + [129.334488, 35.938822, 0], + [129.340668, 35.932985, 0], + [129.345818, 35.927981, 0], + [129.353027, 35.923254, 0], + [129.360924, 35.917972, 0], + [129.369164, 35.913245, 0], + [129.377747, 35.909908, 0], + [129.388315, 35.907527, 0], + [129.400749, 35.904903, 0], + [129.410019, 35.904346, 0] + ] + ] + }, + "properties": { "name": "포항공항", "description": "포항공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.938881, 37.356241, 0], + [127.94452, 37.355116, 0], + [127.953642, 37.35428, 0], + [127.962822, 37.354077, 0], + [127.971988, 37.354511, 0], + [127.981072, 37.355578, 0], + [127.990006, 37.357269, 0], + [127.99872, 37.359572, 0], + [128.007149, 37.362469, 0], + [128.015229, 37.365939, 0], + [128.025055, 37.370703, 0], + [128.033638, 37.376978, 0], + [128.040504, 37.382434, 0], + [128.048363, 37.39081, 0], + [128.056297, 37.401801, 0], + [128.060417, 37.408074, 0], + [128.063327, 37.417326, 0], + [128.066254, 37.426616, 0], + [128.066597, 37.435067, 0], + [128.06694, 37.444063, 0], + [128.064641, 37.453531, 0], + [128.060417, 37.464231, 0], + [128.055976, 37.474262, 0], + [128.051608, 37.480686, 0], + [128.04655, 37.486783, 0], + [128.04084, 37.492506, 0], + [128.034523, 37.497813, 0], + [128.027646, 37.502662, 0], + [128.017845, 37.507547, 0], + [128.012426, 37.510843, 0], + [128.004199, 37.514113, 0], + [127.995643, 37.516802, 0], + [127.98317, 37.519257, 0], + [127.972183, 37.520619, 0], + [127.959467, 37.521396, 0], + [127.95028, 37.520961, 0], + [127.935791, 37.518712, 0], + [127.923494, 37.515888, 0], + [127.915051, 37.512985, 0], + [127.90696, 37.509508, 0], + [127.899282, 37.505485, 0], + [127.892077, 37.500945, 0], + [127.885399, 37.495925, 0], + [127.879305, 37.490467, 0], + [127.873828, 37.484603, 0], + [127.869016, 37.478381, 0], + [127.864908, 37.471851, 0], + [127.858916, 37.458063, 0], + [127.85614, 37.445971, 0], + [127.855788, 37.436362, 0], + [127.856345, 37.429076, 0], + [127.857699, 37.421857, 0], + [127.85984, 37.414758, 0], + [127.862752, 37.407835, 0], + [127.866411, 37.401139, 0], + [127.872276, 37.392528, 0], + [127.877083, 37.386526, 0], + [127.883263, 37.38107, 0], + [127.891159, 37.375341, 0], + [127.899742, 37.369884, 0], + [127.909967, 37.36461, 0], + [127.918182, 37.361346, 0], + [127.926722, 37.358663, 0], + [127.938881, 37.356241, 0] + ] + ] + }, + "properties": { "name": "원주공항", "description": "원주공항 반경 9.3Km 관제권", "type": "0003" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.914923, 37.834493, 0], + [128.898113, 37.828434, 0], + [128.882895, 37.82016, 0], + [128.86973, 37.809923, 0], + [128.864046, 37.804163, 0], + [128.854688, 37.791581, 0], + [128.848241, 37.777906, 0], + [128.844898, 37.763554, 0], + [128.844758, 37.748961, 0], + [128.847826, 37.734571, 0], + [128.854004, 37.72082, 0], + [128.863105, 37.708126, 0], + [128.87485, 37.696874, 0], + [128.888883, 37.687405, 0], + [128.904778, 37.680006, 0], + [128.922051, 37.674901, 0], + [128.940181, 37.672246, 0], + [128.958618, 37.672119, 0], + [128.976803, 37.674526, 0], + [128.994185, 37.679393, 0], + [129.010239, 37.686573, 0], + [129.024477, 37.695848, 0], + [129.036467, 37.706937, 0], + [129.041502, 37.713059, 0], + [129.049461, 37.726225, 0], + [129.054336, 37.736512, 0], + [129.055705, 37.747515, 0], + [129.055886, 37.762108, 0], + [129.052858, 37.776504, 0], + [129.046712, 37.790265, 0], + [129.037633, 37.802973, 0], + [129.032076, 37.80881, 0], + [129.019138, 37.819226, 0], + [129.011856, 37.823726, 0], + [128.995941, 37.83114, 0], + [128.978636, 37.836255, 0], + [128.969626, 37.837899, 0], + [128.951232, 37.839299, 0], + [128.932811, 37.838152, 0], + [128.914923, 37.834493, 0] + ] + ] + }, + "properties": { "name": "강릉비행장(공군)", "description": "강릉비행장(공군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.044856, 37.50983, 0], + [127.032079, 37.49931, 0], + [127.025986, 37.490115, 0], + [127.017702, 37.48064, 0], + [127.011733, 37.466821, 0], + [127.00991, 37.459654, 0], + [127.008653, 37.445079, 0], + [127.009229, 37.437782, 0], + [127.012765, 37.423445, 0], + [127.015698, 37.416515, 0], + [127.023783, 37.403393, 0], + [127.034611, 37.391585, 0], + [127.040953, 37.386287, 0], + [127.055253, 37.377105, 0], + [127.063102, 37.373291, 0], + [127.079901, 37.36736, 0], + [127.097739, 37.363834, 0], + [127.10688, 37.36301, 0], + [127.125258, 37.36327, 0], + [127.1433, 37.366059, 0], + [127.152025, 37.368379, 0], + [127.166061, 37.370703, 0], + [127.176222, 37.378815, 0], + [127.190102, 37.388396, 0], + [127.196203, 37.393869, 0], + [127.206495, 37.405976, 0], + [127.210608, 37.412517, 0], + [127.216608, 37.426327, 0], + [127.218451, 37.433491, 0], + [127.219748, 37.448063, 0], + [127.219193, 37.455361, 0], + [127.215694, 37.469704, 0], + [127.212777, 37.476639, 0], + [127.209109, 37.483346, 0], + [127.204514, 37.493928, 0], + [127.193903, 37.501598, 0], + [127.180661, 37.51175, 0], + [127.173253, 37.516101, 0], + [127.157145, 37.523186, 0], + [127.13973, 37.527942, 0], + [127.121535, 37.530225, 0], + [127.103116, 37.529965, 0], + [127.085035, 37.527169, 0], + [127.067843, 37.521924, 0], + [127.052064, 37.514388, 0], + [127.044856, 37.50983, 0] + ] + ] + }, + "properties": { "name": "서울(성남)공항(공군)", "description": "서울(성남)공항(공군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.944218, 37.308626, 0], + [126.930697, 37.298778, 0], + [126.924799, 37.293188, 0], + [126.914948, 37.28089, 0], + [126.911071, 37.274276, 0], + [126.90556, 37.260368, 0], + [126.903168, 37.24591, 0], + [126.903967, 37.231341, 0], + [126.905559, 37.224154, 0], + [126.911065, 37.210246, 0], + [126.919517, 37.19731, 0], + [126.924771, 37.19133, 0], + [126.937133, 37.180576, 0], + [126.944148, 37.175883, 0], + [126.959578, 37.168041, 0], + [126.97648, 37.162451, 0], + [126.994342, 37.159283, 0], + [127.012621, 37.158632, 0], + [127.021745, 37.159259, 0], + [127.034912, 37.161958, 0], + [127.048226, 37.164883, 0], + [127.064472, 37.171596, 0], + [127.071984, 37.175772, 0], + [127.079012, 37.180453, 0], + [127.091404, 37.191186, 0], + [127.101271, 37.203469, 0], + [127.108314, 37.21693, 0], + [127.112316, 37.23116, 0], + [127.113156, 37.245728, 0], + [127.110804, 37.26019, 0], + [127.106323, 37.270774, 0], + [127.096902, 37.287056, 0], + [127.091655, 37.293043, 0], + [127.079298, 37.303812, 0], + [127.064772, 37.31271, 0], + [127.048521, 37.319465, 0], + [127.03104, 37.32387, 0], + [127.012862, 37.325791, 0], + [127.003684, 37.325799, 0], + [126.9855, 37.32391, 0], + [126.968007, 37.319535, 0], + [126.959687, 37.316455, 0], + [126.944218, 37.308626, 0] + ] + ] + }, + "properties": { "name": "수원비행장(공군)", "description": "수원비행장(공군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.975488, 37.162112, 0], + [126.96068, 37.153499, 0], + [126.95404, 37.148453, 0], + [126.94254, 37.137077, 0], + [126.937766, 37.130833, 0], + [126.930356, 37.117471, 0], + [126.927774, 37.110454, 0], + [126.924956, 37.096018, 0], + [126.925323, 37.08141, 0], + [126.928864, 37.067075, 0], + [126.931794, 37.060147, 0], + [126.939861, 37.047031, 0], + [126.950655, 37.035232, 0], + [126.956976, 37.02994, 0], + [126.96385, 37.025107, 0], + [126.979042, 37.016963, 0], + [126.999893, 37.009681, 0], + [127.017746, 37.006391, 0], + [127.031787, 37.006541, 0], + [127.04998, 37.008089, 0], + [127.058881, 37.009805, 0], + [127.075956, 37.015056, 0], + [127.091632, 37.022593, 0], + [127.098795, 37.02715, 0], + [127.111499, 37.037667, 0], + [127.121726, 37.049785, 0], + [127.129164, 37.063135, 0], + [127.133585, 37.077313, 0], + [127.135849, 37.088049, 0], + [127.134292, 37.099187, 0], + [127.130788, 37.113528, 0], + [127.124213, 37.127165, 0], + [127.114765, 37.139685, 0], + [127.10905, 37.145404, 0], + [127.095854, 37.155545, 0], + [127.080647, 37.163704, 0], + [127.072431, 37.16696, 0], + [127.055088, 37.171701, 0], + [127.036974, 37.173967, 0], + [127.018641, 37.173689, 0], + [127.000648, 37.170877, 0], + [126.983543, 37.165614, 0], + [126.975488, 37.162112, 0] + ] + ] + }, + "properties": { "name": "오산비행장(주한미군)", "description": "오산비행장(주한미군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.019297, 37.041721, 0], + [127.001527, 37.038427, 0], + [126.984746, 37.032718, 0], + [126.962535, 37.020025, 0], + [126.950357, 37.009186, 0], + [126.940725, 36.996822, 0], + [126.93393, 36.98331, 0], + [126.929481, 36.961794, 0], + [126.930473, 36.947255, 0], + [126.934609, 36.933073, 0], + [126.94176, 36.919681, 0], + [126.951709, 36.907484, 0], + [126.95764, 36.901951, 0], + [126.971193, 36.892227, 0], + [126.986648, 36.88453, 0], + [127.003537, 36.879095, 0], + [127.021347, 36.876085, 0], + [127.03954, 36.875592, 0], + [127.061691, 36.878522, 0], + [127.074873, 36.882141, 0], + [127.090943, 36.888984, 0], + [127.09836, 36.893218, 0], + [127.111673, 36.903152, 0], + [127.117469, 36.908776, 0], + [127.127118, 36.921125, 0], + [127.130898, 36.927757, 0], + [127.136225, 36.941682, 0], + [127.138446, 36.956135, 0], + [127.137494, 36.970676, 0], + [127.134476, 36.981164, 0], + [127.12627, 36.998268, 0], + [127.116339, 37.010479, 0], + [127.108383, 37.020098, 0], + [127.096853, 37.02576, 0], + [127.081381, 37.033471, 0], + [127.073071, 37.036489, 0], + [127.055623, 37.040737, 0], + [127.037514, 37.042498, 0], + [127.019297, 37.041721, 0] + ] + ] + }, + "properties": { "name": "평택비행장(주한미군)", "description": "평택비행장(주한미군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.805046, 36.976962, 0], + [127.811154, 36.971526, 0], + [127.817831, 36.966536, 0], + [127.825025, 36.962029, 0], + [127.832683, 36.95804, 0], + [127.840747, 36.954598, 0], + [127.849154, 36.951731, 0], + [127.857841, 36.94946, 0], + [127.866743, 36.947802, 0], + [127.875792, 36.946769, 0], + [127.884918, 36.94637, 0], + [127.894053, 36.946608, 0], + [127.903128, 36.94748, 0], + [127.912073, 36.94898, 0], + [127.920822, 36.951097, 0], + [127.932014, 36.95483, 0], + [127.940941, 36.958946, 0], + [127.949524, 36.96306, 0], + [127.956047, 36.967724, 0], + [127.963257, 36.972935, 0], + [127.96978, 36.978147, 0], + [127.974587, 36.983358, 0], + [127.979365, 36.990138, 0], + [127.984197, 37.000549, 0], + [127.989349, 37.011052, 0], + [127.990446, 37.02183, 0], + [127.991066, 37.030788, 0], + [127.990668, 37.036425, 0], + [127.989349, 37.047231, 0], + [127.985066, 37.057821, 0], + [127.981665, 37.064603, 0], + [127.977536, 37.071123, 0], + [127.97271, 37.07733, 0], + [127.967223, 37.083178, 0], + [127.961118, 37.088622, 0], + [127.95444, 37.09362, 0], + [127.947244, 37.098133, 0], + [127.939578, 37.102129, 0], + [127.931503, 37.105577, 0], + [127.923082, 37.10845, 0], + [127.914379, 37.110727, 0], + [127.905459, 37.112388, 0], + [127.896391, 37.113423, 0], + [127.887245, 37.113823, 0], + [127.878089, 37.113586, 0], + [127.868995, 37.112712, 0], + [127.860031, 37.111208, 0], + [127.851266, 37.109087, 0], + [127.842767, 37.106364, 0], + [127.834598, 37.10306, 0], + [127.826823, 37.0992, 0], + [127.815971, 37.092978, 0], + [127.808075, 37.086406, 0], + [127.80078, 37.078851, 0], + [127.795783, 37.072731, 0], + [127.791473, 37.066286, 0], + [127.787885, 37.059566, 0], + [127.785045, 37.052621, 0], + [127.782975, 37.045506, 0], + [127.781689, 37.038274, 0], + [127.781199, 37.030979, 0], + [127.781982, 37.021469, 0], + [127.783356, 37.011874, 0], + [127.787164, 37.002292, 0], + [127.791939, 36.993504, 0], + [127.794719, 36.989003, 0], + [127.799554, 36.982802, 0], + [127.803612, 36.978695, 0], + [127.805046, 36.976962, 0] + ] + ] + }, + "properties": { "name": "중원비행장(공군)", "description": "중원비행장(공군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.473217, 36.788517, 0], + [126.455432, 36.785285, 0], + [126.446872, 36.78275, 0], + [126.430741, 36.775939, 0], + [126.416336, 36.766986, 0], + [126.404094, 36.756164, 0], + [126.398903, 36.750153, 0], + [126.390578, 36.73716, 0], + [126.385198, 36.723206, 0], + [126.382599, 36.712467, 0], + [126.382977, 36.701406, 0], + [126.385459, 36.686937, 0], + [126.391034, 36.673033, 0], + [126.394932, 36.666426, 0], + [126.404801, 36.654153, 0], + [126.414871, 36.647487, 0], + [126.424182, 36.638771, 0], + [126.439584, 36.630988, 0], + [126.456433, 36.625468, 0], + [126.474219, 36.622377, 0], + [126.483295, 36.621775, 0], + [126.501471, 36.62248, 0], + [126.51922, 36.625704, 0], + [126.536004, 36.631351, 0], + [126.551314, 36.639249, 0], + [126.564686, 36.649159, 0], + [126.575713, 36.66078, 0], + [126.58406, 36.67376, 0], + [126.589473, 36.687705, 0], + [126.591785, 36.702192, 0], + [126.590925, 36.716781, 0], + [126.586916, 36.731028, 0], + [126.57988, 36.744501, 0], + [126.570028, 36.756789, 0], + [126.557659, 36.767518, 0], + [126.543149, 36.776362, 0], + [126.526939, 36.783052, 0], + [126.509524, 36.787382, 0], + [126.491433, 36.789223, 0], + [126.473217, 36.788517, 0] + ] + ] + }, + "properties": { "name": "서산비행장(공군)", "description": "서산비행장(공군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.281662, 36.511568, 0], + [126.288528, 36.510464, 0], + [126.29527, 36.510817, 0], + [126.309471, 36.511016, 0], + [126.320114, 36.512948, 0], + [126.33089, 36.515592, 0], + [126.335907, 36.517086, 0], + [126.34739, 36.521622, 0], + [126.355088, 36.52548, 0], + [126.364403, 36.531433, 0], + [126.369088, 36.534734, 0], + [126.375284, 36.54006, 0], + [126.383286, 36.548535, 0], + [126.389122, 36.556257, 0], + [126.394958, 36.567839, 0], + [126.398533, 36.57908, 0], + [126.400108, 36.591274, 0], + [126.400108, 36.604504, 0], + [126.397024, 36.615235, 0], + [126.394381, 36.62221, 0], + [126.390989, 36.628974, 0], + [126.386875, 36.635474, 0], + [126.378822, 36.645834, 0], + [126.370539, 36.652913, 0], + [126.362, 36.659882, 0], + [126.35273, 36.664839, 0], + [126.343803, 36.66897, 0], + [126.33274, 36.672644, 0], + [126.324097, 36.674902, 0], + [126.315241, 36.676546, 0], + [126.30624, 36.677564, 0], + [126.293335, 36.678057, 0], + [126.283379, 36.676955, 0], + [126.270163, 36.675295, 0], + [126.26147, 36.673164, 0], + [126.253042, 36.670433, 0], + [126.244944, 36.667122, 0], + [126.237238, 36.663257, 0], + [126.229981, 36.658868, 0], + [126.22323, 36.653988, 0], + [126.217035, 36.648654, 0], + [126.211444, 36.642906, 0], + [126.2065, 36.63679, 0], + [126.20224, 36.630351, 0], + [126.197548, 36.621314, 0], + [126.195145, 36.614425, 0], + [126.193085, 36.606433, 0], + [126.192055, 36.597062, 0], + [126.192454, 36.587811, 0], + [126.193567, 36.580576, 0], + [126.195461, 36.573446, 0], + [126.198121, 36.566475, 0], + [126.201527, 36.559717, 0], + [126.205652, 36.553223, 0], + [126.210465, 36.547043, 0], + [126.21593, 36.541223, 0], + [126.222005, 36.535807, 0], + [126.228643, 36.530837, 0], + [126.235794, 36.52635, 0], + [126.243404, 36.522381, 0], + [126.251414, 36.518959, 0], + [126.259765, 36.516111, 0], + [126.268392, 36.513858, 0], + [126.281662, 36.511568, 0] + ] + ] + }, + "properties": { "name": "한서비행장(민간사설)", "description": "한서비행장(민간사설) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.488442, 36.486453, 0], + [127.494488, 36.485928, 0], + [127.503562, 36.485856, 0], + [127.515564, 36.486453, 0], + [127.527237, 36.488661, 0], + [127.538906, 36.491855, 0], + [127.547169, 36.49487, 0], + [127.555075, 36.498451, 0], + [127.562563, 36.502573, 0], + [127.569577, 36.507203, 0], + [127.576063, 36.512306, 0], + [127.581971, 36.517844, 0], + [127.587258, 36.523775, 0], + [127.591882, 36.530053, 0], + [127.597618, 36.54026, 0], + [127.601452, 36.550484, 0], + [127.603455, 36.559842, 0], + [127.604485, 36.568115, 0], + [127.603424, 36.579483, 0], + [127.601395, 36.590171, 0], + [127.596674, 36.600629, 0], + [127.590065, 36.61167, 0], + [127.583331, 36.619651, 0], + [127.577563, 36.62529, 0], + [127.568436, 36.632611, 0], + [127.55691, 36.639498, 0], + [127.545433, 36.644732, 0], + [127.53582, 36.648314, 0], + [127.525864, 36.650792, 0], + [127.514674, 36.652226, 0], + [127.498741, 36.653272, 0], + [127.487465, 36.652441, 0], + [127.478496, 36.651243, 0], + [127.461117, 36.646993, 0], + [127.449989, 36.642529, 0], + [127.440376, 36.638397, 0], + [127.430412, 36.631617, 0], + [127.423926, 36.626505, 0], + [127.415314, 36.618008, 0], + [127.409821, 36.611118, 0], + [127.405701, 36.604228, 0], + [127.401031, 36.595319, 0], + [127.398491, 36.586587, 0], + [127.396774, 36.578868, 0], + [127.396088, 36.570321, 0], + [127.396088, 36.563703, 0], + [127.397118, 36.55543, 0], + [127.399864, 36.547156, 0], + [127.40351, 36.538152, 0], + [127.407274, 36.531513, 0], + [127.411739, 36.525168, 0], + [127.415314, 36.521225, 0], + [127.420464, 36.515431, 0], + [127.42901, 36.508319, 0], + [127.433166, 36.504945, 0], + [127.440033, 36.500529, 0], + [127.45111, 36.495632, 0], + [127.461662, 36.491421, 0], + [127.476537, 36.487971, 0], + [127.488442, 36.486453, 0] + ] + ] + }, + "properties": { "name": "성무비행장(공군)", "description": "성무비행장(공군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.459222, 36.631456, 0], + [128.459358, 36.6406, 0], + [128.456612, 36.650792, 0], + [128.453024, 36.660117, 0], + [128.449561, 36.666876, 0], + [128.445376, 36.673366, 0], + [128.440501, 36.679539, 0], + [128.434972, 36.685347, 0], + [128.428833, 36.690747, 0], + [128.419189, 36.697604, 0], + [128.407237, 36.704098, 0], + [128.399161, 36.707486, 0], + [128.3852, 36.712192, 0], + [128.373165, 36.714103, 0], + [128.359451, 36.71577, 0], + [128.348808, 36.715219, 0], + [128.336888, 36.714153, 0], + [128.327986, 36.712582, 0], + [128.319289, 36.710395, 0], + [128.310864, 36.707608, 0], + [128.302774, 36.704242, 0], + [128.295082, 36.700323, 0], + [128.287845, 36.695881, 0], + [128.281121, 36.69095, 0], + [128.274958, 36.685567, 0], + [128.269405, 36.679774, 0], + [128.264503, 36.673615, 0], + [128.26029, 36.667136, 0], + [128.256798, 36.660387, 0], + [128.254053, 36.65342, 0], + [128.252076, 36.646287, 0], + [128.250881, 36.639043, 0], + [128.250478, 36.631744, 0], + [128.250961, 36.622692, 0], + [128.252335, 36.614701, 0], + [128.254016, 36.610063, 0], + [128.256747, 36.603093, 0], + [128.260224, 36.59634, 0], + [128.26442, 36.589856, 0], + [128.269303, 36.58369, 0], + [128.272934, 36.579695, 0], + [128.278084, 36.575008, 0], + [128.283234, 36.570597, 0], + [128.290787, 36.565909, 0], + [128.297653, 36.561773, 0], + [128.302557, 36.559168, 0], + [128.310621, 36.555786, 0], + [128.316536, 36.553775, 0], + [128.323059, 36.551845, 0], + [128.331642, 36.549914, 0], + [128.342285, 36.548259, 0], + [128.354671, 36.547886, 0], + [128.363759, 36.548192, 0], + [128.372779, 36.549132, 0], + [128.384171, 36.551293, 0], + [128.393097, 36.5535, 0], + [128.402023, 36.556809, 0], + [128.41198, 36.561497, 0], + [128.421747, 36.567371, 0], + [128.42847, 36.572294, 0], + [128.436356, 36.579695, 0], + [128.445101, 36.589607, 0], + [128.451462, 36.598992, 0], + [128.454552, 36.60726, 0], + [128.456955, 36.614976, 0], + [128.4588, 36.624157, 0], + [128.459222, 36.631456, 0] + ] + ] + }, + "properties": { "name": "예천비행장(공군)", "description": "예천비행장(공군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.671532, 35.059229, 0], + [128.676497, 35.058442, 0], + [128.685348, 35.0574, 0], + [128.694275, 35.056992, 0], + [128.703212, 35.057222, 0], + [128.712091, 35.058089, 0], + [128.720844, 35.059585, 0], + [128.725777, 35.060634, 0], + [128.732987, 35.062882, 0], + [128.740196, 35.06513, 0], + [128.745691, 35.067713, 0], + [128.753294, 35.071567, 0], + [128.760457, 35.075948, 0], + [128.767128, 35.080824, 0], + [128.773255, 35.086156, 0], + [128.778792, 35.091904, 0], + [128.783696, 35.098026, 0], + [128.78793, 35.104473, 0], + [128.792381, 35.113449, 0], + [128.795471, 35.122998, 0], + [128.797599, 35.132517, 0], + [128.798107, 35.139825, 0], + [128.797834, 35.14714, 0], + [128.796783, 35.154409, 0], + [128.794441, 35.163705, 0], + [128.791008, 35.171563, 0], + [128.787231, 35.17886, 0], + [128.782082, 35.186155, 0], + [128.774958, 35.194005, 0], + [128.768992, 35.199465, 0], + [128.764916, 35.202709, 0], + [128.759079, 35.206917, 0], + [128.750839, 35.211685, 0], + [128.740043, 35.216479, 0], + [128.731809, 35.219365, 0], + [128.720284, 35.222624, 0], + [128.71067, 35.223746, 0], + [128.696763, 35.224777, 0], + [128.687807, 35.224546, 0], + [128.670141, 35.222179, 0], + [128.661565, 35.220061, 0], + [128.653248, 35.21734, 0], + [128.645254, 35.214036, 0], + [128.637643, 35.210175, 0], + [128.630474, 35.205787, 0], + [128.623801, 35.200904, 0], + [128.617675, 35.195564, 0], + [128.610763, 35.187839, 0], + [128.605614, 35.180824, 0], + [128.600464, 35.172686, 0], + [128.596717, 35.16354, 0], + [128.594682, 35.156412, 0], + [128.592911, 35.147424, 0], + [128.592911, 35.139844, 0], + [128.593941, 35.129737, 0], + [128.596126, 35.120113, 0], + [128.598721, 35.113109, 0], + [128.602053, 35.106316, 0], + [128.606095, 35.099786, 0], + [128.610816, 35.093569, 0], + [128.616181, 35.087713, 0], + [128.622148, 35.082261, 0], + [128.63205, 35.074965, 0], + [128.643192, 35.068729, 0], + [128.657112, 35.063163, 0], + [128.671532, 35.059229, 0] + ] + ] + }, + "properties": { "name": "진해비행장(해군)", "description": "진해비행장(해군) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.737251, 33.474981, 0], + [126.739646, 33.474836, 0], + [126.731109, 33.476494, 0], + [126.72243, 33.477525, 0], + [126.708756, 33.477559, 0], + [126.696213, 33.476797, 0], + [126.687636, 33.475288, 0], + [126.674423, 33.471831, 0], + [126.663304, 33.467118, 0], + [126.652107, 33.460661, 0], + [126.642342, 33.453969, 0], + [126.636359, 33.448626, 0], + [126.630958, 33.442869, 0], + [126.622238, 33.432301, 0], + [126.618632, 33.423558, 0], + [126.615028, 33.414248, 0], + [126.612968, 33.406224, 0], + [126.612625, 33.399345, 0], + [126.612282, 33.391033, 0], + [126.613616, 33.380376, 0], + [126.615431, 33.373223, 0], + [126.617985, 33.366229, 0], + [126.621259, 33.359448, 0], + [126.625227, 33.35293, 0], + [126.62986, 33.346727, 0], + [126.635122, 33.340884, 0], + [126.640973, 33.335446, 0], + [126.647368, 33.330455, 0], + [126.654259, 33.325948, 0], + [126.661593, 33.321959, 0], + [126.669314, 33.318519, 0], + [126.677364, 33.315655, 0], + [126.685682, 33.313387, 0], + [126.694205, 33.311732, 0], + [126.706009, 33.310159, 0], + [126.720348, 33.310555, 0], + [126.732788, 33.31102, 0], + [126.745967, 33.315068, 0], + [126.758194, 33.318767, 0], + [126.76932, 33.324964, 0], + [126.77632, 33.329352, 0], + [126.782836, 33.334233, 0], + [126.791496, 33.341715, 0], + [126.797676, 33.349458, 0], + [126.803133, 33.357893, 0], + [126.806573, 33.364616, 0], + [126.811066, 33.376699, 0], + [126.813126, 33.389313, 0], + [126.812439, 33.402785, 0], + [126.811066, 33.411669, 0], + [126.805229, 33.425424, 0], + [126.801453, 33.43316, 0], + [126.795483, 33.441462, 0], + [126.790224, 33.447311, 0], + [126.78154, 33.455219, 0], + [126.7733, 33.460661, 0], + [126.76374, 33.466259, 0], + [126.751671, 33.471831, 0], + [126.737251, 33.474981, 0] + ] + ] + }, + "properties": { "name": "정석비행장(민간사설)", "description": "정석비행장(민간사설) 반경 9.3Km 비행장", "type": "0004" } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [127.115577, 37.3849, 0] }, + "properties": { + "name": "탄천 RC비행장", + "description": "경기도 성남시 분당구 수내동 45", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [126.8584, 37.5783, 0] }, + "properties": { + "name": "가양대교 북단 RC 비행장", + "description": "경기 고양시 덕양구 덕은동 520-26 (서울 P-73 공역 비행통제 지역으로서 허가를 받은 후 비행)", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [127.2158, 37.5583, 0] }, + "properties": { + "name": "미사리 RC비행장", + "description": "경기도 하남시 미사동 57-2", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [126.6563, 37.1907, 0] }, + "properties": { + "name": "전곡항 RC비행장", + "description": "경기도 화성시 서신면 전곡리 전곡항 교차로", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [127.1194, 37.5473, 0] }, + "properties": { + "name": "광나루 RC비행장", + "description": "서울특별시 강동구 천호동 351-1 (한강시민공원광나루지구4주차장)", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [126.7482, 37.5334, 0] }, + "properties": { + "name": "계양 경기장 RC비행장", + "description": "인천광역시 계양구 서운동 111 (양궁훈련이 있을 경우 비행을 할 수 없습니다)", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [127.1003, 37.4969, 0] }, + "properties": { + "name": "탄천 유수지 RC비행장", + "description": "서울특별시 송파구 가락동 508", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [126.7595, 37.4023, 0] }, + "properties": { + "name": "포동 RC비행장", + "description": "경기도 시흥시 방산동 779-63", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [127.4066, 37.7206, 0] }, + "properties": { + "name": "신청평대교 RC비행장", + "description": "경기도 가평군 청평면 대성리 산2-1", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [126.995, 37.1682, 0] }, + "properties": { + "name": "용수교 RC비행장", + "description": "경기도 화성시 정남면 발산리 16-1", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [126.872566, 35.234922, 0] + }, + "properties": { + "name": "광주 하늘사랑 무선모형 비행클럽 RC비행장", + "description": "광주광역시 북구 지야동 682", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [126.891268, 37.419289, 0] + }, + "properties": { + "name": "광명역 RC비행장", + "description": "경기도 안양시 만안구 석수동 안양석수스마트타운", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [126.8775845, 37.5170106, 0] + }, + "properties": { "name": "신정교 RC 비행장", + "description": "경기도 안양시 만안구 석수동 안양석수스마트타운", + "type": "0005" + } + }, + { + "type": "Feature", + "geometry": { "type": "LineString", + "coordinates": [ + [127.023178, 35.729104, 70.42], + [127.022043, 35.728036, 63.26], + [127.020797, 35.727053, 66], + [127.019451, 35.726162, 85.07], + [127.018014, 35.725369, 115.47], + [127.016497, 35.724681, 117.54], + [127.014913, 35.724103, 123.83], + [127.013272, 35.723639, 130.38], + [127.011588, 35.723294, 129.65], + [127.009873, 35.723068, 127.37], + [127.008141, 35.722965, 104.11], + [127.006404, 35.722985, 62.97], + [127.004675, 35.723127, 50.18], + [127.002969, 35.723391, 36.53], + [127.001297, 35.723775, 30.39], + [126.999673, 35.724276, 29], + [126.998109, 35.72489, 27.88], + [126.996617, 35.725612, 26.08], + [126.995208, 35.726436, 24.59], + [126.993893, 35.727358, 23.43], + [126.992681, 35.728369, 21.5], + [126.991583, 35.729462, 19.57], + [126.990606, 35.730628, 18.32], + [126.989758, 35.731859, 17.93], + [126.989046, 35.733145, 17.64], + [126.988474, 35.734477, 17.9], + [126.988048, 35.735844, 18.26], + [126.987769, 35.737236, 18.11], + [126.987642, 35.738643, 17.86], + [126.987666, 35.740053, 17.91], + [126.987841, 35.741456, 19.15], + [126.988166, 35.742842, 21.67], + [126.988639, 35.744199, 24.39], + [126.989256, 35.745517, 27.28], + [126.990012, 35.746787, 30.34], + [126.990901, 35.747999, 33.53], + [126.991918, 35.749143, 36.82], + [126.993053, 35.75021, 35.56], + [126.994299, 35.751194, 31.75], + [126.995645, 35.752085, 28.02], + [126.997083, 35.752878, 29.09], + [126.998599, 35.753566, 33.43], + [127.000185, 35.754144, 40.19], + [127.001826, 35.754608, 41.77], + [127.00351, 35.754954, 57.3], + [127.005226, 35.75518, 74.55], + [127.006959, 35.755283, 87.26], + [127.008697, 35.755263, 106.79], + [127.010426, 35.755121, 134.69], + [127.012133, 35.754856, 165.27], + [127.013805, 35.754472, 196.91], + [127.01543, 35.753971, 225.04], + [127.016994, 35.753357, 246.78], + [127.018487, 35.752635, 293.57], + [127.019896, 35.75181, 282.64], + [127.021212, 35.750888, 309.31], + [127.022423, 35.749877, 343.91], + [127.023521, 35.748784, 413.87], + [127.024497, 35.747617, 422.86], + [127.025345, 35.746386, 375.48], + [127.026057, 35.745099, 302.1], + [127.026628, 35.743767, 245.85], + [127.027054, 35.7424, 226.87], + [127.027331, 35.741008, 235.81], + [127.027458, 35.739601, 235.43], + [127.027433, 35.738191, 222.18], + [127.027257, 35.736788, 203.97], + [127.026931, 35.735403, 188.58], + [127.026458, 35.734046, 153.11], + [127.025841, 35.732727, 110.17], + [127.025084, 35.731458, 93.28], + [127.024194, 35.730247, 81.03], + [127.023178, 35.729104, 70.42] + ] + }, + "properties": { + "name": "구성산 반경 1.8Km", + "description": "전라북도 김제시 금산면 삼봉리 124-1", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [128.423422, 35.735448, 61.15], + [128.422995, 35.735022, 30.47], + [128.422524, 35.734628, 26.59], + [128.422013, 35.734268, 22.84], + [128.421465, 35.733946, 19.23], + [128.420885, 35.733665, 15.79], + [128.420276, 35.733425, 12.55], + [128.419644, 35.733229, 9.54], + [128.418994, 35.733079, 7.2], + [128.41833, 35.732975, 8.1], + [128.417657, 35.732919, 8.97], + [128.416981, 35.73291, 9.8], + [128.416306, 35.732949, 10.39], + [128.415638, 35.733036, 10.41], + [128.414982, 35.73317, 24.05], + [128.414343, 35.73335, 24.8], + [128.413726, 35.733574, 20.13], + [128.413135, 35.733841, 18.43], + [128.412575, 35.734149, 21.29], + [128.41205, 35.734495, 21.21], + [128.411564, 35.734877, 21.28], + [128.411121, 35.735292, 21.12], + [128.410725, 35.735737, 20.74], + [128.410377, 35.736208, 20.14], + [128.410082, 35.736702, 17.03], + [128.409841, 35.737215, 13.26], + [128.409655, 35.737743, 9.54], + [128.409527, 35.738282, 7.98], + [128.409458, 35.738828, 9.16], + [128.409447, 35.739377, 10.56], + [128.409496, 35.739925, 11.09], + [128.409603, 35.740467, 13.07], + [128.409768, 35.740999, 15.75], + [128.409989, 35.741518, 17.6], + [128.410265, 35.742019, 19.2], + [128.410594, 35.742499, 19.78], + [128.410973, 35.742953, 19.27], + [128.4114, 35.74338, 18.79], + [128.411871, 35.743774, 18.33], + [128.412382, 35.744133, 20.08], + [128.41293, 35.744455, 31.43], + [128.413511, 35.744737, 41.66], + [128.414119, 35.744977, 37.94], + [128.414751, 35.745173, 40.36], + [128.415402, 35.745323, 46.83], + [128.416066, 35.745427, 48.15], + [128.416739, 35.745483, 49.38], + [128.417415, 35.745492, 53.29], + [128.41809, 35.745452, 63.09], + [128.418758, 35.745366, 74.22], + [128.419414, 35.745232, 78.43], + [128.420053, 35.745052, 66.9], + [128.42067, 35.744828, 52.04], + [128.421261, 35.744561, 42.52], + [128.421822, 35.744253, 35.95], + [128.422346, 35.743906, 38.33], + [128.422832, 35.743524, 44.87], + [128.423275, 35.743109, 45.76], + [128.423672, 35.742664, 45.91], + [128.424019, 35.742193, 44.45], + [128.424314, 35.741699, 36.55], + [128.424555, 35.741186, 28.89], + [128.424741, 35.740658, 35.1], + [128.424868, 35.740119, 39.29], + [128.424938, 35.739573, 56.98], + [128.424948, 35.739024, 75.28], + [128.4249, 35.738477, 87.78], + [128.424793, 35.737934, 97.41], + [128.424628, 35.737402, 104.3], + [128.424406, 35.736883, 109], + [128.42413, 35.736382, 107.92], + [128.423801, 35.735902, 87.73], + [128.423422, 35.735448, 61.15] + ] + }, + "properties": { + "name": "약산 반경 0.7Km", + "description": "대구광역시 달성군 논공읍 하리 757", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [129.063101, 35.598445, 259.84], + [129.06031, 35.600617, 270.31], + [129.057763, 35.602978, 278.07], + [129.055478, 35.605511, 326.98], + [129.053473, 35.608196, 402.16], + [129.051764, 35.611013, 377.99], + [129.050362, 35.61394, 270.03], + [129.049281, 35.616955, 237.02], + [129.048526, 35.620036, 271.82], + [129.048105, 35.623158, 355.33], + [129.04802, 35.626298, 435.81], + [129.048272, 35.629433, 453.78], + [129.048859, 35.632537, 419.71], + [129.049777, 35.635588, 403.61], + [129.051019, 35.638563, 403.36], + [129.052575, 35.641438, 454.38], + [129.054434, 35.644192, 531.01], + [129.056581, 35.646804, 593.83], + [129.059, 35.649253, 609.72], + [129.061674, 35.651522, 577.54], + [129.06458, 35.653593, 521.73], + [129.067698, 35.65545, 517.45], + [129.071003, 35.657079, 503.15], + [129.07447, 35.658468, 534.27], + [129.078074, 35.659606, 503.39], + [129.081785, 35.660484, 487.77], + [129.085577, 35.661096, 477.95], + [129.089421, 35.661436, 469.79], + [129.093286, 35.661504, 465.79], + [129.097143, 35.661297, 491.96], + [129.100964, 35.660817, 540.98], + [129.104719, 35.660069, 575.48], + [129.108379, 35.659057, 582.74], + [129.111916, 35.657791, 571.09], + [129.115304, 35.656278, 484.89], + [129.118517, 35.654531, 462.29], + [129.121529, 35.652563, 393.03], + [129.124319, 35.650389, 322.53], + [129.126866, 35.648025, 389.32], + [129.129148, 35.645491, 455.78], + [129.13115, 35.642804, 444.16], + [129.132857, 35.639985, 410.05], + [129.134254, 35.637057, 382.27], + [129.135331, 35.63404, 340.9], + [129.136081, 35.630959, 262.61], + [129.136498, 35.627836, 222.92], + [129.136578, 35.624696, 185], + [129.136322, 35.621562, 149.13], + [129.13573, 35.618458, 160.52], + [129.134807, 35.615408, 195.08], + [129.133561, 35.612434, 187.68], + [129.132002, 35.609561, 182.92], + [129.13014, 35.606809, 180.38], + [129.12799, 35.604199, 169.44], + [129.125569, 35.601751, 158.58], + [129.122895, 35.599484, 188.81], + [129.119988, 35.597416, 179.01], + [129.11687, 35.595561, 110.17], + [129.113566, 35.593934, 110.5], + [129.1101, 35.592547, 117.28], + [129.106499, 35.591412, 147.57], + [129.10279, 35.590535, 144.77], + [129.099001, 35.589925, 135.16], + [129.095161, 35.589586, 136.08], + [129.091299, 35.58952, 140.67], + [129.087445, 35.589727, 139.66], + [129.083628, 35.590208, 133.02], + [129.079876, 35.590956, 148.73], + [129.07622, 35.591968, 166.91], + [129.072685, 35.593235, 175.08], + [129.0693, 35.594747, 194.21], + [129.066089, 35.596494, 246.4], + [129.063101, 35.598445, 259.84] + ] + }, + "properties": { + "name": "봉화산 반경 4Km", + "description": "울산광역시 울주군 상북면 궁근정리 산125-2", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { "type": "LineString", + "coordinates": [ + [127.498239, 35.382618, 655.18], + [127.495257, 35.385181, 577.08], + [127.492559, 35.387947, 527.94], + [127.490168, 35.390893, 529.07], + [127.4881, 35.393998, 491.49], + [127.486372, 35.397238, 569.15], + [127.484997, 35.400589, 641.66], + [127.483985, 35.404024, 628.82], + [127.483345, 35.407518, 501.81], + [127.48308, 35.411045, 451.61], + [127.483194, 35.414577, 397.16], + [127.483685, 35.418087, 447.21], + [127.48455, 35.421549, 395.79], + [127.485782, 35.424937, 347], + [127.487371, 35.428224, 412.8], + [127.489306, 35.431385, 468.03], + [127.491573, 35.434397, 542.71], + [127.494153, 35.437237, 533.95], + [127.497027, 35.439883, 530.82], + [127.500174, 35.442314, 493.74], + [127.503568, 35.444512, 483.9], + [127.507186, 35.446461, 492.73], + [127.510998, 35.448146, 484.75], + [127.514976, 35.449553, 479.91], + [127.51909, 35.450673, 479.06], + [127.523307, 35.451496, 481.77], + [127.527597, 35.452016, 479.62], + [127.531927, 35.452229, 482.38], + [127.536262, 35.452134, 473.24], + [127.540571, 35.451731, 467.55], + [127.54482, 35.451024, 457.84], + [127.548978, 35.450018, 453.48], + [127.553012, 35.44872, 456.74], + [127.556891, 35.447141, 476.03], + [127.560587, 35.445292, 522.32], + [127.56407, 35.443187, 627.13], + [127.567315, 35.440843, 727.06], + [127.570297, 35.438278, 781.82], + [127.572992, 35.43551, 734.29], + [127.575381, 35.432562, 878.64], + [127.577445, 35.429455, 1018.94], + [127.579169, 35.426213, 1102.37], + [127.58054, 35.422861, 1018.87], + [127.581547, 35.419424, 1011.7], + [127.582182, 35.41593, 913.51], + [127.582441, 35.412403, 780.61], + [127.582322, 35.408871, 660.32], + [127.581825, 35.405361, 662.11], + [127.580955, 35.4019, 809.24], + [127.579719, 35.398514, 977.3], + [127.578125, 35.395228, 916.5], + [127.576186, 35.392068, 760.94], + [127.573917, 35.389058, 650.1], + [127.571335, 35.386221, 657.75], + [127.568459, 35.383578, 780.06], + [127.565312, 35.381149, 910.29], + [127.561918, 35.378953, 944.32], + [127.558302, 35.377006, 918.78], + [127.554491, 35.375324, 893.27], + [127.550516, 35.373919, 1024.06], + [127.546405, 35.372801, 926.45], + [127.542191, 35.37198, 1034.51], + [127.537905, 35.371461, 1053.01], + [127.53358, 35.371249, 1056.67], + [127.529249, 35.371345, 1198.64], + [127.524944, 35.371748, 1211.89], + [127.520699, 35.372455, 1037.89], + [127.516546, 35.373462, 882.59], + [127.512515, 35.374759, 778.41], + [127.508639, 35.376338, 682.31], + [127.504946, 35.378186, 698.02], + [127.501465, 35.38029, 707.68], + [127.498239, 35.382618, 655.18] + ] + }, + "properties": { + "name": "덕두산 반경 4.5Km", + "description": "전라북도 남원시 운봉읍 공안리 519-1", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [127.967629, 34.721124, 242.73], + [127.966062, 34.722156, 194.34], + [127.96461, 34.723297, 129.52], + [127.963284, 34.724536, 74.93], + [127.962094, 34.725867, 45.15], + [127.961051, 34.727277, 77.16], + [127.96016, 34.728757, 110.07], + [127.95943, 34.730294, 149.97], + [127.958866, 34.731879, 108.92], + [127.958472, 34.733497, 75.75], + [127.958251, 34.735138, 31.21], + [127.958205, 34.736788, 25.72], + [127.958334, 34.738436, 75.65], + [127.958638, 34.740067, 89.63], + [127.959113, 34.741671, 100.68], + [127.959757, 34.743235, 147.22], + [127.960564, 34.744747, 152.5], + [127.961528, 34.746195, 187.52], + [127.962643, 34.747568, 215.26], + [127.963898, 34.748857, 248.11], + [127.965286, 34.75005, 230.65], + [127.966795, 34.75114, 299.35], + [127.968414, 34.752117, 364.32], + [127.970131, 34.752975, 391.31], + [127.971932, 34.753706, 393.84], + [127.973804, 34.754306, 424.1], + [127.975732, 34.75477, 478.32], + [127.977702, 34.755093, 541.28], + [127.979699, 34.755274, 602.99], + [127.981708, 34.755312, 663.92], + [127.983713, 34.755205, 629.93], + [127.985699, 34.754955, 591.06], + [127.987651, 34.754564, 565.89], + [127.989554, 34.754035, 589.71], + [127.991393, 34.753371, 602.13], + [127.993156, 34.752578, 558.92], + [127.994827, 34.751662, 466.75], + [127.996395, 34.75063, 423.48], + [127.997847, 34.749489, 382.7], + [127.999172, 34.748249, 400.57], + [128.000361, 34.746918, 356.06], + [128.001405, 34.745508, 319.45], + [128.002294, 34.744028, 310.05], + [128.003024, 34.74249, 258.14], + [128.003587, 34.740905, 246.81], + [128.00398, 34.739286, 267.67], + [128.0042, 34.737646, 253.83], + [128.004245, 34.735995, 175.77], + [128.004115, 34.734348, 138.34], + [128.003811, 34.732716, 103.97], + [128.003334, 34.731113, 113.96], + [128.00269, 34.729549, 165.1], + [128.001882, 34.728038, 226.76], + [128.000917, 34.72659, 257.94], + [127.999802, 34.725217, 236.74], + [127.998546, 34.723929, 181.96], + [127.997159, 34.722736, 109.97], + [127.995649, 34.721647, 67.88], + [127.994031, 34.72067, 37.49], + [127.992315, 34.719812, 9.64], + [127.990514, 34.719081, 0], + [127.988643, 34.718482, 0], + [127.986715, 34.718019, 0.9], + [127.984746, 34.717695, 1.95], + [127.98275, 34.717514, 20.76], + [127.980742, 34.717477, 69.87], + [127.978738, 34.717583, 133.44], + [127.976753, 34.717833, 193.75], + [127.974802, 34.718224, 167.21], + [127.972899, 34.718753, 151.18], + [127.971061, 34.719417, 190.33], + [127.969299, 34.720209, 232.65], + [127.967629, 34.721124, 242.73] + ] + }, + "properties": { + "name": "금산 반경 2.1Km", + "description": "경상남도 남해군 상주면 상주리 산270-14", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [127.094163, 35.826471, 51.72], + [127.09396, 35.825556, 43.46], + [127.093659, 35.82466, 41.83], + [127.093264, 35.823788, 40.53], + [127.092776, 35.822947, 40.2], + [127.092199, 35.822144, 40.93], + [127.091539, 35.821385, 41.63], + [127.090799, 35.820675, 42.27], + [127.089986, 35.82002, 42.81], + [127.089106, 35.819426, 43.42], + [127.088165, 35.818895, 44.62], + [127.087171, 35.818434, 45.88], + [127.08613, 35.818044, 47.16], + [127.085052, 35.817729, 50.67], + [127.083945, 35.817492, 60.87], + [127.082816, 35.817334, 70.8], + [127.081674, 35.817256, 80.39], + [127.080528, 35.817259, 80.43], + [127.079387, 35.817343, 72.58], + [127.078259, 35.817508, 64.67], + [127.077153, 35.817751, 56.75], + [127.076078, 35.818072, 53.66], + [127.075041, 35.818467, 53.73], + [127.074051, 35.818935, 53.78], + [127.073114, 35.81947, 53.81], + [127.072239, 35.82007, 53.51], + [127.071432, 35.820729, 51.79], + [127.070698, 35.821443, 50.08], + [127.070044, 35.822205, 48.39], + [127.069474, 35.823012, 46.72], + [127.068993, 35.823855, 45.11], + [127.068605, 35.824729, 43.54], + [127.068312, 35.825627, 42.05], + [127.068117, 35.826543, 40.64], + [127.068021, 35.827469, 39.31], + [127.068025, 35.828398, 38.09], + [127.068128, 35.829323, 36.97], + [127.068331, 35.830238, 35.98], + [127.068631, 35.831134, 35.11], + [127.069027, 35.832006, 34.37], + [127.069515, 35.832847, 33.77], + [127.070091, 35.83365, 33.31], + [127.070751, 35.834409, 33], + [127.071491, 35.835119, 34.58], + [127.072304, 35.835774, 36.47], + [127.073185, 35.836369, 38.52], + [127.074126, 35.836899, 40.72], + [127.07512, 35.837361, 43.04], + [127.07616, 35.837751, 45.47], + [127.077239, 35.838065, 47.99], + [127.078347, 35.838303, 50.59], + [127.079476, 35.838461, 53.24], + [127.080618, 35.838539, 55.91], + [127.081764, 35.838536, 58.6], + [127.082906, 35.838451, 61.28], + [127.084034, 35.838287, 63.93], + [127.08514, 35.838043, 66.53], + [127.086215, 35.837722, 100], + [127.087252, 35.837327, 125.26], + [127.088243, 35.836859, 148.13], + [127.089179, 35.836324, 155.09], + [127.090055, 35.835724, 124.41], + [127.090862, 35.835065, 105.54], + [127.091596, 35.834351, 97.24], + [127.09225, 35.833588, 95.28], + [127.092819, 35.832781, 93.63], + [127.0933, 35.831938, 92.3], + [127.093688, 35.831064, 91.29], + [127.09398, 35.830165, 80.82], + [127.094175, 35.82925, 62.83], + [127.094271, 35.828324, 50.18], + [127.094267, 35.827395, 47.65], + [127.094163, 35.826471, 51.72] + ] + }, + "properties": { + "name": "홍산 반경 1.2Km", + "description": "전라북도 전주시 완산구 상림동 23-3", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [126.707398, 35.356274, 299.98], + [126.704265, 35.358102, 349.1], + [126.70134, 35.360146, 342.03], + [126.698645, 35.362389, 249.86], + [126.696199, 35.364816, 224.18], + [126.694022, 35.367407, 160.02], + [126.692129, 35.370143, 133.25], + [126.690537, 35.373003, 92.48], + [126.689256, 35.375965, 110.69], + [126.688296, 35.379008, 138.4], + [126.687666, 35.382106, 154.49], + [126.687369, 35.385238, 163.23], + [126.687408, 35.388379, 140.49], + [126.687782, 35.391505, 99.09], + [126.68849, 35.394593, 58.67], + [126.689525, 35.397619, 59.23], + [126.690879, 35.400559, 62.5], + [126.692543, 35.403392, 67.38], + [126.694504, 35.406097, 75.13], + [126.696747, 35.408651, 91.44], + [126.699254, 35.411036, 111.06], + [126.702007, 35.413235, 111.47], + [126.704985, 35.415229, 102.69], + [126.708165, 35.417004, 103.79], + [126.711523, 35.418546, 161.25], + [126.715033, 35.419844, 190.92], + [126.718669, 35.420887, 271.6], + [126.722402, 35.421668, 174.23], + [126.726205, 35.422181, 87.84], + [126.730048, 35.422421, 95.55], + [126.733903, 35.422388, 103.7], + [126.737739, 35.422081, 117.71], + [126.741527, 35.421502, 167.18], + [126.74524, 35.420656, 201.33], + [126.748847, 35.41955, 259.71], + [126.752322, 35.418192, 357.55], + [126.755639, 35.416592, 370.1], + [126.758772, 35.414762, 270.87], + [126.761697, 35.412717, 251.35], + [126.764392, 35.410471, 278.92], + [126.766837, 35.408043, 353.73], + [126.769012, 35.40545, 250.86], + [126.770902, 35.402712, 187.79], + [126.772491, 35.399851, 186.29], + [126.773769, 35.396888, 174.09], + [126.774725, 35.393845, 136.85], + [126.775351, 35.390745, 132.66], + [126.775644, 35.387613, 103.96], + [126.775601, 35.384472, 175.67], + [126.775222, 35.381347, 200.2], + [126.774511, 35.37826, 209.5], + [126.773472, 35.375235, 166.37], + [126.772114, 35.372295, 159.12], + [126.770448, 35.369463, 192.34], + [126.768484, 35.366761, 163.01], + [126.76624, 35.364208, 101.98], + [126.763732, 35.361824, 145.71], + [126.760978, 35.359628, 155.08], + [126.758, 35.357636, 94.85], + [126.754821, 35.355863, 92.59], + [126.751465, 35.354322, 125.53], + [126.747957, 35.353026, 133.58], + [126.744323, 35.351984, 191.48], + [126.740593, 35.351205, 269.65], + [126.736793, 35.350693, 214.36], + [126.732953, 35.350453, 170.4], + [126.729102, 35.350487, 208.51], + [126.72527, 35.350795, 233.97], + [126.721484, 35.351373, 259.83], + [126.717775, 35.352219, 341.66], + [126.714171, 35.353325, 473.56], + [126.710698, 35.354683, 379.41], + [126.707398, 35.356274, 299.98] + ] + }, + "properties": { + "name": "고창 반경 4Km", + "description": "전라남도 장성군 북일면 문암리 산236", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [126.459929, 34.687277, 1.02], + [126.458887, 34.691416, 5.75], + [126.458287, 34.695613, 7], + [126.458135, 34.699837, 6.46], + [126.45843, 34.704057, 5.74], + [126.459173, 34.708239, 3.03], + [126.460356, 34.712351, 0.22], + [126.46197, 34.716364, 0], + [126.464004, 34.720245, 0.18], + [126.466442, 34.723966, 0.93], + [126.469266, 34.727498, 1.62], + [126.472453, 34.730814, 2.23], + [126.475981, 34.733889, 2.55], + [126.479821, 34.7367, 3.06], + [126.483945, 34.739225, 9.37], + [126.488322, 34.741445, 10.9], + [126.492917, 34.743342, 11.68], + [126.497697, 34.744903, 12.27], + [126.502624, 34.746116, 11.33], + [126.507661, 34.746971, 11.58], + [126.512769, 34.747462, 12.68], + [126.51791, 34.747585, 10.64], + [126.523045, 34.747339, 15.96], + [126.528134, 34.746726, 22.19], + [126.533138, 34.745751, 28.71], + [126.53802, 34.744421, 42.66], + [126.542742, 34.742746, 92.44], + [126.547268, 34.740739, 115.5], + [126.551564, 34.738415, 100.32], + [126.555597, 34.735793, 75.38], + [126.559336, 34.732891, 44.57], + [126.562753, 34.729733, 17.78], + [126.565822, 34.726342, 10.07], + [126.568519, 34.722744, 26.27], + [126.570824, 34.718966, 56.56], + [126.57272, 34.715038, 58.21], + [126.574191, 34.710988, 27.31], + [126.575228, 34.706849, 17.06], + [126.575822, 34.702651, 18.25], + [126.575968, 34.698427, 18.42], + [126.575666, 34.694208, 16.65], + [126.574918, 34.690027, 18.87], + [126.57373, 34.685915, 47.07], + [126.572111, 34.681904, 140.34], + [126.570072, 34.678024, 125.1], + [126.567631, 34.674306, 96.36], + [126.564805, 34.670776, 108.45], + [126.561616, 34.667462, 94.57], + [126.558088, 34.664389, 11.04], + [126.554249, 34.661581, 0], + [126.550126, 34.659059, 0], + [126.545752, 34.656841, 0], + [126.541161, 34.654945, 0], + [126.536386, 34.653386, 0], + [126.531464, 34.652175, 0], + [126.526432, 34.651321, 0], + [126.521329, 34.65083, 0], + [126.516194, 34.650708, 0.05], + [126.511066, 34.650953, 0], + [126.505982, 34.651566, 0], + [126.500983, 34.65254, 0], + [126.496106, 34.653868, 0], + [126.491388, 34.655541, 0], + [126.486865, 34.657546, 0], + [126.482572, 34.659867, 0], + [126.478541, 34.662487, 0], + [126.474802, 34.665386, 0], + [126.471384, 34.668542, 0], + [126.468314, 34.671931, 0], + [126.465614, 34.675527, 0], + [126.463305, 34.679303, 0], + [126.461405, 34.683229, 0], + [126.459929, 34.687277, 1.02] + ] + }, + "properties": { "name": "성화대", + "description": "성화대 반경 5.4Km", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [126.715947, 35.429372, 83.31], + [126.713887, 35.431022, 59.46], + [126.712012, 35.432813, 56.48], + [126.710336, 35.434729, 53.18], + [126.70887, 35.436758, 56.9], + [126.707628, 35.438882, 90.41], + [126.706617, 35.441087, 132.52], + [126.705846, 35.443355, 107.24], + [126.70532, 35.44567, 80.1], + [126.705045, 35.448013, 63.69], + [126.70502, 35.450366, 64.78], + [126.705248, 35.452712, 65.97], + [126.705726, 35.455034, 86.53], + [126.706451, 35.457312, 91.32], + [126.707417, 35.45953, 91.42], + [126.708616, 35.461672, 85.91], + [126.71004, 35.463719, 62.47], + [126.711678, 35.465659, 57.78], + [126.713517, 35.467474, 55.66], + [126.715544, 35.469152, 47.84], + [126.717743, 35.470679, 49.54], + [126.720096, 35.472045, 53.61], + [126.722587, 35.473238, 57.92], + [126.725197, 35.47425, 62.44], + [126.727905, 35.475073, 67.25], + [126.73069, 35.4757, 68.24], + [126.733532, 35.476127, 69.74], + [126.736409, 35.476351, 71.03], + [126.739299, 35.476369, 77.3], + [126.74218, 35.476182, 92.85], + [126.74503, 35.475792, 108.01], + [126.747828, 35.4752, 122.65], + [126.750551, 35.474412, 148.88], + [126.75318, 35.473434, 188.38], + [126.755694, 35.472273, 229.56], + [126.758073, 35.470938, 323.61], + [126.760301, 35.469439, 361.87], + [126.76236, 35.467787, 482.94], + [126.764234, 35.465996, 556.08], + [126.76591, 35.464078, 524.83], + [126.767373, 35.462048, 442.07], + [126.768614, 35.459923, 362.99], + [126.769622, 35.457717, 297.16], + [126.770391, 35.455448, 243.62], + [126.770914, 35.453134, 250.97], + [126.771187, 35.45079, 246.59], + [126.771208, 35.448437, 257.94], + [126.770977, 35.446091, 225.98], + [126.770497, 35.44377, 203.53], + [126.76977, 35.441492, 183.01], + [126.768802, 35.439275, 207.39], + [126.7676, 35.437134, 262.19], + [126.766174, 35.435087, 256.98], + [126.764535, 35.433149, 211.76], + [126.762695, 35.431335, 208.38], + [126.760667, 35.429659, 256.96], + [126.758469, 35.428133, 258.11], + [126.756115, 35.426768, 264.9], + [126.753624, 35.425576, 326.13], + [126.751016, 35.424566, 344.42], + [126.748309, 35.423744, 286.84], + [126.745525, 35.423118, 231.82], + [126.742685, 35.422692, 186.07], + [126.739809, 35.422469, 138.73], + [126.736921, 35.422451, 113.19], + [126.734042, 35.422639, 104.6], + [126.731194, 35.42303, 91.21], + [126.728399, 35.423621, 91.44], + [126.725677, 35.424409, 83.84], + [126.72305, 35.425388, 105.13], + [126.720538, 35.426549, 150.64], + [126.718159, 35.427884, 136.28], + [126.715947, 35.429372, 83.31] + ] + }, + "properties": { "name": "방장산", + "description": "방장산 반경 5.4Km", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [127.155989, 34.582098, 85.26], + [127.153121, 34.585795, 80.12], + [127.150655, 34.589684, 129.1], + [127.148611, 34.593735, 51.74], + [127.147002, 34.597918, 0], + [127.145843, 34.602199, 0], + [127.145141, 34.606548, 0], + [127.144903, 34.61093, 0], + [127.145129, 34.615313, 0], + [127.145819, 34.619663, 0], + [127.146966, 34.623947, 0], + [127.148564, 34.628132, 0], + [127.150598, 34.632187, 0], + [127.153055, 34.636081, 0], + [127.155915, 34.639783, 0], + [127.159157, 34.643266, 0], + [127.162755, 34.646503, 0], + [127.166683, 34.64947, 0], + [127.170911, 34.652144, 0], + [127.175406, 34.654504, 0], + [127.180134, 34.656533, 0], + [127.18506, 34.658215, 0], + [127.190145, 34.659537, 0], + [127.195351, 34.66049, 0], + [127.200638, 34.661065, 0], + [127.205966, 34.661259, 0], + [127.211295, 34.66107, 0], + [127.216583, 34.660499, 0], + [127.22179, 34.659552, 0.25], + [127.226877, 34.658234, 13.25], + [127.231805, 34.656557, 8.54], + [127.236536, 34.654532, 3.49], + [127.241034, 34.652176, 30.59], + [127.245266, 34.649506, 65.41], + [127.249198, 34.646543, 119.55], + [127.2528, 34.643309, 112.86], + [127.256047, 34.639829, 74.12], + [127.258912, 34.636129, 85.91], + [127.261374, 34.632238, 92.34], + [127.263414, 34.628185, 94.89], + [127.265017, 34.624001, 176.57], + [127.26617, 34.619718, 147.94], + [127.266866, 34.615369, 88.62], + [127.267098, 34.610986, 48.01], + [127.266865, 34.606604, 71.75], + [127.26617, 34.602254, 63.42], + [127.265016, 34.597972, 87.93], + [127.263413, 34.593788, 106.35], + [127.261374, 34.589735, 83.89], + [127.258914, 34.585844, 59.13], + [127.256051, 34.582144, 32.4], + [127.252808, 34.578663, 26.35], + [127.249209, 34.575429, 58.73], + [127.245281, 34.572465, 49.08], + [127.241055, 34.569793, 51.06], + [127.236563, 34.567436, 88.73], + [127.231838, 34.565409, 106.71], + [127.226917, 34.563729, 76.4], + [127.221837, 34.562408, 38.5], + [127.216637, 34.561457, 10.59], + [127.211356, 34.560882, 1.13], + [127.206034, 34.560688, 11.86], + [127.200712, 34.560877, 29.24], + [127.195431, 34.561447, 14.29], + [127.190229, 34.562394, 3.69], + [127.185147, 34.56371, 13.65], + [127.180224, 34.565385, 27.05], + [127.175497, 34.567408, 30.05], + [127.171001, 34.569761, 25.62], + [127.166772, 34.572429, 57.94], + [127.16284, 34.575389, 70.74], + [127.159237, 34.578621, 70.26], + [127.155989, 34.582098, 85.26] + ] + }, + "properties": { "name": "고흥", + "description": "고흥 반경 5.4Km", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { "type": "LineString", + "coordinates": [ + [126.988376, 35.30438, 64.03], + [126.984556, 35.307483, 60.73], + [126.981082, 35.310844, 49.64], + [126.97798, 35.314441, 46.54], + [126.975273, 35.318244, 46.86], + [126.972983, 35.322225, 47.32], + [126.971127, 35.326353, 58.26], + [126.969718, 35.330598, 49.79], + [126.968768, 35.334927, 48.86], + [126.968284, 35.339307, 51.72], + [126.96827, 35.343705, 55.05], + [126.968726, 35.348087, 61.25], + [126.969649, 35.35242, 80.4], + [126.971031, 35.35667, 111.09], + [126.972863, 35.360807, 161.83], + [126.975129, 35.364797, 238.41], + [126.977814, 35.368611, 180.42], + [126.980896, 35.37222, 100.91], + [126.984353, 35.375595, 128.26], + [126.988158, 35.378713, 189.64], + [126.992281, 35.381547, 160.08], + [126.996693, 35.384078, 202.42], + [127.001358, 35.386286, 293.84], + [127.006242, 35.388153, 128.04], + [127.011307, 35.389666, 134.52], + [127.016514, 35.390813, 141.59], + [127.021825, 35.391586, 235.55], + [127.027198, 35.391978, 375.19], + [127.032593, 35.391987, 432.82], + [127.037968, 35.391612, 412.39], + [127.043282, 35.390856, 315.03], + [127.048495, 35.389725, 373.38], + [127.053567, 35.388229, 439.46], + [127.05846, 35.386377, 417.98], + [127.063136, 35.384184, 314.81], + [127.067559, 35.381667, 183.56], + [127.071697, 35.378846, 182.74], + [127.075516, 35.375741, 160.68], + [127.078989, 35.372376, 129.28], + [127.082089, 35.368777, 142.59], + [127.084792, 35.364972, 168.28], + [127.087078, 35.360989, 147.99], + [127.088929, 35.356858, 141.41], + [127.090331, 35.352612, 130.84], + [127.091275, 35.348282, 122.96], + [127.091752, 35.343902, 126.57], + [127.091759, 35.339504, 114.23], + [127.091296, 35.335122, 110.88], + [127.090367, 35.330791, 114.04], + [127.088979, 35.326541, 111.01], + [127.087142, 35.322407, 125.32], + [127.084871, 35.318418, 135.96], + [127.082183, 35.314607, 160.71], + [127.079098, 35.311001, 213.8], + [127.07564, 35.307628, 203.4], + [127.071835, 35.304514, 283.04], + [127.067712, 35.301682, 167.43], + [127.063303, 35.299154, 111.5], + [127.058641, 35.296949, 113.95], + [127.053762, 35.295083, 241.73], + [127.048702, 35.293572, 210.14], + [127.0435, 35.292427, 134.09], + [127.038195, 35.291655, 76.57], + [127.032829, 35.291264, 58.37], + [127.027441, 35.291255, 50.07], + [127.022073, 35.29163, 49.02], + [127.016765, 35.292385, 49.79], + [127.011557, 35.293514, 62.2], + [127.00649, 35.295009, 53.95], + [127.001602, 35.296859, 44.67], + [126.99693, 35.299049, 45.73], + [126.992509, 35.301564, 55.5], + [126.988376, 35.30438, 64.03] + ] + }, + "properties": { + "name": "담양 반경 5.6Km", + "description": "전라남도 담양군 금성면 석현리 590-14", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [126.825527, 33.452855, 176.03], + [126.822889, 33.452767, 186.48], + [126.820251, 33.45287, 197.21], + [126.817635, 33.453165, 208.13], + [126.815058, 33.453649, 217.68], + [126.812543, 33.454318, 221.9], + [126.810106, 33.455168, 225.4], + [126.807768, 33.456191, 227.66], + [126.805545, 33.457381, 220.96], + [126.803456, 33.458728, 208.53], + [126.801514, 33.460221, 211.21], + [126.799736, 33.46185, 214.62], + [126.798135, 33.463603, 211.64], + [126.796723, 33.465464, 209.19], + [126.795511, 33.467422, 206.93], + [126.794508, 33.46946, 203.12], + [126.793722, 33.471563, 197.81], + [126.793158, 33.473715, 189.65], + [126.792822, 33.475901, 181.03], + [126.792715, 33.478102, 173.47], + [126.792838, 33.480303, 169.31], + [126.793191, 33.482486, 166.78], + [126.793771, 33.484635, 163.58], + [126.794573, 33.486734, 158.49], + [126.795592, 33.488767, 157.23], + [126.796819, 33.490718, 151.81], + [126.798246, 33.492572, 146], + [126.799861, 33.494316, 139.84], + [126.801652, 33.495935, 133.75], + [126.803605, 33.497419, 127.72], + [126.805707, 33.498754, 124.97], + [126.807939, 33.499932, 116.61], + [126.810287, 33.500942, 108.07], + [126.812731, 33.501779, 101.53], + [126.815254, 33.502434, 99.78], + [126.817835, 33.502903, 91.87], + [126.820456, 33.503184, 87.12], + [126.823096, 33.503272, 82.69], + [126.825735, 33.503168, 79.26], + [126.828353, 33.502873, 74.02], + [126.830931, 33.502388, 70.03], + [126.833447, 33.501718, 66.42], + [126.835885, 33.500868, 63.21], + [126.838224, 33.499844, 61.29], + [126.840447, 33.498653, 62.94], + [126.842537, 33.497305, 65.12], + [126.844478, 33.495811, 69.67], + [126.846255, 33.494181, 73.44], + [126.847856, 33.492428, 75.89], + [126.849267, 33.490566, 76.14], + [126.850478, 33.488608, 76.52], + [126.851479, 33.486569, 76.3], + [126.852264, 33.484465, 85.15], + [126.852826, 33.482313, 88.71], + [126.853161, 33.480127, 92.17], + [126.853266, 33.477926, 95.86], + [126.85314, 33.475725, 101.49], + [126.852785, 33.473542, 108.56], + [126.852204, 33.471393, 115.7], + [126.8514, 33.469294, 115.2], + [126.85038, 33.467262, 114.21], + [126.849151, 33.465312, 116.83], + [126.847724, 33.463458, 130.32], + [126.846108, 33.461716, 131.77], + [126.844317, 33.460097, 128.21], + [126.842363, 33.458615, 135.08], + [126.840262, 33.45728, 142.79], + [126.83803, 33.456103, 150.61], + [126.835683, 33.455093, 158.35], + [126.833239, 33.454258, 164.64], + [126.830718, 33.453603, 167.59], + [126.828138, 33.453134, 170.91], + [126.825527, 33.452855, 176.03] + ] + }, + "properties": { + "name": "구좌 반경 2.8Km", + "description": "제주특별자치도 제주시 구좌읍 세화리 산6", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { "type": "LineString", + "coordinates": [ + [126.557191, 33.289318, 330.27], + [126.556076, 33.289163, 332.05], + [126.554949, 33.28909, 333.69], + [126.553819, 33.289099, 336.26], + [126.552695, 33.28919, 339.75], + [126.551584, 33.289363, 344.14], + [126.550495, 33.289616, 350.96], + [126.549437, 33.289948, 358.66], + [126.548417, 33.290355, 367.07], + [126.547444, 33.290836, 376.13], + [126.546524, 33.291385, 385.77], + [126.545666, 33.291999, 395.92], + [126.544874, 33.292673, 406.5], + [126.544156, 33.293403, 417.42], + [126.543517, 33.294182, 426.73], + [126.542961, 33.295004, 434.34], + [126.542493, 33.295864, 442.13], + [126.542117, 33.296755, 452.48], + [126.541835, 33.29767, 467.01], + [126.541649, 33.298602, 484.09], + [126.541562, 33.299544, 500.93], + [126.541573, 33.300488, 510.91], + [126.541682, 33.301429, 520.49], + [126.541889, 33.302357, 529.51], + [126.542192, 33.303267, 537.92], + [126.542589, 33.304152, 547.33], + [126.543076, 33.305004, 557.38], + [126.543651, 33.305818, 566.49], + [126.544308, 33.306586, 574.6], + [126.545043, 33.307304, 581.64], + [126.54585, 33.307965, 587.56], + [126.546723, 33.308566, 592.31], + [126.547655, 33.3091, 595.87], + [126.54864, 33.309564, 596.47], + [126.549669, 33.309955, 588.24], + [126.550735, 33.310269, 574.65], + [126.551829, 33.310505, 553.63], + [126.552945, 33.31066, 538.86], + [126.554072, 33.310733, 536.85], + [126.555202, 33.310724, 532.12], + [126.556327, 33.310632, 525.64], + [126.557438, 33.310459, 518.81], + [126.558527, 33.310205, 511.86], + [126.559585, 33.309873, 503.58], + [126.560605, 33.309465, 496.75], + [126.561578, 33.308985, 488.36], + [126.562498, 33.308435, 475.26], + [126.563356, 33.307821, 464.16], + [126.564148, 33.307146, 453.38], + [126.564865, 33.306417, 441.99], + [126.565504, 33.305637, 430.08], + [126.56606, 33.304815, 419.18], + [126.566527, 33.303954, 408.82], + [126.566903, 33.303064, 398.69], + [126.567184, 33.302149, 395.19], + [126.567369, 33.301217, 391.01], + [126.567457, 33.300275, 385.94], + [126.567445, 33.29933, 377.42], + [126.567335, 33.29839, 368.7], + [126.567128, 33.297461, 358.29], + [126.566824, 33.296551, 350.94], + [126.566427, 33.295667, 345.59], + [126.565939, 33.294815, 341.19], + [126.565364, 33.294002, 337.77], + [126.564706, 33.293233, 335.35], + [126.563971, 33.292516, 333.95], + [126.563164, 33.291855, 333.58], + [126.562291, 33.291255, 333.35], + [126.561359, 33.290721, 331.02], + [126.560374, 33.290257, 329.49], + [126.559345, 33.289866, 328.76], + [126.558279, 33.289552, 328.84], + [126.557191, 33.289318, 330.27] + ] + }, + "properties": { "name": "미악산", + "description": "미악산 반경 1.2Km", + "type": "0006", + "tessellate": true + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.383333, 37.502778, 0], + [127.383333, 37.45, 0], + [127.533333, 37.45, 0], + [127.533333, 37.502778, 0], + [127.383333, 37.502778, 0] + ] + ] + }, + "properties": { "name": "양평", + "description": "양평 초경량비행장치", + "type": "0006" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.904722, 36.528056, 0], + [126.9075, 36.468056, 0], + [127.098056, 36.434444, 0], + [127.120278, 36.500556, 0], + [126.962778, 36.5125, 0], + [126.937222, 36.540278, 0], + [126.904722, 36.528056, 0] + ] + ] + }, + "properties": { + "name": "공주", + "description": "초경량비행장치 전용 공역", + "type": "0006" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.555278, 37.237222, 0], + [126.561667, 37.212222, 0], + [126.674722, 37.2125, 0], + [126.774444, 37.220833, 0], + [126.833333, 37.241667, 0], + [126.833333, 37.29, 0], + [126.704167, 37.2975, 0], + [126.555278, 37.237222, 0] + ] + ] + }, + "properties": { + "name": "시화", + "description": "초경량비행장치 전용 공역", + "type": "0006" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [128.391944, 37.369722, 0], + [128.436111, 37.364722, 0], + [128.469444, 37.402778, 0], + [128.405278, 37.443889, 0], + [128.391944, 37.369722, 0] + ] + ] + }, + "properties": { + "name": "장암산", + "description": "초경량비행장치 전용 공역", + "type": "0006" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [127.723333, 34.987778, 0], + [127.794167, 34.9875, 0], + [127.794722, 35.029167, 0], + [127.723611, 35.029722, 0], + [127.723333, 34.987778, 0] + ] + ] + }, + "properties": { + "name": "하동", + "description": "초경량비행장치 전용 공역", + "type": "0006" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.79372200000002, 37.642065321423125, 0], + [126.79556331708322, 37.6420525830803, 0], + [126.79740407139138, 37.64201437194515, 0], + [126.79924370032316, 37.641950699696444, 0], + [126.80108164162465, 37.64186158579482, 0], + [126.80291733356297, 37.64174705747672, 0], + [126.8047502150997, 37.641607149746044, 0], + [126.8065797260639, 37.64144190536327, 0], + [126.80840530732533, 37.64125137483235, 0], + [126.81022640096666, 37.64103561638503, 0], + [126.81204245045593, 37.64079469596291, 0], + [126.81385290081819, 37.64052868719711, 0], + [126.8156571988067, 37.6402376713855, 0], + [126.81745479307371, 37.63992173746762, 0], + [126.81924513434046, 37.63958098199724, 0], + [126.8210276755666, 37.63921550911257, 0], + [126.82280187211899, 37.63882543050407, 0], + [126.82456718193943, 37.63841086538005, 0], + [126.82632306571195, 37.63797194042983, 0], + [126.82806898702893, 37.63750878978467, 0], + [126.8298044125564, 37.637021554976386, 0], + [126.83152881219839, 37.636510384893676, 0], + [126.83324165926012, 37.635975435736206, 0], + [126.83494243061023, 37.635416870966395, 0], + [126.83663060684185, 37.63483486125903, 0], + [126.83830567243236, 37.63422958444861, 0], + [126.83996711590206, 37.63360122547451, 0], + [126.84161442997153, 37.632949976323914, 0], + [126.84324711171743, 37.632276035972694, 0], + [126.84486466272732, 37.631579610324025, 0], + [126.84646658925253, 37.6308609121449, 0], + [126.84805240236012, 37.63012016100053, 0], + [126.84962161808271, 37.62935758318677, 0], + [126.85117375756717, 37.62857341166028, 0], + [126.85270834722151, 37.627767885966804, 0], + [126.85422491886007, 37.62694125216734, 0], + [126.85572300984705, 37.62609376276238, 0], + [126.85720216323826, 37.6252256766141, 0], + [126.85866192792102, 37.62433725886664, 0], + [126.86010185875227, 37.62342878086451, 0], + [126.86152151669471, 37.62250052006899, 0], + [126.86292046895107, 37.621552759972786, 0], + [126.86429828909641, 37.6205857900127, 0], + [126.86565455720829, 37.61959990548062, 0], + [126.86698885999493, 37.61859540743262, 0], + [126.86830079092145, 37.61757260259639, 0], + [126.86958995033358, 37.61653180327683, 0], + [126.8708559455796, 37.61547332726007, 0], + [126.87209839112988, 37.6143974977157, 0], + [126.87331690869404, 37.61330464309744, 0], + [126.87451112733608, 37.612195097042196, 0], + [126.87568068358706, 37.61106919826745, 0], + [126.87682522155544, 37.60992729046731, 0], + [126.87794439303497, 37.60876972220679, 0], + [126.87903785761031, 37.607596846814815, 0], + [126.88010528276007, 37.6064090222757, 0], + [126.88114634395731, 37.605206611119236, 0], + [126.88216072476787, 37.603989980309365, 0], + [126.8831481169456, 37.602759501131594, 0], + [126.88410822052562, 37.60151554907904, 0], + [126.88504074391454, 37.60025850373721, 0], + [126.88594540397823, 37.59898874866758, 0], + [126.88682192612698, 37.59770667128998, 0], + [126.88767004439794, 37.596412662763754, 0], + [126.88848950153479, 37.595107117867876, 0], + [126.88928004906484, 37.59379043487999, 0], + [126.89004144737326, 37.59246301545427, 0], + [126.8907734657747, 37.591125264498494, 0], + [126.89147588258186, 37.58977759004986, 0], + [126.8921484851716, 37.5884204031502, 0], + [126.89279107004796, 37.58705411772004, 0], + [126.89340344290254, 37.58567915043185, 0], + [126.89398541867179, 37.58429592058265, 0], + [126.89453682159174, 37.58290484996566, 0], + [126.89505748524964, 37.58150636274122, 0], + [126.89554725263262, 37.58010088530718, 0], + [126.89600597617381, 37.57868884616844, 0], + [126.89643351779507, 37.57727067580597, 0], + [126.89682974894727, 37.575846806545286, 0], + [126.89719455064711, 37.574417672424325, 0], + [126.89752781351154, 37.572983709060836, 0], + [126.89782943778876, 37.57154535351937, 0], + [126.89809933338651, 37.570103044177834, 0], + [126.89833741989744, 37.568657220593586, 0], + [126.89854362662119, 37.5672083233694, 0], + [126.89871789258385, 37.56575679401895, 0], + [126.89886016655427, 37.56430307483211, 0], + [126.89897040705738, 37.56284760874014, 0], + [126.89904858238452, 37.56139083918054, 0], + [126.8990946706009, 37.55993320996194, 0], + [126.89910865954995, 37.55847516512879, 0], + [126.89909054685465, 37.557017148826084, 0], + [126.89904033991613, 37.555559605164056, 0], + [126.89895805590896, 37.554102978082945, 0], + [126.8988437217737, 37.55264771121777, 0], + [126.8986973742064, 37.55119424776332, 0], + [126.89851905964518, 37.54974303033927, 0], + [126.89830883425377, 37.548294500855484, 0], + [126.89806676390215, 37.546849100377585, 0], + [126.89779292414427, 37.545407268992875, 0], + [126.89748740019294, 37.5439694456764, 0], + [126.89715028689147, 37.54253606815764, 0], + [126.89678168868282, 37.541107572787375, 0], + [126.89638171957547, 37.539684394405164, 0], + [126.89595050310679, 37.53826696620721, 0], + [126.89548817230316, 37.53685571961481, 0], + [126.89499486963759, 37.535451084143375, 0], + [126.89447074698414, 37.53405348727201, 0], + [126.89391596556989, 37.53266335431378, 0], + [126.89333069592377, 37.53128110828668, 0], + [126.89271511782283, 37.52990716978528, 0], + [126.8920694202357, 37.52854195685318, 0], + [126.89139380126313, 37.527185884856245, 0], + [126.89068846807609, 37.525839366356614, 0], + [126.8899536368509, 37.52450281098779, 0], + [126.88918953270179, 37.52317662533038, 0], + [126.88839638961082, 37.52186121278897, 0], + [126.88757445035509, 37.52055697346992, 0], + [126.8867239664314, 37.519264304060236, 0], + [126.88584519797826, 37.517983597707385, 0], + [126.88493841369528, 37.51671524390037, 0], + [126.88400389076027, 37.51545962835176, 0], + [126.88304191474349, 37.51421713288109, 0], + [126.8820527795196, 37.512988135299246, 0], + [126.88103678717721, 37.51177300929427, 0], + [126.87999424792581, 37.51057212431826, 0], + [126.87892548000045, 37.509385845475784, 0], + [126.877830809564, 37.50821453341343, 0], + [126.87671057060705, 37.507058544210864, 0], + [126.87556510484555, 37.50591822927314, 0], + [126.87439476161614, 37.50479393522466, 0], + [126.87319989776918, 37.50368600380439, 0], + [126.8719808775598, 37.502594771762645, 0], + [126.87073807253635, 37.50152057075948, 0], + [126.86947186142723, 37.500463727264474, 0], + [126.86818263002509, 37.499424562458266, 0], + [126.86687077106947, 37.49840339213555, 0], + [126.86553668412685, 37.49740052660986, 0], + [126.86418077546932, 37.49641627061988, 0], + [126.86280345795068, 37.49545092323756, 0], + [126.86140515088098, 37.49450477777794, 0], + [126.85998627989926, 37.49357812171061, 0], + [126.85854727684394, 37.49267123657318, 0], + [126.857088579622, 37.491784397886256, 0], + [126.85561063207605, 37.49091787507049, 0], + [126.85411388384958, 37.49007193136536, 0], + [126.85259879025094, 37.489246823749816, 0], + [126.85106581211515, 37.488442802864945, 0], + [126.84951541566454, 37.48766011293834, 0], + [126.84794807236749, 37.48689899171065, 0], + [126.84636425879586, 37.486159670363904, 0], + [126.84476445648092, 37.48544237345194, 0], + [126.84314915176765, 37.48474731883276, 0], + [126.84151883566794, 37.48407471760296, 0], + [126.8398740037121, 37.48342477403416, 0], + [126.8382151557993, 37.48279768551159, 0], + [126.83654279604683, 37.48219364247459, 0], + [126.83485743263763, 37.48161282835936, 0], + [126.8331595776674, 37.48105541954373, 0], + [126.83144974698983, 37.48052158529412, 0], + [126.8297284600613, 37.48001148771461, 0], + [126.82799623978414, 37.479525281698194, 0], + [126.8262536123493, 37.4790631148801, 0], + [126.82450110707764, 37.4786251275935, 0], + [126.82273925626053, 37.478211452827274, 0], + [126.82096859499973, 37.47782221618595, 0], + [126.81918966104615, 37.47745753585202, 0], + [126.81740299463806, 37.477117522550344, 0], + [126.81560913833852, 37.47680227951489, 0], + [126.8138086368721, 37.4765119024577, 0], + [126.81200203696113, 37.476246479540094, 0], + [126.81018988716103, 37.47600609134615, 0], + [126.80837273769563, 37.47579081085855, 0], + [126.80655114029152, 37.47560070343657, 0], + [126.80472564801217, 37.47543582679647, 0], + [126.80289681509177, 37.47529623099413, 0], + [126.80106519676852, 37.47518195841001, 0], + [126.79923134911775, 37.475093043736436, 0], + [126.79739582888485, 37.475029513967115, 0], + [126.79555919331786, 37.47499138838909, 0], + [126.79372200000002, 37.47497867857689, 0], + [126.79188480668218, 37.47499138838909, 0], + [126.79004817111517, 37.475029513967115, 0], + [126.78821265088227, 37.475093043736436, 0], + [126.78637880323151, 37.47518195841001, 0], + [126.78454718490825, 37.47529623099413, 0], + [126.78271835198785, 37.47543582679647, 0], + [126.7808928597085, 37.47560070343657, 0], + [126.77907126230438, 37.47579081085855, 0], + [126.77725411283899, 37.47600609134615, 0], + [126.7754419630389, 37.476246479540094, 0], + [126.77363536312792, 37.4765119024577, 0], + [126.7718348616615, 37.47680227951489, 0], + [126.77004100536197, 37.477117522550344, 0], + [126.76825433895387, 37.47745753585202, 0], + [126.76647540500029, 37.47782221618595, 0], + [126.76470474373949, 37.478211452827274, 0], + [126.76294289292238, 37.4786251275935, 0], + [126.76119038765071, 37.4790631148801, 0], + [126.75944776021588, 37.479525281698194, 0], + [126.75771553993873, 37.48001148771461, 0], + [126.75599425301019, 37.48052158529412, 0], + [126.75428442233262, 37.48105541954373, 0], + [126.75258656736239, 37.48161282835936, 0], + [126.7509012039532, 37.48219364247459, 0], + [126.74922884420072, 37.48279768551159, 0], + [126.74756999628792, 37.48342477403416, 0], + [126.74592516433208, 37.48407471760296, 0], + [126.74429484823237, 37.48474731883276, 0], + [126.7426795435191, 37.48544237345194, 0], + [126.74107974120417, 37.486159670363904, 0], + [126.73949592763253, 37.48689899171065, 0], + [126.73792858433548, 37.48766011293834, 0], + [126.73637818788487, 37.488442802864945, 0], + [126.73484520974908, 37.489246823749816, 0], + [126.73333011615044, 37.49007193136536, 0], + [126.73183336792397, 37.49091787507049, 0], + [126.73035542037802, 37.491784397886256, 0], + [126.7288967231561, 37.49267123657318, 0], + [126.72745772010076, 37.49357812171061, 0], + [126.72603884911904, 37.49450477777794, 0], + [126.72464054204934, 37.49545092323756, 0], + [126.72326322453071, 37.49641627061988, 0], + [126.72190731587317, 37.49740052660986, 0], + [126.72057322893056, 37.49840339213555, 0], + [126.71926136997493, 37.499424562458266, 0], + [126.7179721385728, 37.500463727264474, 0], + [126.71670592746366, 37.50152057075948, 0], + [126.71546312244021, 37.502594771762645, 0], + [126.71424410223084, 37.50368600380439, 0], + [126.71304923838387, 37.50479393522466, 0], + [126.71187889515447, 37.50591822927314, 0], + [126.71073342939297, 37.507058544210864, 0], + [126.70961319043602, 37.50821453341343, 0], + [126.70851851999957, 37.509385845475784, 0], + [126.70744975207421, 37.51057212431826, 0], + [126.70640721282282, 37.51177300929427, 0], + [126.70539122048042, 37.512988135299246, 0], + [126.70440208525653, 37.51421713288109, 0], + [126.70344010923976, 37.51545962835176, 0], + [126.70250558630474, 37.51671524390037, 0], + [126.70159880202176, 37.517983597707385, 0], + [126.70072003356862, 37.519264304060236, 0], + [126.69986954964493, 37.52055697346992, 0], + [126.69904761038921, 37.52186121278897, 0], + [126.69825446729824, 37.52317662533038, 0], + [126.69749036314913, 37.52450281098779, 0], + [126.69675553192393, 37.525839366356614, 0], + [126.6960501987369, 37.527185884856245, 0], + [126.69537457976432, 37.52854195685318, 0], + [126.6947288821772, 37.52990716978528, 0], + [126.69411330407625, 37.53128110828668, 0], + [126.69352803443013, 37.53266335431378, 0], + [126.69297325301588, 37.53405348727201, 0], + [126.69244913036243, 37.535451084143375, 0], + [126.69195582769687, 37.53685571961481, 0], + [126.69149349689323, 37.53826696620721, 0], + [126.69106228042455, 37.539684394405164, 0], + [126.6906623113172, 37.541107572787375, 0], + [126.69029371310855, 37.54253606815764, 0], + [126.68995659980708, 37.5439694456764, 0], + [126.68965107585575, 37.545407268992875, 0], + [126.68937723609788, 37.546849100377585, 0], + [126.68913516574626, 37.548294500855484, 0], + [126.68892494035484, 37.54974303033927, 0], + [126.68874662579361, 37.55119424776332, 0], + [126.68860027822632, 37.55264771121777, 0], + [126.68848594409107, 37.554102978082945, 0], + [126.68840366008389, 37.555559605164056, 0], + [126.68835345314537, 37.557017148826084, 0], + [126.68833534045007, 37.55847516512879, 0], + [126.68834932939913, 37.55993320996194, 0], + [126.68839541761551, 37.56139083918054, 0], + [126.68847359294264, 37.56284760874014, 0], + [126.68858383344576, 37.56430307483211, 0], + [126.68872610741617, 37.56575679401895, 0], + [126.68890037337883, 37.5672083233694, 0], + [126.68910658010257, 37.568657220593586, 0], + [126.68934466661351, 37.570103044177834, 0], + [126.68961456221126, 37.57154535351937, 0], + [126.68991618648847, 37.572983709060836, 0], + [126.69024944935292, 37.574417672424325, 0], + [126.69061425105275, 37.575846806545286, 0], + [126.69101048220494, 37.57727067580597, 0], + [126.69143802382622, 37.57868884616844, 0], + [126.6918967473674, 37.58010088530718, 0], + [126.69238651475038, 37.58150636274122, 0], + [126.69290717840828, 37.58290484996566, 0], + [126.69345858132824, 37.58429592058265, 0], + [126.6940405570975, 37.58567915043185, 0], + [126.69465292995206, 37.58705411772004, 0], + [126.69529551482843, 37.5884204031502, 0], + [126.69596811741816, 37.58977759004986, 0], + [126.69667053422532, 37.591125264498494, 0], + [126.69740255262676, 37.59246301545427, 0], + [126.69816395093518, 37.59379043487999, 0], + [126.69895449846523, 37.595107117867876, 0], + [126.69977395560208, 37.596412662763754, 0], + [126.70062207387303, 37.59770667128998, 0], + [126.7014985960218, 37.59898874866758, 0], + [126.70240325608547, 37.60025850373721, 0], + [126.7033357794744, 37.60151554907904, 0], + [126.70429588305441, 37.602759501131594, 0], + [126.70528327523216, 37.603989980309365, 0], + [126.70629765604271, 37.605206611119236, 0], + [126.70733871723995, 37.6064090222757, 0], + [126.7084061423897, 37.607596846814815, 0], + [126.70949960696505, 37.60876972220679, 0], + [126.71061877844458, 37.60992729046731, 0], + [126.71176331641296, 37.61106919826745, 0], + [126.71293287266396, 37.612195097042196, 0], + [126.71412709130598, 37.61330464309744, 0], + [126.71534560887014, 37.6143974977157, 0], + [126.71658805442041, 37.61547332726007, 0], + [126.71785404966644, 37.61653180327683, 0], + [126.71914320907857, 37.61757260259639, 0], + [126.72045514000509, 37.61859540743262, 0], + [126.72178944279175, 37.61959990548062, 0], + [126.72314571090361, 37.6205857900127, 0], + [126.72452353104894, 37.621552759972786, 0], + [126.72592248330533, 37.62250052006899, 0], + [126.72734214124775, 37.62342878086451, 0], + [126.728782072079, 37.62433725886664, 0], + [126.73024183676176, 37.6252256766141, 0], + [126.73172099015297, 37.62609376276238, 0], + [126.73321908113995, 37.62694125216734, 0], + [126.73473565277853, 37.627767885966804, 0], + [126.73627024243285, 37.62857341166028, 0], + [126.73782238191731, 37.62935758318677, 0], + [126.73939159763991, 37.63012016100053, 0], + [126.74097741074749, 37.6308609121449, 0], + [126.74257933727272, 37.631579610324025, 0], + [126.74419688828259, 37.632276035972694, 0], + [126.7458295700285, 37.632949976323914, 0], + [126.74747688409796, 37.63360122547451, 0], + [126.74913832756768, 37.63422958444861, 0], + [126.75081339315817, 37.63483486125903, 0], + [126.75250156938979, 37.635416870966395, 0], + [126.7542023407399, 37.635975435736206, 0], + [126.75591518780163, 37.636510384893676, 0], + [126.75763958744362, 37.637021554976386, 0], + [126.75937501297109, 37.63750878978467, 0], + [126.76112093428807, 37.63797194042983, 0], + [126.7628768180606, 37.63841086538005, 0], + [126.76464212788103, 37.63882543050407, 0], + [126.76641632443342, 37.63921550911257, 0], + [126.76819886565956, 37.63958098199724, 0], + [126.76998920692631, 37.63992173746762, 0], + [126.77178680119331, 37.6402376713855, 0], + [126.77359109918183, 37.64052868719711, 0], + [126.77540154954409, 37.64079469596291, 0], + [126.77721759903336, 37.64103561638503, 0], + [126.7790386926747, 37.64125137483235, 0], + [126.78086427393612, 37.64144190536327, 0], + [126.78269378490033, 37.641607149746044, 0], + [126.78452666643705, 37.64174705747672, 0], + [126.78636235837538, 37.64186158579482, 0], + [126.78820029967686, 37.641950699696444, 0], + [126.79003992860864, 37.64201437194515, 0], + [126.7918806829168, 37.6420525830803, 0], + [126.79372200000002, 37.642065321423125, 0] + ] + ] + }, + "properties": { + "name": "김포공항", + "description": "김포공항 비행금지구역", + "type": "0006" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.55852145849355, 0], + [126.78239009643008, 37.56750461133475, 0], + [126.79372336640101, 37.56750406965258, 0], + [126.79372336640101, 37.55852091681139, 0], + [126.78239009643008, 37.55852145849355, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.56750461133475, 0], + [126.78239009643008, 37.576487764175944, 0], + [126.7937247334926, 37.576487222318015, 0], + [126.7937247334926, 37.567504069476826, 0], + [126.78239009643008, 37.56750461133475, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.576487764175944, 0], + [126.78239009643008, 37.58547091701714, 0], + [126.79372610119273, 37.585470374983416, 0], + [126.79372610119273, 37.57648722214222, 0], + [126.78239009643008, 37.576487764175944, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.58547091701714, 0], + [126.78239009643008, 37.594454069858344, 0], + [126.7937274695017, 37.594453527648774, 0], + [126.7937274695017, 37.585470374807585, 0], + [126.78239009643008, 37.58547091701714, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.594454069858344, 0], + [126.78239009643008, 37.60343722269954, 0], + [126.7937288384198, 37.6034366803141, 0], + [126.7937288384198, 37.5944535274729, 0], + [126.78239009643008, 37.594454069858344, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.60343722269954, 0], + [126.78239009643008, 37.612420375540744, 0], + [126.7937302079473, 37.61241983297936, 0], + [126.7937302079473, 37.60343668013817, 0], + [126.78239009643008, 37.60343722269954, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.612420375540744, 0], + [126.78239009643008, 37.62140352838194, 0], + [126.7937315780845, 37.62140298564459, 0], + [126.7937315780845, 37.61241983280339, 0], + [126.78239009643008, 37.612420375540744, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.62140352838194, 0], + [126.78239009643008, 37.63038668122315, 0], + [126.7937329488317, 37.63038613830978, 0], + [126.7937329488317, 37.621402985468585, 0], + [126.78239009643008, 37.62140352838194, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.63038668122315, 0], + [126.78239009643008, 37.63936983406435, 0], + [126.79373432018917, 37.63936929097492, 0], + [126.79373432018917, 37.63038613813373, 0], + [126.78239009643008, 37.63038668122315, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.63936983406435, 0], + [126.78239009643008, 37.64835298690554, 0], + [126.79373569215718, 37.648352443640015, 0], + [126.79373569215718, 37.63936929079882, 0], + [126.78239009643008, 37.63936983406435, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.55852145849355, 0], + [126.79372199991768, 37.5585209169871, 0], + [126.79372199991768, 37.54953776414592, 0], + [126.78239146238776, 37.549537222815154, 0], + [126.78239009643008, 37.55852145849355, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.549538305652355, 0], + [126.7937206340423, 37.549537764321585, 0], + [126.7937206340423, 37.54055461148039, 0], + [126.78239146178002, 37.54055407032526, 0], + [126.78239009643008, 37.549538305652355, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.54055515281116, 0], + [126.79371926877462, 37.54055461165601, 0], + [126.79371926877462, 37.531571458814824, 0], + [126.78239146117255, 37.53157091783528, 0], + [126.78239009643008, 37.54055515281116, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.53157199996997, 0], + [126.79371790411433, 37.53157145899041, 0], + [126.79371790411433, 37.522588306149224, 0], + [126.78239146056538, 37.52258776534523, 0], + [126.78239009643008, 37.53157199996997, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.52258884712877, 0], + [126.79371654006117, 37.522588306324764, 0], + [126.79371654006117, 37.513605153483574, 0], + [126.78239145995848, 37.513604612855076, 0], + [126.78239009643008, 37.52258884712877, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.513605694287584, 0], + [126.79371517661484, 37.51360515365907, 0], + [126.79371517661484, 37.50462200081788, 0], + [126.78239145935189, 37.50462146036486, 0], + [126.78239009643008, 37.513605694287584, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.50462254144639, 0], + [126.79371381377504, 37.50462200099335, 0], + [126.79371381377504, 37.495638848152154, 0], + [126.78239145874556, 37.49563830787455, 0], + [126.78239009643008, 37.50462254144639, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.4956393886052, 0], + [126.79371245154148, 37.49563884832757, 0], + [126.79371245154148, 37.48665569548638, 0], + [126.78239145813953, 37.48665515538414, 0], + [126.78239009643008, 37.4956393886052, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.486656235764, 0], + [126.79371108991391, 37.48665569566176, 0], + [126.79371108991391, 37.477672542820564, 0], + [126.7823914575338, 37.47767200289366, 0], + [126.78239009643008, 37.486656235764, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.78239009643008, 37.47767308292281, 0], + [126.793709728892, 37.4776725429959, 0], + [126.793709728892, 37.468689390154715, 0], + [126.78239145692832, 37.46868885040311, 0], + [126.78239009643008, 37.47767308292281, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.558519833974195, 0], + [126.77105819318955, 37.5675029868154, 0], + [126.78239146291328, 37.56750244513326, 0], + [126.78239146291328, 37.55851929229207, 0], + [126.77105819318955, 37.558519833974195, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.5675029868154, 0], + [126.77105819318955, 37.576486139656595, 0], + [126.78239283000477, 37.576485597798694, 0], + [126.78239283000477, 37.5675024449575, 0], + [126.77105819318955, 37.5675029868154, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.576486139656595, 0], + [126.77105819318955, 37.58546929249779, 0], + [126.7823941977048, 37.585468750464095, 0], + [126.7823941977048, 37.5764855976229, 0], + [126.77105819318955, 37.576486139656595, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.58546929249779, 0], + [126.77105819318955, 37.59445244533898, 0], + [126.78239556601368, 37.594451903129446, 0], + [126.78239556601368, 37.58546875028825, 0], + [126.77105819318955, 37.58546929249779, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.59445244533898, 0], + [126.77105819318955, 37.60343559818017, 0], + [126.78239693493167, 37.60343505579474, 0], + [126.78239693493167, 37.59445190295355, 0], + [126.77105819318955, 37.59445244533898, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.60343559818017, 0], + [126.77105819318955, 37.612418751021366, 0], + [126.78239830445905, 37.61241820846003, 0], + [126.78239830445905, 37.60343505561884, 0], + [126.77105819318955, 37.60343559818017, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.612418751021366, 0], + [126.77105819318955, 37.621401903862576, 0], + [126.78239967459615, 37.62140136112526, 0], + [126.78239967459615, 37.61241820828406, 0], + [126.77105819318955, 37.612418751021366, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.621401903862576, 0], + [126.77105819318955, 37.63038505670378, 0], + [126.78240104534324, 37.630384513790446, 0], + [126.78240104534324, 37.62140136094925, 0], + [126.77105819318955, 37.621401903862576, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.63038505670378, 0], + [126.77105819318955, 37.639368209544976, 0], + [126.78240241670058, 37.639367666455584, 0], + [126.78240241670058, 37.63038451361439, 0], + [126.77105819318955, 37.63038505670378, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.639368209544976, 0], + [126.77105819318955, 37.64835136238617, 0], + [126.78240378866849, 37.64835081912069, 0], + [126.78240378866849, 37.639367666279504, 0], + [126.77105819318955, 37.639368209544976, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.558519833974195, 0], + [126.78239009643008, 37.55851929246778, 0], + [126.78239009643008, 37.54953613962659, 0], + [126.77105955914713, 37.549535598295854, 0], + [126.77105819318955, 37.558519833974195, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.549536681133, 0], + [126.78238873055481, 37.549536139802264, 0], + [126.78238873055481, 37.54055298696107, 0], + [126.77105955853936, 37.54055244580596, 0], + [126.77105819318955, 37.549536681133, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.54055352829182, 0], + [126.78238736528726, 37.5405529871367, 0], + [126.78238736528726, 37.5315698342955, 0], + [126.77105955793192, 37.53156929331599, 0], + [126.77105819318955, 37.54055352829182, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.53157037545062, 0], + [126.78238600062707, 37.53156983447109, 0], + [126.78238600062707, 37.5225866816299, 0], + [126.77105955732472, 37.52258614082594, 0], + [126.77105819318955, 37.53157037545062, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.522587222609424, 0], + [126.78238463657404, 37.52258668180545, 0], + [126.78238463657404, 37.51360352896426, 0], + [126.77105955671784, 37.513602988335805, 0], + [126.77105819318955, 37.522587222609424, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.51360406976823, 0], + [126.7823832731278, 37.51360352913976, 0], + [126.7823832731278, 37.50462037629857, 0], + [126.77105955611125, 37.50461983584556, 0], + [126.77105819318955, 37.51360406976823, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.50462091692704, 0], + [126.78238191028811, 37.50462037647403, 0], + [126.78238191028811, 37.49563722363284, 0], + [126.77105955550493, 37.495636683355265, 0], + [126.77105819318955, 37.50462091692704, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.49563776408584, 0], + [126.78238054805466, 37.49563722380826, 0], + [126.78238054805466, 37.48665407096708, 0], + [126.77105955489887, 37.48665353086487, 0], + [126.77105819318955, 37.49563776408584, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.48665461124465, 0], + [126.78237918642719, 37.48665407114244, 0], + [126.78237918642719, 37.47767091830124, 0], + [126.77105955429315, 37.47767037837438, 0], + [126.77105819318955, 37.48665461124465, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.77105819318955, 37.47767145840346, 0], + [126.7823778254054, 37.47767091847658, 0], + [126.7823778254054, 37.46868776563539, 0], + [126.77105955368769, 37.46868722588382, 0], + [126.77105819318955, 37.47767145840346, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.55851712644207, 0], + [126.75972629060786, 37.56750027928327, 0], + [126.77105955991965, 37.5674997376012, 0], + [126.77105955991965, 37.55851658476001, 0], + [126.75972629060786, 37.55851712644207, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.56750027928327, 0], + [126.75972629060786, 37.576483432124476, 0], + [126.77106092701095, 37.57648289026663, 0], + [126.77106092701095, 37.567499737425436, 0], + [126.75972629060786, 37.56750027928327, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.576483432124476, 0], + [126.75972629060786, 37.58546658496567, 0], + [126.77106229471079, 37.58546604293203, 0], + [126.77106229471079, 37.57648289009084, 0], + [126.75972629060786, 37.576483432124476, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.58546658496567, 0], + [126.75972629060786, 37.59444973780687, 0], + [126.77106366301948, 37.59444919559738, 0], + [126.77106366301948, 37.58546604275619, 0], + [126.75972629060786, 37.58546658496567, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.59444973780687, 0], + [126.75972629060786, 37.60343289064805, 0], + [126.77106503193728, 37.60343234826268, 0], + [126.77106503193728, 37.59444919542148, 0], + [126.75972629060786, 37.59444973780687, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.60343289064805, 0], + [126.75972629060786, 37.61241604348925, 0], + [126.7710664014645, 37.61241550092796, 0], + [126.7710664014645, 37.60343234808676, 0], + [126.75972629060786, 37.60343289064805, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.61241604348925, 0], + [126.75972629060786, 37.62139919633045, 0], + [126.7710677716014, 37.62139865359319, 0], + [126.7710677716014, 37.612415500752, 0], + [126.75972629060786, 37.61241604348925, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.62139919633045, 0], + [126.75972629060786, 37.630382349171654, 0], + [126.7710691423483, 37.63038180625836, 0], + [126.7710691423483, 37.621398653417174, 0], + [126.75972629060786, 37.62139919633045, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.630382349171654, 0], + [126.75972629060786, 37.63936550201285, 0], + [126.77107051370547, 37.639364958923515, 0], + [126.77107051370547, 37.63038180608232, 0], + [126.75972629060786, 37.630382349171654, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.63936550201285, 0], + [126.75972629060786, 37.648348654854054, 0], + [126.7710718856732, 37.64834811158862, 0], + [126.7710718856732, 37.63936495874742, 0], + [126.75972629060786, 37.63936550201285, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.55851712644207, 0], + [126.77105819343662, 37.5585165849357, 0], + [126.77105819343662, 37.549533432094506, 0], + [126.75972765656526, 37.54953289076383, 0], + [126.75972629060786, 37.55851712644207, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.54953397360087, 0], + [126.77105682756152, 37.54953343227019, 0], + [126.77105682756152, 37.54055027942899, 0], + [126.75972765595749, 37.540549738273945, 0], + [126.75972629060786, 37.54953397360087, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.540550820759684, 0], + [126.77105546229416, 37.54055027960463, 0], + [126.77105546229416, 37.53156712676344, 0], + [126.75972765535003, 37.53156658578398, 0], + [126.75972629060786, 37.540550820759684, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.531567667918495, 0], + [126.77105409763418, 37.531567126939024, 0], + [126.77105409763418, 37.52258397409783, 0], + [126.75972765474285, 37.52258343329392, 0], + [126.75972629060786, 37.531567667918495, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.522584515077305, 0], + [126.77105273358129, 37.52258397427339, 0], + [126.77105273358129, 37.513600821432206, 0], + [126.75972765413594, 37.5136002808038, 0], + [126.75972629060786, 37.522584515077305, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.51360136223611, 0], + [126.77105137013525, 37.513600821607696, 0], + [126.77105137013525, 37.5046176687665, 0], + [126.75972765352938, 37.50461712831355, 0], + [126.75972629060786, 37.51360136223611, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.50461820939492, 0], + [126.77105000729574, 37.50461766894197, 0], + [126.77105000729574, 37.495634516100765, 0], + [126.75972765292306, 37.495633975823246, 0], + [126.75972629060786, 37.50461820939492, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.49563505655373, 0], + [126.77104864506249, 37.4956345162762, 0], + [126.77104864506249, 37.486651363435016, 0], + [126.75972765231703, 37.48665082333287, 0], + [126.75972629060786, 37.49563505655373, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.48665190371254, 0], + [126.7710472834352, 37.486651363610385, 0], + [126.7710472834352, 37.477668210769195, 0], + [126.75972765171127, 37.47766767084238, 0], + [126.75972629060786, 37.48665190371254, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.75972629060786, 37.477668750871345, 0], + [126.77104592241359, 37.47766821094453, 0], + [126.77104592241359, 37.46868505810333, 0], + [126.75972765110582, 37.46868451835182, 0], + [126.75972629060786, 37.477668750871345, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.558513335897345, 0], + [126.7483943890144, 37.567496488738534, 0], + [126.75972765774947, 37.56749594705653, 0], + [126.75972765774947, 37.55851279421533, 0], + [126.7483943890144, 37.558513335897345, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.567496488738534, 0], + [126.7483943890144, 37.57647964157973, 0], + [126.75972902484051, 37.576479099721965, 0], + [126.75972902484051, 37.567495946880776, 0], + [126.7483943890144, 37.567496488738534, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.57647964157973, 0], + [126.7483943890144, 37.585462794420934, 0], + [126.75973039254009, 37.58546225238737, 0], + [126.75973039254009, 37.576479099546184, 0], + [126.7483943890144, 37.57647964157973, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.585462794420934, 0], + [126.7483943890144, 37.594445947262145, 0], + [126.75973176084851, 37.59444540505273, 0], + [126.75973176084851, 37.585462252211535, 0], + [126.7483943890144, 37.585462794420934, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.594445947262145, 0], + [126.7483943890144, 37.60342910010335, 0], + [126.75973312976606, 37.603428557718054, 0], + [126.75973312976606, 37.59444540487686, 0], + [126.7483943890144, 37.594445947262145, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.60342910010335, 0], + [126.7483943890144, 37.61241225294455, 0], + [126.759734499293, 37.61241171038333, 0], + [126.759734499293, 37.60342855754213, 0], + [126.7483943890144, 37.60342910010335, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.61241225294455, 0], + [126.7483943890144, 37.62139540578575, 0], + [126.75973586942966, 37.62139486304856, 0], + [126.75973586942966, 37.61241171020737, 0], + [126.7483943890144, 37.61241225294455, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.62139540578575, 0], + [126.7483943890144, 37.630378558626944, 0], + [126.7597372401763, 37.63037801571373, 0], + [126.7597372401763, 37.62139486287254, 0], + [126.7483943890144, 37.62139540578575, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.630378558626944, 0], + [126.7483943890144, 37.63936171146814, 0], + [126.75973861153322, 37.63936116837887, 0], + [126.75973861153322, 37.63037801553768, 0], + [126.7483943890144, 37.630378558626944, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.558513335897345, 0], + [126.75972629126669, 37.558512794391056, 0], + [126.75972629126669, 37.54952964154986, 0], + [126.74839575497154, 37.54952910021925, 0], + [126.7483943890144, 37.558513335897345, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.549530183056156, 0], + [126.75972492539185, 37.54952964172554, 0], + [126.75972492539185, 37.54054648888434, 0], + [126.74839575436377, 37.54054594772937, 0], + [126.7483943890144, 37.549530183056156, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.54054703021497, 0], + [126.75972356012474, 37.540546489059984, 0], + [126.75972356012474, 37.53156333621879, 0], + [126.74839575375631, 37.531562795239395, 0], + [126.7483943890144, 37.54054703021497, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.53156387737377, 0], + [126.759722195465, 37.53156333639437, 0], + [126.759722195465, 37.52258018355318, 0], + [126.74839575314914, 37.52257964274934, 0], + [126.7483943890144, 37.53156387737377, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.52258072453258, 0], + [126.75972083141238, 37.522580183728735, 0], + [126.75972083141238, 37.51359703088754, 0], + [126.74839575254224, 37.5135964902592, 0], + [126.7483943890144, 37.52258072453258, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.51359757169139, 0], + [126.7597194679666, 37.51359703106305, 0], + [126.7597194679666, 37.50461387822186, 0], + [126.74839575193566, 37.50461333776898, 0], + [126.7483943890144, 37.51359757169139, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.5046144188502, 0], + [126.75971810512733, 37.50461387839732, 0], + [126.75971810512733, 37.495630725556126, 0], + [126.74839575132933, 37.495630185278664, 0], + [126.7483943890144, 37.5046144188502, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.495631266009006, 0], + [126.75971674289434, 37.495630725731544, 0], + [126.75971674289434, 37.48664757289035, 0], + [126.74839575072332, 37.48664703278827, 0], + [126.7483943890144, 37.495631266009006, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7483943890144, 37.48664811316782, 0], + [126.75971538126731, 37.48664757306573, 0], + [126.75971538126731, 37.477664420224535, 0], + [126.74839575011755, 37.4776638802978, 0], + [126.7483943890144, 37.48664811316782, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.558508462340285, 0], + [126.7370624887386, 37.56749161518148, 0], + [126.74839575673214, 37.567491073499575, 0], + [126.74839575673214, 37.558507920658386, 0], + [126.7370624887386, 37.558508462340285, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.56749161518148, 0], + [126.7370624887386, 37.576474768022685, 0], + [126.74839712382287, 37.57647422616501, 0], + [126.74839712382287, 37.56749107332382, 0], + [126.7370624887386, 37.56749161518148, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.576474768022685, 0], + [126.7370624887386, 37.58545792086388, 0], + [126.74839849152214, 37.585457378830405, 0], + [126.74839849152214, 37.5764742259892, 0], + [126.7370624887386, 37.576474768022685, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.58545792086388, 0], + [126.7370624887386, 37.59444107370507, 0], + [126.74839985983022, 37.59444053149576, 0], + [126.74839985983022, 37.58545737865457, 0], + [126.7370624887386, 37.58545792086388, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.59444107370507, 0], + [126.7370624887386, 37.603424226546274, 0], + [126.74840122874744, 37.60342368416108, 0], + [126.74840122874744, 37.59444053131988, 0], + [126.7370624887386, 37.59444107370507, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.603424226546274, 0], + [126.7370624887386, 37.61240737938748, 0], + [126.74840259827405, 37.61240683682635, 0], + [126.74840259827405, 37.60342368398516, 0], + [126.7370624887386, 37.603424226546274, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.61240737938748, 0], + [126.7370624887386, 37.62139053222868, 0], + [126.74840396841037, 37.621389989491576, 0], + [126.74840396841037, 37.61240683665038, 0], + [126.7370624887386, 37.61240737938748, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.62139053222868, 0], + [126.7370624887386, 37.63037368506988, 0], + [126.74840533915668, 37.63037314215676, 0], + [126.74840533915668, 37.62138998931557, 0], + [126.7370624887386, 37.62139053222868, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.63037368506988, 0], + [126.7370624887386, 37.639356837911066, 0], + [126.74840671051328, 37.6393562948219, 0], + [126.74840671051328, 37.63037314198071, 0], + [126.7370624887386, 37.63037368506988, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.558508462340285, 0], + [126.7483943902497, 37.55850792083409, 0], + [126.7483943902497, 37.54952476799289, 0], + [126.73706385469539, 37.54952422666238, 0], + [126.7370624887386, 37.558508462340285, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.549525309499096, 0], + [126.74839302437522, 37.54952476816858, 0], + [126.74839302437522, 37.54054161532739, 0], + [126.73706385408765, 37.540541074172516, 0], + [126.7370624887386, 37.549525309499096, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.5405421566579, 0], + [126.7483916591084, 37.54054161550301, 0], + [126.7483916591084, 37.53155846266183, 0], + [126.7370638534802, 37.531557921682534, 0], + [126.7370624887386, 37.5405421566579, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.53155900381671, 0], + [126.74839029444901, 37.53155846283741, 0], + [126.74839029444901, 37.52257530999622, 0], + [126.737063852873, 37.522574769192474, 0], + [126.7370624887386, 37.53155900381671, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.52257585097552, 0], + [126.74838893039674, 37.52257531017176, 0], + [126.74838893039674, 37.51359215733057, 0], + [126.73706385226613, 37.51359161670233, 0], + [126.7370624887386, 37.52257585097552, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.51359269813433, 0], + [126.74838756695127, 37.51359215750608, 0], + [126.74838756695127, 37.50460900466489, 0], + [126.73706385165951, 37.50460846421212, 0], + [126.7370624887386, 37.51359269813433, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.504609545293135, 0], + [126.74838620411234, 37.504609004840354, 0], + [126.74838620411234, 37.495625851999165, 0], + [126.7370638510532, 37.49562531172181, 0], + [126.7370624887386, 37.504609545293135, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.49562639245195, 0], + [126.74838484187967, 37.49562585217458, 0], + [126.74838484187967, 37.48664269933338, 0], + [126.73706385044719, 37.4866421592314, 0], + [126.7370624887386, 37.49562639245195, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7370624887386, 37.48664323961076, 0], + [126.74838348025297, 37.48664269950877, 0], + [126.74838348025297, 37.477659546667574, 0], + [126.73706384984143, 37.477659006740936, 0], + [126.7370624887386, 37.48664323961076, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.558502505771216, 0], + [126.72573059010988, 37.56748565861242, 0], + [126.73706385719714, 37.56748511693062, 0], + [126.73706385719714, 37.55850196408944, 0], + [126.72573059010988, 37.558502505771216, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.56748565861242, 0], + [126.72573059010988, 37.576468811453616, 0], + [126.73706522428745, 37.57646826959606, 0], + [126.73706522428745, 37.567485116754874, 0], + [126.72573059010988, 37.56748565861242, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.576468811453616, 0], + [126.72573059010988, 37.58545196429482, 0], + [126.73706659198629, 37.58545142226148, 0], + [126.73706659198629, 37.57646826942029, 0], + [126.72573059010988, 37.576468811453616, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.58545196429482, 0], + [126.72573059010988, 37.59443511713603, 0], + [126.737067960294, 37.59443457492684, 0], + [126.737067960294, 37.58545142208565, 0], + [126.72573059010988, 37.58545196429482, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.59443511713603, 0], + [126.72573059010988, 37.60341826997724, 0], + [126.73706932921081, 37.603417727592166, 0], + [126.73706932921081, 37.59443457475098, 0], + [126.72573059010988, 37.59443511713603, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.60341826997724, 0], + [126.72573059010988, 37.61240142281845, 0], + [126.73707069873701, 37.61240088025744, 0], + [126.73707069873701, 37.60341772741625, 0], + [126.72573059010988, 37.60341826997724, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.61240142281845, 0], + [126.72573059010988, 37.62138457565965, 0], + [126.73707206887293, 37.62138403292267, 0], + [126.73707206887293, 37.61240088008147, 0], + [126.72573059010988, 37.61240142281845, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.62138457565965, 0], + [126.72573059010988, 37.63036772850085, 0], + [126.73707343961884, 37.63036718558785, 0], + [126.73707343961884, 37.62138403274666, 0], + [126.72573059010988, 37.62138457565965, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.558502505771216, 0], + [126.7370624907151, 37.55850196426514, 0], + [126.7370624907151, 37.549518811423944, 0], + [126.72573195606628, 37.54951827009355, 0], + [126.72573059010988, 37.558502505771216, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.54951935293003, 0], + [126.737061124841, 37.54951881159962, 0], + [126.737061124841, 37.54053565875843, 0], + [126.72573195545851, 37.54053511760367, 0], + [126.72573059010988, 37.54951935293003, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.54053620008884, 0], + [126.7370597595746, 37.54053565893406, 0], + [126.7370597595746, 37.531552506092865, 0], + [126.72573195485106, 37.53155196511369, 0], + [126.72573059010988, 37.54053620008884, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.53155304724764, 0], + [126.7370583949156, 37.53155250626846, 0], + [126.7370583949156, 37.52256935342727, 0], + [126.72573195424388, 37.52256881262365, 0], + [126.72573059010988, 37.53155304724764, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.52256989440645, 0], + [126.73705703086374, 37.52256935360281, 0], + [126.73705703086374, 37.51358620076162, 0], + [126.72573195363701, 37.51358566013351, 0], + [126.72573059010988, 37.52256989440645, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.51358674156526, 0], + [126.73705566741867, 37.51358620093713, 0], + [126.73705566741867, 37.50460304809593, 0], + [126.7257319530304, 37.50460250764327, 0], + [126.72573059010988, 37.51358674156526, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.50460358872407, 0], + [126.73705430458016, 37.5046030482714, 0], + [126.73705430458016, 37.49561989543021, 0], + [126.7257319524241, 37.49561935515296, 0], + [126.72573059010988, 37.50460358872407, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.72573059010988, 37.49562043588288, 0], + [126.73705294234787, 37.49561989560563, 0], + [126.73705294234787, 37.48663674276444, 0], + [126.72573195181806, 37.486636202662574, 0], + [126.72573059010988, 37.49562043588288, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.558495466190564, 0], + [126.71439869345765, 37.56747861903177, 0], + [126.72573195947383, 37.56747807735012, 0], + [126.72573195947383, 37.558494924508935, 0], + [126.71439869345765, 37.558495466190564, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.56747861903177, 0], + [126.71439869345765, 37.57646177187297, 0], + [126.72573332656368, 37.57646123001556, 0], + [126.72573332656368, 37.56747807717437, 0], + [126.71439869345765, 37.56747861903177, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.57646177187297, 0], + [126.71439869345765, 37.585444924714174, 0], + [126.72573469426204, 37.585444382680954, 0], + [126.72573469426204, 37.57646122983976, 0], + [126.71439869345765, 37.57646177187297, 0] + ] + ] + }, + "properties": { + "name":"비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.585444924714174, 0], + [126.71439869345765, 37.59442807755537, 0], + [126.72573606256925, 37.594427535346306, 0], + [126.72573606256925, 37.585444382505116, 0], + [126.71439869345765, 37.585444924714174, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.59442807755537, 0], + [126.71439869345765, 37.60341123039657, 0], + [126.7257374314856, 37.60341068801162, 0], + [126.7257374314856, 37.59442753517043, 0], + [126.71439869345765, 37.59442807755537, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.60341123039657, 0], + [126.71439869345765, 37.61239438323776, 0], + [126.72573880101135, 37.61239384067689, 0], + [126.72573880101135, 37.6034106878357, 0], + [126.71439869345765, 37.60341123039657, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.61239438323776, 0], + [126.71439869345765, 37.62137753607896, 0], + [126.72574017114677, 37.62137699334211, 0], + [126.72574017114677, 37.61239384050092, 0], + [126.71439869345765, 37.61239438323776, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.62137753607896, 0], + [126.71439869345765, 37.630360688920156, 0], + [126.7257415418922, 37.63036014600729, 0], + [126.7257415418922, 37.62137699316611, 0], + [126.71439869345765, 37.62137753607896, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.558495466190564, 0], + [126.72573059299228, 37.558494924684624, 0], + [126.72573059299228, 37.549511771843434, 0], + [126.71440005941358, 37.54951123051318, 0], + [126.71439869345765, 37.558495466190564, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.54951231334938, 0], + [126.72572922711866, 37.54951177201911, 0], + [126.72572922711866, 37.54052861917791, 0], + [126.71440005880584, 37.540528078023286, 0], + [126.71439869345765, 37.54951231334938, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.54052916050819, 0], + [126.72572786185275, 37.54052861935355, 0], + [126.72572786185275, 37.53154546651236, 0], + [126.71440005819835, 37.531544925533325, 0], + [126.71439869345765, 37.54052916050819, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.531546007667, 0], + [126.72572649719423, 37.53154546668796, 0], + [126.72572649719423, 37.52256231384676, 0], + [126.71440005759119, 37.52256177304327, 0], + [126.71439869345765, 37.531546007667, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.522562854825814, 0], + [126.72572513314283, 37.522562314022316, 0], + [126.72572513314283, 37.51357916118113, 0], + [126.71440005698432, 37.51357862055314, 0], + [126.71439869345765, 37.522562854825814, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.513579701984625, 0], + [126.72572376969822, 37.513579161356624, 0], + [126.72572376969822, 37.50459600851543, 0], + [126.7144000563777, 37.50459546806291, 0], + [126.71439869345765, 37.513579701984625, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.50459654914343, 0], + [126.72572240686017, 37.504596008690896, 0], + [126.72572240686017, 37.49561285584971, 0], + [126.71440005577138, 37.49561231557261, 0], + [126.71439869345765, 37.50459654914343, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.71439869345765, 37.49561339630224, 0], + [126.72572104462837, 37.49561285602512, 0], + [126.72572104462837, 37.48662970318393, 0], + [126.71440005516534, 37.486629163082206, 0], + [126.71439869345765, 37.49561339630224, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.5584873435988, 0], + [126.7030667991113, 37.567470496439995, 0], + [126.71440006389165, 37.567469954758494, 0], + [126.71440006389165, 37.558486801917304, 0], + [126.7030667991113, 37.5584873435988, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.567470496439995, 0], + [126.7030667991113, 37.576453649281184, 0], + [126.71440143098091, 37.57645310742392, 0], + [126.71440143098091, 37.567469954582734, 0], + [126.7030667991113, 37.567470496439995, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.576453649281184, 0], + [126.7030667991113, 37.58543680212237, 0], + [126.71440279867876, 37.585436260089324, 0], + [126.71440279867876, 37.576453107248135, 0], + [126.7030667991113, 37.576453649281184, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.58543680212237, 0], + [126.7030667991113, 37.59441995496358, 0], + [126.71440416698542, 37.59441941275468, 0], + [126.71440416698542, 37.58543625991349, 0], + [126.7030667991113, 37.58543680212237, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.59441995496358, 0], + [126.7030667991113, 37.60340310780478, 0], + [126.7144055359012, 37.60340256542, 0], + [126.7144055359012, 37.59441941257881, 0], + [126.7030667991113, 37.59441995496358, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.60340310780478, 0], + [126.7030667991113, 37.612386260645984, 0], + [126.71440690542639, 37.61238571808527, 0], + [126.71440690542639, 37.603402565244075, 0], + [126.7030667991113, 37.60340310780478, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.612386260645984, 0], + [126.7030667991113, 37.621369413487194, 0], + [126.71440827556128, 37.621368870750516, 0], + [126.71440827556128, 37.612385717909326, 0], + [126.7030667991113, 37.612386260645984, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.5584873435988, 0], + [126.71439869741063, 37.558486802093014, 0], + [126.71439869741063, 37.549503649251825, 0], + [126.7030681650667, 37.54950310792172, 0], + [126.7030667991113, 37.612386260645984, 0], + [126.7030667991113, 37.5584873435988, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.5495041907576, 0], + [126.71439733153757, 37.54950364942749, 0], + [126.71439733153757, 37.5405204965863, 0], + [126.70306816445893, 37.54051995543184, 0], + [126.7030667991113, 37.5495041907576, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.540521037916406, 0], + [126.71439596627219, 37.54052049676192, 0], + [126.71439596627219, 37.531537343920725, 0], + [126.70306816385147, 37.53153680294186, 0], + [126.7030667991113, 37.540521037916406, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.5315378850752, 0], + [126.71439460161423, 37.531537344096314, 0], + [126.71439460161423, 37.522554191255125, 0], + [126.70306816324431, 37.52255365045179, 0], + [126.7030667991113, 37.5315378850752, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.52255473223402, 0], + [126.71439323756336, 37.52255419143067, 0], + [126.71439323756336, 37.513571038589475, 0], + [126.70306816263741, 37.51357049796165, 0], + [126.7030667991113, 37.52255473223402, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.513571579392824, 0], + [126.71439187411931, 37.51357103876498, 0], + [126.71439187411931, 37.50458788592379, 0], + [126.70306816203079, 37.50458734547142, 0], + [126.7030667991113, 37.513571579392824, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.7030667991113, 37.50458842655163, 0], + [126.71439051128183, 37.50458788609925, 0], + [126.71439051128183, 37.49560473325806, 0], + [126.7030681614245, 37.49560419298111, 0], + [126.7030667991113, 37.50458842655163, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.55847813799645, 0], + [126.69173490740026, 37.56746129083764, 0], + [126.70306817077996, 37.567460749156325, 0], + [126.70306817077996, 37.558477596315136, 0], + [126.69173490740026, 37.55847813799645, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.56746129083764, 0], + [126.69173490740026, 37.576444443678845, 0], + [126.70306953786861, 37.57644390182177, 0], + [126.70306953786861, 37.56746074898058, 0], + [126.69173490740026, 37.56746129083764, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.576444443678845, 0], + [126.69173490740026, 37.58542759652004, 0], + [126.70307090556584, 37.58542705448716, 0], + [126.70307090556584, 37.576443901645966, 0], + [126.69173490740026, 37.576444443678845, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.58542759652004, 0], + [126.69173490740026, 37.59441074936124, 0], + [126.70307227387188, 37.594410207152514, 0], + [126.70307227387188, 37.58542705431132, 0], + [126.69173490740026, 37.58542759652004, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.59441074936124, 0], + [126.69173490740026, 37.603393902202434, 0], + [126.70307364278702, 37.60339335981783, 0], + [126.70307364278702, 37.59441020697664, 0], + [126.69173490740026, 37.59441074936124, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.55847813799645, 0], + [126.70306680429958, 37.55847759649085, 0], + [126.70306680429958, 37.54949444364967, 0], + [126.69173627335502, 37.549493902319746, 0], + [126.69173490740026, 37.55847813799645, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.54949498515526, 0], + [126.70306543842713, 37.549494443825324, 0], + [126.70306543842713, 37.540511290984135, 0], + [126.69173627274728, 37.54051074982984, 0], + [126.69173490740026, 37.54949498515526, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.54051183231407, 0], + [126.70306407316238, 37.540511291159774, 0], + [126.70306407316238, 37.531528138318585, 0], + [126.69173627213979, 37.53152759733989, 0], + [126.69173490740026, 37.54051183231407, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.53152867947288, 0], + [126.70306270850504, 37.53152813849417, 0], + [126.70306270850504, 37.52254498565297, 0], + [126.69173627153263, 37.522544444849814, 0], + [126.69173490740026, 37.53152867947288, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.69173490740026, 37.52254552663168, 0], + [126.70306134445481, 37.522544985828524, 0], + [126.70306134445481, 37.51356183298733, 0], + [126.69173627092576, 37.513561292359675, 0], + [126.69173490740026, 37.52254552663168, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.68040301865392, 37.55846784938418, 0], + [126.68040301865392, 37.56745100222538, 0], + [126.69173628046823, 37.567450460544265, 0], + [126.69173628046823, 37.558467307703076, 0], + [126.68040301865392, 37.55846784938418, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.68040301865392, 37.56745100222538, 0], + [126.68040301865392, 37.57643415506658, 0], + [126.69173764755618, 37.5764336132097, 0], + [126.69173764755618, 37.56745046036851, 0], + [126.68040301865392, 37.56745100222538, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.68040301865392, 37.57643415506658, 0], + [126.68040301865392, 37.58541730790778, 0], + [126.69173901525268, 37.58541676587511, 0], + [126.69173901525268, 37.576433613033906, 0], + [126.68040301865392, 37.57643415506658, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.68040301865392, 37.55846784938418, 0], + [126.69173491398851, 37.55846730787878, 0], + [126.69173491398851, 37.54948415503759, 0], + [126.68040438460797, 37.54948361370787, 0], + [126.68040301865392, 37.55846784938418, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.68040301865392, 37.54948469654299, 0], + [126.69173354811679, 37.54948415521326, 0], + [126.69173354811679, 37.54050100237206, 0], + [126.68040438400023, 37.540500461217974, 0], + [126.68040301865392, 37.54948469654299, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.68040301865392, 37.540501543701794, 0], + [126.69173218285275, 37.5405010025477, 0], + [126.69173218285275, 37.53151784970651, 0], + [126.6804043833928, 37.53151730872801, 0], + [126.68040301865392, 37.540501543701794, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.55852145849355, 0], + [126.80505390356994, 37.56750461133475, 0], + [126.79372063359901, 37.56750406965258, 0], + [126.79372063359901, 37.55852091681139, 0], + [126.80505390356994, 37.55852145849355, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.56750461133475, 0], + [126.80505390356994, 37.576487764175944, 0], + [126.79371926650742, 37.576487222318015, 0], + [126.79371926650742, 37.567504069476826, 0], + [126.80505390356994, 37.56750461133475, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.576487764175944, 0], + [126.80505390356994, 37.58547091701714, 0], + [126.79371789880729, 37.585470374983416, 0], + [126.79371789880729, 37.57648722214222, 0], + [126.80505390356994, 37.576487764175944, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.58547091701714, 0], + [126.80505390356994, 37.594454069858344, 0], + [126.79371653049832, 37.594453527648774, 0], + [126.79371653049832, 37.585470374807585, 0], + [126.80505390356994, 37.58547091701714, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.594454069858344, 0], + [126.80505390356994, 37.60343722269954, 0], + [126.79371516158022, 37.6034366803141, 0], + [126.79371516158022, 37.5944535274729, 0], + [126.80505390356994, 37.594454069858344, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.60343722269954, 0], + [126.80505390356994, 37.612420375540744, 0], + [126.79371379205271, 37.61241983297936, 0], + [126.79371379205271, 37.60343668013817, 0], + [126.80505390356994, 37.60343722269954, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.612420375540744, 0], + [126.80505390356994, 37.62140352838194, 0], + [126.79371242191552, 37.62140298564459, 0], + [126.79371242191552, 37.61241983280339, 0], + [126.80505390356994, 37.612420375540744, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.62140352838194, 0], + [126.80505390356994, 37.63038668122315, 0], + [126.79371105116833, 37.63038613830978, 0], + [126.79371105116833, 37.621402985468585, 0], + [126.80505390356994, 37.62140352838194, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.63038668122315, 0], + [126.80505390356994, 37.63936983406435, 0], + [126.79370967981085, 37.63936929097492, 0], + [126.79370967981085, 37.63038613813373, 0], + [126.80505390356994, 37.63038668122315, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.63936983406435, 0], + [126.80505390356994, 37.64835298690554, 0], + [126.79370830784283, 37.648352443640015, 0], + [126.79370830784283, 37.63936929079882, 0], + [126.80505390356994, 37.63936983406435, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.55852145849355, 0], + [126.79372200008235, 37.5585209169871, 0], + [126.79372200008235, 37.54953776414592, 0], + [126.80505253761227, 37.549537222815154, 0], + [126.80505390356994, 37.55852145849355, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.549538305652355, 0], + [126.79372336595772, 37.549537764321585, 0], + [126.79372336595772, 37.54055461148039, 0], + [126.80505253822001, 37.54055407032526, 0], + [126.80505390356994, 37.549538305652355, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.54055515281116, 0], + [126.7937247312254, 37.54055461165601, 0], + [126.7937247312254, 37.531571458814824, 0], + [126.80505253882747, 37.53157091783528, 0], + [126.80505390356994, 37.54055515281116, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.53157199996997, 0], + [126.79372609588569, 37.53157145899041, 0], + [126.79372609588569, 37.522588306149224, 0], + [126.80505253943464, 37.52258776534523, 0], + [126.80505390356994, 37.53157199996997, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.52258884712877, 0], + [126.79372745993885, 37.522588306324764, 0], + [126.79372745993885, 37.513605153483574, 0], + [126.80505254004154, 37.513604612855076, 0], + [126.80505390356994, 37.52258884712877, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.513605694287584, 0], + [126.79372882338518, 37.51360515365907, 0], + [126.79372882338518, 37.50462200081788, 0], + [126.80505254064815, 37.50462146036486, 0], + [126.80505390356994, 37.513605694287584, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.50462254144639, 0], + [126.79373018622498, 37.50462200099335, 0], + [126.79373018622498, 37.495638848152154, 0], + [126.80505254125445, 37.49563830787455, 0], + [126.80505390356994, 37.50462254144639, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.4956393886052, 0], + [126.79373154845854, 37.49563884832757, 0], + [126.79373154845854, 37.48665569548638, 0], + [126.80505254186049, 37.48665515538414, 0], + [126.80505390356994, 37.4956393886052, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.486656235764, 0], + [126.7937329100861, 37.48665569566176, 0], + [126.7937329100861, 37.477672542820564, 0], + [126.80505254246623, 37.47767200289366, 0], + [126.80505390356994, 37.486656235764, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.80505390356994, 37.47767308292281, 0], + [126.79373427110802, 37.4776725429959, 0], + [126.79373427110802, 37.468689390154715, 0], + [126.8050525430717, 37.46868885040311, 0], + [126.80505390356994, 37.47767308292281, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.558519833974195, 0], + [126.81638580681047, 37.5675029868154, 0], + [126.80505253708674, 37.56750244513326, 0], + [126.80505253708674, 37.55851929229207, 0], + [126.81638580681047, 37.558519833974195, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.5675029868154, 0], + [126.81638580681047, 37.576486139656595, 0], + [126.80505116999525, 37.576485597798694, 0], + [126.80505116999525, 37.5675024449575, 0], + [126.81638580681047, 37.5675029868154, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.576486139656595, 0], + [126.81638580681047, 37.58546929249779, 0], + [126.80504980229522, 37.585468750464095, 0], + [126.80504980229522, 37.5764855976229, 0], + [126.81638580681047, 37.576486139656595, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.58546929249779, 0], + [126.81638580681047, 37.59445244533898, 0], + [126.80504843398634, 37.594451903129446, 0], + [126.80504843398634, 37.58546875028825, 0], + [126.81638580681047, 37.58546929249779, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.59445244533898, 0], + [126.81638580681047, 37.60343559818017, 0], + [126.80504706506835, 37.60343505579474, 0], + [126.80504706506835, 37.59445190295355, 0], + [126.81638580681047, 37.59445244533898, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.60343559818017, 0], + [126.81638580681047, 37.612418751021366, 0], + [126.80504569554097, 37.61241820846003, 0], + [126.80504569554097, 37.60343505561884, 0], + [126.81638580681047, 37.60343559818017, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.612418751021366, 0], + [126.81638580681047, 37.621401903862576, 0], + [126.80504432540387, 37.62140136112526, 0], + [126.80504432540387, 37.61241820828406, 0], + [126.81638580681047, 37.612418751021366, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.621401903862576, 0], + [126.81638580681047, 37.63038505670378, 0], + [126.80504295465678, 37.630384513790446, 0], + [126.80504295465678, 37.62140136094925, 0], + [126.81638580681047, 37.621401903862576, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.63038505670378, 0], + [126.81638580681047, 37.639368209544976, 0], + [126.80504158329944, 37.639367666455584, 0], + [126.80504158329944, 37.63038451361439, 0], + [126.81638580681047, 37.63038505670378, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.639368209544976, 0], + [126.81638580681047, 37.64835136238617, 0], + [126.80504021133153, 37.64835081912069, 0], + [126.80504021133153, 37.639367666279504, 0], + [126.81638580681047, 37.639368209544976, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.558519833974195, 0], + [126.80505390356994, 37.55851929246778, 0], + [126.80505390356994, 37.54953613962659, 0], + [126.8163844408529, 37.549535598295854, 0], + [126.81638580681047, 37.558519833974195, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.549536681133, 0], + [126.8050552694452, 37.549536139802264, 0], + [126.8050552694452, 37.54055298696107, 0], + [126.81638444146066, 37.54055244580596, 0], + [126.81638580681047, 37.549536681133, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.54055352829182, 0], + [126.80505663471276, 37.5405529871367, 0], + [126.80505663471276, 37.5315698342955, 0], + [126.8163844420681, 37.53156929331599, 0], + [126.81638580681047, 37.54055352829182, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.53157037545062, 0], + [126.80505799937295, 37.53156983447109, 0], + [126.80505799937295, 37.5225866816299, 0], + [126.8163844426753, 37.52258614082594, 0], + [126.81638580681047, 37.53157037545062, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.522587222609424, 0], + [126.80505936342598, 37.52258668180545, 0], + [126.80505936342598, 37.51360352896426, 0], + [126.81638444328217, 37.513602988335805, 0], + [126.81638580681047, 37.522587222609424, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.51360406976823, 0], + [126.80506072687221, 37.51360352913976, 0], + [126.80506072687221, 37.50462037629857, 0], + [126.81638444388878, 37.50461983584556, 0], + [126.81638580681047, 37.51360406976823, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.50462091692704, 0], + [126.80506208971191, 37.50462037647403, 0], + [126.80506208971191, 37.49563722363284, 0], + [126.81638444449509, 37.495636683355265, 0], + [126.81638580681047, 37.50462091692704, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.49563776408584, 0], + [126.80506345194536, 37.49563722380826, 0], + [126.80506345194536, 37.48665407096708, 0], + [126.81638444510115, 37.48665353086487, 0], + [126.81638580681047, 37.49563776408584, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.48665461124465, 0], + [126.80506481357283, 37.48665407114244, 0], + [126.80506481357283, 37.47767091830124, 0], + [126.81638444570687, 37.47767037837438, 0], + [126.81638580681047, 37.48665461124465, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.81638580681047, 37.47767145840346, 0], + [126.80506617459463, 37.47767091847658, 0], + [126.80506617459463, 37.46868776563539, 0], + [126.81638444631233, 37.46868722588382, 0], + [126.81638580681047, 37.47767145840346, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.55851712644207, 0], + [126.82771770939216, 37.56750027928327, 0], + [126.81638444008037, 37.5674997376012, 0], + [126.81638444008037, 37.55851658476001, 0], + [126.82771770939216, 37.55851712644207, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.56750027928327, 0], + [126.82771770939216, 37.576483432124476, 0], + [126.81638307298907, 37.57648289026663, 0], + [126.81638307298907, 37.567499737425436, 0], + [126.82771770939216, 37.56750027928327, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.576483432124476, 0], + [126.82771770939216, 37.58546658496567, 0], + [126.81638170528923, 37.58546604293203, 0], + [126.81638170528923, 37.57648289009084, 0], + [126.82771770939216, 37.576483432124476, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.58546658496567, 0], + [126.82771770939216, 37.59444973780687, 0], + [126.81638033698054, 37.59444919559738, 0], + [126.81638033698054, 37.58546604275619, 0], + [126.82771770939216, 37.58546658496567, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.59444973780687, 0], + [126.82771770939216, 37.60343289064805, 0], + [126.81637896806274, 37.60343234826268, 0], + [126.81637896806274, 37.59444919542148, 0], + [126.82771770939216, 37.59444973780687, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.60343289064805, 0], + [126.82771770939216, 37.61241604348925, 0], + [126.81637759853554, 37.61241550092796, 0], + [126.81637759853554, 37.60343234808676, 0], + [126.82771770939216, 37.60343289064805, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.61241604348925, 0], + [126.82771770939216, 37.62139919633045, 0], + [126.81637622839862, 37.62139865359319, 0], + [126.81637622839862, 37.612415500752, 0], + [126.82771770939216, 37.61241604348925, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.62139919633045, 0], + [126.82771770939216, 37.630382349171654, 0], + [126.81637485765172, 37.63038180625836, 0], + [126.81637485765172, 37.621398653417174, 0], + [126.82771770939216, 37.62139919633045, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.630382349171654, 0], + [126.82771770939216, 37.63936550201285, 0], + [126.81637348629455, 37.639364958923515, 0], + [126.81637348629455, 37.63038180608232, 0], + [126.82771770939216, 37.630382349171654, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.63936550201285, 0], + [126.82771770939216, 37.648348654854054, 0], + [126.81637211432682, 37.64834811158862, 0], + [126.81637211432682, 37.63936495874742, 0], + [126.82771770939216, 37.63936550201285, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.55851712644207, 0], + [126.8163858065634, 37.5585165849357, 0], + [126.8163858065634, 37.549533432094506, 0], + [126.82771634343477, 37.54953289076383, 0], + [126.82771770939216, 37.55851712644207, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.54953397360087, 0], + [126.8163871724385, 37.54953343227019, 0], + [126.8163871724385, 37.54055027942899, 0], + [126.82771634404253, 37.540549738273945, 0], + [126.82771770939216, 37.54953397360087, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.540550820759684, 0], + [126.81638853770586, 37.54055027960463, 0], + [126.81638853770586, 37.53156712676344, 0], + [126.82771634465, 37.53156658578398, 0], + [126.82771770939216, 37.540550820759684, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.531567667918495, 0], + [126.81638990236586, 37.531567126939024, 0], + [126.81638990236586, 37.52258397409783, 0], + [126.82771634525717, 37.52258343329392, 0], + [126.82771770939216, 37.531567667918495, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.522584515077305, 0], + [126.81639126641873, 37.52258397427339, 0], + [126.81639126641873, 37.513600821432206, 0], + [126.82771634586408, 37.5136002808038, 0], + [126.82771770939216, 37.522584515077305, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.51360136223611, 0], + [126.81639262986477, 37.513600821607696, 0], + [126.81639262986477, 37.5046176687665, 0], + [126.82771634647065, 37.50461712831355, 0], + [126.82771770939216, 37.51360136223611, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.50461820939492, 0], + [126.81639399270428, 37.50461766894197, 0], + [126.81639399270428, 37.495634516100765, 0], + [126.82771634707696, 37.495633975823246, 0], + [126.82771770939216, 37.50461820939492, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.49563505655373, 0], + [126.81639535493753, 37.4956345162762, 0], + [126.81639535493753, 37.486651363435016, 0], + [126.827716347683, 37.48665082333287, 0], + [126.82771770939216, 37.49563505655373, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.48665190371254, 0], + [126.81639671656482, 37.486651363610385, 0], + [126.81639671656482, 37.477668210769195, 0], + [126.82771634828875, 37.47766767084238, 0], + [126.82771770939216, 37.48665190371254, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.82771770939216, 37.477668750871345, 0], + [126.81639807758643, 37.47766821094453, 0], + [126.81639807758643, 37.46868505810333, 0], + [126.8277163488942, 37.46868451835182, 0], + [126.82771770939216, 37.477668750871345, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.558513335897345, 0], + [126.83904961098563, 37.567496488738534, 0], + [126.82771634225055, 37.56749594705653, 0], + [126.82771634225055, 37.55851279421533, 0], + [126.83904961098563, 37.558513335897345, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.567496488738534, 0], + [126.83904961098563, 37.57647964157973, 0], + [126.82771497515951, 37.576479099721965, 0], + [126.82771497515951, 37.567495946880776, 0], + [126.83904961098563, 37.567496488738534, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.57647964157973, 0], + [126.83904961098563, 37.585462794420934, 0], + [126.82771360745993, 37.58546225238737, 0], + [126.82771360745993, 37.576479099546184, 0], + [126.83904961098563, 37.57647964157973, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.585462794420934, 0], + [126.83904961098563, 37.594445947262145, 0], + [126.82771223915151, 37.59444540505273, 0], + [126.82771223915151, 37.585462252211535, 0], + [126.83904961098563, 37.585462794420934, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.594445947262145, 0], + [126.83904961098563, 37.60342910010335, 0], + [126.82771087023396, 37.603428557718054, 0], + [126.82771087023396, 37.59444540487686, 0], + [126.83904961098563, 37.594445947262145, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.60342910010335, 0], + [126.83904961098563, 37.61241225294455, 0], + [126.82770950070702, 37.61241171038333, 0], + [126.82770950070702, 37.60342855754213, 0], + [126.83904961098563, 37.60342910010335, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.61241225294455, 0], + [126.83904961098563, 37.62139540578575, 0], + [126.82770813057036, 37.62139486304856, 0], + [126.82770813057036, 37.61241171020737, 0], + [126.83904961098563, 37.61241225294455, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.62139540578575, 0], + [126.83904961098563, 37.630378558626944, 0], + [126.82770675982371, 37.63037801571373, 0], + [126.82770675982371, 37.62139486287254, 0], + [126.83904961098563, 37.62139540578575, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.630378558626944, 0], + [126.83904961098563, 37.63936171146814, 0], + [126.8277053884668, 37.63936116837887, 0], + [126.8277053884668, 37.63037801553768, 0], + [126.83904961098563, 37.630378558626944, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.558513335897345, 0], + [126.82771770873333, 37.558512794391056, 0], + [126.82771770873333, 37.54952964154986, 0], + [126.83904824502848, 37.54952910021925, 0], + [126.83904961098563, 37.558513335897345, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.549530183056156, 0], + [126.82771907460817, 37.54952964172554, 0], + [126.82771907460817, 37.54054648888434, 0], + [126.83904824563625, 37.54054594772937, 0], + [126.83904961098563, 37.549530183056156, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.54054703021497, 0], + [126.82772043987528, 37.540546489059984, 0], + [126.82772043987528, 37.53156333621879, 0], + [126.8390482462437, 37.531562795239395, 0], + [126.83904961098563, 37.54054703021497, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.53156387737377, 0], + [126.82772180453502, 37.53156333639437, 0], + [126.82772180453502, 37.52258018355318, 0], + [126.8390482468509, 37.52257964274934, 0], + [126.83904961098563, 37.53156387737377, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.52258072453258, 0], + [126.82772316858764, 37.522580183728735, 0], + [126.82772316858764, 37.51359703088754, 0], + [126.8390482474578, 37.5135964902592, 0], + [126.83904961098563, 37.52258072453258, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.51359757169139, 0], + [126.82772453203343, 37.51359703106305, 0], + [126.82772453203343, 37.50461387822186, 0], + [126.83904824806436, 37.50461333776898, 0], + [126.83904961098563, 37.51359757169139, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.5046144188502, 0], + [126.82772589487269, 37.50461387839732, 0], + [126.82772589487269, 37.495630725556126, 0], + [126.83904824867071, 37.495630185278664, 0], + [126.83904961098563, 37.5046144188502, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.495631266009006, 0], + [126.82772725710568, 37.495630725731544, 0], + [126.82772725710568, 37.48664757289035, 0], + [126.83904824927671, 37.48664703278827, 0], + [126.83904961098563, 37.495631266009006, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.83904961098563, 37.48664811316782, 0], + [126.8277286187327, 37.48664757306573, 0], + [126.8277286187327, 37.477664420224535, 0], + [126.83904824988247, 37.4776638802978, 0], + [126.83904961098563, 37.48664811316782, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.558508462340285, 0], + [126.85038151126142, 37.56749161518148, 0], + [126.83904824326788, 37.567491073499575, 0], + [126.83904824326788, 37.558507920658386, 0], + [126.85038151126142, 37.558508462340285, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.56749161518148, 0], + [126.85038151126142, 37.576474768022685, 0], + [126.83904687617716, 37.57647422616501, 0], + [126.83904687617716, 37.56749107332382, 0], + [126.85038151126142, 37.56749161518148, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.576474768022685, 0], + [126.85038151126142, 37.58545792086388, 0], + [126.83904550847788, 37.585457378830405, 0], + [126.83904550847788, 37.5764742259892, 0], + [126.85038151126142, 37.576474768022685, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.58545792086388, 0], + [126.85038151126142, 37.59444107370507, 0], + [126.8390441401698, 37.59444053149576, 0], + [126.8390441401698, 37.58545737865457, 0], + [126.85038151126142, 37.58545792086388, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.59444107370507, 0], + [126.85038151126142, 37.603424226546274, 0], + [126.83904277125258, 37.60342368416108, 0], + [126.83904277125258, 37.59444053131988, 0], + [126.85038151126142, 37.59444107370507, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.603424226546274, 0], + [126.85038151126142, 37.61240737938748, 0], + [126.83904140172596, 37.61240683682635, 0], + [126.83904140172596, 37.60342368398516, 0], + [126.85038151126142, 37.603424226546274, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.61240737938748, 0], + [126.85038151126142, 37.62139053222868, 0], + [126.83904003158965, 37.621389989491576, 0], + [126.83904003158965, 37.61240683665038, 0], + [126.85038151126142, 37.61240737938748, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.62139053222868, 0], + [126.85038151126142, 37.63037368506988, 0], + [126.83903866084334, 37.63037314215676, 0], + [126.83903866084334, 37.62138998931557, 0], + [126.85038151126142, 37.62139053222868, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.63037368506988, 0], + [126.85038151126142, 37.639356837911066, 0], + [126.83903728948674, 37.6393562948219, 0], + [126.83903728948674, 37.63037314198071, 0], + [126.85038151126142, 37.63037368506988, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.558508462340285, 0], + [126.83904960975032, 37.55850792083409, 0], + [126.83904960975032, 37.54952476799289, 0], + [126.85038014530463, 37.54952422666238, 0], + [126.85038151126142, 37.558508462340285, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.549525309499096, 0], + [126.8390509756248, 37.54952476816858, 0], + [126.8390509756248, 37.54054161532739, 0], + [126.85038014591237, 37.540541074172516, 0], + [126.85038151126142, 37.549525309499096, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.5405421566579, 0], + [126.83905234089161, 37.54054161550301, 0], + [126.83905234089161, 37.53155846266183, 0], + [126.85038014651984, 37.531557921682534, 0], + [126.85038151126142, 37.5405421566579, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.53155900381671, 0], + [126.83905370555101, 37.53155846283741, 0], + [126.83905370555101, 37.52257530999622, 0], + [126.85038014712701, 37.522574769192474, 0], + [126.85038151126142, 37.53155900381671, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.52257585097552, 0], + [126.83905506960329, 37.52257531017176, 0], + [126.83905506960329, 37.51359215733057, 0], + [126.85038014773389, 37.51359161670233, 0], + [126.85038151126142, 37.52257585097552, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.51359269813433, 0], + [126.83905643304875, 37.51359215750608, 0], + [126.83905643304875, 37.50460900466489, 0], + [126.8503801483405, 37.50460846421212, 0], + [126.85038151126142, 37.51359269813433, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.504609545293135, 0], + [126.83905779588768, 37.504609004840354, 0], + [126.83905779588768, 37.495625851999165, 0], + [126.85038014894683, 37.49562531172181, 0], + [126.85038151126142, 37.504609545293135, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.49562639245195, 0], + [126.83905915812035, 37.49562585217458, 0], + [126.83905915812035, 37.48664269933338, 0], + [126.85038014955283, 37.4866421592314, 0], + [126.85038151126142, 37.49562639245195, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.85038151126142, 37.48664323961076, 0], + [126.83906051974705, 37.48664269950877, 0], + [126.83906051974705, 37.477659546667574, 0], + [126.85038015015859, 37.477659006740936, 0], + [126.85038151126142, 37.48664323961076, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.558502505771216, 0], + [126.86171340989014, 37.56748565861242, 0], + [126.85038014280289, 37.56748511693062, 0], + [126.85038014280289, 37.55850196408944, 0], + [126.86171340989014, 37.558502505771216, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.56748565861242, 0], + [126.86171340989014, 37.576468811453616, 0], + [126.85037877571257, 37.57646826959606, 0], + [126.85037877571257, 37.567485116754874, 0], + [126.86171340989014, 37.56748565861242, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.576468811453616, 0], + [126.86171340989014, 37.58545196429482, 0], + [126.85037740801373, 37.58545142226148, 0], + [126.85037740801373, 37.57646826942029, 0], + [126.86171340989014, 37.576468811453616, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.58545196429482, 0], + [126.86171340989014, 37.59443511713603, 0], + [126.85037603970603, 37.59443457492684, 0], + [126.85037603970603, 37.58545142208565, 0], + [126.86171340989014, 37.58545196429482, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.59443511713603, 0], + [126.86171340989014, 37.60341826997724, 0], + [126.85037467078921, 37.603417727592166, 0], + [126.85037467078921, 37.59443457475098, 0], + [126.86171340989014, 37.59443511713603, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.60341826997724, 0], + [126.86171340989014, 37.61240142281845, 0], + [126.850373301263, 37.61240088025744, 0], + [126.850373301263, 37.60341772741625, 0], + [126.86171340989014, 37.60341826997724, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.61240142281845, 0], + [126.86171340989014, 37.62138457565965, 0], + [126.85037193112709, 37.62138403292267, 0], + [126.85037193112709, 37.61240088008147, 0], + [126.86171340989014, 37.61240142281845, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.62138457565965, 0], + [126.86171340989014, 37.63036772850085, 0], + [126.85037056038118, 37.63036718558785, 0], + [126.85037056038118, 37.62138403274666, 0], + [126.86171340989014, 37.62138457565965, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.558502505771216, 0], + [126.85038150928492, 37.55850196426514, 0], + [126.85038150928492, 37.549518811423944, 0], + [126.86171204393374, 37.54951827009355, 0], + [126.86171340989014, 37.558502505771216, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.54951935293003, 0], + [126.85038287515901, 37.54951881159962, 0], + [126.85038287515901, 37.54053565875843, 0], + [126.8617120445415, 37.54053511760367, 0], + [126.86171340989014, 37.54951935293003, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.54053620008884, 0], + [126.85038424042543, 37.54053565893406, 0], + [126.85038424042543, 37.531552506092865, 0], + [126.86171204514896, 37.53155196511369, 0], + [126.86171340989014, 37.54053620008884, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.53155304724764, 0], + [126.85038560508441, 37.53155250626846, 0], + [126.85038560508441, 37.52256935342727, 0], + [126.86171204575615, 37.52256881262365, 0], + [126.86171340989014, 37.53155304724764, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 45m 이하~", + "airspace": 45, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.52256989440645, 0], + [126.85038696913628, 37.52256935360281, 0], + [126.85038696913628, 37.51358620076162, 0], + [126.86171204636302, 37.51358566013351, 0], + [126.86171340989014, 37.52256989440645, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.51358674156526, 0], + [126.85038833258135, 37.51358620093713, 0], + [126.85038833258135, 37.50460304809593, 0], + [126.86171204696961, 37.50460250764327, 0], + [126.86171340989014, 37.51358674156526, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.50460358872407, 0], + [126.85038969541986, 37.5046030482714, 0], + [126.85038969541986, 37.49561989543021, 0], + [126.86171204757594, 37.49561935515296, 0], + [126.86171340989014, 37.50460358872407, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.86171340989014, 37.49562043588288, 0], + [126.85039105765215, 37.49561989560563, 0], + [126.85039105765215, 37.48663674276444, 0], + [126.86171204818197, 37.486636202662574, 0], + [126.86171340989014, 37.49562043588288, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.558495466190564, 0], + [126.87304530654237, 37.56747861903177, 0], + [126.8617120405262, 37.56747807735012, 0], + [126.8617120405262, 37.558494924508935, 0], + [126.87304530654237, 37.558495466190564, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.56747861903177, 0], + [126.87304530654237, 37.57646177187297, 0], + [126.86171067343633, 37.57646123001556, 0], + [126.86171067343633, 37.56747807717437, 0], + [126.87304530654237, 37.56747861903177, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.57646177187297, 0], + [126.87304530654237, 37.585444924714174, 0], + [126.86170930573797, 37.585444382680954, 0], + [126.86170930573797, 37.57646122983976, 0], + [126.87304530654237, 37.57646177187297, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.585444924714174, 0], + [126.87304530654237, 37.59442807755537, 0], + [126.86170793743077, 37.594427535346306, 0], + [126.86170793743077, 37.585444382505116, 0], + [126.87304530654237, 37.585444924714174, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.59442807755537, 0], + [126.87304530654237, 37.60341123039657, 0], + [126.86170656851444, 37.60341068801162, 0], + [126.86170656851444, 37.59442753517043, 0], + [126.87304530654237, 37.59442807755537, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.60341123039657, 0], + [126.87304530654237, 37.61239438323776, 0], + [126.86170519898867, 37.61239384067689, 0], + [126.86170519898867, 37.6034106878357, 0], + [126.87304530654237, 37.60341123039657, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.61239438323776, 0], + [126.87304530654237, 37.62137753607896, 0], + [126.86170382885325, 37.62137699334211, 0], + [126.86170382885325, 37.61239384050092, 0], + [126.87304530654237, 37.61239438323776, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.62137753607896, 0], + [126.87304530654237, 37.630360688920156, 0], + [126.86170245810781, 37.63036014600729, 0], + [126.86170245810781, 37.62137699316611, 0], + [126.87304530654237, 37.62137753607896, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.558495466190564, 0], + [126.86171340700774, 37.558494924684624, 0], + [126.86171340700774, 37.549511771843434, 0], + [126.87304394058644, 37.54951123051318, 0], + [126.87304530654237, 37.558495466190564, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.54951231334938, 0], + [126.86171477288136, 37.54951177201911, 0], + [126.86171477288136, 37.54052861917791, 0], + [126.87304394119418, 37.540528078023286, 0], + [126.87304530654237, 37.54951231334938, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.54052916050819, 0], + [126.86171613814727, 37.54052861935355, 0], + [126.86171613814727, 37.53154546651236, 0], + [126.87304394180167, 37.531544925533325, 0], + [126.87304530654237, 37.54052916050819, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 100m 이하~ ", + "airspace": 100, + "type": "0006" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.531546007667, 0], + [126.86171750280579, 37.53154546668796, 0], + [126.86171750280579, 37.52256231384676, 0], + [126.87304394240883, 37.52256177304327, 0], + [126.87304530654237, 37.531546007667, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.522562854825814, 0], + [126.8617188668572, 37.522562314022316, 0], + [126.8617188668572, 37.51357916118113, 0], + [126.8730439430157, 37.51357862055314, 0], + [126.87304530654237, 37.522562854825814, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.513579701984625, 0], + [126.8617202303018, 37.513579161356624, 0], + [126.8617202303018, 37.50459600851543, 0], + [126.87304394362232, 37.50459546806291, 0], + [126.87304530654237, 37.513579701984625, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.50459654914343, 0], + [126.86172159313985, 37.504596008690896, 0], + [126.86172159313985, 37.49561285584971, 0], + [126.87304394422864, 37.49561231557261, 0], + [126.87304530654237, 37.50459654914343, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.87304530654237, 37.49561339630224, 0], + [126.86172295537165, 37.49561285602512, 0], + [126.86172295537165, 37.48662970318393, 0], + [126.87304394483468, 37.486629163082206, 0], + [126.87304530654237, 37.49561339630224, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.5584873435988, 0], + [126.88437720088872, 37.567470496439995, 0], + [126.87304393610837, 37.567469954758494, 0], + [126.87304393610837, 37.558486801917304, 0], + [126.88437720088872, 37.5584873435988, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.567470496439995, 0], + [126.88437720088872, 37.576453649281184, 0], + [126.8730425690191, 37.57645310742392, 0], + [126.8730425690191, 37.567469954582734, 0], + [126.88437720088872, 37.567470496439995, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.576453649281184, 0], + [126.88437720088872, 37.58543680212237, 0], + [126.87304120132126, 37.585436260089324, 0], + [126.87304120132126, 37.576453107248135, 0], + [126.88437720088872, 37.576453649281184, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.58543680212237, 0], + [126.88437720088872, 37.59441995496358, 0], + [126.8730398330146, 37.59441941275468, 0], + [126.8730398330146, 37.58543625991349, 0], + [126.88437720088872, 37.58543680212237, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.59441995496358, 0], + [126.88437720088872, 37.60340310780478, 0], + [126.87303846409883, 37.60340256542, 0], + [126.87303846409883, 37.59441941257881, 0], + [126.88437720088872, 37.59441995496358, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.60340310780478, 0], + [126.88437720088872, 37.612386260645984, 0], + [126.87303709457363, 37.61238571808527, 0], + [126.87303709457363, 37.603402565244075, 0], + [126.88437720088872, 37.60340310780478, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.612386260645984, 0], + [126.88437720088872, 37.621369413487194, 0], + [126.87303572443874, 37.621368870750516, 0], + [126.87303572443874, 37.612385717909326, 0], + [126.88437720088872, 37.612386260645984, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.5584873435988, 0], + [126.8730453025894, 37.558486802093014, 0], + [126.8730453025894, 37.549503649251825, 0], + [126.88437583493334, 37.54950310792172, 0], + [126.88437720088872, 37.5584873435988, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.5495041907576, 0], + [126.87304666846245, 37.54950364942749, 0], + [126.87304666846245, 37.5405204965863, 0], + [126.88437583554109, 37.54051995543184, 0], + [126.88437720088872, 37.5495041907576, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.540521037916406, 0], + [126.87304803372784, 37.54052049676192, 0], + [126.87304803372784, 37.531537343920725, 0], + [126.88437583614855, 37.53153680294186, 0], + [126.88437720088872, 37.540521037916406, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.5315378850752, 0], + [126.87304939838579, 37.531537344096314, 0], + [126.87304939838579, 37.522554191255125, 0], + [126.88437583675571, 37.52255365045179, 0], + [126.88437720088872, 37.5315378850752, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.52255473223402, 0], + [126.87305076243666, 37.52255419143067, 0], + [126.87305076243666, 37.513571038589475, 0], + [126.88437583736261, 37.51357049796165, 0], + [126.88437720088872, 37.52255473223402, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.513571579392824, 0], + [126.8730521258807, 37.51357103876498, 0], + [126.8730521258807, 37.50458788592379, 0], + [126.88437583796923, 37.50458734547142, 0], + [126.88437720088872, 37.513571579392824, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.88437720088872, 37.50458842655163, 0], + [126.87305348871818, 37.50458788609925, 0], + [126.87305348871818, 37.49560473325806, 0], + [126.88437583857552, 37.49560419298111, 0], + [126.88437720088872, 37.50458842655163, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 0m 이하~", + "airspace": 0, + "type": "0001" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.55847813799645, 0], + [126.89570909259976, 37.56746129083764, 0], + [126.88437582922006, 37.567460749156325, 0], + [126.88437582922006, 37.558477596315136, 0], + [126.89570909259976, 37.55847813799645, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.56746129083764, 0], + [126.89570909259976, 37.576444443678845, 0], + [126.8843744621314, 37.57644390182177, 0], + [126.8843744621314, 37.56746074898058, 0], + [126.89570909259976, 37.56746129083764, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.576444443678845, 0], + [126.89570909259976, 37.58542759652004, 0], + [126.8843730944342, 37.58542705448716, 0], + [126.8843730944342, 37.576443901645966, 0], + [126.89570909259976, 37.576444443678845, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.58542759652004, 0], + [126.89570909259976, 37.59441074936124, 0], + [126.88437172612814, 37.594410207152514, 0], + [126.88437172612814, 37.58542705431132, 0], + [126.89570909259976, 37.58542759652004, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.59441074936124, 0], + [126.89570909259976, 37.603393902202434, 0], + [126.884370357213, 37.60339335981783, 0], + [126.884370357213, 37.59441020697664, 0], + [126.89570909259976, 37.59441074936124, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.55847813799645, 0], + [126.88437719570045, 37.55847759649085, 0], + [126.88437719570045, 37.54949444364967, 0], + [126.89570772664501, 37.549493902319746, 0], + [126.89570909259976, 37.55847813799645, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.54949498515526, 0], + [126.88437856157289, 37.549494443825324, 0], + [126.88437856157289, 37.540511290984135, 0], + [126.89570772725276, 37.54051074982984, 0], + [126.89570909259976, 37.54949498515526, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.54051183231407, 0], + [126.88437992683764, 37.540511291159774, 0], + [126.88437992683764, 37.531528138318585, 0], + [126.89570772786024, 37.53152759733989, 0], + [126.89570909259976, 37.54051183231407, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.53152867947288, 0], + [126.88438129149498, 37.53152813849417, 0], + [126.88438129149498, 37.52254498565297, 0], + [126.89570772846739, 37.522544444849814, 0], + [126.89570909259976, 37.53152867947288, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.89570909259976, 37.52254552663168, 0], + [126.88438265554521, 37.522544985828524, 0], + [126.88438265554521, 37.51356183298733, 0], + [126.89570772907426, 37.513561292359675, 0], + [126.89570909259976, 37.52254552663168, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.9070409813461, 37.55846784938418, 0], + [126.9070409813461, 37.56745100222538, 0], + [126.89570771953179, 37.567450460544265, 0], + [126.89570771953179, 37.558467307703076, 0], + [126.9070409813461, 37.55846784938418, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.9070409813461, 37.56745100222538, 0], + [126.9070409813461, 37.57643415506658, 0], + [126.89570635244384, 37.5764336132097, 0], + [126.89570635244384, 37.56745046036851, 0], + [126.9070409813461, 37.56745100222538, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.9070409813461, 37.57643415506658, 0], + [126.9070409813461, 37.58541730790778, 0], + [126.89570498474734, 37.58541676587511, 0], + [126.89570498474734, 37.576433613033906, 0], + [126.9070409813461, 37.57643415506658, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.9070409813461, 37.55846784938418, 0], + [126.89570908601151, 37.55846730787878, 0], + [126.89570908601151, 37.54948415503759, 0], + [126.90703961539205, 37.54948361370787, 0], + [126.9070409813461, 37.55846784938418, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.9070409813461, 37.54948469654299, 0], + [126.89571045188323, 37.54948415521326, 0], + [126.89571045188323, 37.54050100237206, 0], + [126.90703961599979, 37.540500461217974, 0], + [126.9070409813461, 37.54948469654299, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +}, +{ + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [126.9070409813461, 37.540501543701794, 0], + [126.89571181714727, 37.5405010025477, 0], + [126.89571181714727, 37.53151784970651, 0], + [126.90703961660724, 37.53151730872801, 0], + [126.9070409813461, 37.540501543701794, 0] + ] + ] + }, + "properties": { + "name": "비행금지구역", + "description": "김포공항 120m 이하~", + "airspace": 120, + "type": "0003" + } +} + ] +} diff --git a/pav-server/src/main/resources/application-database.yml b/pav-server/src/main/resources/application-database.yml new file mode 100644 index 00000000..084f0567 --- /dev/null +++ b/pav-server/src/main/resources/application-database.yml @@ -0,0 +1,68 @@ +spring: + config: + activate: + on-profile: local + datasource: + control: + driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbc-url: jdbc:log4jdbc:mysql://43.200.235.135:3306/PAV?characterEncoding=UTF-8&autoReconnect=true&useSSL=false + username: pav + password: palnet!234 +# minimumidle: 5 + maximumpoolsize: 1 + idletimeout: 60000 + maxlifetime: 300000 + connectiontimeout: 30000 + validationtimeout: 5000 +--- +spring: + config: + activate: + on-profile: dev + datasource: + control: + driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbc-url: jdbc:log4jdbc:mysql://43.200.235.135:3306/PAV?characterEncoding=UTF-8&autoReconnect=true&useSSL=false + username: pav + password: palnet!234 + minimumidle: 5 + maximumpoolsize: 5 + idletimeout: 60000 + maxlifetime: 300000 + connectiontimeout: 30000 + validationtimeout: 5000 +--- +spring: + config: + activate: + on-profile: prod + datasource: + control: + driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbc-url: jdbc:log4jdbc:mysql://palnet.cexpliz30rwl.ap-northeast-2.rds.amazonaws.com:3306/PAV?characterEncoding=UTF-8&autoReconnect=true&useSSL=false + username: pav + password: palnet!234 + minimumidle: 10 + maximumpoolsize: 20 + idletimeout: 60000 + maxlifetime: 300000 + connectiontimeout: 30000 + validationtimeout: 5000 + +--- +spring: + config: + activate: + on-profile: prod2 + datasource: + control: + driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbc-url: jdbc:log4jdbc:mysql://palnet.cexpliz30rwl.ap-northeast-2.rds.amazonaws.com:3306/PAV?characterEncoding=UTF-8&autoReconnect=true&useSSL=false + username: pav + password: palnet!234 + minimumidle: 10 + maximumpoolsize: 20 + idletimeout: 60000 + maxlifetime: 300000 + connectiontimeout: 30000 + validationtimeout: 5000 diff --git a/pav-server/src/main/resources/application-dev.properties b/pav-server/src/main/resources/application-dev.properties new file mode 100644 index 00000000..0ab92633 --- /dev/null +++ b/pav-server/src/main/resources/application-dev.properties @@ -0,0 +1,13 @@ +## file save +file.path.save=/download/save + +################# SMS ###################### +sms.usercode = palnet +sms.deptcode = C2-2C0-0H +sms.reqname = PAV +sms.reqphone = 02-6200-3912 +sms.result = 0 +sms.reqtime = 00000000000000 +sms.kind = S +sms.subject.certify = PAV +sms.callname.certify = PAV \ No newline at end of file diff --git a/pav-server/src/main/resources/application-local.properties b/pav-server/src/main/resources/application-local.properties new file mode 100644 index 00000000..02497f71 --- /dev/null +++ b/pav-server/src/main/resources/application-local.properties @@ -0,0 +1,14 @@ + +file.path.save=/files + + +################# SMS ###################### +sms.usercode = palnet +sms.deptcode = C2-2C0-0H +sms.reqname = PAV +sms.reqphone = 02-6200-3912 +sms.result = 0 +sms.reqtime = 00000000000000 +sms.kind = S +sms.subject.certify = PAV +sms.callname.certify = PAV \ No newline at end of file diff --git a/pav-server/src/main/resources/application-prod.properties b/pav-server/src/main/resources/application-prod.properties new file mode 100644 index 00000000..def31297 --- /dev/null +++ b/pav-server/src/main/resources/application-prod.properties @@ -0,0 +1,14 @@ +## file save +file.path.save=/download/save + + +################# SMS ###################### +sms.usercode = palnet +sms.deptcode = C2-2C0-0H +sms.reqname = PAV +sms.reqphone = 02-6200-3912 +sms.result = 0 +sms.reqtime = 00000000000000 +sms.kind = S +sms.subject.certify = PAV +sms.callname.certify = PAV \ No newline at end of file diff --git a/pav-server/src/main/resources/application-prod2.properties b/pav-server/src/main/resources/application-prod2.properties new file mode 100644 index 00000000..def31297 --- /dev/null +++ b/pav-server/src/main/resources/application-prod2.properties @@ -0,0 +1,14 @@ +## file save +file.path.save=/download/save + + +################# SMS ###################### +sms.usercode = palnet +sms.deptcode = C2-2C0-0H +sms.reqname = PAV +sms.reqphone = 02-6200-3912 +sms.result = 0 +sms.reqtime = 00000000000000 +sms.kind = S +sms.subject.certify = PAV +sms.callname.certify = PAV \ No newline at end of file diff --git a/pav-server/src/main/resources/application.properties b/pav-server/src/main/resources/application.properties new file mode 100644 index 00000000..572c3e1e --- /dev/null +++ b/pav-server/src/main/resources/application.properties @@ -0,0 +1,27 @@ + + +###### GP 데이터 데이터 저장 설정 ####### +gp.remove.time = 5 +gp.insert.count = 1000 +gp.end.time= 1 + +####### Naver 주소변화 API 값 ############# +naver.api.id=5md90yszqj +naver.api.key=uCJci6Ixm4DN7hUGtSrjKh6NU6z0SOKq9idpkLat +naver.api.url=https://naveropenapi.apigw.ntruss.com/map-reversegeocode/v2/gc + +### Token key ###### +spring.jwt.secret=jwtsecretkey +spring.jwt.prefix=palnet + + +### AWS S3 #### +#cloud.aws.credentials.accessKey=AKIAW75VMZKFTMBRXK4I +cloud.aws.credentials.accessKey=AKIAW75VMZKFTMBRXK4I +cloud.aws.credentials.secretKey=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 +cloud.aws.stack.auto=false + +cloud.aws.s3.bucket=palnet-file +cloud.aws.region.static=ap-northeast-2 + +cloud.aws.s3.bucket.url=https://s3.ap-northeast-2.amazonaws.com/palnet-file \ No newline at end of file diff --git a/pav-server/src/main/resources/application.yml b/pav-server/src/main/resources/application.yml new file mode 100644 index 00000000..f2f46360 --- /dev/null +++ b/pav-server/src/main/resources/application.yml @@ -0,0 +1,303 @@ +spring: + profiles: + include: + - database + jackson: + time-zone: Asia/Seoul + +# mvc: +# view: +# prefix: /WEB-INF/jsp/ +# suffix: .jsp + +logging: + config: classpath:config/log/logback-spring.xml +# level: +# org: +# hibernate: +# type: +# descriptor: +# sql: trace + +--- + +spring: + config: + activate: + on-profile: local + devtools: + livereload: + enabled: true +# redis: +# host: ec2-54-180-88-137.ap-northeast-2.compute.amazonaws.com +# port: 6379 +# database: 3 + servlet: + multipart: + enabled: true + file-size-threshold: 2KB + max-file-size: 100MB + max-request-size: 100MB + jpa: + hibernate: + naming: + physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl + ddl-auto: none + properties: + hibernate: +# use_sql_comments: true +# use_sql_comments: false +# show_sql: true +# format_sql: true + rabbitmq: + host: 192.168.0.26 + port: 5672 + username: palnet + password: palnet!234 + listener: + simple: + acknowledge-mode: manual + retry: + enabled: true + initial-interval: 3s + max-interval: 10s + max-attempts: 2 + multiplier: 2 + +server: + port: 8080 + servlet: + context-path: / + +netty: + task : + controlinfoTime: 2000 + + websocket: + port: 8081 + thread: + boss: 1 + worker: 1 + socket: + port: 8082 + thread: + boss: 1 + worker: 1 +message: + app: + queue-name: app.drone.queue + exchange-name: app.drone.exchange + routing-key: app.drone.routing.# + websocket: + queue-name: websocket.drone.queue + exchange-name: websocket.drone.exchange + routing-key: websocket.drone.routing.# + +api: + naver: + client-id: WGEct3bJhQC0pyMsP_GK + client-secret-key: Q4K4OtUYol + search-url : https://openapi.naver.com/v1/search/local.json + +--- + +spring: + config: + activate: + on-profile: dev + devtools: + livereload: + enabled: true +# redis: +# host: ec2-54-180-88-137.ap-northeast-2.compute.amazonaws.com +# port: 6379 +# database: 3 + jpa: + hibernate: + naming: + physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl + ddl-auto: none + properties: + hibernate: + use_sql_comments: false + show_sql: false + format_sql: false +server: + port: 8080 + servlet: + context-path: / + +netty: + task : + controlinfoTime: 1000 + + websocket: + port: 8081 + thread: + boss: 1 + worker: 1 + socket: + port: 8082 + thread: + boss: 1 + worker: 1 + +api: + naver: + client-id: WGEct3bJhQC0pyMsP_GK + client-secret-key: Q4K4OtUYol + search-url : https://openapi.naver.com/v1/search/local.json + +--- + +spring: + config: + activate: + on-profile: prod + devtools: + livereload: + enabled: true +# redis: +# host: qrcode-redis-common.lh9tsq.ng.0001.apn2.cache.amazonaws.com +# port: 6379 +# database: 1 + jpa: + hibernate: + naming: + physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl + ddl-auto: none + properties: + hibernate: + use_sql_comments: false + show_sql: false + format_sql: false + rabbitmq: + host: 211.253.38.218 + port: 5672 + username: palnet + password: palnet1234 + listener: + simple: + acknowledge-mode: manual + retry: + enabled: true + initial-interval: 3s + max-interval: 10s + max-attempts: 2 + multiplier: 2 + +server: + port: 8080 + servlet: + context-path: / + tomcat: + max-connections: 5000 + max-threads: 200 + use-relative-redirects: true + +netty: + task : + controlinfoTime: 10000 + + websocket: + port: 8081 + thread: + boss: 1 + worker: 1 + socket: + port: 8082 + thread: + boss: 1 + worker: 1 +message: + app: + queue-name: app.drone.queue + exchange-name: app.drone.exchange + routing-key: app.drone.routing.# + websocket: + queue-name: websocket.drone.queue + exchange-name: websocket.drone.exchange + routing-key: websocket.drone.routing.# + +api: + naver: + client-id: WGEct3bJhQC0pyMsP_GK + client-secret-key: Q4K4OtUYol + search-url : https://openapi.naver.com/v1/search/local.json + +--- + +spring: + config: + activate: + on-profile: prod2 + devtools: + livereload: + enabled: true +# redis: +# host: qrcode-redis-common.lh9tsq.ng.0001.apn2.cache.amazonaws.com +# port: 6379 +# database: 1 + jpa: + hibernate: + naming: + physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl + ddl-auto: none + properties: + hibernate: + use_sql_comments: false + show_sql: false + format_sql: false + rabbitmq: + host: 211.253.38.218 + port: 5672 + username: palnet + password: palnet1234 + listener: + simple: + acknowledge-mode: manual + retry: + enabled: true + initial-interval: 3s + max-interval: 10s + max-attempts: 2 + multiplier: 2 + +server: + port: 8080 + servlet: + context-path: / + tomcat: + max-connections: 10000 + max-threads: 200 + use-relative-redirects: true + +netty: + task : + controlinfoTime: 1000 + + websocket: + port: 8081 + thread: + boss: 1 + worker: 1 + socket: + port: 8082 + thread: + boss: 1 + worker: 1 +message: + app: + queue-name: app.drone.queue + exchange-name: app.drone.exchange + routing-key: app.drone.routing.# + websocket: + queue-name: websocket.drone.queue + exchange-name: websocket.drone.exchange + routing-key: websocket.drone.routing.# + +api: + naver: + client-id: WGEct3bJhQC0pyMsP_GK + client-secret-key: Q4K4OtUYol + search-url : https://openapi.naver.com/v1/search/local.json \ No newline at end of file diff --git a/pav-server/src/main/resources/config/log/logback-spring.xml b/pav-server/src/main/resources/config/log/logback-spring.xml new file mode 100644 index 00000000..280b1da0 --- /dev/null +++ b/pav-server/src/main/resources/config/log/logback-spring.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + ${LOG_PATH_NAME} + + + ${LOG_PATH_NAME}.%d{yyyyMMdd} + 60 + + + %d{yyyy-MM-dd HH:mm:ss} [%-5p] [%F]%M\(%L\) : %m%n + + + + + + + + %d{yyyy-MM-dd HH:mm:ss} [%-5p][$thread] %logger{40} [%F]%M\(%L\) : %m%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pav-socket/build.gradle b/pav-socket/build.gradle new file mode 100644 index 00000000..bffee469 --- /dev/null +++ b/pav-socket/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '2.5.1' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' +} + +group = 'com.palnet' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '11' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'org.springframework.boot:spring-boot-starter-webflux' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + implementation 'io.netty:netty-all:4.1.63.Final' + + + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/pav-socket/settings.gradle b/pav-socket/settings.gradle new file mode 100644 index 00000000..ec8605ca --- /dev/null +++ b/pav-socket/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'pav-socket' diff --git a/pav-socket/src/main/java/com/palnet/SocketApplication.java b/pav-socket/src/main/java/com/palnet/SocketApplication.java new file mode 100644 index 00000000..d3a7110b --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/SocketApplication.java @@ -0,0 +1,38 @@ +package com.palnet; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +@EnableAsync +@EnableScheduling +@SpringBootApplication +public class SocketApplication { + public static void main(String[] args) { + SpringApplication.run(SocketApplication.class, args); + } + + @Bean + public ObjectMapper objectMapper() { + return new ObjectMapper(); + } + + + @Bean("asyncExecutor") + public Executor asyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(1); // 기본 스레드 수 + executor.setMaxPoolSize(10); // 최대 스레드 수 + executor.setQueueCapacity(50); // Max 스레드가 동작하는 경우 대기하는 Queue + executor.setThreadNamePrefix("Async-"); + executor.initialize(); + return executor; + } + +} diff --git a/pav-socket/src/main/java/com/palnet/comn/collection/AuthCollection.java b/pav-socket/src/main/java/com/palnet/comn/collection/AuthCollection.java new file mode 100644 index 00000000..30175686 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/collection/AuthCollection.java @@ -0,0 +1,47 @@ +package com.palnet.comn.collection; + +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +@Slf4j +public class AuthCollection { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + private static Set authkeyList = new HashSet<>(); + + public void reloadAuthkey() { + // 인증키 하드코딩 처리 + authkeyList.add("1cc2e08e-0c5c-43b2-8d4d-cddd3de558e3");// 지텔인증키 + authkeyList.add("35ea4080-a3f2-4e34-8361-78db06bac6fc");// PAL 인증키 + authkeyList.add("4d244c0a-6cf5-4d57-ae48-331a71010c3d");// ADS-B + +// authkeyList.add(null) + } + + public boolean checkAuthkey(String authKey) { + boolean result = false; + + for (Iterator iterator = authkeyList.iterator(); iterator.hasNext();) { + String item = iterator.next(); + + if(authKey.equals(item)) { + result = true; + } + } + + return result; + } + + + public static void main(String [] agrs) { + AuthCollection auth = new AuthCollection(); + auth.reloadAuthkey(); + + System.out.println("1>>>>> " + auth.checkAuthkey("!234")); + System.out.println("2>>>>> " + auth.checkAuthkey("1cc2e08e-0c5c-43b2-8d4d-cddd3de558e3")); + } +} diff --git a/pav-socket/src/main/java/com/palnet/comn/collection/GPCollection.java b/pav-socket/src/main/java/com/palnet/comn/collection/GPCollection.java new file mode 100644 index 00000000..57d209b9 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/collection/GPCollection.java @@ -0,0 +1,106 @@ +package com.palnet.comn.collection; + +import com.palnet.comn.model.GPModel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.util.*; + +/** + * 현재 움직이는 물체/비행체에 대한 정보를 전송하기 위해 저장하는 Collection + * + * @author kang + */ + +@Slf4j +@Component +public class GPCollection { + + private static Map> gpMap = Collections.synchronizedMap(new HashMap<>()); // 누적 GPModel key-objectId + + public static void init() { + gpMap = Collections.synchronizedMap(new HashMap<>()); + } + + public static void init(String objectId) { + if (objectId == null || objectId.isEmpty()) { + return; + } + gpMap.remove(objectId); + } + + public static Map> getAll() { + if (gpMap.keySet().size() < 1) { + return null; + } + return gpMap; + } + + public static List get(String objectId) { + if (objectId == null || objectId.isEmpty()) { + return null; + } + if (gpMap.get(objectId) == null) { + return null; + } + return gpMap.get(objectId); + } + + public static void set(GPModel model) { + if (model == null || model.getObjectId() == null || model.getObjectId().isEmpty()) { + return; + } + List list = gpMap.get(model.getObjectId()); + if (list == null) { + list = new ArrayList<>(); + } + list.add(model); + gpMap.put(model.getObjectId(), list); + } + + public static List send(String objectId) { + if (objectId == null || objectId.isEmpty()) { + return null; + } + if (!gpMap.containsKey(objectId)) { + return null; + } + List list = gpMap.get(objectId); + gpMap.remove(objectId); + return list; + } + + public static Map> sendAll() { + log.info("sendAll start - GPMap size : {}", gpMap.size()); + if(gpMap.keySet().size() < 1) { + return null; + } + Map> map = gpMap; + GPCollection.init(); + log.info("sendAll end - GPMap size : {}/{}", gpMap.size(), map.size()); + return map; + } + + // 1분마다 데이터 삭제 + @Scheduled(fixedDelay = 1000 * 60) + public void removeSchedule() { + log.info("removeSchedule start - GPMap size : {}", gpMap.size()); + for (String key : gpMap.keySet()) { + List list = gpMap.get(key); + if (list == null || list.size() == 0) { + continue; + } + GPModel model = list.get(list.size() - 1); + // 1분 이상된 데이터 삭제 + Instant compareTime = Instant.now().minusSeconds(60); + if (compareTime.isAfter(model.getRegDt())) { + log.info("remove data - 1 munite over : {}", key); + gpMap.remove(key); + } + } + log.info("removeSchedule end - GPMap size : {}", gpMap.size()); + } + +} diff --git a/pav-socket/src/main/java/com/palnet/comn/model/ControlCacheModel.java b/pav-socket/src/main/java/com/palnet/comn/model/ControlCacheModel.java new file mode 100644 index 00000000..e76d49ee --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/model/ControlCacheModel.java @@ -0,0 +1,12 @@ +package com.palnet.comn.model; + +import lombok.Data; + +@Data +public class ControlCacheModel { + private String controlId; + private String typeCd; + private String areaTrnsYn; + private boolean controlWarnCd; + private Long regTime; +} diff --git a/pav-socket/src/main/java/com/palnet/comn/model/GPDatabaseModel.java b/pav-socket/src/main/java/com/palnet/comn/model/GPDatabaseModel.java new file mode 100644 index 00000000..0d1a6f90 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/model/GPDatabaseModel.java @@ -0,0 +1,65 @@ +package com.palnet.comn.model; + +import lombok.Data; + +@Data +public class GPDatabaseModel { + + private String typeCd; // 01 : 최초 들어온 데이터 , 99 : 종료 시킬 데이터 + + private String messageType; + + private String terminalId; + + private Double moveDistance = 0.0; + + private String moveDistanceType; + + private String prodNumber; + + private String controlId; + + private String objectType; + + private String objectId; + + private Double lat = 0.0; + + private Double lng = 0.0; + + private String elevType; + + private Double elev = 0.0; + + private String speedType; + + private Double speed = 0.0; + + private Double betteryLevel = 0.0; + + private Double betteryVoltage = 0.0; + + private String dronStatus; + + private Double heading = 0.0; + + private String terminalRcvDt; + + private String serverRcvDt; + + private String controlStartDt; + + private String controlEndDt; + + private String areaTrnsYn; + + private String endTypeCd; // 01: 일정시간 위치 정보가 들어오지 않는 경우 , 02 : 데이터 베이스에 종료 시점이 명시 되지 않은 경우 + + // 환경센서 필드 + private Double sensorCo = 0.0; + private Double sensorSo2 = 0.0; + private Double sensorNo2 = 0.0; + private Double sensorO3 = 0.0; + private Double sensorDust = 0.0; + +} diff --git a/pav-socket/src/main/java/com/palnet/comn/model/GPHistoryModel.java b/pav-socket/src/main/java/com/palnet/comn/model/GPHistoryModel.java new file mode 100644 index 00000000..7262a455 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/model/GPHistoryModel.java @@ -0,0 +1,15 @@ +package com.palnet.comn.model; + +import lombok.Data; + +@Data +public class GPHistoryModel { + + private String objectId; + + private Double lat = 0.0; + + private Double lng = 0.0; + + +} diff --git a/pav-socket/src/main/java/com/palnet/comn/model/GPModel.java b/pav-socket/src/main/java/com/palnet/comn/model/GPModel.java new file mode 100644 index 00000000..3a9835ae --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/model/GPModel.java @@ -0,0 +1,74 @@ +package com.palnet.comn.model; + +import lombok.Data; + +import java.time.Instant; +import java.util.List; + +@Data +public class GPModel { + + private String typeCd; // 01 : 최초 들어온 데이터 , 99 : 종료 시킬 데이터 + + private String messageType; + + private String terminalId; + + private Double moveDistance = 0.0; + + private String moveDistanceType; + + private String controlId; // 처음 위치 데이터가 들어 왔을때 생성 함 + + private String objectType; + + private String objectId; + + private Double lat = 0.0; + + private Double lng = 0.0; + + private String elevType; + + private Double elev = 0.0; + + private String speedType; + + private Double speed = 0.0; + + private Double betteryLevel = 0.0; + + private Double betteryVoltage = 0.0; + + private String dronStatus; + + private Double heading = 0.0; + + private String terminalRcvDt; + + private String serverRcvDt; + + private String controlStartDt; + + private String controlEndDt; + + private String areaTrnsYn; + + // 환경센서 필드 + private Double sensorCo = 0.0; + private Double sensorSo2 = 0.0; + private Double sensorNo2 = 0.0; + private Double sensorO3 = 0.0; + private Double sensorDust = 0.0; + + //최근 5건만 저장 + private List recentPositionHistory; + + // 전체 히스토리 저장 + private List postionHistory; + + // 비정상 상황 식별 코드 + private boolean controlWarnCd; + private Instant regDt; + +} diff --git a/pav-socket/src/main/java/com/palnet/comn/utils/ContextUtils.java b/pav-socket/src/main/java/com/palnet/comn/utils/ContextUtils.java new file mode 100644 index 00000000..34ee00bc --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/utils/ContextUtils.java @@ -0,0 +1,25 @@ +package com.palnet.comn.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class ContextUtils implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext ctx) throws BeansException { + applicationContext = ctx; + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static Object getBean(String beanName) { + return getApplicationContext().getBean(beanName); + } +} diff --git a/pav-socket/src/main/java/com/palnet/comn/utils/ControlCacheUtils.java b/pav-socket/src/main/java/com/palnet/comn/utils/ControlCacheUtils.java new file mode 100644 index 00000000..75893db8 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/utils/ControlCacheUtils.java @@ -0,0 +1,42 @@ +package com.palnet.comn.utils; + +import com.palnet.comn.model.ControlCacheModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class ControlCacheUtils { + private Logger logger = LoggerFactory.getLogger(getClass()); + private static Map controls = new ConcurrentHashMap<>(); + private Integer removeTime = 1000 * 10; // 10초 + + public static void setControl(String objectId, ControlCacheModel control) { + controls.put(objectId, control); + } + + public static void removeControl(String objectId) { + controls.remove(objectId); + } + + public static ControlCacheModel getControl(String objectId) { + return controls.get(objectId); + } + + // 일정 시간마다 오랜된 데이터 삭제 + @Scheduled(fixedDelay = 1000 * 10) + public void remove() { + logger.info("controls keys : {}",controls.keySet().size()); + for (String key : controls.keySet()) { + ControlCacheModel model = controls.get(key); + Long diff = System.currentTimeMillis() - model.getRegTime(); + if(diff > removeTime){ + removeControl(key); + } + } + } +} diff --git a/pav-socket/src/main/java/com/palnet/comn/utils/DateUtils.java b/pav-socket/src/main/java/com/palnet/comn/utils/DateUtils.java new file mode 100644 index 00000000..3a1f867a --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/utils/DateUtils.java @@ -0,0 +1,153 @@ +package com.palnet.comn.utils; + +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.util.Date; + +public class DateUtils { + + public static String getCurrentTime(){ + return new SimpleDateFormat("yyyyMMddHHmmss").format(System.currentTimeMillis()); + } + + public static String stringToFormat(String str) { + Date date = stringToDatetime(str); + + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date); + } + + + public static Date stringToDatetime(String date) { + + SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + Date result = null; + try { + if(date.length() == 14) { + result = transFormat.parse(date); + } + }catch(Exception e) { + e.printStackTrace(); + } + + return result; + } + + public static Date stringToDate(String date) { + SimpleDateFormat transFormat = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat transFormat2 = new SimpleDateFormat("yyyyMMdd"); + Date result = null; + try { + if(date.length() == 10) { + result = transFormat.parse(date); + }else if(date.length() == 8) { + result = transFormat2.parse(date); + } + }catch(Exception e) { + e.printStackTrace(); + } + + return result; + } + + public static LocalDateTime stringToLocalDateTime(String date) { + + DateTimeFormatter transFormat = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + LocalDateTime localDateTime = LocalDateTime.parse(date , transFormat); + + return localDateTime; + + } + + + + public static LocalDateTime stringToLocalDate(String date) { + DateTimeFormatter transFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + DateTimeFormatter DATEFORMATTER = new DateTimeFormatterBuilder().append(transFormat) + .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) + .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) + .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) + .toFormatter(); + + + LocalDateTime localDateTime = LocalDateTime.parse(date , DATEFORMATTER); + + return localDateTime; + } + + + public static Date nowDate() { + return new Date(System.currentTimeMillis()); + } + + public static long diffSecond(Date firstDate , Date secondDate) { + + long diffDate = secondDate.getTime() - firstDate.getTime(); + long diffTime = diffDate / (1000); + + return diffTime; + + } + + public static long diffMinute(Date firstDate , Date secondDate) { + + long diffDate = secondDate.getTime() - firstDate.getTime(); + long diffTime = diffDate / (1000 * 60); + + return diffTime; + + } + + + +// public static void main(String[] args) { +// +// Date firstDate = stringToDate("20210630142014"); +// +// Date secondDate = stringToDate("20210630142914"); +// +// LocalDateTime dateTime = stringToLocalDate("2021-07-20"); +// +// System.out.println(">>>>" + dateTime); +// +// +// System.out.println("두 날짜의 차이 분: "+diffMinute(firstDate , secondDate)); +// +// System.out.println(">>>" + stringToFormat("20210630142014")); +// +// +// +// +// +//// List> list = new ArrayList>(); +//// +//// +//// for( double i= 0 ; i < 1000 ; i ++) { +//// Map position = new HashMap(); +//// position.put("lat", 11111.0); +//// position.put("lng", 11111.0); +//// position.put("date", i); +//// list.add(position); +//// } +//// +//// int limitSize = 1000; +//// if(list.size() < 1000) { +//// limitSize = list.size(); +//// } +//// +//// List> lastThreeThings = list.subList(list.size() - limitSize, list.size()); +//// +//// //뒤집기 +//// Collections.reverse(lastThreeThings); +//// +//// for(Map data : lastThreeThings) { +//// +//// +//// System.out.println(data); +//// } +// +// } +} diff --git a/pav-socket/src/main/java/com/palnet/comn/utils/JsonUtils.java b/pav-socket/src/main/java/com/palnet/comn/utils/JsonUtils.java new file mode 100644 index 00000000..6b28ef2b --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/comn/utils/JsonUtils.java @@ -0,0 +1,80 @@ +package com.palnet.comn.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +public class JsonUtils { + + private static ObjectMapper getObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper; + } + + public static String toJson(Object object) { + String json = null; + + try { + json = getObjectMapper().writeValueAsString(object); + } catch (JsonProcessingException e) { + log.error("", e); + } + + return json; + } + + public static T fromJson(String val, Class clazz){ + T object = null; + + try { + object = getObjectMapper().readValue(val, clazz); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T fromJson(byte[] bytes, Class clazz){ + T object = null; + + try { + object = getObjectMapper().readValue(bytes, clazz); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T fromJson(String val, TypeReference type){ + T object = null; + + try { + object = getObjectMapper().readValue(val, type); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T bytesToJson(byte[] bytes, TypeReference type){ + T object = null; + + try { + object = getObjectMapper().readValue(bytes, type); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + +} diff --git a/pav-socket/src/main/java/com/palnet/server/SocketServer.java b/pav-socket/src/main/java/com/palnet/server/SocketServer.java new file mode 100644 index 00000000..f12fb564 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/SocketServer.java @@ -0,0 +1,100 @@ +package com.palnet.server; + +import com.palnet.server.initializer.SocketInitializer; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +@Component +public class SocketServer { + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Value("${netty.socket.port}") + private int socketPort; + + @Value("${netty.websocket.port}") + private int websocketPort; + + private EventLoopGroup bossGroup; + private EventLoopGroup workerGroup; + private ServerBootstrap b = new ServerBootstrap(); + +// @Autowired +// private AdsbClient client; +// + + @PostConstruct + public void postConstruct(){ + start(); + } + + + @PreDestroy + public void preDestroy(){ + + stop(); + } + + public void start(){ + try { + bossGroup = new NioEventLoopGroup(10); + workerGroup =new NioEventLoopGroup(); + + b.group(bossGroup , workerGroup) // bossGroup과 workerGroup은 NioEventLoopGroup의 인스턴스입니다.이 때 스레드 개수를 설정할 수 있음 각각 1, Runtime.getRuntime().availableProcessors() * 2로 설정했습니다. + .channel(NioServerSocketChannel.class) +// .handler(new LoggingHandler(LogLevel.valueOf(logBootstrap))) +// .handler(bootstrapHandler) // 채널이 활성화되면 소켓 서버와 소켓 클라이언트를 구동하게 되는 핸들러를 등록합니다. + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) + .option(ChannelOption.SO_BACKLOG, 1000) // 동시에 수용할 수 있는 소켓 연결 요청 수입니다. + +// .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(1024 , 1024 * 16 , 1024 * 1024)) + .childOption(ChannelOption.TCP_NODELAY, false) // 반응속도를 높이기 위해 Nagle 알고리즘을 비활성화 합니다 + + .childOption(ChannelOption.SO_LINGER, 0) // 소켓이 close될 때 신뢰성있는 종료를 위해 4way-handshake가 발생하고 이때 TIME_WAIT로 리소스가 낭비됩니다. 이를 방지하기 위해 0으로 설정합니다. + .childOption(ChannelOption.SO_KEEPALIVE, false) // Keep-alive를 켭니다. + .childOption(ChannelOption.SO_REUSEADDR, false) // SO_LINGER설정이 있으면 안해도 되나 혹시나병(!)으로 TIME_WAIT걸린 포트를 재사용할 수 있도록 설정합니다. + .childHandler(new SocketInitializer()); + + connection(); + + logger.warn("====== [SOCKET SERVER] Start ====== "); + }catch (Exception e) { + logger.warn("====== [SOCKET SERVER] Fail ====== "); + logger.error(e.getMessage()); + } + + } + + private void connection() { + //서버는 Listen 상태로 기다려야하는데, 톰캣이 Timeout 발생함, 이를 방지하기 위해서 별도의 thread 로 처리한다. + new Thread(() -> { + try { + ChannelFuture socketFuture = b.bind(socketPort).sync(); + socketFuture.channel().closeFuture().sync(); + + } catch (InterruptedException e) { + logger.error("InterruptedException", e); + } + }).start(); + } + + + public void stop(){ + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + logger.warn("====== [SOCKET SERVER] STOP ====== "); + + } + +} diff --git a/pav-socket/src/main/java/com/palnet/server/codec/BigIntegerDecoder.java b/pav-socket/src/main/java/com/palnet/server/codec/BigIntegerDecoder.java new file mode 100644 index 00000000..290ac399 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/codec/BigIntegerDecoder.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package com.palnet.server.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.math.BigInteger; +import java.util.List; + +/** + * Decodes the binary representation of a {@link BigInteger} prepended + * with a magic number ('F' or 0x46) and a 32-bit integer length prefix into a + * {@link BigInteger} instance. For example, { 'F', 0, 0, 0, 1, 42 } will be + * decoded into new BigInteger("42"). + */ +public class BigIntegerDecoder extends ByteToMessageDecoder { + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { + + + + System.out.println(">>>>>>>>>>>>>>>>>>>>>" + in.readableBytes()); + + if (in.isReadable()) { + byte[] bytes = new byte[in.readableBytes()]; + + int readerIndex = in.readerIndex(); + in.getBytes(readerIndex, bytes); + + System.out.println(">>>" + new String(bytes)); + + } + // Wait until the length prefix is available. + + } +} diff --git a/pav-socket/src/main/java/com/palnet/server/codec/SocketPayLoadDecoder.java b/pav-socket/src/main/java/com/palnet/server/codec/SocketPayLoadDecoder.java new file mode 100644 index 00000000..2d697abe --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/codec/SocketPayLoadDecoder.java @@ -0,0 +1,39 @@ +package com.palnet.server.codec; + +import com.palnet.comn.utils.JsonUtils; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +@Sharable +public class SocketPayLoadDecoder extends MessageToMessageDecoder { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + protected void decode(ChannelHandlerContext ctx, Object msg, List out){ +// logger.info("[SocketPayLoadDecoder] Init 2 " ); + SocketPayload payload = null; + + try { + payload = JsonUtils.fromJson((String) msg, SocketPayload.class); + if(payload != null) { + out.add(payload); + + } + }catch(Exception e) { + logger.info("MSG => " + msg ); + logger.error(e.getMessage()); + + } + + + + } + + +} diff --git a/pav-socket/src/main/java/com/palnet/server/codec/SocketPayLoadEncorder.java b/pav-socket/src/main/java/com/palnet/server/codec/SocketPayLoadEncorder.java new file mode 100644 index 00000000..d2e3776b --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/codec/SocketPayLoadEncorder.java @@ -0,0 +1,34 @@ +package com.palnet.server.codec; + +import com.palnet.comn.utils.JsonUtils; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +@Sharable +public class SocketPayLoadEncorder extends MessageToMessageEncoder { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + + @Override + protected void encode(ChannelHandlerContext ctx, SocketPayloadResponse msg, List out){ + try { + out.add(JsonUtils.toJson(msg)); + }catch(Exception e) { + logger.info("MSG => " + msg ); + logger.error(e.getMessage()); + } + + + + } + + + + +} diff --git a/pav-socket/src/main/java/com/palnet/server/codec/SocketPayload.java b/pav-socket/src/main/java/com/palnet/server/codec/SocketPayload.java new file mode 100644 index 00000000..31feda72 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/codec/SocketPayload.java @@ -0,0 +1,22 @@ +package com.palnet.server.codec; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SocketPayload implements Serializable{ + + private static final long serialVersionUID = 1L; + + private String authKey; + + private String terminalId; + + private String command; + + private Object body; + + + +} diff --git a/pav-socket/src/main/java/com/palnet/server/codec/SocketPayloadResponse.java b/pav-socket/src/main/java/com/palnet/server/codec/SocketPayloadResponse.java new file mode 100644 index 00000000..bf9712a0 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/codec/SocketPayloadResponse.java @@ -0,0 +1,18 @@ +package com.palnet.server.codec; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SocketPayloadResponse implements Serializable{ + + private static final long serialVersionUID = 1L; + + private String rspCode; + + private String rspMessage; + + + +} diff --git a/pav-socket/src/main/java/com/palnet/server/collection/ChannelCollection.java b/pav-socket/src/main/java/com/palnet/server/collection/ChannelCollection.java new file mode 100644 index 00000000..65246901 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/collection/ChannelCollection.java @@ -0,0 +1,26 @@ +package com.palnet.server.collection; + +import io.netty.channel.Channel; +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + + +public class ChannelCollection { + + private static final long serialVersionUID = 1L; + + //접속 되어있는 모든 Channel + private static final ChannelGroup allChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + + + public void setAllChannels(Channel ch) { + allChannels.add(ch); + } + + public ChannelGroup getAllChannels() { + return allChannels; + } + + +} diff --git a/pav-socket/src/main/java/com/palnet/server/command/SocketCommand.java b/pav-socket/src/main/java/com/palnet/server/command/SocketCommand.java new file mode 100644 index 00000000..97ce61e9 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/command/SocketCommand.java @@ -0,0 +1,427 @@ +package com.palnet.server.command; + +import com.palnet.comn.collection.GPCollection; +import com.palnet.comn.model.ControlCacheModel; +import com.palnet.comn.model.GPHistoryModel; +import com.palnet.comn.model.GPModel; +import com.palnet.comn.utils.ContextUtils; +import com.palnet.comn.utils.ControlCacheUtils; +import com.palnet.comn.utils.DateUtils; +import com.palnet.comn.utils.JsonUtils; +import com.palnet.server.codec.SocketPayload; +import com.palnet.server.task.server.service.TaskServerService; +import com.palnet.server.task.wb.service.TaskWbService; +import com.sun.tools.javac.Main; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.task.TaskRejectedException; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Instant; +import java.time.LocalDateTime; +import java.util.*; + +public class SocketCommand { + + private Logger logger = LoggerFactory.getLogger(getClass()); + // private MessageProducer messageProducer; + private TaskWbService taskWbService; + private TaskServerService taskServerService; + private Environment env; + + public SocketCommand() { +// this.messageProducer = (MessageProducer) ContextUtils.getBean("messageProducer"); + this.taskWbService = (TaskWbService) ContextUtils.getBean("taskWbService"); + this.taskServerService = (TaskServerService) ContextUtils.getBean("taskServerService"); + this.env = (Environment) ContextUtils.getBean("environment"); + } + + /** + * 들어온 데이터의 좌표가 한반도 영역에 포함되어 있는지 검사한다. + * + * @param lat , lon + */ + public boolean latlonCheck(double lat, double lon) { + boolean Check = false; + if (lat > 32 && lat < 44 && lon > 124 && lon < 133) { + Check = true; + } + return Check; + } + + + /** + * 들어온 데이터를 collection넣는 작업을 한다. + * + * @param payload + */ + + public void sandBoxCommand(final SocketPayload payload) { + List> resultList = (ArrayList) payload.getBody(); + + /** 전문 설정 ***/ + final String messageType = "LTEM"; + final String objectType = "DRON"; + + /** 데이터 모델링 **/ + for (LinkedHashMap obj : resultList) { + // 위,경도 좌표가 0으로 들어오는 것은 무시 처리 + if (this.latlonCheck((double) obj.get("lat"), (double) obj.get("lon"))) { + GPModel model = new GPModel(); + + model.setObjectType(objectType); + model.setMessageType(messageType); + model.setObjectId(obj.get("objectId").toString().trim()); + model.setTerminalId(payload.getTerminalId()); + model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); + model.setSpeedType((String) obj.get("speedType")); + model.setElevType((String) obj.get("elevType")); + model.setDronStatus((String) obj.get("dronStatus")); + model.setRegDt(Instant.now()); + + if (obj.get("lat") != null) model.setLat(Double.valueOf(obj.get("lat").toString())); + if (obj.get("lon") != null) model.setLng(Double.valueOf(obj.get("lon").toString())); + if (obj.get("elev") != null) model.setElev(Double.valueOf(obj.get("elev").toString())); + if (obj.get("speed") != null) model.setSpeed(Double.valueOf(obj.get("speed").toString())); + if (obj.get("heading") != null) model.setHeading(Double.valueOf(obj.get("heading").toString())); + + // 서버 수신 시간 정보 + model.setServerRcvDt(DateUtils.getCurrentTime()); + + // 관제 이력 정보 + List hisList; + + GPHistoryModel history = new GPHistoryModel(); + history.setObjectId(model.getObjectId()); + history.setLat(model.getLat()); + history.setLng(model.getLng()); + + if (model.getPostionHistory() != null) { + hisList = model.getPostionHistory(); + } else { + hisList = new ArrayList<>(); + } + + hisList.add(history); + model.setPostionHistory(hisList); + +// Long start = System.currentTimeMillis(); + // STEP 1. 전에 내부 메모리에서 controlId 조회 + ControlCacheModel control = ControlCacheUtils.getControl(model.getObjectId()); + + if (control == null) { + // STEP 1. Control ID 발급 -> Application Server Http 통신 + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI( + env.getProperty("app.host") + "/api/ctr/cntrl/id/" + model.getObjectId() + )) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + + HttpResponse response = HttpClient + .newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + logger.debug("CONTROL ID RESPONSE : {}", response.body()); + + Map body = JsonUtils.fromJson(response.body(), HashMap.class); + + Map data = (Map) body.get("data"); + model.setControlId((String) data.get("controlId")); + model.setTypeCd((String) data.get("typeCd")); + model.setAreaTrnsYn((String) data.get("areaTrnsYn")); + model.setControlStartDt(DateUtils.getCurrentTime()); + + ControlCacheModel ccm = new ControlCacheModel(); + ccm.setControlId((String) data.get("controlId")); + ccm.setTypeCd((String) data.get("typeCd")); + ccm.setAreaTrnsYn((String) data.get("areaTrnsYn")); + ccm.setRegTime(System.currentTimeMillis()); + ControlCacheUtils.setControl(model.getObjectId(), ccm); + + } catch (IOException e) { + logger.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + } + + } else { + model.setControlId(control.getControlId()); + model.setTypeCd("02"); + model.setAreaTrnsYn(control.getAreaTrnsYn()); + model.setControlWarnCd(control.isControlWarnCd()); + control.setRegTime(System.currentTimeMillis()); + ControlCacheUtils.setControl(model.getObjectId(), control); + } +// Long end = System.currentTimeMillis(); +// logger.info(">>> during time : {}::{}", model.getObjectId(),end - start); + // STEP 2. 이력 생성할 전문 전달 -> DRON의 대한 식별정보만 이력 관리 + + if (model.getObjectId().indexOf("PA") > -1) { +// messageProducer.sendControlHistoryMessage(model); + try { + taskWbService.sendDataWebClient(model); + } catch (Exception e) { + logger.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + } + } + + // STEP 3. 화면에 표출할 정보 WebSocket 전달 +// messageProducer.sendControlMessage(model); + try { +// taskServerService.sendData(model); +// taskServerService.sendDataWebClient(model); + GPCollection.set(model); + } catch (Exception e) { + logger.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + } + + } else { + logger.error("좌표 정보가 존재하지 않습니다."); + throw new IllegalArgumentException("좌표 정보가 존재하지 않습니다."); + } + } + } + + public void ADSBCommand(final SocketPayload payload) { + List> resultList = (ArrayList) payload.getBody(); + + /** 전문 설정 ***/ + final String messageType = "LTEM"; + final String objectType = "DRON"; + + /** 데이터 모델링 **/ + for (LinkedHashMap obj : resultList) { + // 위,경도 좌표가 0으로 들어오는 것은 무시 처리 + if (this.latlonCheck((double) obj.get("lat"), (double) obj.get("lon"))) { + GPModel model = new GPModel(); + + model.setObjectType(objectType); + model.setMessageType(messageType); + model.setObjectId(obj.get("objectId").toString().trim()); + model.setTerminalId(payload.getTerminalId()); + model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); + model.setSpeedType((String) obj.get("speedType")); + model.setElevType((String) obj.get("elevType")); + model.setDronStatus((String) obj.get("dronStatus")); + + if (obj.get("lat") != null) model.setLat(Double.valueOf(obj.get("lat").toString())); + if (obj.get("lon") != null) model.setLng(Double.valueOf(obj.get("lon").toString())); + if (obj.get("elev") != null) model.setElev(Double.valueOf(obj.get("elev").toString())); + if (obj.get("speed") != null) model.setSpeed(Double.valueOf(obj.get("speed").toString())); + if (obj.get("heading") != null) model.setHeading(Double.valueOf(obj.get("heading").toString())); + + // 서버 수신 시간 정보 + model.setServerRcvDt(DateUtils.getCurrentTime()); + + // 관제 이력 정보 + List hisList; + + GPHistoryModel history = new GPHistoryModel(); + history.setObjectId(model.getObjectId()); + history.setLat(model.getLat()); + history.setLng(model.getLng()); + + if (model.getPostionHistory() != null) { + hisList = model.getPostionHistory(); + } else { + hisList = new ArrayList<>(); + } + + hisList.add(history); + model.setPostionHistory(hisList); + + + // STEP 1. 전에 내부 메모리에서 controlId 조회 + ControlCacheModel control = ControlCacheUtils.getControl(model.getObjectId()); + + if (control == null) { + // STEP 1. Control ID 발급 -> Application Server Http 통신 + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI( + env.getProperty("app.host") + "/api/ctr/cntrl/id/" + model.getObjectId() + )) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + + HttpResponse response = HttpClient + .newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + logger.debug("CONTROL ID RESPONSE : {}", response.body()); + + Map body = JsonUtils.fromJson(response.body(), HashMap.class); + + Map data = (Map) body.get("data"); + model.setControlId((String) data.get("controlId")); + model.setTypeCd((String) data.get("typeCd")); + model.setAreaTrnsYn((String) data.get("areaTrnsYn")); + model.setControlStartDt(DateUtils.getCurrentTime()); + + ControlCacheModel ccm = new ControlCacheModel(); + ccm.setControlId((String) data.get("controlId")); + ccm.setTypeCd((String) data.get("typeCd")); + ccm.setAreaTrnsYn((String) data.get("areaTrnsYn")); + ccm.setRegTime(System.currentTimeMillis()); + ControlCacheUtils.setControl(model.getObjectId(), ccm); + + } catch (IOException e) { + logger.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + } + + } else { + model.setControlId(control.getControlId()); + model.setTypeCd("02"); + model.setAreaTrnsYn(control.getAreaTrnsYn()); + model.setControlWarnCd(control.isControlWarnCd()); + control.setRegTime(System.currentTimeMillis()); + ControlCacheUtils.setControl(model.getObjectId(), control); + } + // STEP 2. 이력 생성할 전문 전달 -> DRON의 대한 식별정보만 이력 관리 + + if ("PA".equals(model.getObjectId().substring(0, 2))) { +// messageProducer.sendControlHistoryMessage(model); + taskWbService.sendData(model); + } + + // STEP 3. 화면에 표출할 정보 WebSocket 전달 +// messageProducer.sendControlMessage(model); + taskServerService.sendData(model); + + } else { + logger.error("좌표 정보가 존재하지 않습니다."); + throw new IllegalArgumentException("좌표 정보가 존재하지 않습니다."); + } + } + } + + public void ANTOSCommand(final SocketPayload payload) { + List> resultList = (ArrayList) payload.getBody(); + + /** 전문 설정 ***/ + final String messageType = "LTEM"; + final String objectType = "DRON"; + + /** 데이터 모델링 **/ + for (LinkedHashMap obj : resultList) { + // 위,경도 좌표가 0으로 들어오는 것은 무시 처리 + if (this.latlonCheck((double) obj.get("lat"), (double) obj.get("lon"))) { + GPModel model = new GPModel(); + + model.setObjectType(objectType); + model.setMessageType(messageType); + model.setObjectId(obj.get("objectId").toString().trim()); + model.setTerminalId(payload.getTerminalId()); + model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); + model.setSpeedType((String) obj.get("speedType")); + model.setElevType((String) obj.get("elevType")); + model.setDronStatus((String) obj.get("dronStatus")); + + if (obj.get("lat") != null) model.setLat(Double.valueOf(obj.get("lat").toString())); + if (obj.get("lon") != null) model.setLng(Double.valueOf(obj.get("lon").toString())); + if (obj.get("elev") != null) model.setElev(Double.valueOf(obj.get("elev").toString())); + if (obj.get("speed") != null) model.setSpeed(Double.valueOf(obj.get("speed").toString())); + if (obj.get("heading") != null) model.setHeading(Double.valueOf(obj.get("heading").toString())); + + // 서버 수신 시간 정보 + model.setServerRcvDt(DateUtils.getCurrentTime()); + + // 관제 이력 정보 + List hisList; + + GPHistoryModel history = new GPHistoryModel(); + history.setObjectId(model.getObjectId()); + history.setLat(model.getLat()); + history.setLng(model.getLng()); + + if (model.getPostionHistory() != null) { + hisList = model.getPostionHistory(); + } else { + hisList = new ArrayList<>(); + } + + hisList.add(history); + model.setPostionHistory(hisList); + + + // STEP 1. 전에 내부 메모리에서 controlId 조회 + ControlCacheModel control = ControlCacheUtils.getControl(model.getObjectId()); + + if (control == null) { + // STEP 1. Control ID 발급 -> Application Server Http 통신 + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI( + env.getProperty("app.host") + "/api/ctr/cntrl/id/" + model.getObjectId() + )) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + + HttpResponse response = HttpClient + .newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + logger.debug("CONTROL ID RESPONSE : {}", response.body()); + + Map body = JsonUtils.fromJson(response.body(), HashMap.class); + + Map data = (Map) body.get("data"); + model.setControlId((String) data.get("controlId")); + model.setTypeCd((String) data.get("typeCd")); + model.setAreaTrnsYn((String) data.get("areaTrnsYn")); + model.setControlStartDt(DateUtils.getCurrentTime()); + + ControlCacheModel ccm = new ControlCacheModel(); + ccm.setControlId((String) data.get("controlId")); + ccm.setTypeCd((String) data.get("typeCd")); + ccm.setAreaTrnsYn((String) data.get("areaTrnsYn")); + ccm.setRegTime(System.currentTimeMillis()); + ControlCacheUtils.setControl(model.getObjectId(), ccm); + + } catch (IOException e) { + logger.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + } + + } else { + model.setControlId(control.getControlId()); + model.setTypeCd("02"); + model.setAreaTrnsYn(control.getAreaTrnsYn()); + model.setControlWarnCd(control.isControlWarnCd()); + control.setRegTime(System.currentTimeMillis()); + ControlCacheUtils.setControl(model.getObjectId(), control); + } + // STEP 2. 이력 생성할 전문 전달 -> DRON의 대한 식별정보만 이력 관리 + + if ("PA".equals(model.getObjectId().substring(0, 2))) { +// messageProducer.sendControlHistoryMessage(model); + taskWbService.sendData(model); + } + + // STEP 3. 화면에 표출할 정보 WebSocket 전달 +// messageProducer.sendControlMessage(model); + taskServerService.sendData(model); + + } else { + logger.error("좌표 정보가 존재하지 않습니다."); + throw new IllegalArgumentException("좌표 정보가 존재하지 않습니다."); + } + } + + + } + +} diff --git a/pav-socket/src/main/java/com/palnet/server/encrptn/kisa/KISA_SEED_CBC.java b/pav-socket/src/main/java/com/palnet/server/encrptn/kisa/KISA_SEED_CBC.java new file mode 100644 index 00000000..95cba27b --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/encrptn/kisa/KISA_SEED_CBC.java @@ -0,0 +1,1923 @@ +package com.palnet.server.encrptn.kisa; + +public class KISA_SEED_CBC { + + + // DEFAULT : JAVA = BIG_ENDIAN + private static int ENDIAN = Common.BIG_ENDIAN; + + // S-BOX + private static final int SS0[] = + { + 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124, + 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, + 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, + 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec, + 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, + 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, + 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8, + 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, + 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, + 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4, + 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, + 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, + 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8, + 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, + 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, + 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264, + 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, + 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, + 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038, + 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, + 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, + 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4, + 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, + 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, + 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040, + 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, + 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, + 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8, + 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, + 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, + 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330, + 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298 + }; + + private static final int SS1[] = + { + 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0, + 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, + 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, + 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43, + 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, + 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, + 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3, + 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, + 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, + 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430, + 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, + 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, + 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1, + 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171, + 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, + 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0, + 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, + 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, + 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62, + 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, + 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, + 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901, + 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, + 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, + 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971, + 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, + 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, + 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1, + 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, + 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393, + 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783, + 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3 + }; + + private static final int SS2[] = + { + 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505, + 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, + 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, + 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece, + 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, + 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, + 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9, + 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, + 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, + 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5, + 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, + 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, + 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b, + 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, + 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, + 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646, + 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, + 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, + 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808, + 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, + 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, + 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4, + 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, + 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, + 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040, + 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, + 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, + 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca, + 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, + 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, + 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303, + 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a + }; + + private static final int SS3[] = + { + 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838, + 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, + 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, + 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b, + 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, + 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, + 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f, + 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, + 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, + 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434, + 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, + 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, + 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031, + 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031, + 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, + 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010, + 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, + 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, + 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e, + 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, + 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, + 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809, + 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, + 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, + 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839, + 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, + 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, + 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d, + 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, + 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013, + 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407, + 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437 + }; + + private static final int BLOCK_SIZE_SEED = 16; + private static final int BLOCK_SIZE_SEED_INT = 4; + + private static final byte GetB0(int A) { return (byte)(A & 0x0ff); } + private static final byte GetB1(int A) { return (byte)((A>>8) & 0x0ff); } + private static final byte GetB2(int A) { return (byte)((A>>16) & 0x0ff); } + private static final byte GetB3(int A) { return (byte)((A>>24) & 0x0ff); } + + // Round function F and adding output of F to L. + // L0, L1 : left input values at each round + // R0, R1 : right input values at each round + // K : round keys at each round + private static final void SeedRound(int[] T, int LR[], int L0, int L1, int R0, int R1, int[] K, int K_offset) { + T[0] = LR[R0] ^ K[K_offset+0]; + T[1] = LR[R1] ^ K[K_offset+1]; + T[1] ^= T[0]; + T[1] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ + SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + T[0] += T[1]; + T[0] = SS0[GetB0(T[0])&0x0ff] ^ SS1[GetB1(T[0])&0x0ff] ^ + SS2[GetB2(T[0])&0x0ff] ^ SS3[GetB3(T[0])&0x0ff]; + T[1] += T[0]; + T[1] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ + SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + T[0] += T[1]; + LR[L0] ^= T[0]; LR[L1] ^= T[1]; + } + + + + private static final int EndianChange(int dwS) { return ( (/*ROTL(dwS,8)*/(((dwS) << (8)) | (((dwS) >> (32-(8)))&0x000000ff)) & 0x00ff00ff) | (/*ROTL(dwS,24)*/(((dwS) << (24)) | (((dwS) >> (32-(24)))&0x00ffffff)) & 0xff00ff00) ); } + + /************************ Constants for Key schedule **************************/ + private static final int KC0 = 0x9e3779b9; + private static final int KC1 = 0x3c6ef373; + private static final int KC2 = 0x78dde6e6; + private static final int KC3 = 0xf1bbcdcc; + private static final int KC4 = 0xe3779b99; + private static final int KC5 = 0xc6ef3733; + private static final int KC6 = 0x8dde6e67; + private static final int KC7 = 0x1bbcdccf; + private static final int KC8 = 0x3779b99e; + private static final int KC9 = 0x6ef3733c; + private static final int KC10 = 0xdde6e678; + private static final int KC11 = 0xbbcdccf1; + private static final int KC12 = 0x779b99e3; + private static final int KC13 = 0xef3733c6; + private static final int KC14 = 0xde6e678d; + private static final int KC15 = 0xbcdccf1b; + + + + + private static final int ABCD_A = 0; + private static final int ABCD_B = 1; + private static final int ABCD_C = 2; + private static final int ABCD_D = 3; + + private static final void RoundKeyUpdate0(int T[], int[] K, int K_offset, int ABCD[], int KC) { + T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC; + T[1] = ABCD[ABCD_B] + KC - ABCD[ABCD_D]; + K[K_offset+0] = SS0[GetB0(T[0])&0x0ff] ^ SS1[GetB1(T[0])&0x0ff] ^ SS2[GetB2(T[0])&0x0ff] ^ SS3[GetB3(T[0])&0x0ff]; + K[K_offset+1] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + T[0] = ABCD[ABCD_A]; + ABCD[ABCD_A] = ((ABCD[ABCD_A]>>8)&0x00ffffff) ^ (ABCD[ABCD_B]<<24); + ABCD[ABCD_B] = ((ABCD[ABCD_B]>>8)&0x00ffffff) ^ (T[0]<<24); + } + + private static final void RoundKeyUpdate1(int T[], int []K, int K_offset, int ABCD[], int KC) { + T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC; + T[1] = ABCD[ABCD_B] + KC - ABCD[ABCD_D]; + K[K_offset+0] = SS0[GetB0(T[0])&0x0ff] ^ SS1[GetB1(T[0])&0x0ff] ^ SS2[GetB2(T[0])&0x0ff] ^ SS3[GetB3(T[0])&0x0ff]; + K[K_offset+1] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + T[0] = ABCD[ABCD_C]; + ABCD[ABCD_C] = (ABCD[ABCD_C]<<8) ^ ((ABCD[ABCD_D]>>24)&0x000000ff); + ABCD[ABCD_D] = (ABCD[ABCD_D]<<8) ^ ((T[0]>>24)&0x000000ff); + } + + private static void BLOCK_XOR_CBC(int[] OUT_VALUE, int out_value_offset, int[] IN_VALUE1, int in_value1_offset, int[] IN_VALUE2, int in_value2_offset) { + OUT_VALUE[out_value_offset+0] = (in_value1_offset 0) + len = (inLen/4)+1; + else + len = (inLen/4); + + data = new int[len]; + + for(i=0;i> ((i%4)*8)); + } + } else { + for(i=0;i> ((3-(i%4))*8)); + } + } + + return data; + } + + + public static int SEED_CBC_init( KISA_SEED_INFO pInfo, KISA_ENC_DEC enc, byte[] pbszUserKey, byte[] pbszIV ) { + int ABCD[] = new int[4]; // Iuput/output values at each rounds(�� ���� ��/���) + int T[] = new int[2]; // Temporary variable + int K[]; + + if( null == pInfo || + null == pbszUserKey || + null == pbszIV ) + return 0; + + K = pInfo.seed_key.key_data; // Pointer of round keys + pInfo.encrypt = enc.value; // + Common.memcpy(pInfo.ivec, pbszIV, 16, ENDIAN); + pInfo.last_block_flag = pInfo.buffer_length = 0; + + // Set up input values for Key Schedule + ABCD[ABCD_A] = Common.byte_to_int(pbszUserKey, 0*4, ENDIAN); + ABCD[ABCD_B] = Common.byte_to_int(pbszUserKey, 1*4, ENDIAN); + ABCD[ABCD_C] = Common.byte_to_int(pbszUserKey, 2*4, ENDIAN); + ABCD[ABCD_D] = Common.byte_to_int(pbszUserKey, 3*4, ENDIAN); + + // Reorder for big endian + if(Common.BIG_ENDIAN != ENDIAN) { + ABCD[ABCD_A] = EndianChange(ABCD[ABCD_A]); + ABCD[ABCD_B] = EndianChange(ABCD[ABCD_B]); + ABCD[ABCD_C] = EndianChange(ABCD[ABCD_C]); + ABCD[ABCD_D] = EndianChange(ABCD[ABCD_D]); + } + + // i-th round keys( K_i,0 and K_i,1 ) are denoted as K[2*(i-1)] and K[2*i-1], respectively + RoundKeyUpdate0(T, K, 0, ABCD, KC0 ); // K_1,0 and K_1,1 + RoundKeyUpdate1(T, K, 2, ABCD, KC1 ); // K_2,0 and K_2,1 + RoundKeyUpdate0(T, K, 4, ABCD, KC2 ); // K_3,0 and K_3,1 + RoundKeyUpdate1(T, K, 6, ABCD, KC3 ); // K_4,0 and K_4,1 + RoundKeyUpdate0(T, K, 8, ABCD, KC4 ); // K_5,0 and K_5,1 + RoundKeyUpdate1(T, K, 10, ABCD, KC5 ); // K_6,0 and K_6,1 + RoundKeyUpdate0(T, K, 12, ABCD, KC6 ); // K_7,0 and K_7,1 + RoundKeyUpdate1(T, K, 14, ABCD, KC7 ); // K_8,0 and K_8,1 + RoundKeyUpdate0(T, K, 16, ABCD, KC8 ); // K_9,0 and K_9,1 + RoundKeyUpdate1(T, K, 18, ABCD, KC9 ); // K_10,0 and K_10,1 + RoundKeyUpdate0(T, K, 20, ABCD, KC10); // K_11,0 and K_11,1 + RoundKeyUpdate1(T, K, 22, ABCD, KC11); // K_12,0 and K_12,1 + RoundKeyUpdate0(T, K, 24, ABCD, KC12); // K_13,0 and K_13,1 + RoundKeyUpdate1(T, K, 26, ABCD, KC13); // K_14,0 and K_14,1 + RoundKeyUpdate0(T, K, 28, ABCD, KC14); // K_15,0 and K_15,1 + + T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC15; + T[1] = ABCD[ABCD_B] - ABCD[ABCD_D] + KC15; + + K[30] = SS0[GetB0(T[0])&0x0ff] ^ SS1[GetB1(T[0])&0x0ff] ^ // K_16,0 + SS2[GetB2(T[0])&0x0ff] ^ SS3[GetB3(T[0])&0x0ff]; + K[31] = SS0[GetB0(T[1])&0x0ff] ^ SS1[GetB1(T[1])&0x0ff] ^ // K_16,1 + SS2[GetB2(T[1])&0x0ff] ^ SS3[GetB3(T[1])&0x0ff]; + + return 1; + + + } + + + public static int SEED_CBC_Process( KISA_SEED_INFO pInfo, int[] in, int inLen, int[] out, int[] outLen ) { + int nCurrentCount = BLOCK_SIZE_SEED; + int[] pdwXOR = null; + int in_offset = 0; + int out_offset = 0; + int pdwXOR_offset = 0; + + if( null == pInfo || + null == in || + null == out || + 0 > inLen ) + return 0; + + + if( KISA_ENC_DEC._KISA_ENCRYPT == pInfo.encrypt ) { + pdwXOR = pInfo.ivec; + in_offset = 0; + out_offset = 0; + pdwXOR_offset = 0; + + + while( nCurrentCount <= inLen ) + { + BLOCK_XOR_CBC( out, out_offset, in, in_offset, pdwXOR, pdwXOR_offset ); + + KISA_SEED_Encrypt_Block_forCBC( out, out_offset, out, out_offset, pInfo.seed_key ); + + pdwXOR = out; + pdwXOR_offset = out_offset; + + nCurrentCount += BLOCK_SIZE_SEED; + in_offset += BLOCK_SIZE_SEED_INT; + out_offset += BLOCK_SIZE_SEED_INT; + } + + outLen[0] = nCurrentCount - BLOCK_SIZE_SEED; + pInfo.buffer_length = (inLen - outLen[0]); + + Common.memcpy( pInfo.ivec, pdwXOR, pdwXOR_offset, BLOCK_SIZE_SEED ); + Common.memcpy( pInfo.cbc_buffer, in, in_offset, pInfo.buffer_length ); + } + else { + pdwXOR = pInfo.ivec; + in_offset = 0; + out_offset = 0; + pdwXOR_offset = 0; + + while( nCurrentCount <= inLen ) + { + KISA_SEED_Decrypt_Block_forCBC( in, in_offset, out, out_offset, pInfo.seed_key ); + + BLOCK_XOR_CBC( out, out_offset, out, out_offset, pdwXOR, pdwXOR_offset ); + + pdwXOR = in; + pdwXOR_offset = in_offset; + + nCurrentCount += BLOCK_SIZE_SEED; + in_offset += BLOCK_SIZE_SEED_INT; + out_offset += BLOCK_SIZE_SEED_INT; + } + + outLen[0] = nCurrentCount - BLOCK_SIZE_SEED; + + + + Common.memcpy( pInfo.ivec, pdwXOR, pdwXOR_offset, BLOCK_SIZE_SEED ); + Common.memcpy( pInfo.cbc_last_block, out, out_offset-BLOCK_SIZE_SEED_INT, BLOCK_SIZE_SEED ); + + + } + + return 1; + + } + + + public static int SEED_CBC_Close( KISA_SEED_INFO pInfo, int[] out, int out_offset, int[] outLen ) { + int nPaddngLeng; + int i; + + outLen[0] = 0; + + if( null == out ) + return 0; + + if( KISA_ENC_DEC._KISA_ENCRYPT == pInfo.encrypt ) { + nPaddngLeng = BLOCK_SIZE_SEED - pInfo.buffer_length; + + for( i = pInfo.buffer_length; i 0 && nPaddngLeng <= BLOCK_SIZE_SEED ) + { + for(i=nPaddngLeng; i>0; i--) + { + Common.set_byte_for_int(out, out_offset-i, (byte)0x00, ENDIAN); + } + + outLen[0] = nPaddngLeng; + } + else + return 0; + + + } + return 1; + + + } + + + + + + + + public static byte[] SEED_CBC_Encrypt( byte[] pbszUserKey, byte[] pbszIV, byte[] message, int message_offset, int message_length ) { + KISA_SEED_INFO info = new KISA_SEED_INFO(); + int[] outbuf; + int[] data; + byte[] cdata; + int outlen; + int nRetOutLeng[] = new int[] { 0 }; + int nPaddingLeng[] = new int[] { 0 }; + + byte[] pbszPlainText = new byte[message_length]; + System.arraycopy(message, message_offset, pbszPlainText, 0, message_length); + int nPlainTextLen = pbszPlainText.length; + + + int nPlainTextPadding = BLOCK_SIZE_SEED - (nPlainTextLen % BLOCK_SIZE_SEED); + byte []newpbszPlainText = new byte[nPlainTextLen+nPlainTextPadding]; + Common.arraycopy(newpbszPlainText, pbszPlainText, nPlainTextLen); + + byte[] pbszCipherText = new byte[newpbszPlainText.length]; + + + SEED_CBC_init( info, KISA_ENC_DEC.KISA_ENCRYPT, pbszUserKey, pbszIV ); + + outlen = ((newpbszPlainText.length/BLOCK_SIZE_SEED) ) * BLOCK_SIZE_SEED_INT ; + outbuf = new int[outlen]; + data = chartoint32_for_SEED_CBC(newpbszPlainText, nPlainTextLen); + + SEED_CBC_Process( info, data, nPlainTextLen, outbuf, nRetOutLeng ); + SEED_CBC_Close( info, outbuf, (nRetOutLeng[0]/4), nPaddingLeng ); + + cdata = int32tochar_for_SEED_CBC(outbuf, nRetOutLeng[0]+nPaddingLeng[0]); + Common.arraycopy(pbszCipherText, cdata, nRetOutLeng[0]+nPaddingLeng[0]); + + data = null; + cdata = null; + outbuf = null; + + return pbszCipherText; + } + + + + + + + + + + + + public static byte[] SEED_CBC_Decrypt( byte[] pbszUserKey, byte[] pbszIV, byte[] message, int message_offset, int message_length ) { + KISA_SEED_INFO info = new KISA_SEED_INFO(); + int[] outbuf; + int[] data; + byte[] cdata; + int outlen; + int nRetOutLeng[] = new int[] { 0 }; + int nPaddingLeng[] = new int[] { 0 }; + + + + byte[] pbszCipherText = new byte[message_length]; + System.arraycopy(message, message_offset, pbszCipherText, 0, message_length); + int nCipherTextLen = pbszCipherText.length; + + if( (nCipherTextLen%BLOCK_SIZE_SEED) != 0 ) + { + byte result[] = null; + return result; + } + + + byte []newpbszCipherText = new byte[nCipherTextLen]; + Common.arraycopy(newpbszCipherText, pbszCipherText, nCipherTextLen); + + nCipherTextLen = newpbszCipherText.length; + + + SEED_CBC_init( info, KISA_ENC_DEC.KISA_DECRYPT, pbszUserKey, pbszIV ); + + outlen = ((nCipherTextLen/16)) *4 ; + outbuf = new int[outlen]; + data = chartoint32_for_SEED_CBC(newpbszCipherText, nCipherTextLen); + + SEED_CBC_Process( info, data, nCipherTextLen, outbuf, nRetOutLeng ); + + + if( SEED_CBC_Close( info, outbuf, (nRetOutLeng[0]), nPaddingLeng ) == 1 ) + { + cdata = int32tochar_for_SEED_CBC( outbuf, nRetOutLeng[0]-nPaddingLeng[0] ); + + byte[] pbszPlainText = new byte[nRetOutLeng[0]-nPaddingLeng[0]]; + + Common.arraycopy(pbszPlainText, cdata, nRetOutLeng[0]-nPaddingLeng[0]); + + int pdmessage_length = nRetOutLeng[0]-nPaddingLeng[0]; + byte[] result = new byte[pdmessage_length]; + System.arraycopy(pbszPlainText, 0, result, 0, pdmessage_length); + + data = null; + cdata = null; + outbuf = null; + + return result; + + } + else + { + byte result[] = null; + return result; + } + + + } + + + + + + + + + + + + public static final class KISA_ENC_DEC { + public static final int _KISA_DECRYPT = 0; + public static final int _KISA_ENCRYPT = 1; + + public int value; + + public KISA_ENC_DEC(int value ) { + this.value = value; + } + + public static final KISA_ENC_DEC KISA_ENCRYPT = new KISA_ENC_DEC(_KISA_ENCRYPT); + public static final KISA_ENC_DEC KISA_DECRYPT = new KISA_ENC_DEC(_KISA_DECRYPT); + + } + + public static final class KISA_SEED_KEY { + public int[] key_data = new int[32]; + + public void init() { + for(int i=0; i> shift_value; + return (byte)value; + } else { + int shift_value = (b_offset%4)*8; + int mask_value = 0x0ff << shift_value; + int value = (src[b_offset/4] & mask_value) >> shift_value; + return (byte)value; + } + + } + + public static byte[] get_bytes_for_ints(int[] src, int offset, int ENDIAN) { + int iLen = src.length-offset; + byte[] result = new byte[(iLen)*4]; + for(int i=0; i> 24) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+3] = (byte)((src) & 0x0ff); + } else { + dst[dst_offset] = (byte)((src) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+3] = (byte)((src >> 24) & 0x0ff); + } + + } + + public static void int_to_byte_unit_big_endian(byte[] dst, int dst_offset, int src) { + dst[dst_offset] = (byte)((src>> 24) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+3] = (byte)((src) & 0x0ff); + } + + public static int URShift(int x, int n) { + if(n == 0) + return x; + if(n >= 32) + return 0; + int v = x >> n; + int v_mask = ~(0x80000000 >> (n-1)); + return v & v_mask; + } + + public static final long INT_RANGE_MAX = (long)Math.pow(2, 32); + + public static long intToUnsigned(int x) { + if(x >= 0) + return x; + return x + INT_RANGE_MAX; + } + + //Padding : PKSC #7 + //��� : PADDING �� ����(����Ʈ����) + public static int Padding(byte[] pbData, byte[] padData, int length) { + int i; + int padvalue = 16 - (length%16); + Common.arraycopy(padData, pbData, length); + i = length; + do { + padData[i] = (byte)(padvalue); + i++; + }while((i%16) != 0); + return i; + } + + + //1��(128��Ʈ XOR) + public static void BLOCK_XOR_PROPOSAL(int[] OUT_VALUE, int out_value_offset, int[] IN_VALUE1, int in_value1_offset, int[] IN_VALUE2, int in_value2_offset) { + OUT_VALUE[out_value_offset+0] = (in_value1_offset= SHA256_DIGEST_BLOCKLEN) { + Common.arraycopy_offset(Info.szBuffer, 0, pszMessage, pszMessage_offset, SHA256_DIGEST_BLOCKLEN); + SHA256_Transform(Info.szBuffer, Info.uChainVar); + pszMessage_offset += SHA256_DIGEST_BLOCKLEN; + uDataLen -= SHA256_DIGEST_BLOCKLEN; + } + + Common.arraycopy_offset(Info.szBuffer, 0, pszMessage, pszMessage_offset, uDataLen); + } + + /** + @brief �޽��� �����̱�� ���� �����̱⸦ ������ �� ������ �޽��� ����� ������ �����Լ��� ȣ���ϴ� �Լ� + @param Info : SHA256_Init ȣ���Ͽ� �ʱ�ȭ�� ����ü(���������� ���ȴ�.) + @param pszDigest : ��ȣ�� + */ + public static void SHA256_Close( SHA256_INFO Info, byte[] pszDigest ) { + int i, Index; + + Index = Common.URShift(Info.uLowLength, 3) % SHA256_DIGEST_BLOCKLEN; + Info.szBuffer[Index++] = (byte)0x80; + + if (Index > SHA256_DIGEST_BLOCKLEN - 8) { + Common.arrayinit_offset(Info.szBuffer, Index, (byte)0, SHA256_DIGEST_BLOCKLEN - Index); + SHA256_Transform(Info.szBuffer, Info.uChainVar); + Common.arrayinit(Info.szBuffer, (byte)0, SHA256_DIGEST_BLOCKLEN - 8); + } + else { + Common.arrayinit_offset(Info.szBuffer, Index, (byte)0, SHA256_DIGEST_BLOCKLEN - Index - 8); + } + + if(ENDIAN == Common.LITTLE_ENDIAN) { + Info.uLowLength = ENDIAN_REVERSE_ULONG(Info.uLowLength); + Info.uHighLength = ENDIAN_REVERSE_ULONG(Info.uHighLength); + } + + Common.int_to_byte_unit(Info.szBuffer, ((int)(SHA256_DIGEST_BLOCKLEN / 4 - 2))*4, Info.uHighLength, ENDIAN); + Common.int_to_byte_unit(Info.szBuffer, ((int)(SHA256_DIGEST_BLOCKLEN / 4 - 1))*4, Info.uLowLength, ENDIAN); + + SHA256_Transform(Info.szBuffer, Info.uChainVar); + + for (i = 0; i < SHA256_DIGEST_VALUELEN; i += 4) + BIG_D2B((Info.uChainVar)[i / 4], pszDigest, i); + } + + /** + @brief ����� �Է� ���� �ѹ��� ó�� + @param pszMessage : ����� �Է� �� + @param pszDigest : ��ȣ�� + @remarks ���������� SHA256_Init, SHA256_Process, SHA256_Close�� ȣ���Ѵ�. + */ + public static void SHA256_Encrpyt( byte[] pszMessage, int uPlainTextLen, byte[] pszDigest ) { + SHA256_INFO info = new SHA256_INFO(); + SHA256_Init( info ); + SHA256_Process( info, pszMessage, uPlainTextLen ); + SHA256_Close( info, pszDigest ); + } + + + public static class SHA256_INFO { + public int uChainVar[] = new int[SHA256_DIGEST_VALUELEN / 4]; + public int uHighLength; + public int uLowLength; + public byte szBuffer[] = new byte[SHA256_DIGEST_BLOCKLEN]; + } + + public static class Common { + + public static final int BIG_ENDIAN = 0; + public static final int LITTLE_ENDIAN = 1; + + public static void arraycopy(byte[] dst, byte[] src, int length) { + for(int i=0; i> shift_value; + return (byte)value; + } else { + int shift_value = (b_offset%4)*8; + int mask_value = 0x0ff << shift_value; + int value = (src[b_offset/4] & mask_value) >> shift_value; + return (byte)value; + } + + } + + public static byte[] get_bytes_for_ints(int[] src, int offset, int ENDIAN) { + int iLen = src.length-offset; + byte[] result = new byte[(iLen)*4]; + for(int i=0; i> 24) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+3] = (byte)((src) & 0x0ff); + } else { + dst[dst_offset] = (byte)((src) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+3] = (byte)((src >> 24) & 0x0ff); + } + + } + + public static void int_to_byte_unit_big_endian(byte[] dst, int dst_offset, int src) { + dst[dst_offset] = (byte)((src>> 24) & 0x0ff); + dst[dst_offset+1] = (byte)((src >> 16) & 0x0ff); + dst[dst_offset+2] = (byte)((src >> 8) & 0x0ff); + dst[dst_offset+3] = (byte)((src) & 0x0ff); + } + + public static int URShift(int x, int n) { + if(n == 0) + return x; + if(n >= 32) + return 0; + int v = x >> n; + int v_mask = ~(0x80000000 >> (n-1)); + return v & v_mask; + } + + public static final long INT_RANGE_MAX = (long)Math.pow(2, 32); + + public static long intToUnsigned(int x) { + if(x >= 0) + return x; + return x + INT_RANGE_MAX; + } + } + + public static void main(String[] args) + { + byte pbData[] = {(byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, + (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F, + (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F, + (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, + (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F, + (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F}; + byte pbData1[] = {(byte)0x61}; + + byte pbCipher[] = new byte[32]; + byte pbPlain[] = new byte[16]; + + System.out.print("[ Test SHA256 reference code ]"+"\n"); + System.out.print("\n\n"); + System.out.print("[ Test HASH mode ]"+"\n"); + System.out.print("\n"); + + int Plaintext_length = 1; + + for(int k=0; k<30; k++) + { + + System.out.print("Plaintext\t: "); + for (int i=0; i { + + private Logger logger = LoggerFactory.getLogger(getClass()); + private SocketCommand command = new SocketCommand(); + + private AuthCollection auth = new AuthCollection(); + private SocketPayloadResponse res = new SocketPayloadResponse(); + + + @Override + public void channelActive(ChannelHandlerContext ctx) { + auth.reloadAuthkey(); // 채널 활성화 되면 인증키 정보를 다시 불러옴 + + logger.debug("==================== [SocketHandler channelActive ] ==================== "); + ctx.writeAndFlush("Server Connection"); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, SocketPayload payload) { + + try { + logger.debug("==================== [SocketHandler channelRead0 ] ==================== "); + + if (payload.getAuthKey().isEmpty()) { + res.setRspCode("-2000"); + res.setRspMessage("auth key is empty !"); + + } else if (!auth.checkAuthkey(payload.getAuthKey().trim())) { + res.setRspCode("-2000"); + res.setRspMessage("Invalid auth key !"); + + } else { + logger.info("====> SOCKET BODY : {}", JsonUtils.toJson(payload)); + + switch (payload.getCommand().trim()) { + case "SANDBOX": + command.sandBoxCommand(payload); + break; + case "ADS-B": + command.ADSBCommand(payload); + case "ANTOS": + command.ANTOSCommand(payload); + break; + default: + break; + } + + res.setRspCode("0"); + res.setRspMessage("SUCCESS"); + } + + } catch (Exception e) { + res.setRspCode("-9999"); + res.setRspMessage("Etc error"); + + e.printStackTrace(); + } finally { + logger.debug("res >>>" + JsonUtils.toJson(res)); + ctx.writeAndFlush(res); + } + + + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.info("=========== [exceptionCaught ] ===================="); + res.setRspCode("-9999"); + res.setRspMessage("Etc error"); + ctx.writeAndFlush(res); + logger.error("ERROR : {}\n{}", cause.getMessage(), cause.getStackTrace()); + ctx.close(); + } +} diff --git a/pav-socket/src/main/java/com/palnet/server/initializer/SocketInitializer.java b/pav-socket/src/main/java/com/palnet/server/initializer/SocketInitializer.java new file mode 100644 index 00000000..28149984 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/initializer/SocketInitializer.java @@ -0,0 +1,25 @@ +package com.palnet.server.initializer; + +import com.palnet.server.codec.SocketPayLoadDecoder; +import com.palnet.server.codec.SocketPayLoadEncorder; +import com.palnet.server.handler.SocketHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.json.JsonObjectDecoder; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.util.CharsetUtil; + +public class SocketInitializer extends ChannelInitializer{ + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline() + .addLast(new JsonObjectDecoder(655360)) + .addLast(new StringDecoder(CharsetUtil.UTF_8), new StringEncoder(CharsetUtil.UTF_8)) + .addLast(new SocketPayLoadDecoder() , new SocketPayLoadEncorder()) + .addLast(new SocketHandler()); + } + +} diff --git a/pav-socket/src/main/java/com/palnet/server/task/server/service/TaskServerService.java b/pav-socket/src/main/java/com/palnet/server/task/server/service/TaskServerService.java new file mode 100644 index 00000000..5ae683c2 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/task/server/service/TaskServerService.java @@ -0,0 +1,132 @@ +package com.palnet.server.task.server.service; + +import com.palnet.comn.collection.GPCollection; +import com.palnet.comn.model.GPModel; +import com.palnet.comn.utils.JsonUtils; +import io.netty.channel.ChannelOption; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +/** + * packageName : com.palnet.server.task.wb.service + * fileName : TaskWbService + * author : dhji + * date : 2023-08-28(028) + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2023-08-28(028) dhji 최초 생성 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class TaskServerService { + @Value("${app.host}") + private String APP_HOST; + + private final String APP_SEND_ASYNC_URI = "/api/server/receiver/async"; + private final String APP_SEND_URI = "/api/server/receiver"; + private final String APP_SEND_ALL_URI = "/api/server/receiver/all"; + + public void sendData(GPModel model) { + HttpRequest request = null; + try { + request = HttpRequest.newBuilder() + .uri(new URI( + APP_HOST + APP_SEND_URI + )) + .version(HttpClient.Version.HTTP_2) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(JsonUtils.toJson(model))) + .build(); + HttpResponse response = HttpClient + .newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + } catch (URISyntaxException | InterruptedException | IOException e) { + log.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); + } catch (Exception e) { + log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + } + +// log.info("websocket send message : {}", JsonUtils.toJson(model)); + } + + @Async("asyncExecutor") + public CompletableFuture sendDataAsync(GPModel model) { + HttpRequest request = null; + try { + request = HttpRequest.newBuilder() + .uri(new URI( + APP_HOST + APP_SEND_ASYNC_URI + )) + .version(HttpClient.Version.HTTP_2) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(JsonUtils.toJson(model))) + .build(); + HttpResponse response = HttpClient + .newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + } catch (URISyntaxException | InterruptedException | IOException e) { + log.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); + } catch (Exception e) { + log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + } + +// log.info("websocket send message : {}", JsonUtils.toJson(model)); + return CompletableFuture.completedFuture(null); + } + + + public void sendDataWebClient(GPModel model) { + + WebClient client = WebClient.builder() + .baseUrl(APP_HOST) + .defaultHeader("Content-Type", "application/json") + .build(); + + client.post() + .uri(APP_SEND_URI) + .body(Mono.just(model), GPModel.class) + .retrieve() + .bodyToMono(Void.class).subscribe(); + + + } + + + @Scheduled(fixedDelay = 1000 * 20) + public void sendDataAllWebClient() { + Map> all = GPCollection.sendAll(); + if (all == null) { + return; + } + WebClient client = WebClient.builder() + .baseUrl(APP_HOST) + .defaultHeader("Content-Type", "application/json") + .build(); + + client.post() + .uri(APP_SEND_ALL_URI) + .body(Mono.just(all), Map.class) + .retrieve() + .bodyToMono(Void.class).subscribe(); + } + +} diff --git a/pav-socket/src/main/java/com/palnet/server/task/wb/service/TaskWbService.java b/pav-socket/src/main/java/com/palnet/server/task/wb/service/TaskWbService.java new file mode 100644 index 00000000..1fd17391 --- /dev/null +++ b/pav-socket/src/main/java/com/palnet/server/task/wb/service/TaskWbService.java @@ -0,0 +1,109 @@ +package com.palnet.server.task.wb.service; + +import com.palnet.comn.model.GPModel; +import com.palnet.comn.utils.JsonUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClientRequest; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.concurrent.CompletableFuture; + +/** + * packageName : com.palnet.server.task.wb.service + * fileName : TaskWbService + * author : dhji + * date : 2023-08-28(028) + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2023-08-28(028) dhji 최초 생성 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class TaskWbService { + @Value("${web-socket.host}") + private String WS_HOST; + + private final String WS_SEND_ASYNC_URI = "/api/ws/receiver/async"; + private final String WS_SEND_URI = "/api/ws/receiver"; + + @Async("asyncExecutor") + public CompletableFuture sendDataAsync(GPModel model) { +// log.info(">>> wb sendData model :: {}", model); + HttpRequest request = null; + try { + request = HttpRequest.newBuilder() + .uri(new URI( + WS_HOST + WS_SEND_ASYNC_URI + )) + .version(HttpClient.Version.HTTP_2) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(JsonUtils.toJson(model))) + .build(); + HttpResponse response = HttpClient + .newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + } catch (URISyntaxException | InterruptedException | IOException e) { + log.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); + } catch (Exception e) { + log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + } + +// log.info("websocket send message : {}", JsonUtils.toJson(model)); + return CompletableFuture.completedFuture(null); + } + + public void sendData(GPModel model) { +// log.info(">>> wb sendData model :: {}", model); + HttpRequest request = null; + try { + request = HttpRequest.newBuilder() + .uri(new URI( + WS_HOST + WS_SEND_URI + )) + .version(HttpClient.Version.HTTP_2) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(JsonUtils.toJson(model))) + .build(); + HttpResponse response = HttpClient + .newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + } catch (URISyntaxException | InterruptedException | IOException e) { + log.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); + } catch (Exception e) { + log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + } + +// log.info("websocket send message : {}", JsonUtils.toJson(model)); + } + + public void sendDataWebClient(GPModel model){ + + WebClient client = WebClient.builder() + .baseUrl(WS_HOST) + .defaultHeader("Content-Type", "application/json") + .build(); + + client.post() + .uri(WS_SEND_URI) + .body(Mono.just(model), GPModel.class) + .retrieve() + .bodyToMono(Void.class) + .subscribe(); + + } +} diff --git a/pav-socket/src/main/resources/application.yml b/pav-socket/src/main/resources/application.yml new file mode 100644 index 00000000..04815064 --- /dev/null +++ b/pav-socket/src/main/resources/application.yml @@ -0,0 +1,219 @@ +spring: + config: + activate: + on-profile: local +# rabbitmq: +# host: 192.168.0.26 +# port: 5672 +# username: palnet +# password: palnet!234 +# virtual-host: / + +netty: + task: + controlinfoTime: 2000 + socket: + port: 8082 + thread: + boss: 1 + worker: 1 + websocket: + host: 127.0.0.1 + port: 8081 + +server: + port: 8182 + +#message: +# app: +# queue-name: app.drone.queue +# exchange-name: app.drone.exchange +# routing-key: app.drone.routing.# +# websocket: +# queue-name: websocket.drone.queue +# exchange-name: websocket.drone.exchange +# routing-key: websocket.drone.routing.# + +app: + host: http://127.0.0.1:8080 +web-socket: + host: http://127.0.0.1:8181 + +#management: +# endpoints: +# web: +# base-path: /management +# path-mapping: +# health: health_check +# exposure: +# include: health, info + +--- + +spring: + config: + activate: + on-profile: dev +# rabbitmq: +# host: 192.168.0.26 +# port: 5672 +# username: guest +# password: guest + +netty: + task: + controlinfoTime: 2000 + socket: + port: 8082 + thread: + boss: 1 + worker: 1 + +server: + port: 8182 + +#message: +# app: +# queue-name: app.drone.queue +# exchange-name: app.drone.exchange +# routing-key: app.drone.routing.# +# websocket: +# queue-name: websocket.drone.queue +# exchange-name: websocket.drone.exchange +# routing-key: websocket.drone.routing.# + +app: + host: http://211.253.38.218:8080 +web-socket: + host: http://211.253.38.218:8081 + +#management: +# endpoints: +# web: +# base-path: /management +# path-mapping: +# health: health_check +# exposure: +# include: health, info + +--- + +spring: + config: + activate: + on-profile: prod +# rabbitmq: +# host: 211.253.38.218 +# port: 5672 +# username: palnet +# password: palnet1234 + +netty: + task: + controlinfoTime: 10000 + socket: + port: 8082 + thread: + boss: 1 + worker: 1 + websocket: + host: pav.palntour.com + port: 8081 + +server: + port: 8182 + +#message: +# app: +# queue-name: app.drone.queue +# exchange-name: app.drone.exchange +# routing-key: app.drone.routing.# +# websocket: +# queue-name: websocket.drone.queue +# exchange-name: websocket.drone.exchange +# routing-key: websocket.drone.routing.# + +logging: + pattern: + console: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' + file: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' + file: + name: /data/logs/data.log + level: + com.palnet: info + +app: + host: http://211.253.38.218:8080 +web-socket: + host: http://211.253.38.218:8081 + + +#management: +# endpoints: +# web: +# base-path: /management +# path-mapping: +# health: health_check +# exposure: +# include: health, info + +--- + +spring: + config: + activate: + on-profile: prod2 +# rabbitmq: +# host: 211.253.38.218 +# port: 5672 +# username: palnet +# password: palnet1234 + +netty: + task: + controlinfoTime: 10000 + socket: + port: 8082 + thread: + boss: 1 + worker: 1 + websocket: + host: pav.palntour.com + port: 8081 + +server: + port: 8182 + +#message: +# app: +# queue-name: app.drone.queue +# exchange-name: app.drone.exchange +# routing-key: app.drone.routing.# +# websocket: +# queue-name: websocket.drone.queue +# exchange-name: websocket.drone.exchange +# routing-key: websocket.drone.routing.# + +logging: + pattern: + console: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' + file: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' + file: + name: /data/logs/data.log + level: + com.palnet: info + +app: + host: http://211.253.38.218:8080 +web-socket: + host: http://211.253.38.218:8081 + + +#management: +# endpoints: +# web: +# base-path: /management +# path-mapping: +# health: health_check +# exposure: +# include: health, info \ No newline at end of file diff --git a/pav-websocket/build.gradle b/pav-websocket/build.gradle new file mode 100644 index 00000000..b3d13f64 --- /dev/null +++ b/pav-websocket/build.gradle @@ -0,0 +1,30 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '2.5.1' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' +} + +group = 'com.palnet' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '11' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'io.netty:netty-all:4.1.63.Final' + + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/pav-websocket/settings.gradle b/pav-websocket/settings.gradle new file mode 100644 index 00000000..869d5710 --- /dev/null +++ b/pav-websocket/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'pav-websocket' diff --git a/pav-websocket/src/main/java/com/palnet/PavWebsocketApplication.java b/pav-websocket/src/main/java/com/palnet/PavWebsocketApplication.java new file mode 100644 index 00000000..960d8cd1 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/PavWebsocketApplication.java @@ -0,0 +1,16 @@ +package com.palnet; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +public class PavWebsocketApplication { + + public static void main(String[] args) { + SpringApplication.run(PavWebsocketApplication.class, args); + } + + +} diff --git a/pav-websocket/src/main/java/com/palnet/comn/model/CtrCntrlModel.java b/pav-websocket/src/main/java/com/palnet/comn/model/CtrCntrlModel.java new file mode 100644 index 00000000..392b1657 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/comn/model/CtrCntrlModel.java @@ -0,0 +1,131 @@ +package com.palnet.comn.model; + +import com.palnet.comn.utils.DateUtils; +import io.netty.util.internal.StringUtil; +import lombok.Data; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +@Data +public class CtrCntrlModel implements Comparable{ + + private String messageTypeCd; + + private String controlId; + + private String trmnlId; + + private String objectTypeCd; + + private String objectId; + + private Double lat; + + private Double lng; + + private String elevType; + + private Double elev; + + private String speedType; + + private Double speed; + + private Double betteryLevel; + + private Double betteryVoltage; + + private String takeOffPositon; + + private String dronStatus; + + private Double heading; + + private String terminalRcvDt; + + private String serverRcvDt; + + private String controlStartDt; + + private Double moveDistance; + + private String moveDistanceType; + + // 환경센서 필드 + private Double sensorCo; + private Double sensorSo2; + private Double sensorNo2; + private Double sensorO3; + private Double sensorDust; + + private List> lastHistory; + + // 비정상 상황 식별 코드 (비정상: true) + private boolean controlWarnCd; + // 비정상 상황 알림 표출 코드 (알림: true, 미알림: false) + private boolean controlWarnNotyCd; + // 비정상 상황 알림 중복 체크 + private Integer controlCacheCount; + + @Override + public int compareTo(CtrCntrlModel o) { + + if(!StringUtil.isNullOrEmpty(o.getControlStartDt()) && !StringUtil.isNullOrEmpty(controlStartDt)) { + long targetStartDt = Long.parseLong(o.getControlStartDt()); + long startDt = Long.parseLong(controlStartDt); + + if(startDt == targetStartDt) { + return 0; + }else if(startDt > targetStartDt) { + return 1; + }else if(startDt < targetStartDt) { + return -1; + } + } + + return 0; + + } + + public static void main(String [] args) { + List list = new ArrayList(); + + try { + for(int i = 0 ; i < 5 ; i++) { + Thread.sleep(1000); + System.out.println(">>>" + DateUtils.getCurrentTime()); + CtrCntrlModel model = new CtrCntrlModel(); + model.setControlStartDt(DateUtils.getCurrentTime()); + list.add(model); + } + + list.sort(Comparator.naturalOrder()); + + System.out.println("오름차순 정렬"); + for(CtrCntrlModel data :list) { + + System.out.println(data.getControlStartDt()); + } + + + list.sort(Comparator.reverseOrder()); + System.out.println("내림차순 정렬"); + for(CtrCntrlModel data :list) { + + System.out.println(data.getControlStartDt()); + } + }catch(Exception e) { + e.printStackTrace(); + } + + + + + } + + + +} diff --git a/pav-websocket/src/main/java/com/palnet/comn/model/CtrHistoryShareContext.java b/pav-websocket/src/main/java/com/palnet/comn/model/CtrHistoryShareContext.java new file mode 100644 index 00000000..5fcc3bea --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/comn/model/CtrHistoryShareContext.java @@ -0,0 +1,39 @@ +package com.palnet.comn.model; + +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class CtrHistoryShareContext { + + /* + * GPS Data History ( Websocket <-> Client Data Share ) + * key : 식별 장치 번호 + * Value : History Object + * + * */ + + private final Map maps; + + public CtrHistoryShareContext() { + this.maps = new ConcurrentHashMap<>(); + } + + public void putHistory(String key, CtrCntrlModel value) { + this.maps.put(key, value); + } + + public CtrCntrlModel getHistory(String key) { + return this.maps.get(key); + } + + public void removeHistory(String key) { + this.maps.remove(key); + } + + public Map getAllHistory() { + return this.maps; + } +} diff --git a/pav-websocket/src/main/java/com/palnet/comn/model/GPDatabaseModel.java b/pav-websocket/src/main/java/com/palnet/comn/model/GPDatabaseModel.java new file mode 100644 index 00000000..4a21891c --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/comn/model/GPDatabaseModel.java @@ -0,0 +1,68 @@ +package com.palnet.comn.model; + +import lombok.Data; + +@Data +public class GPDatabaseModel { + + private String typeCd; // 01 : 최초 들어온 데이터 , 99 : 종료 시킬 데이터 + + private String messageType; + + private String terminalId; + + private Double moveDistance = 0.0; + + private String moveDistanceType; + + private String prodNumber; + + private String controlId; + + private String objectType; + + private String objectId; + + private Double lat = 0.0; + + private Double lng = 0.0; + + private String elevType; + + private Double elev = 0.0; + + private String speedType; + + private Double speed = 0.0; + + private Double betteryLevel = 0.0; + + private Double betteryVoltage = 0.0; + + private String dronStatus; + + private Double heading = 0.0; + + private String terminalRcvDt; + + private String serverRcvDt; + + private String controlStartDt; + + private String controlEndDt; + + private String areaTrnsYn; + + private String endTypeCd; // 01: 일정시간 위치 정보가 들어오지 않는 경우 , 02 : 데이터 베이스에 종료 시점이 명시 되지 않은 경우 + + // 환경센서 필드 + private Double sensorCo = 0.0; + private Double sensorSo2 = 0.0; + private Double sensorNo2 = 0.0; + private Double sensorO3 = 0.0; + private Double sensorDust = 0.0; + + // 비정상 상황 식별 코드 + private boolean controlWarnCd; // 정상: false, 비정상: true + +} diff --git a/pav-websocket/src/main/java/com/palnet/comn/model/GPHistoryModel.java b/pav-websocket/src/main/java/com/palnet/comn/model/GPHistoryModel.java new file mode 100644 index 00000000..7262a455 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/comn/model/GPHistoryModel.java @@ -0,0 +1,15 @@ +package com.palnet.comn.model; + +import lombok.Data; + +@Data +public class GPHistoryModel { + + private String objectId; + + private Double lat = 0.0; + + private Double lng = 0.0; + + +} diff --git a/pav-websocket/src/main/java/com/palnet/comn/model/GPModel.java b/pav-websocket/src/main/java/com/palnet/comn/model/GPModel.java new file mode 100644 index 00000000..91cd6c92 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/comn/model/GPModel.java @@ -0,0 +1,73 @@ +package com.palnet.comn.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class GPModel { + + private String typeCd; // 01 : 최초 들어온 데이터 , 99 : 종료 시킬 데이터 + + private String messageType; + + private String terminalId; + + private Double moveDistance = 0.0; + + private String moveDistanceType; + + private String controlId; // 처음 위치 데이터가 들어 왔을때 생성 함 + + private String objectType; + + private String objectId; + + private Double lat = 0.0; + + private Double lng = 0.0; + + private String elevType; + + private Double elev = 0.0; + + private String speedType; + + private Double speed = 0.0; + + private Double betteryLevel = 0.0; + + private Double betteryVoltage = 0.0; + + private String dronStatus; + + private Double heading = 0.0; + + private String terminalRcvDt; + + private String serverRcvDt; + + private String controlStartDt; + + private String controlEndDt; + + private String areaTrnsYn; + + // 환경센서 필드 + private Double sensorCo = 0.0; + private Double sensorSo2 = 0.0; + private Double sensorNo2 = 0.0; + private Double sensorO3 = 0.0; + private Double sensorDust = 0.0; + + //최근 5건만 저장 + private List recentPositionHistory; + + // 전체 히스토리 저장 + private List postionHistory; + + // 비정상 상황 식별 코드 + private boolean controlWarnCd = true; + + +} diff --git a/pav-websocket/src/main/java/com/palnet/comn/utils/ContextUtils.java b/pav-websocket/src/main/java/com/palnet/comn/utils/ContextUtils.java new file mode 100644 index 00000000..34ee00bc --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/comn/utils/ContextUtils.java @@ -0,0 +1,25 @@ +package com.palnet.comn.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class ContextUtils implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext ctx) throws BeansException { + applicationContext = ctx; + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static Object getBean(String beanName) { + return getApplicationContext().getBean(beanName); + } +} diff --git a/pav-websocket/src/main/java/com/palnet/comn/utils/DateUtils.java b/pav-websocket/src/main/java/com/palnet/comn/utils/DateUtils.java new file mode 100644 index 00000000..3a1f867a --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/comn/utils/DateUtils.java @@ -0,0 +1,153 @@ +package com.palnet.comn.utils; + +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.util.Date; + +public class DateUtils { + + public static String getCurrentTime(){ + return new SimpleDateFormat("yyyyMMddHHmmss").format(System.currentTimeMillis()); + } + + public static String stringToFormat(String str) { + Date date = stringToDatetime(str); + + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date); + } + + + public static Date stringToDatetime(String date) { + + SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + Date result = null; + try { + if(date.length() == 14) { + result = transFormat.parse(date); + } + }catch(Exception e) { + e.printStackTrace(); + } + + return result; + } + + public static Date stringToDate(String date) { + SimpleDateFormat transFormat = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat transFormat2 = new SimpleDateFormat("yyyyMMdd"); + Date result = null; + try { + if(date.length() == 10) { + result = transFormat.parse(date); + }else if(date.length() == 8) { + result = transFormat2.parse(date); + } + }catch(Exception e) { + e.printStackTrace(); + } + + return result; + } + + public static LocalDateTime stringToLocalDateTime(String date) { + + DateTimeFormatter transFormat = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + LocalDateTime localDateTime = LocalDateTime.parse(date , transFormat); + + return localDateTime; + + } + + + + public static LocalDateTime stringToLocalDate(String date) { + DateTimeFormatter transFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + DateTimeFormatter DATEFORMATTER = new DateTimeFormatterBuilder().append(transFormat) + .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) + .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) + .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) + .toFormatter(); + + + LocalDateTime localDateTime = LocalDateTime.parse(date , DATEFORMATTER); + + return localDateTime; + } + + + public static Date nowDate() { + return new Date(System.currentTimeMillis()); + } + + public static long diffSecond(Date firstDate , Date secondDate) { + + long diffDate = secondDate.getTime() - firstDate.getTime(); + long diffTime = diffDate / (1000); + + return diffTime; + + } + + public static long diffMinute(Date firstDate , Date secondDate) { + + long diffDate = secondDate.getTime() - firstDate.getTime(); + long diffTime = diffDate / (1000 * 60); + + return diffTime; + + } + + + +// public static void main(String[] args) { +// +// Date firstDate = stringToDate("20210630142014"); +// +// Date secondDate = stringToDate("20210630142914"); +// +// LocalDateTime dateTime = stringToLocalDate("2021-07-20"); +// +// System.out.println(">>>>" + dateTime); +// +// +// System.out.println("두 날짜의 차이 분: "+diffMinute(firstDate , secondDate)); +// +// System.out.println(">>>" + stringToFormat("20210630142014")); +// +// +// +// +// +//// List> list = new ArrayList>(); +//// +//// +//// for( double i= 0 ; i < 1000 ; i ++) { +//// Map position = new HashMap(); +//// position.put("lat", 11111.0); +//// position.put("lng", 11111.0); +//// position.put("date", i); +//// list.add(position); +//// } +//// +//// int limitSize = 1000; +//// if(list.size() < 1000) { +//// limitSize = list.size(); +//// } +//// +//// List> lastThreeThings = list.subList(list.size() - limitSize, list.size()); +//// +//// //뒤집기 +//// Collections.reverse(lastThreeThings); +//// +//// for(Map data : lastThreeThings) { +//// +//// +//// System.out.println(data); +//// } +// +// } +} diff --git a/pav-websocket/src/main/java/com/palnet/comn/utils/JsonUtils.java b/pav-websocket/src/main/java/com/palnet/comn/utils/JsonUtils.java new file mode 100644 index 00000000..dbcb8d70 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/comn/utils/JsonUtils.java @@ -0,0 +1,80 @@ +package com.palnet.comn.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +public class JsonUtils { + + public static ObjectMapper getObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper; + } + + public static String toJson(Object object) { + String json = null; + + try { + json = getObjectMapper().writeValueAsString(object); + } catch (JsonProcessingException e) { + log.error("", e); + } + + return json; + } + + public static T fromJson(String val, Class clazz){ + T object = null; + + try { + object = getObjectMapper().readValue(val, clazz); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T fromJson(byte[] bytes, Class clazz){ + T object = null; + + try { + object = getObjectMapper().readValue(bytes, clazz); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T fromJson(String val, TypeReference type){ + T object = null; + + try { + object = getObjectMapper().readValue(val, type); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + + public static T bytesToJson(byte[] bytes, TypeReference type){ + T object = null; + + try { + object = getObjectMapper().readValue(bytes, type); + } catch (IOException e) { + log.error("", e); + } + + return object; + } + +} diff --git a/pav-websocket/src/main/java/com/palnet/process/scheduler/GpHistoryScheduler.java b/pav-websocket/src/main/java/com/palnet/process/scheduler/GpHistoryScheduler.java new file mode 100644 index 00000000..b7837b1b --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/process/scheduler/GpHistoryScheduler.java @@ -0,0 +1,43 @@ +package com.palnet.process.scheduler; + +import com.palnet.comn.model.CtrCntrlModel; +import com.palnet.comn.model.CtrHistoryShareContext; +import com.palnet.comn.utils.DateUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.Map; +import java.util.Objects; + +@Slf4j +@Component +public class GpHistoryScheduler { + + private final int timeLimit = 60; // -- 화면 노출시간 1분 + private final CtrHistoryShareContext gpHistoryShareContext; + + public GpHistoryScheduler(CtrHistoryShareContext gpHistoryShareContext) { + this.gpHistoryShareContext = gpHistoryShareContext; + } + + @Scheduled(fixedDelay = 1000 * 10) + public void removeHistory() { + log.info(">>> removeHistory :: "); + Map allHistory = gpHistoryShareContext.getAllHistory(); + + // Key 의 존재하는 데이터는 마지막 서버수신 History Data + if(Objects.nonNull(allHistory)) { + allHistory.forEach((k, v) -> { + Date serverRcvDt = DateUtils.stringToDatetime(v.getServerRcvDt()); + long diffSecond = DateUtils.diffSecond(serverRcvDt, new Date()); + + if(diffSecond > timeLimit) { + gpHistoryShareContext.removeHistory(k); + } + }); + } + } + +} diff --git a/pav-websocket/src/main/java/com/palnet/server/WebServer.java b/pav-websocket/src/main/java/com/palnet/server/WebServer.java new file mode 100644 index 00000000..9789526e --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/WebServer.java @@ -0,0 +1,107 @@ +package com.palnet.server; + +import com.palnet.server.initializer.WebInitializer; +import com.palnet.server.task.ctr.CtrCntrlTask; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Component +@RequiredArgsConstructor +public class WebServer { + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Value("${netty.websocket.port}") + private int port; + + @Value("${netty.task.controlinfoTime}") + private int controlinfoTime; + + private final CtrCntrlTask ctrCntrlTask; + + private EventLoopGroup bossGroup ; + private EventLoopGroup workerGroup ; + private ServerBootstrap b = new ServerBootstrap(); + + @PostConstruct + public void postConstruct(){ + start(); + } + + @PreDestroy + public void preDestroy(){ + stop(); + } + + public void start(){ + try { + bossGroup = new NioEventLoopGroup(); + workerGroup =new NioEventLoopGroup(); + + b.group(bossGroup , workerGroup) // bossGroup과 workerGroup은 NioEventLoopGroup의 인스턴스입니다.이 때 스레드 개수를 설정할 수 있음 각각 1, Runtime.getRuntime().availableProcessors() * 2로 설정했습니다. + .channel(NioServerSocketChannel.class) +// .handler(new LoggingHandler(LogLevel.valueOf(logBootstrap))) +// .handler(bootstrapHandler) // 채널이 활성화되면 소켓 서버와 소켓 클라이언트를 구동하게 되는 핸들러를 등록합니다. + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) + .option(ChannelOption.SO_BACKLOG, 1000) // 동시에 수용할 수 있는 소켓 연결 요청 수입니다. + .childOption(ChannelOption.TCP_NODELAY, true) // 반응속도를 높이기 위해 Nagle 알고리즘을 비활성화 합니다 + .childOption(ChannelOption.SO_LINGER, 0) // 소켓이 close될 때 신뢰성있는 종료를 위해 4way-handshake가 발생하고 이때 TIME_WAIT로 리소스가 낭비됩니다. 이를 방지하기 위해 0으로 설정합니다. + .childOption(ChannelOption.SO_KEEPALIVE, true) // Keep-alive를 켭니다. + .childOption(ChannelOption.SO_REUSEADDR, true) // SO_LINGER설정이 있으면 안해도 되나 혹시나병(!)으로 TIME_WAIT걸린 포트를 재사용할 수 있도록 설정합니다. + .childHandler(new WebInitializer()); + + connection(); + taskProcess(); + + logger.warn("====== [WEBSOCKET SERVER] Start ====== "); + } catch (Exception e) { + logger.warn("====== [WEBSOCKET SERVER] Fail ====== "); + logger.error(e.getMessage()); + } + } + + private void connection() { + //서버는 Listen상태로 기다려야하는데, 톰캣이 Timeout이 발생함 + //이를 방지하기 위해 Thread로 처리한다. + new Thread(new Runnable() { + @Override + public void run() { + try { + ChannelFuture future = b.bind(port).sync(); + future.channel().closeFuture().sync(); + + } catch (InterruptedException e) { + logger.error("InterruptedException", e); + } + } + }).start(); + } + + private void taskProcess() { + ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); + service.scheduleAtFixedRate(ctrCntrlTask,0,controlinfoTime,TimeUnit.MILLISECONDS); + } + + + public void stop(){ + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + logger.warn("====== [WEBSOCKET SERVER] STOP ====== "); + } +} diff --git a/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoad.java b/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoad.java new file mode 100644 index 00000000..9d0808ab --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoad.java @@ -0,0 +1,16 @@ +package com.palnet.server.codec; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class WebPayLoad implements Serializable { + + private static final long serialVersionUID = 1L; + + private String authKey; + private String teminalId; + private String command; + private String body; +} diff --git a/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadDecoder.java b/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadDecoder.java new file mode 100644 index 00000000..1be7b11b --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadDecoder.java @@ -0,0 +1,37 @@ +package com.palnet.server.codec; + +import com.palnet.comn.model.GPModel; +import com.palnet.comn.utils.JsonUtils; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +@Sharable +@Slf4j +public class WebPayLoadDecoder extends MessageToMessageDecoder { + + @Override + protected void decode(ChannelHandlerContext ctx, Object msg, List out) { + GPModel payLoad; + + try { +// payLoad = JsonUtils.fromJson((String) msg, GPModel.class); +// +// if(payLoad != null) { +// out.add(payLoad); +// } + + } catch (Exception e) { + log.error(e.getMessage()); + + } + + } + + +} diff --git a/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadEncorder.java b/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadEncorder.java new file mode 100644 index 00000000..c584e2f5 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadEncorder.java @@ -0,0 +1,31 @@ +package com.palnet.server.codec; + +import com.palnet.comn.utils.JsonUtils; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +@Sharable +@Slf4j +public class WebPayLoadEncorder extends MessageToMessageEncoder { + + @Override + protected void encode(ChannelHandlerContext ctx, WebPayLoadResponse msg, List out) { + + try { +// out.add(JsonUtils.toJson(msg)); + } catch (Exception e) { + log.error(e.getMessage()); + } + + } + + + + +} diff --git a/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadResponse.java b/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadResponse.java new file mode 100644 index 00000000..ed34e6e7 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/codec/WebPayLoadResponse.java @@ -0,0 +1,15 @@ +package com.palnet.server.codec; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class WebPayLoadResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private String rspCode; + + private String rspMessage; +} diff --git a/pav-websocket/src/main/java/com/palnet/server/collection/ChannelCollection.java b/pav-websocket/src/main/java/com/palnet/server/collection/ChannelCollection.java new file mode 100644 index 00000000..65246901 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/collection/ChannelCollection.java @@ -0,0 +1,26 @@ +package com.palnet.server.collection; + +import io.netty.channel.Channel; +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + + +public class ChannelCollection { + + private static final long serialVersionUID = 1L; + + //접속 되어있는 모든 Channel + private static final ChannelGroup allChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + + + public void setAllChannels(Channel ch) { + allChannels.add(ch); + } + + public ChannelGroup getAllChannels() { + return allChannels; + } + + +} diff --git a/pav-websocket/src/main/java/com/palnet/server/controller/SocketReceiverController.java b/pav-websocket/src/main/java/com/palnet/server/controller/SocketReceiverController.java new file mode 100644 index 00000000..befdae3a --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/controller/SocketReceiverController.java @@ -0,0 +1,67 @@ +package com.palnet.server.controller; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.palnet.comn.model.CtrCntrlModel; +import com.palnet.comn.model.CtrHistoryShareContext; +import com.palnet.comn.model.GPModel; +import com.palnet.server.task.ctr.service.CtrCntrlTaskService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.concurrent.Callable; + +/** + * packageName : com.palnet.server.controller + * fileName : WebSocketReceiverController + * author : dhji + * date : 2023-08-28(028) + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2023-08-28(028) dhji 최초 생성 + */ +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/ws") +public class SocketReceiverController { + + private final CtrCntrlTaskService service; + private final CtrHistoryShareContext historyShareContext; + private final ObjectMapper objectMapper; + + @PostMapping("/receiver") + public ResponseEntity receiver(@RequestBody GPModel model) { + log.info("websocket message : {}", model); +// GPModel model = null; +// try { +// model = objectMapper.readValue(message, GPModel.class); +// } catch (JsonProcessingException e) { +// log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); +// throw new RuntimeException(e); +// } + + CtrCntrlModel history = service.modelConvert(model); + + // DRON의 대한 식별정보만 이력 관리 + historyShareContext.putHistory(model.getObjectId(), history); + + return ResponseEntity.ok().build(); + } + + @PostMapping("/receiver/async") + public Callable asyncReceiver(@RequestBody GPModel model) { + return () -> { + log.info("websocket message : {}", model); + CtrCntrlModel history = service.modelConvert(model); + // DRON의 대한 식별정보만 이력 관리 + historyShareContext.putHistory(model.getObjectId(), history); + + return "OK"; + }; + } +} diff --git a/pav-websocket/src/main/java/com/palnet/server/handler/WebHandler.java b/pav-websocket/src/main/java/com/palnet/server/handler/WebHandler.java new file mode 100644 index 00000000..3106d486 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/handler/WebHandler.java @@ -0,0 +1,123 @@ +package com.palnet.server.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.palnet.comn.model.CtrHistoryShareContext; +import com.palnet.comn.utils.ContextUtils; +import com.palnet.comn.utils.JsonUtils; +import com.palnet.server.collection.ChannelCollection; +import com.palnet.server.task.ctr.service.CtrCntrlTaskService; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +@Slf4j +public class WebHandler extends SimpleChannelInboundHandler { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + + private CtrCntrlTaskService taskService; + private CtrHistoryShareContext context; + private ObjectMapper objectMapper; + + public WebHandler() { + this.taskService = (CtrCntrlTaskService) ContextUtils.getBean("ctrCntrlTaskService"); + this.context = (CtrHistoryShareContext) ContextUtils.getBean("ctrHistoryShareContext"); + this.objectMapper = JsonUtils.getObjectMapper(); + } + + ChannelCollection cc = new ChannelCollection(); + + @Override + protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception { + + logger.info("==================== [ channelRead0 ] ==================== "); + + logger.info("Channel Size [" + cc.getAllChannels().size() + "]"); + + cc.getAllChannels().stream().forEach(c -> { + logger.info(":" + c); + c.writeAndFlush(new TextWebSocketFrame("test")); +// command.execute(c, data, result); + }); + } + +// @Override +// public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { +// String json = ((ByteBuf) msg).toString(Charset.forName("UTF8")); +// GPModel model = objectMapper.readValue(json, GPModel.class); +// +// CtrCntrlModel history = taskService.modelConvert(model); +// context.putHistory(model.getObjectId(), history); +// +// log.info("message from received : {}", msg); +// } +// +// @Override +// public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { +// super.exceptionCaught(ctx, cause); +// } + + // @Override +// protected void channelRead0(ChannelHandlerContext ctx, GPModel payload) { +// WebPayLoadResponse response = new WebPayLoadResponse(); +// +// logger.info("==================== [ channelRead0 ] ==================== "); +// logger.info("AUTH KEY : {}", payload.getAuthKey()); +// +// if(payload.getObjectId().isEmpty()) { +// logger.info("====== auth key is empty ======"); +// +// response.setRspCode("-2000"); +// response.setRspMessage("auth key is empty !"); +// } else { +// log.info("WEBSOCKET BODY : {}", payload); +// String json = payload.getBody(); +// GPModel model = objectMapper.readValue(json, GPModel.class); +// +// CtrCntrlModel history = taskService.modelConvert(model); +// context.putHistory(model.getObjectId(), history); +// } +// +// cc.getAllChannels().stream().forEach(c -> { +// logger.info(":" + c); +// c.writeAndFlush(new TextWebSocketFrame("test")); +//// command.execute(c, data, result); +// }); +// +// +// +// } +// + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + cc.setAllChannels(ctx.channel()); + logger.info("==================== [ channelActive ] ==================== "); + logger.info(">>> channelActive : cc : {}", cc.getAllChannels().size()); + logger.info(">>> channelActive : cc : {}", cc.getAllChannels()); + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + logger.info(">>> channelInactive : cc : {}", cc.getAllChannels().size()); + logger.info(">>> channelInactive : cc : {}", cc.getAllChannels()); + logger.info("==================== [ channelInactive ] ==================== "); + } + + + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + //2 Triggered when a connection is established with the selector of a thread in the worker thread group (channel is registered to EventLoop) + logger.info("==================== [ channelRegistered ] ==================== "); + } + + +} diff --git a/pav-websocket/src/main/java/com/palnet/server/initializer/WebInitializer.java b/pav-websocket/src/main/java/com/palnet/server/initializer/WebInitializer.java new file mode 100644 index 00000000..2167dafd --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/initializer/WebInitializer.java @@ -0,0 +1,33 @@ +package com.palnet.server.initializer; + +import com.palnet.server.codec.WebPayLoadDecoder; +import com.palnet.server.codec.WebPayLoadEncorder; +import com.palnet.server.handler.WebHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; +import io.netty.handler.codec.json.JsonObjectDecoder; +import io.netty.handler.timeout.IdleStateHandler; +import org.springframework.stereotype.Component; + + +public class WebInitializer extends ChannelInitializer{ + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline + .addLast(new HttpServerCodec()) + .addLast(new HttpObjectAggregator(65536)) + .addLast(new WebSocketServerCompressionHandler()) + .addLast(new WebSocketServerProtocolHandler("/ws", null, true)) + .addLast(new IdleStateHandler(0, 0, 180)) // [5] + .addLast(new WebPayLoadDecoder() , new WebPayLoadEncorder()) + .addLast(new WebHandler()); + } + +} diff --git a/pav-websocket/src/main/java/com/palnet/server/task/ctr/CtrCntrlTask.java b/pav-websocket/src/main/java/com/palnet/server/task/ctr/CtrCntrlTask.java new file mode 100644 index 00000000..24502bd5 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/task/ctr/CtrCntrlTask.java @@ -0,0 +1,38 @@ +package com.palnet.server.task.ctr; + +import com.palnet.comn.utils.JsonUtils; +import com.palnet.server.collection.ChannelCollection; +import com.palnet.server.task.ctr.service.CtrCntrlTaskService; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; + +@Component +@RequiredArgsConstructor +public class CtrCntrlTask implements Runnable{ + + private ChannelCollection cc = new ChannelCollection(); + + private Logger logger = LoggerFactory.getLogger(getClass()); + private final CtrCntrlTaskService service; + + + @Override + public void run() { + try { +// logger.info(">>> run : {}", cc.getAllChannels()); + cc.getAllChannels().stream().forEach(c -> { // 접속되어 있는 모든 사용자에게 전달 처리 + c.writeAndFlush(new TextWebSocketFrame(JsonUtils.toJson(service.getList()))); + }); + }catch(Exception e) { + e.printStackTrace(); + } + } + + +} diff --git a/pav-websocket/src/main/java/com/palnet/server/task/ctr/service/CtrCntrlTaskService.java b/pav-websocket/src/main/java/com/palnet/server/task/ctr/service/CtrCntrlTaskService.java new file mode 100644 index 00000000..2c284683 --- /dev/null +++ b/pav-websocket/src/main/java/com/palnet/server/task/ctr/service/CtrCntrlTaskService.java @@ -0,0 +1,121 @@ +package com.palnet.server.task.ctr.service; + + +import com.palnet.comn.model.CtrCntrlModel; +import com.palnet.comn.model.CtrHistoryShareContext; + +import com.palnet.comn.model.GPModel; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Map; +import java.util.Objects; + +@Slf4j +@Service +@RequiredArgsConstructor +public class CtrCntrlTaskService { + + private final CtrHistoryShareContext historyShareContext; + + /** + * + */ + public CtrCntrlModel modelConvert(final GPModel dataInfo) { + CtrCntrlModel model = new CtrCntrlModel(); + CtrCntrlModel prevModel = historyShareContext.getHistory(dataInfo.getObjectId()); + + model.setObjectId(dataInfo.getObjectId()); + model.setControlId(dataInfo.getControlId()); + model.setControlStartDt(dataInfo.getControlStartDt()); + model.setObjectTypeCd(dataInfo.getObjectType()); + model.setLat(dataInfo.getLat()); + model.setLng(dataInfo.getLng()); + model.setElevType(dataInfo.getElevType()); + model.setElev(dataInfo.getElev()); + model.setSpeedType(dataInfo.getSpeedType()); + model.setSpeed(dataInfo.getSpeed()); + model.setBetteryLevel(dataInfo.getBetteryLevel()); + model.setBetteryVoltage(dataInfo.getBetteryVoltage()); + model.setDronStatus(dataInfo.getDronStatus()); + model.setHeading(dataInfo.getHeading()); + model.setMoveDistance(dataInfo.getMoveDistance()); + model.setMoveDistanceType(dataInfo.getMoveDistanceType()); + + model.setServerRcvDt(dataInfo.getServerRcvDt()); + + // 환경 데이터 필드 추가 + model.setSensorCo(dataInfo.getSensorCo()); + model.setSensorSo2(dataInfo.getSensorSo2()); + model.setSensorNo2(dataInfo.getSensorNo2()); + model.setSensorO3(dataInfo.getSensorO3()); + model.setSensorDust(dataInfo.getSensorDust()); + + // 비정상 상황 식별코드 추가 + model.setControlWarnCd(dataInfo.isControlWarnCd()); + + if(prevModel == null) { + if(model.isControlWarnCd()) { + model.setControlWarnNotyCd(true); // 최초 비정상 발생 + } + } else { + if(prevModel.isControlWarnCd() && model.isControlWarnCd()) { + model.setControlWarnNotyCd(false); // 비정상 -> 비정상 + } + if(prevModel.isControlWarnCd() && !model.isControlWarnCd()) { + model.setControlWarnNotyCd(false); // 비정상 -> 정상 + } + if(!prevModel.isControlWarnCd() && model.isControlWarnCd()) { + model.setControlWarnNotyCd(true); // 정상 -> 비정상상 + } + } + + model.setControlCacheCount(1); + + return model; + } + + + /** + * Websocket 을 통해 전달될 위치 정보를 관리 + * @return + */ + public ArrayList getList() { + ArrayList list = new ArrayList<>(); + + Map allHistory = historyShareContext.getAllHistory(); + log.info(">>> getList :: {}", allHistory); + + if(Objects.nonNull(allHistory)) { + allHistory.forEach((k, v) -> { +// int cacheCount = v.getControlCacheCount(); +// +// // 데이터가 수신 되지 않고 이전 데이터를 표출하고 있는 경우 +// if(cacheCount == 1) { +// if(v.isControlWarnCd() && v.isControlWarnNotyCd()) { +// v.setControlCacheCount(2); +// } +// } +// +// // 비정상 상황 판별하여 알림 표출 X +// if(cacheCount == 2) { +// if(v.isControlWarnCd() && v.isControlWarnNotyCd()) { +// v.setControlWarnNotyCd(false); +// } +// } + + list.add(v); + }); + } + + //=== 정렬 처리 == + //기준 : 관제 시작일이 가장 느린순으로 상단에 올린다. + list.sort(Comparator.reverseOrder()); + + return list; + } +} diff --git a/pav-websocket/src/main/resources/application.yml b/pav-websocket/src/main/resources/application.yml new file mode 100644 index 00000000..208b9b61 --- /dev/null +++ b/pav-websocket/src/main/resources/application.yml @@ -0,0 +1,118 @@ +spring: + config: + activate: + on-profile: local +# rabbitmq: +# host: 192.168.0.26 +# port: 5672 +# username: palnet +# password: palnet!234 +# virtual-host: / + +server: + port: 8181 + +netty: + task: + controlinfoTime: 2000 + websocket: + port: 8081 + +#message: +# app: +# queue-name: app.drone.queue +# exchange-name: app.drone.exchange +# routing-key: app.drone.routing.# +# websocket: +# queue-name: websocket.drone.queue +# exchange-name: websocket.drone.exchange +# routing-key: websocket.drone.routing.# + +app: + host: http://127.0.0.1:8080/ + +--- + +spring: + config: + activate: + on-profile: prod +# rabbitmq: +# host: 211.253.38.218 +# port: 5672 +# username: palnet +# password: palnet1234 + +server: + port: 8181 + +netty: + task: + controlinfoTime: 2000 + websocket: + port: 8081 + +#message: +# app: +# queue-name: app.drone.queue +# exchange-name: app.drone.exchange +# routing-key: app.drone.routing.# +# websocket: +# queue-name: websocket.drone.queue +# exchange-name: websocket.drone.exchange +# routing-key: websocket.drone.routing.# + +logging: + pattern: + console: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' + file: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' + file: + name: /data/logs/data.log + level: + com.palnet: debug + +app: + host: http://211.253.38.218:8080/ + +--- + +spring: + config: + activate: + on-profile: prod2 +# rabbitmq: +# host: 211.253.38.218 +# port: 5672 +# username: palnet +# password: palnet1234 + +server: + port: 8181 + +netty: + task: + controlinfoTime: 2000 + websocket: + port: 8081 + +#message: +# app: +# queue-name: app.drone.queue +# exchange-name: app.drone.exchange +# routing-key: app.drone.routing.# +# websocket: +# queue-name: websocket.drone.queue +# exchange-name: websocket.drone.exchange +# routing-key: websocket.drone.routing.# + +logging: + pattern: + console: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' + file: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' + file: + name: /data/logs/data.log + level: + com.palnet: debug + +app: + host: http://211.253.38.218:8080/ \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..02e11aa7 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,5 @@ +rootProject.name = 'pav-be-kac' + +include 'pav-socket' +include 'pav-websocket' +include 'pav-server' \ No newline at end of file