package kr.co.icontrols.ilp300_700.global;

import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.CountDownTimer;
import android.provider.Settings;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;

import java.io.File;
import java.io.FilenameFilter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import kr.co.icontrols.iencryptor.aes128.AES_128;
import kr.co.icontrols.iencryptor.aes128.AES_128.ENCRYPTTYPE;
import kr.co.icontrols.iencryptor.aesfp.AES_FingerPrint;
import kr.co.icontrols.iencryptor.ukey.UKEY;
import kr.co.icontrols.ilp300_700.MainActivity;
import kr.co.icontrols.ilp300_700.R;
import kr.co.icontrols.ilp300_700.call.CallManager.CALLTYPE;
import kr.co.icontrols.ilp300_700.ethernet.EthernetCtrl;
import kr.co.icontrols.ilp300_700.ethernet.iMAPCommon.iMAPResult;
import kr.co.icontrols.ilp300_700.ethernet.iMAPServer;
import kr.co.icontrols.ilp300_700.global.Configure.ConfigValKey;
import kr.co.icontrols.ilp300_700.global.Configure.ConfigValue;
import kr.co.icontrols.ilp300_700.global.Configure.DefaultConfigValue;
import kr.co.icontrols.ilp300_700.global.Configure.SetValue;
import kr.co.icontrols.ilp300_700.global.DataClasses.ConfigValueTable;
import kr.co.icontrols.ilp300_700.global.Declare.AccessValues;
import kr.co.icontrols.ilp300_700.global.Declare.DeviceString;
import kr.co.icontrols.ilp300_700.global.Declare.DeviceType;
import kr.co.icontrols.ilp300_700.global.Declare.ServerVersion;
import kr.co.icontrols.ilp300_700.global.Declare.TargetPort;
import kr.co.icontrols.ilp300_700.global.Enumeration.DATAINPUTSCREEN;
import kr.co.icontrols.ilp300_700.global.Enumeration.DATAINPUTSTEP;
import kr.co.icontrols.ilp300_700.global.Enumeration.PWTYPE;
import kr.co.icontrols.ilp300_700.global.Enumeration.TARGETINFOINPUTSTEP;
import kr.co.icontrols.ilp300_700.global.Enumeration.UPGRADESTATUS;
import kr.co.icontrols.ilp300_700.imap.Notices;
import kr.co.icontrols.ilp300_700.imap.Request_alarm_operation;
import kr.co.icontrols.ilp300_700.imap.Request_device_bootup;
import kr.co.icontrols.ilp300_700.imap.Request_elevator_call;
import kr.co.icontrols.ilp300_700.imap.Request_event_notify;
import kr.co.icontrols.ilp300_700.imap.Request_get_setup_info;
import kr.co.icontrols.ilp300_700.imap.Request_lobby_sync_cardinfo;
import kr.co.icontrols.ilp300_700.imap.Request_lobby_sync_dcardinfo;
import kr.co.icontrols.ilp300_700.imap.Request_lobby_sync_mcardinfo;
import kr.co.icontrols.ilp300_700.imap.Request_verify_access_authorization;
import kr.co.icontrols.ilp300_700.imap.iMAPResultCtrl;
import kr.co.icontrols.ilp300_700.rfmsg.Request_MultiRF_Status;

import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;

public final class Global {
    // 로비폰에서 공통으로 사용하는 함수 및 변수를 정의합니다.
    static final String TAG = "Global";

    public static boolean bEnableDeviceInput = false;   // 부팅이 완료되기 전까지 모든 입력(버튼, 시리얼, iMAP)을 차단하기 위한 변수 (JEFF, 2015.03.08)
    public static boolean bSTTTTS = false;   // STT, TTS 기능활성화를 제어하기 위한 변수
    public static int nCurrentScreenID = 0;   // 현재 ScreenID를 저장하는 변수
    public static String strInputPW = "";   // 화면에서 입력하는 비밀번호를 저장한다.
    // 사용금지 비밀번호 (해당 비밀번호를 사전에 차단한다)
    public static String[] astrBlockedPW = {" - - - - ", "0000", "1111", "2222", "3333", "4444", "5555", "6666", "7777", "8888", "9999", "1234"};
    // 관리자 메뉴의 세부설정메뉴에서 상위메뉴로 넘어갈때 이전페이지를 유지하기위해, 메뉴목록의 페이지 번호를 저장한다.
    public static int nAdminSetPageNumber = 1;
    // 로비폰 문열림 관련
    public static int Door_Close = 0;
    public static int Door_Open = 1;
    public static int nDoorOpenCntDN = 0;
    // 로비폰 멀티리더 리셋관련
    public static int MultiRFReader_Off = 0;
    public static int MultiRFReader_On = 1;
    // 로비폰 키패드 리셋관련
    public static int Keypad_Off = 0;
    public static int Keypad_On = 1;
    // 동호입력단계를 저장하기위한 enum
    public static TARGETINFOINPUTSTEP TargetInputStep = TARGETINFOINPUTSTEP.DONG;
    // 관리자 메뉴에서 설정정보 항목단위 입력단계
    public static DATAINPUTSTEP DataInputStep = DATAINPUTSTEP.INPUT_01;
    // 관리자 메뉴에서 설정정보 화면단위 입력단계
    public static DATAINPUTSCREEN DataInputScreen = DATAINPUTSCREEN.DETAIL_01;
    // device_bootup.request/reply 처리관련 함수
    // device_bootup이 실패할 경우, 재시도를 위한 함수
    public static boolean bDevicebootup = false;
    public static int nDevicebootupCnt = 0;
    // 비상알람
    public static int FireSensor_Inactive = 0;
    public static int FireSensor_Active = 1;
    // 스마트폰 원패스용 비콘 전송여부
    public static boolean bSendBeacon = true;
    // 원패스 시험모드 활성화 여부 (원패스문열림 요청 수신시 음원출력, 원패스 동작 관련 토스트메시지 출력, 값을 저장하지 않으므로, 재부팅하면 초기화 됨)
    public static boolean bOnePassTestMode = false;
    // 스마트키 시험모드 활성화 여부 (스마트키문열림 요청 수신시 음원출력, 스마트키 동작 관련 토스트메시지 출력, 값을 저장하지 않으므로, 재부팅하면 초기화 됨)
    public static boolean bSmartKeyTestMode = false;

    static boolean bLOG = true;   // true, false

    // 로비폰 IO Ctrl 관련코드
    static boolean bLOG_DEBUG = false;   // true, false
    static boolean bLOG_INFO = true;   // true, false
    static Context mContext;
    //    static CountDownTimer DoorCtrlTimer;
    static Timer DoorCtrlTimer = null;
    static CountDownTimer KeypadCtrlTimer;
    // Heartbeat 전송 타이머
    static Timer HeartbeatTimer;
    static int nHeartbeatCnt = 0;
    static TimerTask taskHeartbeatSender = new TimerTask() {

        @Override
        public void run() {
            try {
                LOG_INFO("[taskHeartbeatSender] nHeartbeatCnt = " + nHeartbeatCnt);
                checkDevicebootup();
                nHeartbeatCnt--;
                if (nHeartbeatCnt <= 0) {
                    Notices.send_Heartbeat();
                    setHeartbeatCnt();
                }
            } catch (Exception e) {
                Log.e(TAG, "[Exception] taskHeartbeatSender.run() : " + e);
                e.printStackTrace();
            }
        }
    };
    static int MAX_VOLUME_LEVEL = 15;
    static int MIN_VOLUME_LEVEL = 0;
    static int nVolumeLevel = 0;
    static int MAX_MONOOUT_VOLUME_LEVEL = 79;
    static int MIN_MONOOUT_VOLUME_LEVEL = 0;
    static int nMonoVolumeLevel = 0;
    static int[] anSystemVolumeTable = new int[]{0, 44, 46, 48, 50, 53, 56, 60, 64, 68, 72};
    static int[] anMoIPVolumeTable = new int[]{0, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79};
    static boolean bReadytoSync = false;
    static boolean bDoneGeneRandom = false;
    static int nSyncMin = 0;
    private static UPGRADESTATUS UpgradeStatus = UPGRADESTATUS.IDLE;
    private static boolean bRFReaderError = false;

    private static void LOG(String log) {
        if (bLOG) Log.v(TAG, log);
    }

    private static void LOG_DEBUG(String log) {
        if (bLOG_DEBUG) Log.d(TAG, log);
    }

    private static void LOG_INFO(String log) {
        if (bLOG_INFO) Log.i(TAG, log);
    }

    public static boolean getEnableDeviceInput() {
        try {
            return bEnableDeviceInput;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getEnableDeviceInput()");
            e.printStackTrace();
            return false;
        }
    }

    public static void setEnableDeviceInput(boolean bEnable) {
        try {
            bEnableDeviceInput = bEnable;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setEnableDeviceInput(boolean bEnable)");
            e.printStackTrace();
        }
    }

    // Context 전달
    public static boolean setGlobalContext(Context context) {
        try {
            mContext = context;
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setGlobalContext(context) " + e);
            e.printStackTrace();
            return false;
        }
    }

    // 기본 정보 설정
    public class BOARD_TYPE {
        public static final int V40 = 1;
    }

    public static void getConfigValues() {
        setDeviceType();
        printConfigValues();
    }

    public static void setDeviceType() {
        ConfigValue.DEVICE_MODELTYPE = MainActivity.mIOInterface.getDeviceModelType();
        ConfigValue.DEVICE_BOARDTYPE = getBoardType(ConfigValue.DEVICE_MODELTYPE);
    }

    public static int MODEL_ILP_300 = 0;
    public static int MODEL_ILP_700 = 1;

    public static int getBoardType(int nModelType) {
        try {
            if (nModelType == MODEL_ILP_300 || nModelType == MODEL_ILP_700) return BOARD_TYPE.V40;
            else{
                Log.w(TAG, "[getBoardType] Not Supported MODEL_TYPE");
                return -99;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getBoardType(int nModelType)");
            e.printStackTrace();
            return -99;
        }
    }

    public static void printConfigValues() {
        LOG_INFO("[printConfigValues] DEVICE_BOARDTYPE [" + ConfigValue.DEVICE_BOARDTYPE + "]");
        LOG_INFO("[printConfigValues] DEVICE_MODELTYPE [" + ConfigValue.DEVICE_MODELTYPE + "]");
    }

    public static String[] makeDeviceName(String ipaddress) {
        String[] aDeviceName = new String[3];
        try {
            String dong = "101";
            String ho = "101";
            String type = DeviceString.strType_Resi;

            String[] IP_Parse = ipaddress.split("\\.");

            LOG_DEBUG("[makeDeviceName] IP_Parse.length = " + IP_Parse.length);
//            for (int i = 0; i < IP_Parse.length; i++)
//            {
//                Log.d(TAG, "IP_Parse[" + i + "] : " + IP_Parse[i]);
//            }

            dong = Integer.toString((((Integer.parseInt(ConfigValue.strDevice_Dong) / 100) * 100) + Integer.parseInt(IP_Parse[1])));

            if (IP_Parse[2] == "128") {
                // 경비실폰
                type = DeviceString.strType_Guard;
                ho = IP_Parse[3];
            } else if (IP_Parse[2] == "0") {
                // 로비폰
                type = DeviceString.strType_Lobby;
                ho = IP_Parse[3];
            } else {
                type = DeviceString.strType_Resi;
                ho = IP_Parse[2] + ZeroPadding_Head(2, IP_Parse[3]);
            }

            LOG_INFO("[makeDeviceName] type = " + type + ", dong = " + dong + ", ho = " + ho);

            aDeviceName[0] = type;
            aDeviceName[1] = dong;
            aDeviceName[2] = ho;

            return aDeviceName;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] makeDeviceName(...) : " + e);
            e.printStackTrace();
            return aDeviceName;
        }
    }

    public static String ZeroPadding_Head(int nOutLength, String strOriginalString) {
        String strResult = strOriginalString;
        LOG_DEBUG("[ZeroPadding_Head] (Length) strOriginalString [" + strOriginalString.length() + "], nOutLength [" + nOutLength + "]");
        try {
            if (strOriginalString.length() < nOutLength) {
                for (int i = strOriginalString.length(); i < nOutLength; i++) {
                    strResult = "0" + strResult;
                }
                LOG_DEBUG("[ZeroPadding_Head] strResult : " + strResult);
            } else if (strOriginalString.length() == nOutLength) {
                LOG_DEBUG("[ZeroPadding_Head] same length!");
            } else {
                LOG_INFO("[ZeroPadding_Head] strOriginalString(" + strOriginalString.length() + ") is longer than nOutLength(" + nOutLength + ")");
            }
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ZeroPadding_Head(int nOutLength, String strOriginalString)");
            e.printStackTrace();
            return strResult;
        }
    }

    public static String ZeroPadding_Tail(int nOutLength, String strOriginalString) {
        String strResult = strOriginalString;
        LOG_DEBUG("[ZeroPadding_Tail] (Length) strOriginalString [" + strOriginalString.length() + "], nOutLength [" + nOutLength + "]");
        try {
            if (strOriginalString.length() < nOutLength) {
                for (int i = strOriginalString.length(); i < nOutLength; i++) {
                    strResult = strResult + "0";
                }
                LOG_DEBUG("[ZeroPadding_Tail] strResult : " + strResult);
            } else if (strOriginalString.length() == nOutLength) {
                LOG_DEBUG("[ZeroPadding_Tail] same length!");
            } else {
                LOG_INFO("[ZeroPadding_Tail] strOriginalString(" + strOriginalString.length() + ") is longer than nOutLength(" + nOutLength + ")");
            }
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ZeroPadding_Tail(int nOutLength, String strOriginalString)");
            e.printStackTrace();
            return strResult;
        }
    }

    public static boolean ComparePW(PWTYPE PWType, String strPW) {
        try {
            LOG_DEBUG("[ComparePW] PWType [" + PWType + "], strPW [" + strPW + "]");
            if (PWType == PWTYPE.ACCESS_PUBLICPW) {
                if (strPW.equals(ConfigValue.strPublicAccessPW)) return true;
                else return false;
            } else if (PWType == PWTYPE.ACCESS_ADMINPW) {
                if (strPW.equals(ConfigValue.strAdminAccessPW)) return true;
                else return false;
            } else if (PWType == PWTYPE.ADMINSETPW) {
                if (strPW.equals("88771831")) return true;
                else if (strPW.equals("135566545")) {
                    // 관리자 설정 비밀번호를 초기화 한다. (2580)
                    // 비번 : 회사 우편번호(13556) + 콜센터번호 뒷자리(6545)
                    resetAdminSetPW();
                    return false;
                } else if (strPW.equals(ConfigValue.strAdminPW)) return true;
                else return false;
            } else {
                return false;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ComparePW(PWTYPE PWType, String strPW)");
            e.printStackTrace();
            return false;
        }
    }

    public static boolean resetAdminSetPW() {
        try {
            ConfigValue.strAdminPW = "2580";
            if (!MainActivity.ConfigDBManager.setData(Declare.DBInfo.TABLE_NAME_CONFIG, ConfigValKey.AdminPW, ConfigValue.strAdminPW)) return false;
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] resetAdminSetPW()");
            e.printStackTrace();
            return false;
        }
    }

    public static boolean ctrlLobbyDoorNMent(boolean bOpen, boolean bPlayMent, int nOpenSec, boolean bSmartKey, boolean bDurationChange) {
        try {
            LOG_INFO("[ctrlLobbyDoorNMent] bOpen [" + bOpen + "], bPlayMent [" + bPlayMent + "], nOpenSec [" + nOpenSec + "], bSmartKey [" + bSmartKey + "], bDurationChange [" + bDurationChange + "]");
            if (bOpen && nOpenSec < 1) {
                LOG_INFO("[ctrlLobbyDoorNMent] nOpenSec < 1");
                if (bPlayMent && !bSmartKey) MainActivity.mSound.PlayMent_lobby(R.raw.retryinput);
                return true;
            }

            if (bOpen) {
                LOG_INFO("[ctrlLobbyDoorNMent] Door Open!!");
//                if (bPlayMent) MainActivity.mSound.PlayMent_lobby(R.raw.dooropen);
                MainActivity.mIOInterface.ctrlDoorOpen(true);

                if (nDoorOpenCntDN > 0) {
                    // 타이머가 돌아가고 있음, 시간을 연장함.
                    if (bPlayMent && !bSmartKey) MainActivity.mSound.PlayMent_lobby(R.raw.dooropen);
                    if (bDurationChange) nDoorOpenCntDN = nOpenSec;
                    else {
                        if (nDoorOpenCntDN < nOpenSec) nDoorOpenCntDN = nOpenSec;
                    }
                } else {
                    // 타이머가 돌아가지 않고 있음, 새로 구동함.
                    if (bPlayMent) {
                        LOG_INFO("[ctrlLobbyDoorNMent] PlayMent_lobby!!");
//                        MainActivity.mSound.PlayMent_lobby(R.raw.dooropen);
                        MainActivity.mSound.Play_lobby(R.raw.dooropen);
                    }
                    nDoorOpenCntDN = nOpenSec;
                    DoorCtrlTimer = new Timer();
                    DoorCtrlTimer.schedule(new DoorCntDown(), 1000, 1000);
                }
                return true;
            }
            else {
                LOG_INFO("[ctrlLobbyDoorNMent] Door Close!!");
                LOG_INFO("[ctrlLobbyDoorNMent] ConfigValue.eFireSensorDetected = " + ConfigValue.eFireSensorDetected);
                if (ConfigValue.eFireSensorDetected == SetValue.FALSE) {
//                    MainActivity.mIOInterface.ilp300_700_ctrlDoor(Door_Close);
                    MainActivity.mIOInterface.ctrlDoorOpen(false);
                }
                if (bPlayMent && !bSmartKey) MainActivity.mSound.PlayMent_lobby(R.raw.retryinput);
                nDoorOpenCntDN = 0;
                return true;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ctrlLobbyDoorNMent(boolean bOpen, boolean bPlayMent, int nOpenSec, boolean bSmartKey, boolean bDurationChange) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static void KeypadPowerReset() {
        try {
            MainActivity.mIOInterface.ctrlKeypadPower(false);
            KeypadCtrlTimer();
            KeypadCtrlTimer.start();
        } catch (Exception e) {
            Log.d(TAG, "[Exception] KeypadPowerReset()");
        }
    }

    private static void KeypadCtrlTimer() {
        try {
            LOG_INFO("[KeypadCtrlTimer] ===== START =====");
            KeypadCtrlTimer = new CountDownTimer(100, 100) {
                @Override
                public void onTick(long millisUntilFinished) {
                    LOG_DEBUG("[KeypadCtrlTimer] onTick!!");
                    LOG_DEBUG("[KeypadCtrlTimer] Remains = " + millisUntilFinished / 1000);
                }

                @Override
                public void onFinish() {
                    LOG_INFO("[KeypadCtrlTimer] onFinish!!");
                    MainActivity.mIOInterface.ctrlKeypadPower(true);
                    KeypadCtrlTimer.cancel();
                }
            };
        } catch (Exception e) {
            Log.e(TAG, "[Exception] KeypadCtrlTimer() : " + e);
            e.printStackTrace();
        }
    }

    public static boolean setUpgradeStatus(UPGRADESTATUS Status) {
        try {
            LOG_INFO("[setUpgradeStatus] Status = " + Status);
            UpgradeStatus = Status;
            LOG_INFO("[setUpgradeStatus] UpgradeStatus = " + UpgradeStatus);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setUpgradeStatus(Status) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static UPGRADESTATUS getUpgradeStatus() {
        try {
            LOG_INFO("[getUpgradeStatus] UpgradeStatus = " + UpgradeStatus);
            return UpgradeStatus;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getUpgradeStatus() : " + e);
            e.printStackTrace();
            return UPGRADESTATUS.ERROR;
        }
    }

    public static void cancelSystemUpgrade(String[] strFilePath) {
        try {
            LOG_INFO("[cancelSystemUpgrade] ===== START =====");
            if (strFilePath != null) {
                LOG_INFO("[cancelSystemUpgrade] strFilePath.length = " + strFilePath.length);
                for (int i = 0; i < strFilePath.length; i++) {
                    LOG_INFO("[cancelSystemUpgrade] strFilePath[" + i + "] = " + strFilePath[i]);
                }

                File mFile;
                for (int i = 0; i < strFilePath.length; i++) {
                    String[] astrFilePath = strFilePath[i].split("/");
                    String strLocalFilePath = "/sdcard/" + astrFilePath[astrFilePath.length - 1];
                    mFile = new File(strLocalFilePath);
                    if (mFile.exists()) {
                        boolean bResult = mFile.delete();
                        LOG_INFO("[cancelSystemUpgrade] strLocalFilePath = " + strLocalFilePath + ", bResult = " + bResult);
                        Thread.sleep(500);
                    }
                }
            }
            iMAPServer.ProcSysUp = null;
            setUpgradeStatus(UPGRADESTATUS.IDLE);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] cancelSystemUpgrade(strFileName) : " + e);
            e.printStackTrace();
            iMAPServer.ProcSysUp = null;
            setUpgradeStatus(UPGRADESTATUS.IDLE);
        }
    }

    public static void cancelFileUpload() {
        try {
            iMAPServer.mProcFTPUploadThread.interrupt();
            iMAPServer.mProcFTPUploadThread = null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] cancelSystemUpgrade(strFileName) : " + e);
            e.printStackTrace();
        }
    }

    public static boolean startHeartbeatSender() {
        try {
            LOG_INFO("[startHeartbeatSender] ===== START =====");
            HeartbeatTimer = new Timer();
            HeartbeatTimer.schedule(taskHeartbeatSender, 1000, 60000);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] startHeartbeatTimer() : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static void setHeartbeatCnt() {
        try {
            nHeartbeatCnt = ConfigValue.nHearBeatTime;
            LOG_INFO("[setHeartbeatCnt] nHeartbeatCnt = " + nHeartbeatCnt);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setHeartbeatCnt() : " + e);
            e.printStackTrace();
        }
    }

    public static void checkDevicebootup() {
        try {
            LOG_INFO("[checkDevicebootup] bDevicebootup [" + bDevicebootup + "]");
            if (!bDevicebootup) send_device_bootup_request_cnt(nDevicebootupCnt);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkDevicebootup() : " + e);
            e.printStackTrace();
        }
    }

    private static boolean send_device_bootup_request_cnt(int nCnt) {
        try {
            if (nDevicebootupCnt > 9999) nDevicebootupCnt = 0;
            nDevicebootupCnt++;
            final Request_device_bootup device_bootup = new Request_device_bootup(mContext);
            if (device_bootup.send_device_bootup_request_cnt(nCnt)) {
                device_bootup.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[send_device_bootup_request_cnt] (onResult) eResult = " + eResult);
                        if (eResult == iMAPResult.OK) {
                            int nYear = 0, nMonth = 0, nDate = 0, nHour = 0, nMin = 0;
                            String strLocationName = "";
                            int nLocationCode = 0;
                            String strServerVer = "1.0";
                            device_bootup.setItem("date");
                            nYear = Integer.parseInt(device_bootup.getAttributeValue(0, "year"));
                            nMonth = Integer.parseInt(device_bootup.getAttributeValue(0, "month"));
                            nDate = Integer.parseInt(device_bootup.getAttributeValue(0, "date"));
                            device_bootup.setItem("time");
                            nHour = Integer.parseInt(device_bootup.getAttributeValue(0, "hour"));
                            nMin = Integer.parseInt(device_bootup.getAttributeValue(0, "min"));
                            device_bootup.setItem("location");
                            strLocationName = device_bootup.getAttributeValue(0, "name");
                            nLocationCode = Integer.parseInt(device_bootup.getAttributeValue(0, "code"));
                            strServerVer = device_bootup.getItemValue("ver_server");

                            LOG_INFO("[send_device_bootup] Calendar [" + nYear + "/" + nMonth + "/" + nDate + " " + nHour + ":" + nMin + "]");
                            LOG_INFO("[send_device_bootup] strLocationName [" + strLocationName + "], nLocationCode [" + nLocationCode + "]");
                            LOG_INFO("[send_device_bootup] strServerVer [" + strServerVer + "]");

                            Global.bDevicebootup = Global.setSystemTime(nYear, nMonth, nDate, nHour, nMin);
                            Global.setMainServerType(strServerVer);
                            LOG_INFO("[send_device_bootup] Global.bDevicebootup [" + Global.bDevicebootup + "]");
                            if (Global.bDevicebootup) sendAppTimeTickBR();
                        }
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_device_bootup_request_cnt()");
            e.printStackTrace();
            return false;
        }
    }

    private static void sendAppTimeTickBR() {
        try {
            Intent intent = new Intent();
            intent.setAction(Declare.PrivateBR.UPDATE_MAINSCREEN);
            ((MainActivity) mContext).getBaseContext().sendBroadcast(intent);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendAppTimeTickBR()");
            e.printStackTrace();
        }
    }

    // Byte배열을 출력하는 함수
    public static String printHexs(byte[] hdata) {
        try {
            String strResult = "";
            LOG_DEBUG("[printHexs] hdata.length = " + hdata.length);
            for (int i = 0; i < hdata.length; i++) {
                strResult += HextoString((byte) hdata[i]) + " ";
            }
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] HextoString(hdata) : " + e);
            e.printStackTrace();
            return null;
        }
    }

    public static String printHexsDebug(byte[] hdata) {
        try {
            String strResult = "";
            LOG_DEBUG("[printHexs] hdata.length = " + hdata.length);
            for (int i = 0; i < hdata.length; i++) {
                strResult += HextoString((byte) hdata[i]);
            }
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] HextoString(hdata) : " + e);
            e.printStackTrace();
            return null;
        }
    }

    // Byte배열을 출력하는 함수
    public static String getFingerprintInfoString(byte[] hdata) {
        try {
            String strResult = "";
            LOG_DEBUG("[getFingerprintInfoString] hdata.length = " + hdata.length);
            for (int i = 9; i < hdata.length - 2; i++) {
                strResult += HextoString((byte) hdata[i]);
            }
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getFingerprintInfoString(hdata) : " + e);
            e.printStackTrace();
            return null;
        }
    }

    // Byte배열을 출력하는 함수
    public static String printHexs(byte[] hdata, int nLength) {
        try {
            String strResult = "";
            int nDataLength = 0;
            if (hdata.length > nLength) nDataLength = nLength;
            else nDataLength = hdata.length;
            LOG_DEBUG("[printHexs] nDataLength = " + nDataLength);
            for (int i = 0; i < nDataLength; i++) {
                strResult += HextoString((byte) hdata[i]) + " ";
            }
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] printHexs(hdata, nLength) : " + e);
            e.printStackTrace();
            return null;
        }
    }

    // Byte를 String으로 변환
    public static String HextoString(byte data) {
        try {
            return String.format("%02X", data);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] HextoString(data) : " + e);
            e.printStackTrace();
            return null;
        }
    }

    // String을 Byte배열로 변환
    public static byte[] StringToHex(String strTargetData) {
        try {
            if (strTargetData == null || strTargetData.length() == 0) {
                Log.w(TAG, "[StringToHex] strTargetData is null or it's length is 0!!");
                return null;
            }

            if ((strTargetData.length() % 2) != 0) {
                Log.w(TAG, "[StringToHex] The length of strTargetData is not even!!");
                return null;
            }

            byte[] hResult = new byte[strTargetData.length() / 2];

            for (int i = 0; i < hResult.length; i++) {
                hResult[i] = (byte) Integer.parseInt(strTargetData.substring(2 * i, 2 * i + 2), 16);
            }
            Log.i(TAG, "[StringToHex] hResult : " + printHexs(hResult));
            return hResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] StringToHex(String strTargetData)");
            e.printStackTrace();
            return null;
        }
    }

    // Byte배열을 String으로 변환
    public static String HexToString(byte[] hTargetData) {
        try {
            if (hTargetData == null || hTargetData.length == 0) {
                Log.w(TAG, "[StringToHex] hTargetData is null or it's length is 0!!");
                return null;
            }

            StringBuffer mStringBuffer = new StringBuffer(hTargetData.length * 2);
            String strHexNum;
            for (int i = 0; i < hTargetData.length; i++) {
                strHexNum = "0" + Integer.toHexString(0xFF & hTargetData[i]).toUpperCase();
                mStringBuffer.append(strHexNum.substring(strHexNum.length() - 2));
            }
            return mStringBuffer.toString();
        } catch (Exception e) {
            Log.e(TAG, "[Exception] HexToString(hTargetData) : " + e);
            e.printStackTrace();
            return null;
        }
    }

    // Short을 String으로 변환
    public static String ShorttoString(short data) {
        try {
            return String.format("%04X", data);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ShorttoString(short data)");
            e.printStackTrace();
            return null;
        }
    }

    // Char을 String으로 변환
    public static String ChartoString(char data) {
        try {
            return String.format("%04X", (int) data);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ChartoString(char data)");
            e.printStackTrace();
            return null;
        }
    }

    // 시스템 시간을 설정하는 함수
    public static boolean setSystemTime(int year, int month, int date, int hour, int min) {
        try {
            LOG("[setSystemTime] Cal Values [" + year + "/" + month + "/" + date + " " + hour + ":" + min + "]");

            String Calendar = ZeroPadding_Head(2, Integer.toString(month)) + "/" + ZeroPadding_Head(2, Integer.toString(date)) + "/" + ZeroPadding_Head(4, Integer.toString(year));
            if (!isValidCalendar(Calendar)) return false;

            Intent intent = new Intent();
            intent.setAction("SYSTEMTIMESET");
            intent.putExtra("DATE", String.format("%d&&%d&&%d", year, month - 1, date));
            intent.putExtra("TIME", String.format("%d&&%d&&%d", hour, min, 0));
            ((MainActivity) mContext).getBaseContext().sendBroadcast(intent);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setSystemTime(year, month, date, hour, min) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static boolean isValidCalendar(String calendar) {
        try {
            SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("MM/dd/yyyy");
            Date checkDate = null;
            try {
                checkDate = mSimpleDateFormat.parse(calendar);
            } catch (ParseException e) {
                Log.e(TAG, "[ParseException] isValidCalendar(calendar) : " + e);
                e.printStackTrace();
                return false;
            }
            if (!mSimpleDateFormat.format(checkDate).equals(calendar)) {
                Log.e(TAG, "[isValidCalendar] invalid input value!!");
                return false;
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] isValidCalendar(calendar) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static boolean playMelodyRepeat(SetValue eBell) {
        try {
            LOG_INFO("[playMelodyRepeat] eBell [" + eBell + "]");

            if (eBell == SetValue.Bell_1) {
                return MainActivity.mSound.PlayRepeat_lobby(R.raw.bell_01, 0);
            } else if (eBell == SetValue.Bell_2) {
                return MainActivity.mSound.PlayRepeat_lobby(R.raw.bell_02, 0);
            } else if (eBell == SetValue.Bell_3) {
                return MainActivity.mSound.PlayRepeat_lobby(R.raw.bell_03, 0);
            } else if (eBell == SetValue.Bell_4) {
                return MainActivity.mSound.PlayRepeat_lobby(R.raw.bell_04, 0);
            } else if (eBell == SetValue.Bell_5) {
                return MainActivity.mSound.PlayRepeat_lobby(R.raw.bell_05, 0);
            } else if (eBell == SetValue.Bell_6) {
                return MainActivity.mSound.PlayRepeat_lobby(R.raw.bell_06, 0);
            } else {
                stopMelodyRepeat();
                return false;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] playMelodyRepeat(eBell) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static boolean stopMelodyRepeat() {
        try {
            LOG("[stopMelodyRepeat] ===== START =====");
            if (MainActivity.mSound.isPlayRepeating()) {
                return MainActivity.mSound.StopRepeat();
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] stopMelodyRepeat() : " + e);
            e.printStackTrace();
            return false;
        }
    }

    // LCD Backlight Control
    public static boolean setLCDECOMode(int nMin) {
        try {
            LOG("[setLCDECOMode] nMin [" + nMin + "]");
            if (nMin == 0) {
//                MainActivity.mPowerManager.userActivity(2, true);
                ctrlLCDOnOff(true);
            } else {
//                MainActivity.mPowerManager.userActivity(1, true);
                ctrlLCDOnOff(false);
                boolean bResult = Settings.System.putInt(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, nMin * 60 * 1000);
                LOG_INFO("[setLCDECOMode] bResult [" + bResult + "]");
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setLCDECOMode(context, nMin) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static boolean ctrlLCDOnOff(final boolean bOn) {
        try {
            // 절전모드 사용시 호출수신등의 이벤트로 LCD 화면을 ON한다.
            // 모든 이벤트가 끝나고, 메인화면으로 전환시 절전모드를 다시 동작시킨다.
            LOG("[ctrlLCDOnOff] bOn [" + bOn + "]");
            ((MainActivity) mContext).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (bOn) {
                        boolean isScreenOn = MainActivity.mPowerManager.isScreenOn();
                        Log.d(TAG, "[ctrlLCDOnOff] isScreenOn [" + isScreenOn + "]");
                        if (!isScreenOn) {
                            Log.d(TAG, "[ctrlLCDOnOff] V40Interface LcdWakeUp Call!!");
                            MainActivity.mIOInterface.LcdWakeUp();
                        }
                        ((MainActivity) mContext).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                    } else
                        ((MainActivity) mContext).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                }
            });

            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ctrlLCDOnOff(bOn) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static boolean isExistResi(int nHo) {
        try {
            int nLineCnt = ConfigValue.LineInfo.getCnt();
            if (nLineCnt < 1 || 99 < nLineCnt) return false;

            int nHo_Head = nHo / 100;
            int nHo_Tail = nHo % 100;

            for (int i = 0; i < nLineCnt; i++) {
                if (ConfigValue.LineInfo.getLineInfo(i).NAME() == nHo_Tail) {
                    if (ConfigValue.LineInfo.getLineInfo(i).LOW() <= nHo_Head && nHo_Head <= ConfigValue.LineInfo.getLineInfo(i).HIGH()) {
                        // 라인정보를 기반으로 세대가 존재하면 true를 반환한다.
                        return true;
                    }
                }
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] isExistResi(nHo) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    public static String[] fineDirectoryFiles(String strDstDir, final String strKeyword, final String strExtention) {
        try {
            LOG_INFO("[fineDirectoryFiles] strDstDir [" + strDstDir + "], strKeyword [" + strKeyword + "], strExtention [" + strExtention + "]");
            String[] strResult = null;
            if (strDstDir == null) return null;
            File Directory = new File(strDstDir);
            if (Directory.exists()) {
                FilenameFilter mFilenameFilter = new FilenameFilter() {

                    @Override
                    public boolean accept(File dir, String filename) {
                        if (strKeyword != null && strExtention != null) {
                            return (filename.endsWith(strExtention) && filename.matches(".*" + strKeyword + ".*"));
                        } else if (strKeyword != null && strExtention == null) {
                            return filename.matches(".*" + strKeyword + ".*");
                        } else if (strKeyword == null && strExtention != null) {
                            return filename.endsWith(strExtention);
                        } else if (strKeyword == null && strExtention == null) {
                            return true;
                        }
                        return false;
                    }
                };

                String[] mFiles = Directory.list(mFilenameFilter);
                LOG_INFO("[fineDirectoryFiles] mFiles.length = " + mFiles.length);
                strResult = new String[mFiles.length];
                for (int i = 0; i < strResult.length; i++) {
                    strResult[i] = mFiles[i];
                    LOG_INFO("[fineDirectoryFiles] strResult[" + i + "] = " + strResult[i]);
                }
                return strResult;
            } else {
                LOG_INFO("[fineDirectoryFiles] Directory is not exist!! [" + strDstDir + "]");
                return null;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] fineDirectoryFiles() : " + e);
            e.printStackTrace();
            return null;
        }
    }

    // 출입키 암호화 함수 (스마트키, AES 128)
    public static String encryptHDCAccessKeyInfo(String strKeyInfo) {
        try {
            byte[] hCryptTarget = Global.StringToHex(strKeyInfo);
            byte[] hCryptedData = AES_128.Encrypt(ENCRYPTTYPE.NORMAL, hCryptTarget);
            String strCryptedData = "";
            for (int i = 0; i < hCryptedData.length; i++) {
                strCryptedData += Global.HextoString(hCryptedData[i]);
            }
            return strCryptedData;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptHDCAccessKeyInfo(String strKeyInfo) : " + e);
            e.printStackTrace();
            return "ERROR";
        }
    }

    public static String encryptHDCAccessKeyInfo_BLE(String strKeyInfo) {
        try {
            if (strKeyInfo.length() < 32) strKeyInfo = ZeroPadding_Tail(32, strKeyInfo);
            else if (strKeyInfo.length() > 32) return "TOO LONG";

            byte[] hCryptTarget = Global.StringToHex(strKeyInfo);
            byte[] hCryptedData = AES_128.Encrypt_ECB(ENCRYPTTYPE.NORMAL, hCryptTarget);
            String strCryptedData = "";
            for (int i = 0; i < hCryptedData.length; i++) {
                strCryptedData += Global.HextoString(hCryptedData[i]);
            }
            return strCryptedData;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptHDCAccessKeyInfo_BLE(String strKeyInfo) : " + e);
            e.printStackTrace();
            return "ERROR";
        }
    }

    public static String decryptHDCAccessKeyInfo_BLE(String strKeyInfo) {
        try {
            if (strKeyInfo.length() < 32) strKeyInfo = ZeroPadding_Tail(32, strKeyInfo);
            else if (strKeyInfo.length() > 32) return "TOO LONG";

            byte[] hCryptTarget = Global.StringToHex(strKeyInfo);
            byte[] hCryptedData = AES_128.Decrypt_ECB(ENCRYPTTYPE.NORMAL, hCryptTarget);
            String strCryptedData = "";
            for (int i = 0; i < hCryptedData.length; i++) {
                strCryptedData += Global.HextoString(hCryptedData[i]);
            }
            return strCryptedData;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] decryptHDCAccessKeyInfo_BLE(String strKeyInfo) : " + e);
            e.printStackTrace();
            return "ERROR";
        }
    }

    public static void demoAESECBCryption() {
        try {
            String strOriginal = "6859C468";
            String strEncrypted = Global.encryptHDCAccessKeyInfo_BLE(strOriginal);
            String strDecrypted = Global.decryptHDCAccessKeyInfo_BLE(strEncrypted);
            Log.d(TAG, "[demoAESECBCryption] strOriginal [" + strOriginal + "], strEncrypted [" + strEncrypted + "], strDecrypted [" + strDecrypted + "]");
        } catch (Exception e) {
            Log.e(TAG, "[Exception] demoAESECBCryption()");
            e.printStackTrace();
        }
    }

    // 출입키 암호화 함수 (현대건설향, 참슬테크 U-Key)
    public static String encryptHDECAccessKeyInfo(String strKeyInfo) {
        try {
//            Log.w(TAG, "strKeyInfo [" + strKeyInfo + "]");
            byte[] hCryptTarget = Global.StringToHex(strKeyInfo);
            byte[] hCryptedData = UKEY.Encrypt(hCryptTarget);
//            Log.w(TAG, "hCryptedData.length = " + hCryptedData.length);
            String strCryptedData = "";
            for (int i = 0; i < hCryptedData.length; i++) {
                strCryptedData += Global.HextoString(hCryptedData[i]);
            }
            return strCryptedData;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptHDECAccessKeyInfo(String strKeyInfo) : " + e);
            e.printStackTrace();
            return "ERROR";
        }
    }

    public static boolean getFireSensorStatus() {
        try {
            return ((MainActivity.mIOInterface.getFireSensorStatus() == FireSensor_Active) ? true : false);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getFireSensorStatus()");
            e.printStackTrace();
            return true;
        }
    }

    public static void checkRebootEmergencySync() {
        try {
            if (getFireSensorStatus()) {
                if (ConfigValue.eFireSensorDetected == SetValue.FALSE)
                    setEmergencyMode();   // 전원 OFF중 센서감지
            } else {
                if (ConfigValue.eFireSensorDetected == SetValue.TRUE)
                    releaseEmergencyMode();   // 전원 OFF중 센서해제
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkRebootEmergencySync()");
            e.printStackTrace();
        }
    }

    public static Timer FireAlarmTimer = null;
    private static int nFireAlarmCntDN = -99;
    public static int FIRESENSOR_TIMEOUT = 5;   // 화재발생시 화재센서값은 3초 주기로 수신된다.
    public static void setFireAlarmProcess(int nTimeout) {
        try {
            LOG_INFO("[setFireAlarmProcess] nTimeout = " + nTimeout);
            LOG_INFO("[setFireAlarmProcess] nFireAlarmCntDN = " + nFireAlarmCntDN);
            if (FireAlarmTimer == null) LOG_INFO("[setFireAlarmProcess] FireAlarmTimer is null");
            else LOG_INFO("[setFireAlarmProcess] nFireAlarmCntDN is not null");

            if (nTimeout > 0) {
                // 타이머를 생성하거나, 시간을 연장한다.
                if (FireAlarmTimer == null && nFireAlarmCntDN < 0) {
                    LOG_INFO("[setFireAlarmProcess] ===== 1 =====");
                    // 타이머를 생성한다.
                    setEmergencyMode();
                    nFireAlarmCntDN = nTimeout;
                    FireAlarmTimer = new Timer();
                    FireAlarmTimer.schedule(new FireAlarmCntDown(), 1000, 1000);
                } else {
                    LOG_INFO("[setFireAlarmProcess] ===== 2 =====");
                    nFireAlarmCntDN = nTimeout;
                }
            } else {
                // 타이머를 종료한다.
                LOG_INFO("[setFireAlarmProcess] ===== 3 =====");
                if (FireAlarmTimer != null) FireAlarmTimer.cancel();
                FireAlarmTimer = null;
                nFireAlarmCntDN = -99;
            }
            LOG_INFO("[setFireAlarmProcess] ===== 4 =====");
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setFireAlarmProcess()");
            e.printStackTrace();
        }
    }

    public static class FireAlarmCntDown extends TimerTask {
        @Override
        public void run() {
//            LOG_DEBUG("[FireAlarmCntDown().run()] Start!!");
            try {
                nFireAlarmCntDN--;
                LOG_INFO("[FireAlarmCntDown] nCallTimeCntDN = " + nFireAlarmCntDN);
                if (nFireAlarmCntDN <= 0) {
                    // 화재센서가 감지가 타임아웃되면 상황을 종료한다.
                    if (FireAlarmTimer != null) FireAlarmTimer.cancel();
                    nFireAlarmCntDN = -99;
                    FireAlarmTimer = null;
                    releaseEmergencyMode();
                    LOG_INFO("[FireAlarmCntDown] Fire sensor detection finished!!");
                }
            } catch (Exception e) {
                Log.e(TAG, "[Exception] FireAlarmCntDown().run()");
                e.printStackTrace();
            }
        }
    }

    public static void checkEmergencyMode() {
        try {
            LOG("[checkEmergencyMode] ConfigValue.eFireSensorDetected = " + ConfigValue.eFireSensorDetected);
            if (ConfigValue.eFireSensorDetected == SetValue.TRUE) MainActivity.showEmergencyImage(true);
            else MainActivity.showEmergencyImage(false);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkEmergencyMode()");
            e.printStackTrace();
        }
    }

    public static void setEmergencyMode() {
        try {
            // 통화중이었다면 통화를 종료합니다.
            ConfigValue.eFireSensorDetected = SetValue.TRUE;
            if (!MainActivity.ConfigDBManager.setData(Declare.DBInfo.TABLE_NAME_CONFIG, ConfigValKey.FireSensorDetected, ConfigValue.eFireSensorDetected)) {
                LOG("[setEmergencyMode] Fail to set DB!!!");
            }

            MainActivity.mIOInterface.ctrlDoorOpen(true);
            ((MainActivity)mContext).sendHandlerMsg(MainActivity.HANDLERMSG.IMG_ON_EMERGENCY, 0, 0);
            send_alarm_operation_request_Monitor(Declare.Alarm.Mode.Fired, Declare.Alarm.Cause.fire, ConfigValue.strDevice_Dong, ConfigValue.strDevice_ID);
            send_alarm_operation_request_Guard(Declare.Alarm.Mode.Fired, Declare.Alarm.Cause.fire, ConfigValue.strDevice_Dong, ConfigValue.strDevice_ID);
            send_alarm_operation_request_Server(Declare.Alarm.Mode.Fired, Declare.Alarm.Cause.fire, ConfigValue.strDevice_Dong, ConfigValue.strDevice_ID);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setEmergencyMode()");
            e.printStackTrace();
        }
    }

    public static void releaseEmergencyMode() {
        try {
            ConfigValue.eFireSensorDetected = SetValue.FALSE;
            if (!MainActivity.ConfigDBManager.setData(Declare.DBInfo.TABLE_NAME_CONFIG, ConfigValKey.FireSensorDetected, ConfigValue.eFireSensorDetected)) {
                LOG("[releaseEmergencyMode] Fail to set DB!!!");
            }

            MainActivity.mIOInterface.ctrlDoorOpen(false);
            ((MainActivity)mContext).sendHandlerMsg(MainActivity.HANDLERMSG.IMG_OFF_EMERGENCY, 0, 0);
            send_alarm_operation_request_Monitor(Declare.Alarm.Mode.Return, Declare.Alarm.Cause.fire, ConfigValue.strDevice_Dong, ConfigValue.strDevice_ID);
            send_alarm_operation_request_Guard(Declare.Alarm.Mode.Return, Declare.Alarm.Cause.fire, ConfigValue.strDevice_Dong, ConfigValue.strDevice_ID);
            send_alarm_operation_request_Server(Declare.Alarm.Mode.Return, Declare.Alarm.Cause.fire, ConfigValue.strDevice_Dong, ConfigValue.strDevice_ID);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] releaseEmergencyMode()");
            e.printStackTrace();
        }
    }

    private static boolean send_alarm_operation_request_Monitor(String strMode, String strCause, String strDong, String strHo) {
        try {
            Request_alarm_operation alarm_operation = new Request_alarm_operation(mContext);
            if (alarm_operation.send_alarm_operation_request(ConfigValue.strMonitoringPCIPAddress, strMode, strCause, strDong, strHo)) {
                alarm_operation.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        Log.d(TAG, "[send_alarm_operation_request_Monitor] (onResult) eResult =" + eResult);
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_alarm_operation_request_Monitor(strMode, strCause, strDong, strHo)");
            e.printStackTrace();
            return false;
        }
    }

    private static boolean send_alarm_operation_request_Guard(String strMode, String strCause, String strDong, String strHo) {
        try {
            Request_alarm_operation alarm_operation = new Request_alarm_operation(mContext);
            if (alarm_operation.send_alarm_operation_request(ConfigValue.strGuardIPAddress, strMode, strCause, strDong, strHo)) {
                alarm_operation.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        Log.d(TAG, "[send_alarm_operation_request_Guard] (onResult) eResult =" + eResult);
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_alarm_operation_request_Guard(strMode, strCause, strDong, strHo)");
            e.printStackTrace();
            return false;
        }
    }

    private static boolean send_alarm_operation_request_Server(String strMode, String strCause, String strDong, String strHo) {
        try {
            Request_alarm_operation alarm_operation = new Request_alarm_operation(mContext);
            if (alarm_operation.send_alarm_operation_request(ConfigValue.strMainServerIPAddress, strMode, strCause, strDong, strHo)) {
                alarm_operation.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        Log.d(TAG, "[send_alarm_operation_request_Server] (onResult) eResult =" + eResult);
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_alarm_operation_request_Server(strMode, strCause, strDong, strHo)");
            e.printStackTrace();
            return false;
        }
    }

    // 멀티리더 상태조회 체크
    public static void checkRFReaderErrorMode() {
        try {
            if (ConfigValue.eCardReaderType != SetValue.CardReaderType_Standard) return;
            final Request_MultiRF_Status multirf_status = new Request_MultiRF_Status(mContext);
            if (multirf_status.send_multirf_status_request()) {
                multirf_status.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[checkRFReaderErrorMode] (onResult) eResult = " + eResult);
                        if (eResult == iMAPResult.OK) {
                            MainActivity.nFRReaderErrorCnt = 0;
                        } else {
                            MainActivity.nFRReaderErrorCnt++;
                        }
                        MainActivity.displayRFReaderStatus();
                    }
                });
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkRFReaderErrorMode()");
            e.printStackTrace();
        }
    }

    // System volume control
    public static void setMusicStreamVolume(int nVolume) {   // MAX : 15
        try {
            int nCurrentVolume = 0;
            int nMaxVolume = 0;
            LOG_INFO("[setMusicStreamVolume] nVolume = " + nVolume);
            nMaxVolume = MainActivity.mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            nCurrentVolume = MainActivity.mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            LOG_INFO("[setMusicStreamVolume] Before nCurrentVolume [" + nCurrentVolume + "], nMaxVolume [" + nMaxVolume + "]");
            MainActivity.mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, nVolume, 0);
            nCurrentVolume = MainActivity.mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            LOG_INFO("[setMusicStreamVolume] After nCurrentVolume [" + nCurrentVolume + "], nMaxVolume [" + nMaxVolume + "]");
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setMusicStreamVolume(nVolume) : " + e);
            e.printStackTrace();
        }
    }

    public static void setSystemStreamVolume(int nVolume) {   // MAX : 7
        try {
            int nCurrentVolume = 0;
            int nMaxVolume = 0;
            LOG_INFO("[setSystemStreamVolume] nVolume = " + nVolume);
            nMaxVolume = MainActivity.mAudioManager.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);
            nCurrentVolume = MainActivity.mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM);
            LOG_INFO("[setSystemStreamVolume] Before nCurrentVolume [" + nCurrentVolume + "], nMaxVolume [" + nMaxVolume + "]");
            MainActivity.mAudioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, nVolume, 0);
            nCurrentVolume = MainActivity.mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM);
            LOG_INFO("[setSystemStreamVolume] After nCurrentVolume [" + nCurrentVolume + "], nMaxVolume [" + nMaxVolume + "]");
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setSystemStreamVolume(nVolume) : " + e);
            e.printStackTrace();
        }
    }

    public static void setSystemStreamVolume(boolean bUp) {
        try {
            int nMaxVolume = 0;
            int nSystemMaxVolume = MainActivity.mAudioManager.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);
            MainActivity.mAudioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, nSystemMaxVolume, 0);
            LOG_INFO("[setSystemStreamVolume] nSystemMaxVolume [" + nSystemMaxVolume + "]");
            int nRingMaxVolume = MainActivity.mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
            MainActivity.mAudioManager.setStreamVolume(AudioManager.STREAM_RING, nRingMaxVolume, 0);
            LOG_INFO("[setSystemStreamVolume] nRingMaxVolume [" + nRingMaxVolume + "]");
            nMaxVolume = MainActivity.mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            nVolumeLevel = MainActivity.mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            LOG_INFO("[setSystemStreamVolume] nVolumeLevel [" + nVolumeLevel + "], nMaxVolume [" + nMaxVolume + "]");
            if (bUp) {
                nVolumeLevel++;
                if (nVolumeLevel > MAX_VOLUME_LEVEL) nVolumeLevel = MAX_VOLUME_LEVEL;
            } else {
                nVolumeLevel--;
                if (nVolumeLevel < MIN_VOLUME_LEVEL) nVolumeLevel = MIN_VOLUME_LEVEL;
            }
            LOG_INFO("[setSystemStreamVolume] Before nVolumeLevel [" + nVolumeLevel + "], nMaxVolume [" + nMaxVolume + "]");
            MainActivity.mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, nVolumeLevel, 0);
            nVolumeLevel = MainActivity.mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            LOG_INFO("[setSystemStreamVolume] After nVolumeLevel [" + nVolumeLevel + "], nMaxVolume [" + nMaxVolume + "]");
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setSystemStreamVolume(bUp) : " + e);
            e.printStackTrace();
        }
    }

    public static void setSystemVolume(int nLevel) {
        try {
            int nRealLevel = nLevel + 5;   // 전체 1 ~ 15 단계중, 6 ~ 15 단계를 사용한다. (로비폰 10단계)
            LOG("[setSystemVolume] nLevel [" + nLevel + "], nRealLevel [" + nRealLevel + "]");
            LOG("[setSystemVolume] before getSystemVolume() = " + getSystemVolume());
            if (nRealLevel == getSystemVolume()) return;
            final AudioManager audioManager = (AudioManager) mContext.getSystemService(mContext.AUDIO_SERVICE);
            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, nRealLevel, 0);
            LOG("[setSystemVolume] after getSystemVolume() = " + getSystemVolume());
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setSystemVolume(int nLevel)");
            e.printStackTrace();
        }
    }

    // MoIP volume control
    public static int getSystemVolume() {
        try {
            final AudioManager audioManager = (AudioManager) mContext.getSystemService(mContext.AUDIO_SERVICE);
            int nCurrentSysVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            LOG("[getSystemVolume] nCurrentSysVolume [" + nCurrentSysVolume + "]");
            return nCurrentSysVolume;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getSystemVolume()");
            e.printStackTrace();
            return -1;
        }
    }

//    public static int[] nMoIPVolumeTable_Guard = new int[]{0x004C, 0x004C, 0x0080, 0x00B5, 0x0100, 0x016A, 0x01AE, 0x01FF, 0x025F, 0x02D1, 0x0359};
//    public static int[] nMoIPVolumeTable_Residence = new int[]{0x0080, 0x0080, 0x0100, 0x0130, 0x016A, 0x025F, 0x02D1, 0x0359, 0x03FB, 0x04BB, 0x059F};
    public static int[] nMoIPVolumeTable_Guard = new int[]{0x004C, 0x004C, 0x0080, 0x00B5, 0x0100, 0x016A, 0x01AE, 0x01FF, 0x025F, 0x02D1, 0x0359};
    public static int[] nMoIPVolumeTable_Residence = new int[]{0x0040, 0x0040, 0x004C, 0x0080, 0x00B5, 0x0100, 0x016A, 0x01AE, 0x01FF, 0x025F, 0x02D1};

    public static void setMoIPVolume(String sVolume) {
        try {
            LOG("[setMoIPVolume] nVolume [" + sVolume + "]");
            MainActivity.mIOInterface.volumectl(sVolume);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setMoIPVolume(String sVolume)");
            e.printStackTrace();
        }
    }

    public static void setMoIPVolume(int nVolume) {
        try {
            LOG("[setMoIPVolume] nVolume [" + nVolume + "]");
//            if (nLevel == getMoIPoVolume()) return;
            MainActivity.mIOInterface.setVolumeCtl(nVolume);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setMoIPVolume(int nVolume)");
            e.printStackTrace();
        }
    }

    public static int getMoIPoVolume() {
        try {
            int nCurrentVolume = ConfigValue.nVolumeLevel_Talk;
            LOG("[getMoIPVolume] nCurrentVolume [" + nCurrentVolume + "]");
            return nCurrentVolume;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getMoIPoVolume()");
            e.printStackTrace();
            return -1;
        }
    }

    public static void changeVolumeMoIPMode(CALLTYPE eCallType) {
        try {
            if (eCallType == CALLTYPE.RESIDENCE) {
                setMoIPVolume(nMoIPVolumeTable_Residence[ConfigValue.nVolumeLevel_Talk]);
            } else if (eCallType == CALLTYPE.GUARD) {
                setMoIPVolume(nMoIPVolumeTable_Guard[ConfigValue.nVolumeLevel_Talk]);
            } else {
                setSystemVolume(ConfigValue.nVolumeLevel_System);
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] changeVolumeMoIPMode(CALLTYPE eCallType) : " + e);
            e.printStackTrace();
        }
    }

    public static int getCurrentResiVolume(int vol) {
        try {
            Log.d(TAG, "[getCurrentResiVolume] vol [" + vol +"]");
            for (int i = 0; i < nMoIPVolumeTable_Residence.length; i++) {
                if (nMoIPVolumeTable_Residence[i] == vol) {
                    Log.d(TAG, "[getCurrentResiVolume] VOLUME [" + i + "]");
                    return i;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getCurrentResiVolume(int vol)");
            e.printStackTrace();
        }
        return -1;
    }

    public static int getCurrentGuardVolume(int vol) {
        try {
            Log.d(TAG, "[getCurrentGuardVolume] vol [" + vol +"]");
            for (int i = 0; i < nMoIPVolumeTable_Guard.length; i++) {
                if (nMoIPVolumeTable_Guard[i] == vol) {
                    Log.d(TAG, "[getCurrentGuardVolume] VOLUME [" + i + "]");
                    return i;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getCurrentGuardVolume(int vol)");
            e.printStackTrace();
        }
        return -1;
    }

    public static boolean sendSTDRFKeyInfo(String strKeyType, int nDong, int nID, int nIssueCnt) {
        try {
            LOG("[sendSTDRFKeyInfo] strKeyType [" + strKeyType + "], nDong [" + nDong + "], nID [" + nID + "], nIssueCnt [" + nIssueCnt + "]");
            if (ConfigValue.eMainSub == SetValue.Main) {
                // 서브폰들에게 카드정보를 전달한다.
                int nSubCnt = ConfigValue.SubInfo.getCnt();

                if (nSubCnt < 1) {
                    LOG("[sendSTDRFKeyInfo] There is no sub lobbyphone!!");
                    return true;
                }

                for (int i = 0; i < nSubCnt; i++) {
                    LOG("[sendSTDRFKeyInfo] ConfigValue.SubInfo.getSubInfo(" + i + ").IP = " + ConfigValue.SubInfo.getSubInfo(i).IP());
                    if (AccessValues.card.equalsIgnoreCase(strKeyType)) {
                        String strResiIP = EthernetCtrl.makeIPAddress(DeviceType.RESIDENCE, Integer.toString(nDong), Integer.toString(nID));
                        if (!send_lobby_sync_cardinfo_request(ConfigValue.SubInfo.getSubInfo(i).IP(), strResiIP, nIssueCnt)) {
                            return false;
                        }
                    } else if (AccessValues.dcard.equalsIgnoreCase(strKeyType)) {
                        if (!send_lobby_sync_dcardinfo_request(ConfigValue.SubInfo.getSubInfo(i).IP(), nID, nIssueCnt)) {
                            return false;
                        }
                    } else if (AccessValues.mcard.equalsIgnoreCase(strKeyType)) {
                        if (!send_lobby_sync_mcardinfo_request(ConfigValue.SubInfo.getSubInfo(i).IP(), nID, nIssueCnt)) {
                            return false;
                        }
                    }
                }
            } else if (ConfigValue.eMainSub == SetValue.Sub) {
                // 메인로비폰으로 카드정보를 전달한다.
                String strTargetIP = makeLobbyIPAddress(Integer.parseInt(ConfigValue.strDevice_Dong), Integer.parseInt(ConfigValue.strMainLPID));
                if (AccessValues.card.equalsIgnoreCase(strKeyType)) {
                    String strResiIP = EthernetCtrl.makeIPAddress(DeviceType.RESIDENCE, Integer.toString(nDong), Integer.toString(nID));
                    if (!send_lobby_sync_cardinfo_request(strTargetIP, strResiIP, nIssueCnt)) {
                        return false;
                    }
                } else if (AccessValues.dcard.equalsIgnoreCase(strKeyType)) {
                    if (!send_lobby_sync_dcardinfo_request(strTargetIP, nID, nIssueCnt)) {
                        return false;
                    }
                } else if (AccessValues.mcard.equalsIgnoreCase(strKeyType)) {
                    if (!send_lobby_sync_mcardinfo_request(strTargetIP, nID, nIssueCnt)) {
                        return false;
                    }
                }
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendSTDRFKeyInfo(strKeyType, nDong, nHo, nIssueCnt) : " + e);
            e.printStackTrace();
            return false;
        }
    }

    private static boolean send_lobby_sync_cardinfo_request(String strTargetIP, String strResiIP, int nIssueCnt) {
        try {
            Request_lobby_sync_cardinfo lobby_sync_cardinfo = new Request_lobby_sync_cardinfo(mContext);
            if (lobby_sync_cardinfo.send_lobby_sync_cardinfo_request(strTargetIP, strResiIP, nIssueCnt)) {
                lobby_sync_cardinfo.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[send_lobby_sync_cardinfo_request] (onResult) eResult =" + eResult);
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_lobby_sync_cardinfo_request(strTargetIP, strResiIP, nIssueCnt)");
            e.printStackTrace();
            return false;
        }
    }

    private static boolean send_lobby_sync_dcardinfo_request(String strTargetIP, int nIDNo, int nIssueCnt) {
        try {
            Request_lobby_sync_dcardinfo lobby_sync_dcardinfo = new Request_lobby_sync_dcardinfo(mContext);
            if (lobby_sync_dcardinfo.send_lobby_sync_dcardinfo_request(strTargetIP, nIDNo, nIssueCnt)) {
                lobby_sync_dcardinfo.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[send_lobby_sync_dcardinfo_request] (onResult) eResult =" + eResult);
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_lobby_sync_dcardinfo_request(strTargetIP, nIDNo, nIssueCnt)");
            e.printStackTrace();
            return false;
        }
    }

    private static boolean send_lobby_sync_mcardinfo_request(String strTargetIP, int nIDNo, int nIssueCnt) {
        try {
            Request_lobby_sync_mcardinfo lobby_sync_mcardinfo = new Request_lobby_sync_mcardinfo(mContext);
            if (lobby_sync_mcardinfo.send_lobby_sync_mcardinfo_request(strTargetIP, nIDNo, nIssueCnt)) {
                lobby_sync_mcardinfo.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[send_lobby_sync_mcardinfo_request] (onResult) eResult =" + eResult);
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_lobby_sync_mcardinfo_request(strTargetIP, nIDNo, nIssueCnt)");
            e.printStackTrace();
            return false;
        }
    }

    private static String makeLobbyIPAddress(int nDong, int nLobbyID) {
        try {
            LOG("[makeLobbyIPAddress] nDong [" + nDong + "], nLobbyID [" + nLobbyID + "]");
            int nDongIP = nDong % 100;
            if (nLobbyID < 1 || 99 < nLobbyID) {
                LOG("[makeLobbyIPAddress] nLobbyID is out of range!!");
                return "ERROR";
            }
            String strResult = "10." + nDongIP + ".0." + nLobbyID;
            LOG("[makeLobbyIPAddress] strResult [" + strResult + "]");
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] makeLobbyIPAddress(nDong, nLobbyID)");
            e.printStackTrace();
            return "ERROR";
        }
    }

    public static boolean sendElevCallRequest(String strDong, String strHo, boolean bUp) {
        try {
            LOG("[sendElevCallRequest] strDong [" + strDong + "], strHo [" + strHo + "], bUp [" + bUp + "]");
            if (strDong.equalsIgnoreCase("null") || strHo.equalsIgnoreCase("null")) {
                // event_notify.request send
                String strEvent = "elevator_up";
                if (bUp) strEvent = "elevator_up";
                else strEvent = "elevator_dn";
                return send_event_notify_request(strEvent);
            } else {
                // elevator_call.request send
                if (!checkElevDisable(strHo)) return false;
                String strCMD = "up";
                if (bUp) strCMD = "up";
                else strCMD = "down";
                return send_elevator_call_request(strDong, strHo, strCMD);
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendElevCallRequest(strDong, strHo, bUp)");
            e.printStackTrace();
            return false;
        }
    }

    private static boolean checkElevDisable(String strHo) {
        try {
            // Check Elev. disable floors
            // return: true(Elev. Enable), false(Elev. Disable)
            LOG("[checkElevDisable] strHo [" + strHo + "]");
            int nCnt = ConfigValue.ElevDisable.getCnt();
            if (nCnt < 1) {
                // There is no Elev. disabled floors.
                return true;
            }
            int nFloor = Integer.parseInt(strHo) / 100;

            for (int i = 0; i < nCnt; i++) {
                if (ConfigValue.ElevDisable.getElevDisableInfo(i).FLOOR() == nFloor) {
                    LOG_INFO("[checkElevDisable] Elev. disabled floor [" + nFloor + "]");
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkElevDisable(strHo)");
            e.printStackTrace();
            return false;
        }
    }

    private static boolean send_event_notify_request(String strEvent) {
        try {
            Request_event_notify event_notify = new Request_event_notify(mContext);
            if (event_notify.send_event_notify_request(strEvent)) {
                event_notify.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[send_event_notify_request] (onResult) eResult =" + eResult);
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_event_notify_request(strEvent)");
            e.printStackTrace();
            return false;
        }
    }

    private static boolean send_elevator_call_request(String strDong, String strHo, String strCMD) {
        try {
            Request_elevator_call elevator_call = new Request_elevator_call(mContext);
            if (elevator_call.send_elevator_call_request(strDong, strHo, strCMD)) {
                elevator_call.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[send_elevator_call_request] (onResult) eResult =" + eResult);
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_elevator_call_request(strDong, strHo, strCMD)");
            e.printStackTrace();
            return false;
        }
    }

    public static boolean send_verify_access_authorization(String strRecogType, String strOwner, int nDataLength, byte[] hRecogData, String strMessage) {
        try {
//            String strOriginalPFData = getFingerprintInfoString(hRecogData);
            String strEncryptedPFData = AES_FingerPrint.encryptFPData(Integer.parseInt(ConfigValue.strDevice_Dong), Integer.parseInt(ConfigValue.strDevice_ID), getFingerprintInfoString(hRecogData));
//            String strDecryptedPFData = AES_FingerPrint.decryptFPData(Integer.parseInt(ConfigValue.strDevice_Dong), Integer.parseInt(ConfigValue.strDevice_ID), strEncryptedPFData);

//            Log.i(TAG, "[send_verify_access_authorization] Original");
//            Log.i(TAG, "[send_verify_access_authorization] >" + strOriginalPFData);
//            Log.i(TAG, "[send_verify_access_authorization] Encrypted");
//            Log.i(TAG, "[send_verify_access_authorization] >" + strEncryptedPFData);
//            Log.i(TAG, "[send_verify_access_authorization] Decrypted");
//            Log.i(TAG, "[send_verify_access_authorization] >" + strDecryptedPFData);
//            if (strOriginalPFData.equals(strDecryptedPFData)) Log.w(TAG, "[send_verify_access_authorization] The Original data is same as decrypted data!!!");
//            else Log.w(TAG, "[send_verify_access_authorization] The Original data is different from decrypted data!!!");

            final Request_verify_access_authorization verify_access_authorization = new Request_verify_access_authorization(mContext);
            if (verify_access_authorization.send_verify_access_authorization_request(Declare.DeviceInfo.Type.toString().toLowerCase(), ConfigValue.strDeviceIPAddress, strRecogType, strOwner, nDataLength - 11, strEncryptedPFData, strMessage)) {
                verify_access_authorization.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[send_verify_access_authorization] (onResult) eResult =" + eResult);
                        if (eResult == iMAPResult.OK) {
                            verify_access_authorization.setItem("recog_info");
                            String strRecogType = verify_access_authorization.getAttributeValue(0, "type");
                            String strRecogResult = verify_access_authorization.getAttributeValue(0, "result");
                            String strRecogReason = verify_access_authorization.getAttributeValue(0, "reason");
                            verify_access_authorization.setItem("owner_info");
                            String strOwnerID = verify_access_authorization.getAttributeValue(0, "id");
                            String strOwnerName = verify_access_authorization.getAttributeValue(0, "name");

                            LOG_INFO("[send_verify_access_authorization] strRecogType [" + strRecogType + "], strRecogResult [" + strRecogResult + "], strRecogReason [" + strRecogReason + "], strOwnerID [" + strOwnerID + "], strOwnerName [" + strOwnerName + "]");
                            LobbyAccessCtrl.ctrlAccessBioInformation(strRecogType, strRecogResult, strRecogReason, strOwnerID, strOwnerName);
                        }
                        else {
                            MainActivity.mSound.PlayMent_lobby(R.raw.retryinput);
                            Toast.makeText(mContext, "[send_verify_access_authorization] " + eResult.toString(), Toast.LENGTH_LONG).show();
                        }
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_elevator_call_request(strDong, strHo, strCMD)");
            e.printStackTrace();
            return false;
        }
    }

    public static void checkSyncSystemClock() {
        try {
            LOG("[checkSyncSystemClock] bReadytoSync [" + bReadytoSync + "]");
            Calendar Cal = Calendar.getInstance();
            if (bReadytoSync) {
                int nMin = Cal.get(Calendar.MINUTE);   // 시
                LOG("[checkSyncSystemClock] nMin [" + nMin + "]");
                if (nMin == nSyncMin) {
                    syncSystemClock();
                    bDoneGeneRandom = false;
                    bReadytoSync = false;
                    nSyncMin = 0;
                }
            } else {
                if (!bDoneGeneRandom) {
                    int nHour = Cal.get(Calendar.HOUR_OF_DAY);   // 시
                    LOG("[checkSyncSystemClock] nHour [" + nHour + "]");
                    if (nHour == 2 && bDoneGeneRandom == false) {
                        nSyncMin = makeRandomMin();
                        bDoneGeneRandom = true;
                        bReadytoSync = true;
                    }
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkSyncSystemClock() : " + e);
            e.printStackTrace();
        }
    }

    public static void syncSystemClock() {
        try {
            LOG("[syncSystemClock] ===== START =====");
            ConfigValueTable GetSetupTimeSync = new ConfigValueTable();
            GetSetupTimeSync.clearTable();
            GetSetupTimeSync.addConfigValue("datetime", "", "", "", "");
            Global.getDatetime(GetSetupTimeSync);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] syncSystemClock() : " + e);
            e.printStackTrace();
        }
    }

    public static int makeRandomMin() {
        try {
            LOG("[makeRandomMin] ===== START =====");
            Random mRandom = new Random();
            int nRandomMin = Math.abs(mRandom.nextInt(59) + 1);
            LOG("[checkSyncSystemClock] nRandomMin = " + nRandomMin);
            return nRandomMin;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] makeRandomMin() : " + e);
            e.printStackTrace();
            return 30;
        }
    }

    public static boolean getDatetime(ConfigValueTable GetSetupValue) {
        try {
            LOG("[getDatetime] GetSetupValue.getCnt() = " + GetSetupValue.getCnt());
            final Request_get_setup_info get_setup_info = new Request_get_setup_info(mContext);
            if (get_setup_info.send_get_setup_info_request(GetSetupValue)) {
                get_setup_info.setResultCtrl(new iMAPResultCtrl() {

                    @Override
                    public void onResult(iMAPResult eResult) {
                        LOG_INFO("[getDatetime] (onResult) eResult =" + eResult);
                        if (eResult == iMAPResult.OK) {
                            get_setup_info.setItem("setting");
                            String strName = get_setup_info.getAttributeValue(0, "name");
                            String strValue = get_setup_info.getAttributeValue(0, "value");
                            LOG("[getDatetime] strName [" + strName + "], strValue [" + strValue + "]");
                            if (strName.equals("datetime")) {
                                int nYear = Integer.parseInt(strValue.substring(0, 4));
                                int nMonth = Integer.parseInt(strValue.substring(4, 6));
                                int nDate = Integer.parseInt(strValue.substring(6, 8));
                                int nHour = Integer.parseInt(strValue.substring(8, 10));
                                int nMin = Integer.parseInt(strValue.substring(10, 12));

                                LOG("[getDatetime] Cal Values [" + nYear + "/" + nMonth + "/" + nDate + " " + nHour + ":" + nMin + "]");
                                if (Global.setSystemTime(nYear, nMonth, nDate, nHour, nMin)) {
                                    if (Global.nCurrentScreenID == ID.SCREENS.Main) {
                                        LOG_INFO("[getDatetime] Sync Calendar Done!!");
                                        ((MainActivity) mContext).setChangeScreen(ID.SCREENS.Main, false);
                                    }
                                }
                            }
                        }
                    }
                });
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getDatetime(GetSetupValue)");
            e.printStackTrace();
            return false;
        }
    }

    public static boolean setMainServerType(String strVersion) {
        try {
            LOG("[setMainServerType] strVersion [" + strVersion + "], ConfigValue.nMainServerPortNum [" + ConfigValue.nMainServerPortNum + "], ConfigValue.eMainServerType [" + ConfigValue.eMainServerType + "]");

            boolean biMAPServerRestart = false;

            if (strVersion.equalsIgnoreCase(ServerVersion.strVer_1dot0)) {
                if (ConfigValue.eMainServerType == SetValue.Server2dot0_Integrated)
                    biMAPServerRestart = true;

                ConfigValue.eMainServerType = SetValue.Server_Separated;
                ConfigValue.strMonitoringPCIPAddress = DefaultConfigValue.strMonitoringPCIPAddress;
                ConfigValue.nMainServerPortNum = TargetPort.nServer1_X;
            } else if (strVersion.equalsIgnoreCase(ServerVersion.strVer_1dot5)) {
                if (ConfigValue.eMainServerType == SetValue.Server2dot0_Integrated)
                    biMAPServerRestart = true;

                ConfigValue.eMainServerType = SetValue.Server_Integrated;
                ConfigValue.strMonitoringPCIPAddress = DefaultConfigValue.strMainServerIPAddress;
                ConfigValue.nMainServerPortNum = TargetPort.nServer1_X;
            } else if (strVersion.equalsIgnoreCase(ServerVersion.strVer_2dot0)) {
                if (ConfigValue.eMainServerType != SetValue.Server2dot0_Integrated)
                    biMAPServerRestart = true;
                if(ConfigValue.eSubServerType==SetValue.ServerMixed_Integrated){
                    ConfigValue.eMainServerType = SetValue.Server2dot0_Integrated;
                    ConfigValue.strMonitoringPCIPAddress = DefaultConfigValue.strMainServer2IPAddress;
                    ConfigValue.nMainServerPortNum = TargetPort.nServer2_0;
                }else {
                    ConfigValue.eMainServerType = SetValue.Server2dot0_Integrated;
                    ConfigValue.strMonitoringPCIPAddress = DefaultConfigValue.strMainServerIPAddress;
                    ConfigValue.nMainServerPortNum = TargetPort.nServer2_0;
                }
            } else {
                Log.w(TAG, "[setMainServerType] Inavailable server version [" + strVersion + "]");
                return false;
            }

            if (!MainActivity.ConfigDBManager.setData(Declare.DBInfo.TABLE_NAME_CONFIG, ConfigValKey.MainServerType, ConfigValue.eMainServerType))
                return false;
            if (!MainActivity.ConfigDBManager.setData(Declare.DBInfo.TABLE_NAME_CONFIG, ConfigValKey.MonitoringPCIPAddress, ConfigValue.strMonitoringPCIPAddress))
                return false;
            if (!MainActivity.ConfigDBManager.setData(Declare.DBInfo.TABLE_NAME_CONFIG, ConfigValKey.MainServerPortNum, ConfigValue.nMainServerPortNum))
                return false;

            Log.i(TAG, "[setMainServerType] biMAPServerRestart [" + biMAPServerRestart + "], ConfigValue.eMainServerType [" + ConfigValue.eMainServerType + "]");
            Log.i(TAG, "[setMainServerType] ConfigValue.strMonitoringPCIPAddress [" + ConfigValue.strMonitoringPCIPAddress + "], ConfigValue.nMainServerPortNum [" + ConfigValue.nMainServerPortNum + "]");

            if (biMAPServerRestart) ((MainActivity) mContext).restartiMAPServer();

            ((MainActivity) mContext).sendHandlerMsgDelayed(MainActivity.HANDLERMSG.SEND_HEARTBEAT_NOTICE, 0, 0, 2000);

            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setMainServerType(String strVersion)");
            e.printStackTrace();
            return false;
        }
    }

    public void setRFREaqderErrorMode() {
        try {

        } catch (Exception e) {
            Log.e(TAG, "[Exception] setRFREaqderErrorMode() : " + e);
            e.printStackTrace();
        }
    }

    public void releaseRFREaqderErrorMode() {
        try {

        } catch (Exception e) {
            Log.e(TAG, "[Exception] releaseRFREaqderErrorMode() : " + e);
            e.printStackTrace();
        }
    }

    public static class DoorCntDown extends TimerTask {
        @Override
        public void run() {
//            LOG_INFO("[DoorCntDown().run()] Start!!");
            try {
                nDoorOpenCntDN--;
                LOG_INFO("[DoorCntDown] nDoorOpenCntDN = " + nDoorOpenCntDN);
                if (nDoorOpenCntDN <= 0) {
                    // 문을 닫고, 타이머를 종료한다.
                    DoorCtrlTimer.cancel();
                    DoorCtrlTimer = null;

                    LOG_INFO("[DoorCntDown] Door Close!!");
                    LOG_INFO("[DoorCntDown] ConfigValue.eFireSensorDetected = " + ConfigValue.eFireSensorDetected);
                    if (ConfigValue.eFireSensorDetected == SetValue.FALSE) {
//                        MainActivity.mIOInterface.ilp300_700_ctrlDoor(Door_Close);
                        MainActivity.mIOInterface.ctrlDoorOpen(false);
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "[Exception] DoorCntDown().run() : " + e);
                e.printStackTrace();
            }
        }
    }

    public static boolean checkRemoteDebugAccount(String strID, String strPW) {
        try {
            if (strID.equals("icontrols")) {
                if (strPW.equals("hdc1208193646#$")) {
                    Log.i(TAG, "[checkRemoteDebugAccount] Account correct!!");
                    return true;
                }
                else {
                    Log.w(TAG, "[checkRemoteDebugAccount] PW incorrect!!");
                    return false;
                }
            }
            else {
                Log.w(TAG, "[checkRemoteDebugAccount] ID incorrect!!");
                return false;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkRemoteDebugAccount(String strID, String strPW)");
            e.printStackTrace();
            return false;
        }
    }

    public static void ctrlRemoteDebugConnect(boolean bEnable, String strPort, int nConnectMins) {
        try {
            Log.i(TAG, "[ctrlRemoteDebugConnect] bEnable [" + bEnable + "], strPort [" + strPort + "], nConnectMins [" + nConnectMins + "]");
            if (bEnable) {
                if (0 >= nRemoteDebugCntDN) {
                    RemoteDebugTimer = new Timer();
                    RemoteDebugTimer.schedule(new RemoteDebugCntDN(), 1000, 60000);
                    if (MainActivity.mIOInterface.checkADBRemoteConnectionState() == -1) {
                        // 미사용중
                        MainActivity.mIOInterface.enableADBRemoteConnection(strPort);
                    }
                }
                nRemoteDebugCntDN = nConnectMins;
            }
            else {
                MainActivity.mIOInterface.disableADBRemoteConnection();
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] enableRemoteDebugConnect()");
            e.printStackTrace();
        }
    }

    public static int nRemoteDebugCntDN = 0;
    static Timer RemoteDebugTimer = null;
    public static class RemoteDebugCntDN extends TimerTask {
        @Override
        public void run() {
//            LOG_INFO("[RemoteDebugCntDN().run()] Start!!");
            try {
                nRemoteDebugCntDN--;
                LOG_INFO("[RemoteDebugCntDN] nRemoteDebugCntDN = " + nRemoteDebugCntDN);
                if (0 >= nRemoteDebugCntDN) {
                    // 문을 닫고, 타이머를 종료한다.
                    RemoteDebugTimer.cancel();
                    RemoteDebugTimer = null;
                }
            } catch (Exception e) {
                Log.e(TAG, "[Exception] RemoteDebugCntDN().run() : " + e);
                e.printStackTrace();
            }
        }
    }



}