안드로이드 HttpURLConnection을 이용한 CCTV CGI control

1. 개요

안드로이드 환경의 개발보드에서 PTZ 기능이 있는 CCTV를 컨트롤할 필요성이 느껴져서

CCTV API를 살펴보니 CGI를 이용하여 PTZ기능 및 CCTV의 여러 가지 기능을 사용 가능했습니다.

 

CCTV를 컨트롤 할 수 있는 CGI 커맨드가 정리된 Doc파일을 갖고 있다면

이 예제를 통하여 CCTV기능을 컨트롤 가능할 것입니다.

물론 CCTV 뿐만 아니라 CGI 기능을 지원하는 서버의 기능을 이용 가능합니다.

 

 

2. CGI?

CGI는 공용 게이트웨이 인터페이스(Common Gateway Interface)의 약자입니다.

웹 서버 등에서 클라이언트가 사용자 프로그램을 호출하는 조합을 가리키는데,

플랫폼에 의존하지 않는 인터페이스입니다.

 

이번 포스팅에서는 CCTV가 서버 쪽이고, CCTV 내부의 기능을 수행하는 사용자 프로그램을

호출하기 위해 CGI 인터페이스를 사용합니다.

 

N개 이상의 IP CCTV를 구매하여 테스트해보며 IP CCTV의 대부분이 인터페이스로

CGI 프로토콜이 지원하는 것을 확인하였습니다.

혹시 CCTV 회사의 특별한 API를 사용하는 IP CCTV가 있다거나 알고 계시다면

저에게도 정보를 공유 부탁드립니다.

 

3. HttpURLConnection

안드로이드 6.0 이후로 Aparch의 http client 가 기본 지원에서 제외되었습니다.

대신 HttpURLConnection을 사용하여 http 프로토콜을 사용 가능하게 되었습니다.

 

개발 중인 안드로이드 버전이 9.0인 관계로 HttpURLConnection을 사용하였습니다.

아래의 MainActivity에 간단하게 IP CCTV의 PTZ 컨트롤을 하는 코드를 첨부합니다.

public class MainActivity extends AppCompatActivity {

    HttpURLConnection uc;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.button).setOnClickListener(mObjectDetectClickListener);



    }

    private void cctv_down() {
        new Task().execute();
    }

    private class Task extends AsyncTask<Void , Void , Void> {
        @Override
        protected Void doInBackground(Void... voids) {
            try
            {
                URL url = new URL("http://192.168.1.100/cgi-bin/viewer/viewer.cgi?action=ptz.control&ptz_cmd=1");
                uc = (HttpURLConnection) url.openConnection();
                String userpass = "id" + ":" + "password";
                String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
                uc.setRequestProperty ("Authorization", basicAuth);
                uc.setReadTimeout (5000);

                uc.connect();
                int rc = uc.getResponseCode();
                Log.d("rc" , rc+"");

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


    Button.OnClickListener mObjectDetectClickListener = new View.OnClickListener() {
        public void onClick(View v) {
            cctv_down();
        }
    };
}

 

코드를 보시면 버튼을 누를 때마다 URL 주소로 http 접속을 하게 됩니다.

 

IP CCTV 대부분은 ID와 Password를 입력하지 않으면 CGI 접속에서 401 unauthorized 에러를 리턴하게 됩니다.

그 문제를 해결하기 위해 꼭 HttpURLConnection의 RequestProperty 설정을 해주어야 

401 unathorized 에러 대신 200 OK를 rc 변수로 반환하게 되고, 정상적인 CGI 컨트롤이 가능합니다.

 

 

4. Android 9.0 Http

개발보드 Android 버전이 9.0 이상이 되며 보안이 강화로 https가 아닌 http프로토콜 접속에 제한이 생겼습니다.

이를 해결하기 위해 android:usesCleartextTraffic="true" 코드를 아래와 같이

Manifeast.xml에 추가하는 방법으로 해결하였습니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:dist="http://schemas.android.com/apk/distribution"
    package="com.example.altpluscgitest1">

    <dist:module dist:instant="true" />

    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true"
        >
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

이외의 해결 방법이 2가지 정도 더 있는 것 같습니다.

저는 이 방법으로 가장 간단하게 해결하였는데, 다른 방법을 찾고 계시거나 해결이 안 되시는 분들은

https://developside.tistory.com/85

위의 블로그를 참고해 보시길 바랍니다.

 

 

5. 기타 

기본 생성 코드에 버튼을 하나 생성한 간단한 MainActivity에 연결된 레이아웃 코드입니다.

조금이라도 헷갈리지 않도록 포스팅하는 것이 목적이기에

혹시 몰라서 첨부합니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="122dp"
        android:layout_marginLeft="122dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

안드로이드에서 HttpURLConnection CGI를 컨트롤하는 과정에서 도움이 되셨길 바랍니다.

문의 사항이나 오류&기타 질문은 댓글로 남겨 주시면 바로 반영하겠습니다.

 

X. 참고

http://www.masterqna.com/android/75123/cctv-api%EB%A5%BC-%EC%8B%A4%ED%96%89%ED%95%98%EA%B3%A0%EC%8B%B6%EC%8A%B5%EB%8B%88%EB%8B%A4-http%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B1%B0%EB%82%98-%EC%9B%B9%EB%B7%B0%EB%A5%BC-%EC%9D%91%EC%9A%A9%ED%95%B4%EC%95%BC%ED%95%A0%EA%B9%8C%EC%9A%94

https://stackoverflow.com/questions/496651/connecting-to-remote-url-which-requires-authentication-using-java

https://stackoverflow.com/questions/41493469/android-java-httpurlconnection

https://ko.wikipedia.org/wiki/%EA%B3%B5%EC%9A%A9_%EA%B2%8C%EC%9D%B4%ED%8A%B8%EC%9B%A8%EC%9D%B4_%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4

 

댓글

Designed by JB FACTORY