코어 디바이스 설정
    • PDF

    코어 디바이스 설정

    • PDF

    Article Summary

    Classic/VPC 환경에서 이용 가능합니다 .

    코어 디바이스 설정에서는 코어 소프트웨어를 실행하는 엣지 디바이스로 메시지와 데이터를 처리할 수 있습니다.

    코어 디바이스 화면

    코어 디바이스 화면 구성은 다음과 같습니다.
    iotedge-coredevices_01_ko.png

    항목설명
    ① 코어 디바이스 설정코어 디바이스 설정 안내
    ② 코어 디바이스 검색코어 디바이스 이름으로 검색
    ③ 삭제 버튼코어 디바이스 삭제
    ④ 목록코어 디바이스 목록
    ⑤ 상세 정보의 배포 탭코어 디바이스의 최신 배포
    ⑥ 상세 정보의 클라이언트 디바이스 탭코어 디바이스에 설정된 클라이언트 디바이스 목록
    ⑦ 상세 정보의 엔드포인트 탭클라이언트가 접속할 코어 디바이스의 엔드포인트

    사전 요구 사항

    코어 디바이스 설정 시 필요한 사항을 설명합니다.

    Cloud IoT Core 리소스

    코어 디바이스 설정에 필요한 Cloud IoT Core 리소스는 다음과 같습니다.

    • 가상 디바이스: 이미 생성한 가상 디바이스와 동일한 이름으로 코어 디바이스를 생성합니다.
    • 인증서: Edge 코어 소프트웨어는 코어 디바이스로 설정한 가상 디바이스에 연결된 인증서를 사용하여 Cloud IoT Core와 통신합니다.
    참고

    Edge 코어 소프트웨어는 빠른 설치를 위해 Cloud IoT Core 리소스를 자동으로 생성해주는 프로비전 기능을 제공합니다.

    IAM 인증키

    인증키는 코어 디바이스가 필요한 리소스를 프로비전하고 클라우드 서비스와 상호작용하는 데 사용됩니다. 필요한 IAM 인증키 및 정책 권한의 설명은 다음과 같습니다.

    정책 이름정책 설명
    NCP_CLOUD_IOT_CORE_MANAGERCloud IoT Core 서비스 내 모든 기능을 이용할 수 있는 권한

    IAM 인증키를 환경 변수로 제공하기 위해 아래 명령을 디바이스 터미널에 복사하고 ‘=’ 기호 다음에 있는 텍스트를 지정한 정보로 변경해 주십시오.

    export NCLOUD_ACCESS_KEY_ID=<NCLOUD_ACCESS_KEY_ID>
    export NCLOUD_SECRET_KEY=<NCLOUD_SECRET_KEY>
    

    Java

    Edge 코어 소프트웨어는 8 버전 이상의 Java 런타임이 필요합니다.

    • Linux에서 Open JDK를 설치하는 명령어 예시는 다음과 같습니다.
    sudo apt-get install openjdk-8-jdk
    
    • 설치된 Java의 버전을 확인하는 명령어는 다음과 같습니다.
    java -version
    

    코어 디바이스 설정

    코어 디바이스를 설정하는 방법은 다음과 같습니다.

    1. 네이버 클라우드 플랫폼의 콘솔에서 Services > Internet of Things > Cloud IoT Core 메뉴를 차례대로 클릭해 주십시오.
    2. IoT Edge > Core Devices 메뉴를 차례대로 클릭해 주십시오.
    3. [코어 디바이스 설정] 버튼을 클릭해 주십시오.
    4. 코어 디바이스로 설정할 가상 디바이스를 선택해 주십시오.
      • 신규 생성을 선택하면 입력한 이름으로 생성된 가상 디바이스가 코어 디바이스로 설정됩니다.
    5. Edge 코어 소프트웨어를 다운로드하고 설치해 주십시오.
      • 다운로드 후 압축 해제 위치(-d 옵션)는 사용자가 지정할 수 있으며, '입력한 경로/edgecore/' 하위에 소프트웨어 파일이 압축 해제됩니다.
        curl -sL 'https://github.com/NaverCloudPlatform/iot-edge/releases/latest/download/edgecore.zip' -o edgecore.zip && unzip edgecore.zip -d /
        
    6. 다음과 같은 명령어를 사용하여 Edge 코어 소프트웨어를 실행해 주십시오.
      sudo -E java -Droot="/edgecore" -jar /edgecore/lib/edgecore.jar --virtual-device-name <CoreDeviceName> --setup-system-service true --provision true
      
      • Edge 코어 소프트웨어에서 제공하는 실행 옵션은 다음과 같습니다.
        옵션설명기본값
        --hEdge 코어 소프트웨어 실행 옵션 도움말 출력-
        --virdual-device-name, --vdn코어 디바이스로 사용할 가상 디바이스의 이름. 가상 디바이스가 존재하지 않으면 Edge 코어 소프트웨어에서 생성CoreDevice-{임의문자열}
        --starttrue 입력 시 Edge 코어 소프트웨어 프로세스를 바로 시작true
        -- provision, -p코어 디바이스 설정에 필요한 리소스 프로비전.
      • true일 경우: Edge 코어 소프트웨어가 클라우드에 가상 디바이스와 인증서를 생성하고 연결
      • false이면서 가상 디바이스 혹은 인증서가 존재하지 않거나 연결이 올바르지 않을 경우: Edge 코어 소프트웨어가 종료
      • false
        -- setup-system-servicetrue일 경우: Edge 코어 소프트웨어를 디바이스가 부팅될 때 실행되는 시스템 서비스로 설정false
    7. [목록 보기] 버튼을 클릭해 주십시오.
      • IoT 장비에 설치가 완료되면 수 분 이내 목록에서 코어 디바이스를 확인할 수 있습니다.

    코어 디바이스 삭제

    더 이상 사용하지 않는 코어 디바이스를 삭제할 수 있습니다. 코어 디바이스를 삭제하는 방법은 다음과 같습니다.

    1. Edge 코어 소프트웨어를 제거해 주십시오.
      • Edge 코어 소프트웨어를 시스템 서비스(systemctl)로 실행한 경우, 서비스를 정지/비활성화한 후 제거해야 합니다. 아래 명령어를 실행하여 Edge 코어 소프트웨어를 제거해 주십시오.
      //서비스 정지, 비활성화, 제거
      sudo systemctl stop edgecore.service
      sudo systemctl disable edgecore.service
      sudo rm /etc/systemd/system/edgecore.service
      
    2. 네이버 클라우드 플랫폼의 콘솔에서 Services > Internet of Things > Cloud IoT Core 메뉴를 차례대로 클릭해 주십시오.
    3. IoT Edge > Core Devices 메뉴를 차례대로 클릭해 주십시오.
    4. 코어 디바이스 목록에서 삭제할 코어 디바이스를 클릭하여 선택해 주십시오.
    5. [삭제] 버튼을 클릭해 주십시오.
    6. 팝업 창이 나타나면 [삭제] 버튼을 클릭해 주십시오.

    클라이언트 디바이스 관리

    클라이언트 디바이스는 코어 디바이스의 로컬 메시지 브로커에 접근할 수 있는 가상 디바이스입니다. 사전에 설정된 클라이언트 디바이스만이 해당 코어 디바이스에 접근할 수 있습니다. Core Devices 메뉴에서 해당 코어 디바이스에 연결할 클라이언트 디바이스를 한눈에 확인할 수 있습니다.

    참고

    하나의 가상 디바이스를 여러 코어 디바이스에 클라이언트 디바이스로 설정할 수 있습니다.

    클라이언트 디바이스 설정

    클라이언트 디바이스를 설정하는 방법은 다음과 같습니다.

    1. 네이버 클라우드 플랫폼의 콘솔에서 Services > Internet of Things > Cloud IoT Core 메뉴를 차례대로 클릭해 주십시오.
    2. IoT Edge > Core Devices 메뉴를 차례대로 클릭해 주십시오
    3. 코어 디바이스 목록에서 코어 디바이스를 클릭하여 선택해 주십시오.
    4. [클라이언트 디바이스 설정] 버튼을 클릭해 주십시오.
    5. 해당 코어 디바이스에 연결할 클라이언트 디바이스를 클릭하여 선택해 주십시오.
      참고

      클라이언트 디바이스를 이름으로 검색할 수 있습니다.

    6. [저장] 버튼을 클릭해 주십시오.

    클라이언트 디바이스 분리

    코어 디바이스에 설정된 클라이언트 디바이스를 분리하는 방법은 다음과 같습니다.

    1. 네이버 클라우드 플랫폼의 콘솔에서 Services > Internet of Things > Cloud IoT Core 메뉴를 차례대로 클릭해 주십시오.
    2. IoT Edge > Core Devices 메뉴를 차례대로 클릭해 주십시오
    3. 코어 디바이스 목록에서 코어 디바이스를 클릭하여 선택해 주십시오.
    4. [클라이언트 디바이스 설정] 버튼을 클릭해 주십시오.
    5. 분리할 클라이언트 디바이스를 클릭하여 체크 박스를 해제해 주십시오.
    6. [저장] 버튼을 클릭해 주십시오.

    엔드포인트 관리

    클라이언트 디바이스가 코어 디바이스의 로컬 메시지 브로커에 메시지를 전송하기 위해서는 엔드포인트를 알아야 합니다. 각 코어 디바이스의 엔드포인트 정보는 클라우드상에서 관리됩니다.

    엔드포인트 설정

    Edge 코어 소프트웨어는 코어 디바이스의 엔드 포인트 변경을 자동으로 감지하여 클라우드에 업데이트합니다.

    참고

    엔드포인트가 변경되면 클라우드에 업데이트한 후 Edge 코어 소프트웨어가 재시작됩니다.

    엔드포인트 조회

    가상 디바이스는 Discovery API를 사용하여 해당 가상 디바이스가 클라이언트 디바이스로 설정된 코어 디바이스의 엔드포인트를 조회할 수 있습니다. Discover API에 대한 자세한 정보는 Discovery API 문서를 참조해 주십시오.

    참고

    콘솔에서도 각 코어 디바이스의 엔드포인트를 확인할 수 있습니다.

    클라이언트 디바이스를 코어 디바이스에 연결

    클라이언트 디바이스는 코어 디바이스 내 로컬 메시지 브로커를 통해 다른 클라이언트 디바이스와 메시지를 주고받을 수 있습니다. 클라이언트 디바이스가 연결할 수 있는 코어 디바이스를 검색하고 필요한 정보를 조회하는 데에는 Discovery API가 사용됩니다.

    1. 클라이언트 디바이스 설정을 참조하여 연결하고자 하는 코어 디바이스에 클라이언트 디바이스를 설정해 주십시오.
    2. 엔드포인트 조회를 참조하여 코어 디바이스의 엔드포인트가 존재하는지 확인해 주십시오.
      • 클라이언트 디바이스는 코어 디바이스의 엔드포인트에 접근할 수 있어야 합니다.
    3. 인증서 연결을 참조하여 Cloud IoT Core의 인증서를 클라이언트 디바이스와 연결하고 다운로드해 클라이언트 디바이스에 복사해 주십시오.
    4. 클라이언트 디바이스에서 Discovery 예제 코드를 실행해 주십시오.
      • 이 예제에서는 하나의 클라이언트 디바이스가 같은 토픽을 코어 디바이스에 발행하고 구독합니다.

    Java

    Discovery 예제 코드를 실행하기 위한 라이브러리는 다음과 같습니다.

    • maven
    <dependencies>
            <dependency>
                <groupId>org.eclipse.paho</groupId>
                <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
                <version>${version}</version>
            </dependency>
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcpkix-jdk15on</artifactId>
                <version>${version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>${version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>${version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>${version}</version>
            </dependency>
            <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>${version}</version>
            </dependency>
        </dependencies>
    
    • Java Discovery 예제 코드는 다음과 같습니다.
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.apache.commons.codec.binary.Base64;
    import org.apache.http.Header;
    import org.apache.http.HttpEntity;
    import org.apache.http.client.HttpResponseException;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.utils.URIBuilder;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicHeader;
    import org.apache.http.util.EntityUtils;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.openssl.PEMKeyPair;
    import org.bouncycastle.openssl.PEMParser;
    import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
    import org.eclipse.paho.client.mqttv3.*;
    import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManagerFactory;
    import java.io.*;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.nio.charset.StandardCharsets;
    import java.security.*;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    import java.time.Instant;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    import java.util.Random;
    
    public class DiscoveryExample {
    
        /*
         *** Modify device name, file path and authentication key ***
         */
        static String deviceName = "<DEVICE_NAME>}";
        static String clientCaChainFilePath = "/<Your>/<file>/<path>/caChain.pem";
        static String clientCertFilePath = "/<Your>/<file>/<path>/thingCert.crt";
        static String clientKeyFilePath = "/<Your>/<file>/<path>/privKey.key";
    
        static String accessKey = "<NCLOUD_ACCESS_KEY_ID>";
        static String secretKey = "<NCLOUD_SECRET_KEY>}";
    
        static String topic = "/java/action/topic";
        static String message = String.format("{ \"name\": \"device\", \"tempC\": \"15\", \"eventTime\": \"%d\"}", Instant.now().toEpochMilli());
    
        public static final String X_NCP_IAM_ACCESS_KEY = "x-ncp-iam-access-key";
        public static final String X_NCP_APIGW_TIMESTAMP = "x-ncp-apigw-timestamp";
        public static final String X_NCP_APIGW_SIGNATURE_V2 = "x-ncp-apigw-signature-v2";
        public static final String X_NCP_IOT_HOST = "cloudiotcore.apigw.ntruss.com";
    
        public static void main(String[] args) throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException, MqttException, URISyntaxException {
    
            DiscoveryExample app = new DiscoveryExample();
            MqttClient mqttClient = app.getClientFromDiscovery(deviceName);
    
            System.out.println("==== Successfully Connected");
    
            mqttClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {
                    System.out.println("==== Connection Lost");
                }
    
                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    System.out.println("<<< Subscribed from Local MQTT Broker Server. topic: " + topic + ", message: " + message.toString());
                }
    
                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    System.out.println(">>> Published to Local MQTT Broker Server");
                }
            });
    
    
            boolean isConnected = mqttClient.isConnected();
            if (isConnected) {
                mqttClient.subscribe(topic);
            }
    
            if (isConnected) {
                for (int i = 5; i < 10; i++) {
                    Random r = new Random();
                    MqttMessage mqttMessage = new MqttMessage(message.getBytes());
                    mqttMessage.setQos(0);
                    mqttMessage.setRetained(false);
    
                    try {
                        MqttTopic mqttTopic = mqttClient.getTopic(topic);
                        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
                        token.waitForCompletion();
                        Thread.sleep(2000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
    
            mqttClient.disconnect();
            mqttClient.close();
        }
    
        private DiscoveryExample() {
            init();
        }
    
        private MqttClient getClientFromDiscovery(String deviceName) throws MqttException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException, URISyntaxException {
    
            String clientId = deviceName;
    
            //discovery request
            URI uri = new URIBuilder()
                    .setScheme("https")
                    .setHost(X_NCP_IOT_HOST)
                    .setPath(String.format("/iotdeviceedge/v1/discover/device/%s", deviceName))
                    .build();
            Header[] headers = makeHeaders("GET", uri.getRawPath(), Instant.now().toEpochMilli(), accessKey, secretKey);
            OpenApiResponse<EdgeGroupsDto> response = sendGetObject(uri, headers, new TypeReference<OpenApiResponse<EdgeGroupsDto>>() {
            });
    
            List<EdgeGroupDto> edgeGroupList = response.getBody().edgeGroupList;
            if (!edgeGroupList.isEmpty()) {
                for (EdgeGroupDto edgeGroupDto : edgeGroupList) {
                    for (ConnectivityInfoDto connectivityInfo : edgeGroupDto.connectivityList) {
    
                        //endpoint
                        String hostAddress = connectivityInfo.hostAddress;
                        int port = connectivityInfo.portNumber;
                        String endpoint = String.format("ssl://%s:%d", hostAddress, port);
    
                        // set mqtt client
                        MqttClient mqttClient = new MqttClient(endpoint, clientId, new MemoryPersistence());
                        MqttConnectOptions connOpts = new MqttConnectOptions();
                        connOpts.setCleanSession(true);
                        connOpts.setConnectionTimeout(5);
                        connOpts.setKeepAliveInterval(60);
                        connOpts.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
    
                        // create ssl socket factory
                        Optional<String> ca = edgeGroupDto.caList.stream().findFirst();
                        if (ca.isPresent()) {
                            TrustManagerFactory tmf = getTrustManagerFactory(ca.get());
                            KeyManagerFactory kmf = getKeyManagerFactory(clientCaChainFilePath, clientCertFilePath, clientKeyFilePath, "");
                            SSLContext context = SSLContext.getInstance("TLSv1.2");
                            context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
                            connOpts.setSocketFactory(context.getSocketFactory());
                        }
    
                        //connect
                        try {
                            mqttClient.connect(connOpts);
                            return mqttClient;
                        } catch (Exception e) {
                            System.out.println(String.format("client device(%s) failed to connect core device(ssl://%s:%d) with exception %s", deviceName, connectivityInfo.hostAddress, connectivityInfo.getPortNumber(), e.toString()));
                        }
                    }
                }
            } else {
                throw new RuntimeException(String.format("client device(%s) could not connect to core device using any of the edge group endpoint", deviceName));
            }
    
            throw new RuntimeException("There is no edge group to connect client device " + deviceName);
        }
    
    
        private KeyManagerFactory getKeyManagerFactory(String clientCaChainFilePath, String clientCertFilePath, String clientKeyFilePath, String password) throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
            KeyPair key = getClientKey(clientKeyFilePath);
            Certificate clientCert = getClientCert(clientCertFilePath);
            List<Certificate> caChain = getClientCaChain(clientCaChainFilePath, clientCert);
    
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            int caChainSize = caChain.size();
            Certificate[] caChainArray = caChain.toArray(new Certificate[caChainSize]);
            keyStore.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), caChainArray);
    
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keyStore, password.toCharArray());
            return keyManagerFactory;
        }
    
        private TrustManagerFactory getTrustManagerFactory(String coreCaPem) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
            KeyStore rootCaKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            rootCaKeyStore.load(null, null);
            X509Certificate coreCaCert = convertStringToX509Cert(coreCaPem);
            rootCaKeyStore.setCertificateEntry("core", coreCaCert);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
            tmf.init(rootCaKeyStore);
            return tmf;
        }
    
        private void init() {
            Security.addProvider(new BouncyCastleProvider());
        }
    
        private KeyPair getClientKey(String clientKeyFilePath) throws IOException {
            PEMParser pemParser = new PEMParser(new FileReader(clientKeyFilePath));
            Object object = pemParser.readObject();
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
    
            KeyPair key = converter.getKeyPair((PEMKeyPair) object);
            pemParser.close();
            return key;
        }
    
        private List<Certificate> getClientCaChain(String clientCaChainFilePath, Certificate clientCert) throws CertificateException, IOException {
            X509Certificate cert = null;
            List<Certificate> caChain = new ArrayList<Certificate>();
    
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(clientCaChainFilePath));
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
    
            while (bis.available() > 0) {
                cert = (X509Certificate) cf.generateCertificate(bis);
                caChain.add(cert);
            }
            caChain.add(0, clientCert);
            return caChain;
        }
    
        private X509Certificate getClientCert(String clientCertFilePath) throws CertificateException, IOException {
            return getX509Certificate(clientCertFilePath);
        }
    
        private X509Certificate getX509Certificate(String filePath) throws CertificateException, IOException {
            X509Certificate caCert = null;
    
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
    
            while (bis.available() > 0) {
                caCert = (X509Certificate) cf.generateCertificate(bis);
            }
            return caCert;
        }
    
        private X509Certificate convertStringToX509Cert(String certificate) throws CertificateException {
            InputStream targetStream = new ByteArrayInputStream(certificate.getBytes());
            return (X509Certificate) CertificateFactory
                    .getInstance("X509")
                    .generateCertificate(targetStream);
        }
    
        private Header[] makeHeaders(String method, String url, Long epoch, String accessKey, String secretKey) {
            Header[] headers = {
                    new BasicHeader("Content-Type", "application/json"),
                    new BasicHeader(X_NCP_IAM_ACCESS_KEY, accessKey),
                    new BasicHeader(X_NCP_APIGW_TIMESTAMP, String.valueOf(epoch)),
                    new BasicHeader(X_NCP_APIGW_SIGNATURE_V2, makeSignature(method, url, String.valueOf(epoch), accessKey, secretKey))
            };
            return headers;
        }
    
        private String makeSignature(String method, String url, String epoch, String accessKey, String secretKey) {
            String signature = null;
            String message = method + " " + url + "\n" + epoch + "\n" + accessKey;
            try {
                SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
                Mac mac = Mac.getInstance("HmacSHA256");
                mac.init(signingKey);
                byte[] rawHmac = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
                signature = Base64.encodeBase64String(rawHmac);
            } catch (NoSuchAlgorithmException | InvalidKeyException ex) {
                System.out.println(String.format("Failed to make signature with message : $s", message));
            }
            return signature;
        }
    
        private <T> T sendGetObject(URI uri, Header[] headers, TypeReference<T> responseType) throws IOException {
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(uri);
            if (headers != null) {
                httpGet.setHeaders(headers);
            }
            return getResponseObject(httpClient.execute(httpGet), responseType);
        }
    
        private <T> T getResponseObject(CloseableHttpResponse httpResponse, TypeReference<T> responseType) throws IOException {
            try {
                HttpEntity responseEntity = httpResponse.getEntity();
                String resultString = EntityUtils.toString(responseEntity);
                EntityUtils.consume(responseEntity);
    
                if (httpResponse.getStatusLine().getStatusCode() >= 200 && httpResponse.getStatusLine().getStatusCode() <= 299) {
                    return new ObjectMapper().readValue(resultString, responseType);
                }
    
                throw new HttpResponseException(httpResponse.getStatusLine().getStatusCode(), resultString);
            } finally {
                httpResponse.close();
            }
        }
    
        static class OpenApiResponse<T> {
            private String status;
            private T body;
    
            public String getStatus() {
                return status;
            }
    
            public T getBody() {
                return body;
            }
        }
    
        static class EdgeGroupsDto {
            @JsonProperty("EdgeGroups")
            private List<EdgeGroupDto> edgeGroupList;
    
            public EdgeGroupsDto(List<EdgeGroupDto> edgeGroupDtos) {
                this.edgeGroupList = edgeGroupDtos;
            }
    
            public EdgeGroupsDto() {
                this.edgeGroupList = new ArrayList<>();
            }
    
            public List<EdgeGroupDto> getEdgeGroupList() {
                return edgeGroupList;
            }
        }
    
        static class EdgeGroupDto {
            @JsonProperty("EdgeGroupId")
            private String edgeGroupId;
            @JsonProperty("Connectivity")
            private List<ConnectivityInfoDto> connectivityList;
            @JsonProperty("CAs")
            private List<String> caList;
    
            public String getEdgeGroupId() {
                return edgeGroupId;
            }
    
            public List<ConnectivityInfoDto> getConnectivityList() {
                return connectivityList;
            }
    
            public List<String> getCaList() {
                return caList;
            }
        }
    
        static class ConnectivityInfoDto {
            private String hostAddress;
            private int portNumber;
            private String metadata;
    
            public String getHostAddress() {
                return hostAddress;
            }
    
            public int getPortNumber() {
                return portNumber;
            }
    
            public String getMetadata() {
                return metadata;
            }
        }
    
    }
    

    이 문서가 도움이 되었습니까?

    Changing your password will log you out immediately. Use the new password to log back in.
    First name must have atleast 2 characters. Numbers and special characters are not allowed.
    Last name must have atleast 1 characters. Numbers and special characters are not allowed.
    Enter a valid email
    Enter a valid password
    Your profile has been successfully updated.