From 5a0971d9421310da57193f459cac4d8fd1c1da5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dhji=28=EC=A7=80=EB=8C=80=ED=95=9C=29?= Date: Mon, 27 Nov 2023 14:48:59 +0900 Subject: [PATCH] =?UTF-8?q?TS=20qr=20=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pav-server/build.gradle | 4 +- .../laanc/controller/BasLaancController.java | 29 ++++- .../api/bas/laanc/model/BasLaancQrcodeRq.java | 15 +++ .../api/bas/laanc/model/BasLaancQrcodeRs.java | 15 +++ .../bas/laanc/service/BasLaancService.java | 120 ++++++++++++------ .../controller/ExternalLaancController.java | 34 +++++ .../biz/api/external/model/TsQrcodeRq.java | 28 ++++ .../biz/api/external/model/TsQrcodeRs.java | 30 +++++ .../biz/api/external/service/TsService.java | 35 +++++ .../com/palnet/biz/config/WebMvcConfig.java | 6 +- .../convert/CodeToFltPurposeBinding.java | 15 +++ .../src/main/resources/application.properties | 1 + pav-server/src/main/resources/application.yml | 11 ++ 13 files changed, 299 insertions(+), 44 deletions(-) create mode 100644 pav-server/src/main/java/com/palnet/biz/api/bas/laanc/model/BasLaancQrcodeRq.java create mode 100644 pav-server/src/main/java/com/palnet/biz/api/bas/laanc/model/BasLaancQrcodeRs.java create mode 100644 pav-server/src/main/java/com/palnet/biz/api/external/controller/ExternalLaancController.java create mode 100644 pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRq.java create mode 100644 pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRs.java create mode 100644 pav-server/src/main/java/com/palnet/biz/config/convert/CodeToFltPurposeBinding.java diff --git a/pav-server/build.gradle b/pav-server/build.gradle index 92faf42..b5c97ca 100644 --- a/pav-server/build.gradle +++ b/pav-server/build.gradle @@ -101,7 +101,9 @@ dependencies { implementation 'org.geotools:gt-geotiff:29.2' implementation 'org.geotools:gt-epsg-hsql:29.2' - + // QR Code + implementation 'com.google.zxing:core:3.5.2' + implementation 'com.google.zxing:javase:3.5.2' testCompileOnly 'org.projectlombok:lombok:1.18.28' testAnnotationProcessor 'org.projectlombok:lombok:1.18.28' diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/controller/BasLaancController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/controller/BasLaancController.java index 779b556..b1b94f5 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/controller/BasLaancController.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/controller/BasLaancController.java @@ -13,10 +13,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; 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 org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; @@ -168,4 +165,28 @@ public class BasLaancController { return ResponseEntity.ok().body(new SuccessResponse<>(rs)); } +// @GetMapping(value = "/ts/qr", produces = MediaType.IMAGE_JPEG_VALUE) + @GetMapping(value = "/ts/qr") + @ApiOperation(value = "TS QR 코드 생성") + @Tag(name = "LAANC", description = "LAANC 관련 API") + public ResponseEntity getQrCode(BasLaancQrcodeRq rq) { + BasLaancQrcodeRs rs = null; + try { + rs = basLaancService.createQrcode(rq); + } catch (CustomException e) { + Map resultMap = new HashMap<>(); + 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 new ResponseEntity<>(rs, HttpStatus.OK); + } + } diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/model/BasLaancQrcodeRq.java b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/model/BasLaancQrcodeRq.java new file mode 100644 index 0000000..330019b --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/model/BasLaancQrcodeRq.java @@ -0,0 +1,15 @@ +package com.palnet.biz.api.bas.laanc.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BasLaancQrcodeRq { +// private String fltPurpose; // 비행목적 + private String idntfNum; // 기체신고번호 +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/model/BasLaancQrcodeRs.java b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/model/BasLaancQrcodeRs.java new file mode 100644 index 0000000..acc191a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/model/BasLaancQrcodeRs.java @@ -0,0 +1,15 @@ +package com.palnet.biz.api.bas.laanc.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BasLaancQrcodeRs { + private byte[] qrcode; // qr코드 + private String confirmKey; // 인증번호 +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/service/BasLaancService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/service/BasLaancService.java index 3a642b7..f2338bc 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/service/BasLaancService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/service/BasLaancService.java @@ -1,50 +1,27 @@ package com.palnet.biz.api.bas.laanc.service; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import com.palnet.biz.api.bas.laanc.model.*; -import com.palnet.biz.api.comn.sunriseset.model.ComnSunrisesetCoordRq; -import com.palnet.biz.api.comn.sunriseset.model.ComnSunrisesetRs; -import com.palnet.biz.jpa.entity.type.FltMethod; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.Geometry; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - +import com.google.zxing.WriterException; import com.palnet.biz.api.acnt.cstmr.model.AnctCstmrModel; import com.palnet.biz.api.acnt.cstmr.model.AnctCstmrTermsModel; import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.bas.laanc.model.*; import com.palnet.biz.api.comn.file.model.LaancPdfModel; import com.palnet.biz.api.comn.file.service.ComnFileService; import com.palnet.biz.api.comn.sms.model.ComnSmsLaancAprovModel; import com.palnet.biz.api.comn.sms.service.ComnSmsService; +import com.palnet.biz.api.comn.sunriseset.model.ComnSunrisesetCoordRq; +import com.palnet.biz.api.comn.sunriseset.model.ComnSunrisesetRs; import com.palnet.biz.api.external.model.PilotValidRq; import com.palnet.biz.api.external.model.PilotValidRs; +import com.palnet.biz.api.external.model.TsQrcodeRq; import com.palnet.biz.api.external.service.TsService; -import com.palnet.biz.jpa.entity.ComFileBas; -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.entity.PtyGroupBas; -import com.palnet.biz.jpa.entity.PtyTermsAgreeTxn; +import com.palnet.biz.jpa.entity.*; import com.palnet.biz.jpa.entity.type.ArcrftWghtCd; +import com.palnet.biz.jpa.entity.type.FltMethod; +import com.palnet.biz.jpa.entity.type.FltPurpose; import com.palnet.biz.jpa.entity.type.FltType; import com.palnet.biz.jpa.repository.com.ComRiseSetQueryRepository; -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.*; import com.palnet.biz.jpa.repository.pty.PtyCstmrQueryRepository; import com.palnet.biz.jpa.repository.pty.PtyGroupBasRepository; import com.palnet.biz.jpa.repository.pty.PtyTermsAgreeTxnRepository; @@ -52,13 +29,27 @@ 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.AirspaceUtils; -import com.palnet.comn.utils.AreaUtils; -import com.palnet.comn.utils.HttpUtils; -import com.palnet.comn.utils.InstantUtils; - +import com.palnet.comn.utils.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; /** * packageName : com.palnet.biz.api.bas.laanc.service @@ -92,6 +83,12 @@ public class BasLaancService { private final AreaUtils areaUtils; private final ComRiseSetQueryRepository comRiseSetQueryRepository; + @Value("${app.host}") + private String APP_HOST; + + @Value("${external.ts.return.uri}") + private String TS_RETURN_URI; + // LAANC 검증 public BasLaancValidatedRs validationLaanc(BasLaancPlanRq rq) { @@ -612,4 +609,53 @@ public class BasLaancService { return rs; } + + // QR code 생성 + public BasLaancQrcodeRs createQrcode(BasLaancQrcodeRq rq) { + +// if(rq == null || rq.getFltPurpose() == null || rq.getIdntfNum() == null || rq.getIdntfNum().isEmpty()) { +// throw new CustomException(ErrorCode.NON_VALID_PARAMETER); +// } + + Integer cstmrSno = jwtTokenUtil.getCstmrSnoByToken(); + AnctCstmrModel cstmrInfo = ptyCstmrQueryRepository.findByCstmrSno(cstmrSno); + String userCi = cstmrInfo.getIpinCi(); + +// String fltPurposeCode = null; +// if (rq != null && rq.getFltPurpose() != null && !rq.getFltPurpose().isEmpty()) { +//// fltPurposeCode = Objects.requireNonNull(FltPurpose.fromCode(rq.getFltPurpose())).getCode(); +// fltPurposeCode = rq.getFltPurpose(); +// } + String idntfNum = null; + if(rq != null && rq.getIdntfNum() != null && !rq.getIdntfNum().isEmpty()){ + idntfNum = rq.getIdntfNum(); + } + + String confirmKey = UUID.randomUUID().toString(); + byte[] qr = null; + try { + TsQrcodeRq tsRq = TsQrcodeRq.builder() + .rtnUrl(APP_HOST + TS_RETURN_URI) + .reqId(confirmKey) + .submittype(idntfNum) + .applyUser(userCi) + .build(); + + String str = JsonUtils.toJson(tsRq); + + qr = tsService.createQrcode(str); + } catch (WriterException | IOException e) { + log.error("ERROR: ", e); + throw new CustomException(ErrorCode.FAIL, "QR코드 생성 실패"); + } + + // db 저장 - confirmKey(uuid) + + + return BasLaancQrcodeRs.builder() + .qrcode(qr) + .confirmKey(confirmKey) + .build(); + + } } diff --git a/pav-server/src/main/java/com/palnet/biz/api/external/controller/ExternalLaancController.java b/pav-server/src/main/java/com/palnet/biz/api/external/controller/ExternalLaancController.java new file mode 100644 index 0000000..8c1333c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/external/controller/ExternalLaancController.java @@ -0,0 +1,34 @@ +package com.palnet.biz.api.external.controller; + +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; + +@Slf4j +@RequiredArgsConstructor +@RequestMapping("/api/external/laanc") +@RestController +public class ExternalLaancController { + + + // TS로 부터 비행 신청 정보 - endpoint + @PostMapping("/plan/ost") + public ResponseEntity createTsFltPlan(@RequestBody String body) { + log.info(">>>> /plan/ost body: {}", body); + return ResponseEntity.ok().build(); + } + + + + // TS VC 유효성 검토 callback url - endpoint + @PostMapping("/vc/callback") + public ResponseEntity vcCallback(@RequestBody String body) { + log.info(">>>> vc/callback body: {}", body); + return ResponseEntity.ok().build(); + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRq.java b/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRq.java new file mode 100644 index 0000000..bc1f47a --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRq.java @@ -0,0 +1,28 @@ +package com.palnet.biz.api.external.model; + +import lombok.Builder; +import lombok.Data; + +@Data +public class TsQrcodeRq { + private String type; // 5 (한국공항공사) - 고정 + private String rtnUrl; // 리턴 url - 고정 + private String reqId; // 추적 코드 + private String submittype; // 기체신고번호 + private String applyUser; // 사용자 인증 코드 ci + + public TsQrcodeRq() { + this.type = "5"; + this.rtnUrl = ""; + } + + @Builder + public TsQrcodeRq(String rtnUrl, String reqId, String submittype, String applyUser) { + this.type = "5"; + this.rtnUrl = rtnUrl; + this.reqId = reqId; + this.submittype = submittype; + this.applyUser = applyUser; + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRs.java b/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRs.java new file mode 100644 index 0000000..26b30ce --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRs.java @@ -0,0 +1,30 @@ +package com.palnet.biz.api.external.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * packageName : com.palnet.biz.api.external.model + * fileName : PilotValidRq + * author : dhji + * date : 2023-09-21(021) + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2023-09-21(021) dhji 최초 생성 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TsQrcodeRs { + private String rspCode; // 결과코드 + private String rspMessage; // 결과메시지 + private String pilotcredentialyn; // 조종사자격증명여부 + private String arcrftinsuranceyn; // 기체보험가입여부 + private String arcrftdeclaration; // 기체신고여부 + private String corpregyn; // 사업자유무 +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/external/service/TsService.java b/pav-server/src/main/java/com/palnet/biz/api/external/service/TsService.java index 59bc833..5a1254f 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/external/service/TsService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/external/service/TsService.java @@ -1,7 +1,14 @@ package com.palnet.biz.api.external.service; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.WriterException; +import com.google.zxing.client.j2se.MatrixToImageConfig; +import com.google.zxing.client.j2se.MatrixToImageWriter; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; import com.palnet.biz.api.external.model.PilotValidRq; import com.palnet.biz.api.external.model.PilotValidRs; +import com.palnet.biz.api.external.model.TsQrcodeRq; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -15,6 +22,10 @@ import org.springframework.web.util.DefaultUriBuilderFactory; import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriUtils; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -40,6 +51,7 @@ public class TsService { private final String ACCOUNT_VALIDATE_URI = "/api/account/getValidate"; + // 이전 TS 연동 public List getAccountValidate(List rqList) { List rsList = new ArrayList<>(); @@ -58,6 +70,7 @@ public class TsService { } + // 이전 TS 연동 public PilotValidRs callAccountValidate(PilotValidRq rq) { String pilotciEnc = UriUtils.encode(rq.getPilotci(), StandardCharsets.UTF_8); @@ -110,4 +123,26 @@ public class TsService { return rs; } + // QR 코드 생성 + public byte[] createQrcode(String params) throws WriterException, IOException { + // 바코드 색상 값 +// int qrcodeColor = 0xFF2e4e96; + int qrcodeColor = 0xFF000000; + // 배경 색상 값 + int backgroundColor = 0xFFFFFFFF; + + QRCodeWriter qrCodeWriter = new QRCodeWriter(); + // 300x300 + BitMatrix bitMatrix = qrCodeWriter.encode(params, BarcodeFormat.QR_CODE, 300, 300); + + MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(qrcodeColor, backgroundColor); + BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix, matrixToImageConfig); + // ImageIO를 사용한 바코드 파일쓰기 +// boolean png = ImageIO.write(bufferedImage, "png", new File("stoneQR2.png")); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ImageIO.write(bufferedImage, "png", outputStream); + return outputStream.toByteArray(); + + } } 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 index e47826f..3f845c8 100644 --- a/pav-server/src/main/java/com/palnet/biz/config/WebMvcConfig.java +++ b/pav-server/src/main/java/com/palnet/biz/config/WebMvcConfig.java @@ -1,7 +1,6 @@ package com.palnet.biz.config; -import java.time.format.DateTimeFormatter; - +import com.palnet.biz.config.convert.CodeToFltPurposeBinding; import com.palnet.biz.config.convert.StringToInstantBinding; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,6 +12,8 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; +import java.time.format.DateTimeFormatter; + @Configuration public class WebMvcConfig implements WebMvcConfigurer{ @@ -93,6 +94,7 @@ public class WebMvcConfig implements WebMvcConfigurer{ registrar.registerFormatters(registry); registry.addConverter(new StringToInstantBinding()); + registry.addConverter(new CodeToFltPurposeBinding()); /* ISO 타입. registrar.setUseIsoFormat(true); diff --git a/pav-server/src/main/java/com/palnet/biz/config/convert/CodeToFltPurposeBinding.java b/pav-server/src/main/java/com/palnet/biz/config/convert/CodeToFltPurposeBinding.java new file mode 100644 index 0000000..3bca7ba --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/config/convert/CodeToFltPurposeBinding.java @@ -0,0 +1,15 @@ +package com.palnet.biz.config.convert; + +import com.palnet.biz.jpa.entity.type.FltPurpose; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.convert.converter.Converter; + +@Slf4j +public class CodeToFltPurposeBinding implements Converter { + + @Override + public FltPurpose convert(String code) { + return FltPurpose.fromCode(code); + } + +} diff --git a/pav-server/src/main/resources/application.properties b/pav-server/src/main/resources/application.properties index 0c10bc9..3750696 100644 --- a/pav-server/src/main/resources/application.properties +++ b/pav-server/src/main/resources/application.properties @@ -17,6 +17,7 @@ external.sunriseset.key=b/Stm6AMT3EwXc5kOvwnjK/PB57Ay1WzkIGVx5WaMt0MyRt3TEPgcJ/u ### TS ### external.ts.url=http://121.137.95.45:8170 +external.ts.return.uri=/api/external/laanc/vc/callback ### Token key ###### spring.jwt.secret=jwtsecretkey diff --git a/pav-server/src/main/resources/application.yml b/pav-server/src/main/resources/application.yml index 12896de..a7b707c 100644 --- a/pav-server/src/main/resources/application.yml +++ b/pav-server/src/main/resources/application.yml @@ -70,6 +70,10 @@ url: file: files/ coord: C:\\Users\\Jaewoo\\Downloads\\pal\\pav\\kac\\coordinate\\CoordinateFolder\\ +app: + host: http://localhost:8080 +# host: http://211.253.11.189:8080 + --- spring: @@ -120,6 +124,10 @@ url: file: /data/server/files/ coord: /data/coord/coordinateFolder/ +app: + host: http://211.253.11.189:8080 + + --- spring: @@ -179,3 +187,6 @@ url: file: /data/server/files/ coord: /data/coord/coordinateFolder/ + +app: + host: http://211.253.11.189:8080