투케이2K

581. (Android/Java) 안드로이드 : 스마트 콘피그 (SmartConfig) 와이파이 Wifi 연결 및 소켓 통신 수행 본문

Android

581. (Android/Java) 안드로이드 : 스마트 콘피그 (SmartConfig) 와이파이 Wifi 연결 및 소켓 통신 수행

투케이2K 2023. 6. 18. 17:34

[개발 환경 설정]

개발 툴 : AndroidStudio

 

[JAVA : 소스 코드]

        // ---------------------------------------------------------------
        // [퍼미션 요청 실시]
        // ---------------------------------------------------------------
        try {
            C_Permission.checkPermission(A_Intro.this);
        }
        catch (Exception e){
            e.printStackTrace();
        }


        // ---------------------------------------------------------------
        // [로직 처리 실시]
        // ---------------------------------------------------------------
        try {

            // -------------------------------------------------
            // TODO [1]. build.gradle 파일에 라이브러리 의존성 부여
            // -------------------------------------------------
            // [스마트 콘피그 라이브러리 의존성 부여]
            // implementation 'com.github.EspressifApp:lib-esptouch-android:1.1.1'
            // -------------------------------------------------


            // -------------------------------------------------
            // TODO [2]. 모바일을 특정 와이파이에 사전 연결 수행 실시
            // -------------------------------------------------
            // 휴대폰과, 디바이스가 같은 와이파이에 연결되어 통신을 수행하기 위함
            // -------------------------------------------------


            // -------------------------------------------------
            // TODO [3]. 와이파이 리스트 목록 스캔 수행
            // -------------------------------------------------
            C_App.observableWifiScanList(A_Intro.this)
                    .subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
                    .observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
                    .subscribe(new Observer<List<ScanResult>>() { // [Observable.create 타입 지정]
                        @Override
                        public void onSubscribe(@NonNull Disposable d) {
                        }
                        @Override
                        public void onNext(@NonNull List<ScanResult> value) {
                            S_Log._W_("와이파이 스캔 결과 확인", new String[]{
                                    "SCAN COUNT :: " + String.valueOf(value.size()),
                                    "SCAN LIST :: " + String.valueOf(value.toString())
                            });


                            // -------------------------------------------------
                            // TODO [4]. 특정 와이파이 SSID , BSSID 확인 : 현재 휴대폰에 연결된 와이파이
                            // -------------------------------------------------
                            String ssid = "";
                            String bssid = "";
                            String pw = "k0123456789"; // [비밀 번호]

                            for (ScanResult scanResult : value){

                                if (scanResult.SSID.contains("KKH") == true){

                                    ssid = scanResult.SSID.toString();
                                    bssid = scanResult.BSSID.toString();

                                    break;

                                }
                            }
                            S_Log._W_("스마트 콘피그 연결 정보 확인", new String[]{
                                    "SSID :: " + ssid,
                                    "BSSID :: " + bssid,
                                    "PW :: " + pw
                            });


                            // -------------------------------------------------
                            // TODO [5]. EsptouchTask 객체 초기화 및 이벤트 등록
                            // -------------------------------------------------
                            EsptouchTask esptouchTask = new EsptouchTask(ssid, bssid, pw, A_Intro.this);
                            esptouchTask.setPackageBroadcast(true);
                            esptouchTask.setEsptouchListener(new IEsptouchListener() {
                                @Override
                                public void onEsptouchResultAdded(IEsptouchResult result) {
                                    S_Log._W_("연결 상태 콜백 결과 확인", new String[]{ result.toString() });
                                }
                            });



                            // -------------------------------------------------
                            // TODO [6]. EsptouchTask 활성 수행
                            // -------------------------------------------------
                            int expectResultCount = 1;
                            List<IEsptouchResult> results = esptouchTask.executeForResults(expectResultCount);
                            IEsptouchResult first = results.get(0);
                            if (first.isCancelled()) {
                                S_Log._E_("esptouchTask 연결 수행 취소", null);
                                return;
                            }
                            if (first.isSuc()) {
                                S_Log._W_("esptouchTask 연결 수행 성공", null);


                                // -------------------------------------------------
                                // TODO [7]. 디바이스 / 모바일이 모두 같은 와이파이에 연결된 상태 >> 소켓 통신을 하기 위한 IP , PORT 선언
                                // -------------------------------------------------
                                String ip = first.getInetAddress().getHostAddress();
                                int port = 5000;
                                int timeOut = 10000;


                                // --------------------------------------
                                // TODO [8]. [소켓 모듈 클래스 인스턴스 초기화]
                                // --------------------------------------
                                Socket_Module socket_module = Socket_Module.getInstance();
                                socket_module.setContext(A_Intro.this);

                                
                                // --------------------------------------
                                // TODO [9]. [소켓 연결 수행]
                                // --------------------------------------
                                if(socket_module.connectHost(ip, port, timeOut) == true) { // [소켓 연결 상태 확인]


                                    // --------------------------------------
                                    // TODO [10]. [기기 등록 요청 수행]
                                    // --------------------------------------
                                    HashMap<String, Object> deviceRegMap = socket_module.request_Device_Reg();

                                    S_Log._W_("소켓 통신 :: 디바이스 등록 요청 수행 결과 확인", new String[]{
                                            "SUCCESS :: " + String.valueOf(deviceRegMap.get(Socket_Module.RETURN_SUCCESS_FLAG))
                                    });


                                    // --------------------------------------
                                    // TODO [11]. [소켓 연결 종료]
                                    // --------------------------------------
                                    socket_module.closeSocket();

                                }
                                else {
                                    S_Log._E_("소켓 연결 실패", null);
                                }


                            }

                        }
                        @Override
                        public void onError(@NonNull Throwable e) {
                            S_Log._E_("와이파이 스캔 에러", new String[]{ e.getMessage().toString() });
                        }
                        @Override
                        public void onComplete() {
                        }
                    });
        }
        catch (Exception e) {
            e.printStackTrace();
        }
 

[소켓 모듈 : 소스 코드]

package com.example.javaproject;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;

import org.json.JSONObject;

import java.io.DataInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;

public class Socket_Module {


    /**
     * // --------------------------------------------------------------------------------------
     * TODO [빠른 로직 찾기 : 주석 로직 찾기]
     * // --------------------------------------------------------------------------------------
     * // [SEARCH FAST] : [기기 등록 요청 실시 >> 응답 결과 확인]
     * // --------------------------------------------------------------------------------------
     */





    // ------------------------------------------------------------------------------------------
    // TODO [전역 변수 선언]
    // ------------------------------------------------------------------------------------------
    private String ACTIVITY_NAME = "Socket_Module";

    private Context mMainCtx; // [컨텍스트]

    private Socket mSocket; // [소켓]

    private OutputStream mOutputStream; // [스트림]
    private PrintWriter mPrintWriter; // [스트림]
    private InputStream mInputStream; // [스트림]
    private DataInputStream mDataDataInputStream; // [스트림]

    public static final String RETURN_SUCCESS_FLAG = "RETURN_SUCCESS_FLAG"; // [리턴 데이터 반환 키 값]
    public static final String RETURN_ERROR_MESSAGE = "RETURN_ERROR_MESSAGE"; // [리턴 데이터 반환 키 값]




    // ------------------------------------------------------------------------------------------
    // TODO [콘텍스트 지정]
    // ------------------------------------------------------------------------------------------
    public void setContext(Context ctx) {
        mMainCtx = ctx;
    }




    // ------------------------------------------------------------------------------------------
    // TODO [인스턴스 생성]
    // ------------------------------------------------------------------------------------------
    public static Socket_Module getInstance() { return Socket_Module.LazyHolder.INSTANCE; }
    private static class LazyHolder {
        private static final Socket_Module INSTANCE = new Socket_Module();
    }





    // ------------------------------------------------------------------------------------------
    // TODO [소켓 생성 실시]
    // ------------------------------------------------------------------------------------------
    private synchronized Socket createSocket(String host, int port) {
        S_Log._D_("소켓 생성 수행", new String[]{
                "HOST :: " + String.valueOf(host),
                "PORT :: " + String.valueOf(port)
        });

        ConnectivityManager connectivity = (ConnectivityManager) mMainCtx.getSystemService(Context.CONNECTIVITY_SERVICE);
        Socket sock = null;
       
        try{
            if (connectivity != null) {

                for (Network network : connectivity.getAllNetworks()) { // TODO [연결된 네트워크 확인]
                    
                    NetworkInfo networkInfo = connectivity.getNetworkInfo(network);
                    
                    if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { // TODO [와이파이 연결 상태 체크]

                        if (networkInfo.isConnected()) {
                            S_Log._W_("소켓 생성 성공", new String[]{
                                    "HOST :: " + String.valueOf(host),
                                    "PORT :: " + String.valueOf(port)
                            });

                            // [소켓 지정 실시]
                            sock =  network.getSocketFactory().createSocket(host, port);
                        }

                    }
                }
            }
            else {
                S_Log._E_("소켓 생성 에러", new String[]{ "ConnectivityManager is null" });
            }
        } catch (Exception e) {
            S_Log._E_("소켓 생성 에러", new String[]{ String.valueOf(e.getMessage()) });
        }
        return sock;
    }





    // ------------------------------------------------------------------------------------------
    // TODO [디바이스 호스트 연결 실시]
    // ------------------------------------------------------------------------------------------
    public synchronized boolean connectHost(String host, int port, int timeout) {

        // [연결 상태 체크 변수]
        boolean isConnection = false;


        // [로직 처리 수행]
        try {

            // [소켓 연결 수행]
            if(this.mSocket != null) { // TODO [소켓이 널이 아닌 경우]
                S_Log._E_("호스트 연결 실패", new String[]{ "설 명 :: 소켓 연결 된 상태 (Socket Not Null)" });
            }
            else { // TODO [소켓이 널인 경우]
                S_Log._D_("호스트 연결 수행", new String[]{
                        "HOST :: " + String.valueOf(host),
                        "PORT :: " + String.valueOf(port),
                        "TIME_OUT :: " + String.valueOf(timeout)
                });

                this.mSocket = createSocket(host, port); // [소켓 생성]

                this.mSocket.setTcpNoDelay(true);
                this.mSocket.setSoTimeout(0);

                isConnection = this.mSocket.isConnected(); // [소켓 연결 상태 확인]

                if (isConnection == true){
                    S_Log._W_("호스트 연결 성공", new String[]{ "설 명 :: 데이터 송수신을 위한 스트림 설정" });

                    // [데이터 송수신 설정]
                    this.mOutputStream = this.mSocket.getOutputStream(); // [읽기]
                    this.mPrintWriter = new PrintWriter(mOutputStream);

                    this.mInputStream = this.mSocket.getInputStream(); // [쓰기]
                    this.mDataDataInputStream = new DataInputStream(mInputStream);

                }
                else {
                    S_Log._E_("호스트 연결 실패", new String[]{ "설 명 :: mSocket.isConnected false" });
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();

            // [Exception 발생 시 소켓 연결 종료]
            closeSocket();
        }


        // [리턴 반환 수행]
        return isConnection;
    }





    // ------------------------------------------------------------------------------------------
    // TODO [소켓 연결 종료]
    // ------------------------------------------------------------------------------------------
    public synchronized boolean closeSocket() {

        // [리턴 변수 선언]
        boolean isClose = false;
        
        // [로직 처리 수행]
        try {

            // [생성된 소켓이 있는 경우 종료 및 스트림 닫기]
            if(this.mSocket != null) {
                
                this.mPrintWriter.close();
                this.mDataDataInputStream.close();
                this.mOutputStream.close();
                this.mInputStream.close();

                this.mSocket.close();

                isClose = this.mSocket.isClosed();

                this.mSocket = null;
            }
            else {
                isClose = true;
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }


        S_Log._E_("소켓 연결 종료 수행", new String[]{
                "소켓 종료 상태 :: " + String.valueOf(isClose)
        });
        
        
        // [리턴 반환 수행]
        return isClose;
    }





    // ------------------------------------------------------------------------------------------
    // TODO [SEARCH FAST] : [기기 등록 요청 실시 >> 응답 결과 확인]
    // ------------------------------------------------------------------------------------------
    public synchronized HashMap request_Device_Reg() {
        S_Log._D_("기기 등록 요청 수행", null);

        /**
         * // ----------------------------------------
         * TODO [REQUEST] : [APP >> DEVICE]
         * // ----------------------------------------
         *
         * {
         *   "reg_name" : "TOWK"
         * }
         *
         * // ----------------------------------------
         * */


        /**
         * // ----------------------------------------
         * TODO [RESPONSE] : [DEVICE >> APP]
         * // ----------------------------------------
         *
         * {
         *   "result" : true
         * }
         *
         * // ----------------------------------------
         * */



        // -----------------------------------------------
        // [리턴 변수 선언]
        // -----------------------------------------------
        HashMap<String, Object> returnData = new HashMap<>();



        // -----------------------------------------------
        // [로직 처리 수행]
        // -----------------------------------------------
        try {

            // -----------------------------------------

            // TODO [1]. [디바이스 등록 요청 실시]
            JSONObject reqJson = new JSONObject();
            reqJson.put("reg_name", "TWOK");

            String requestData = reqJson.toString();

            S_Log._D_("[요청] :: [APP] >> [DEVICE] :: 기기 등록 요청 수행", new String[]{
                    "REQUEST :: " + requestData.toString()
            });

            mPrintWriter.write(requestData); // [데이터 전송]
            mPrintWriter.flush();
            
            // -----------------------------------------



            // -----------------------------------------

            // TODO [2]. [디바이스 정보 응답 확인 실시]
            int len = 0;
            byte[] buffer = new byte[6144];

            if(mInputStream != null){
                len = mInputStream.read(buffer);
            }

            byte[] subBuffer = new byte[len];
            System.arraycopy(buffer, 0, subBuffer,0, len);


            // [byte to string 변환]
            String jsonString = new String(subBuffer);
            jsonString = jsonString.replaceAll(" ", "");

            S_Log._D_("[응답] :: [DEVICE] >> [APP] :: 기기 등록 응답 확인", new String[]{
                    "RESPONSE :: " + jsonString.toString()
            });


            // [리턴 데이터 삽입]
            returnData.put(RETURN_SUCCESS_FLAG, true);
            returnData.put(RETURN_ERROR_MESSAGE, "");

            // -----------------------------------------

        }
        catch (Exception e){
            e.printStackTrace();

            // [에러 발생 데이터 삽입]
            returnData.put(RETURN_SUCCESS_FLAG, false);
            returnData.put(RETURN_ERROR_MESSAGE, String.valueOf(e.getMessage()));
        }


        // [리턴 반환 실시]
        return returnData;
    }


} // TODO [클래스 종료]
 

[결과 출력]

 

W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.A_Intro$2.onNext(A_Intro.java:183)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: 와이파이 스캔 결과 확인]
I/: ----------------------------------------------------
I/: [LOG :: SCAN COUNT :: 29]
I/: ----------------------------------------------------
I/: [LOG :: SCAN LIST :: [SSID: "eung2", BSSID: 88:36:6c ... ]
W///===========//: ================================================
        
        
W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.A_Intro$2.onNext(A_Intro.java:207)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: 스마트 콘피그 연결 정보 확인]
I/: ----------------------------------------------------
I/: [LOG :: SSID :: KKH2]
I/: ----------------------------------------------------
I/: [LOG :: BSSID :: 3a:db:07:97:e9:b7]
I/: ----------------------------------------------------
I/: [LOG :: PW :: k0123456789]
W///===========//: ================================================


W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.A_Intro$2$1.onEsptouchResultAdded(A_Intro.java:222)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: 연결 상태 콜백 결과 확인]
I/: ----------------------------------------------------
I/: [LOG :: bssid=90380c0acd9c, address=192.168.181.71, suc=true, cancel=false]
W///===========//: ================================================
        
        
D///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.Socket_Module.connectHost(Socket_Module.java:138)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: 호스트 연결 수행]
I/: ----------------------------------------------------
I/: [LOG :: HOST :: 192.168.181.71]
I/: ----------------------------------------------------
I/: [LOG :: PORT :: 6000]
I/: ----------------------------------------------------
I/: [LOG :: TIME_OUT :: 10000]
D///===========//: ================================================        
        

W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.Socket_Module.createSocket(Socket_Module.java:96)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: 소켓 생성 성공]
I/: ----------------------------------------------------
I/: [LOG :: HOST :: 192.168.181.71]
I/: ----------------------------------------------------
I/: [LOG :: PORT :: 6000]
W///===========//: ================================================


D///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.Socket_Module.request_Device_Reg(Socket_Module.java:283)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: [요청] :: [APP] >> [DEVICE] :: 기기 등록 요청 수행]
I/: ----------------------------------------------------
I/: [LOG :: REQUEST :: {"reg_name":"TWOK"}]
D///===========//: ================================================


D///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.Socket_Module.request_Device_Reg(Socket_Module.java:314)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: [응답] :: [DEVICE] >> [APP] :: 기기 등록 응답 확인]
I/: ----------------------------------------------------
I/: [LOG :: RESPONSE :: {"result":true}]
D///===========//: ================================================


E///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.Socket_Module.closeSocket(Socket_Module.java:217)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: 소켓 연결 종료 수행]
I/: ----------------------------------------------------
I/: [LOG :: 소켓 종료 상태 :: true]
E///===========//: ================================================

 

반응형
Comments