본문 바로가기
개발Study/IP Camera

make IP camera using raspberry pi 4 (13) notification

by happy90 2022. 2. 26.
SMALL

app실행시 폰에 simple server를 하나 돌리고, url을 등록한다.
그러면 서버에서 폰에 web hook을 보낼 때 해당 url에 전송하고, url에 request가 왔을 때 alert를 띄우는 기능이 되겠다.
이렇게 하려고했더니 자료가 잘 없다.
몇년전까지 android에서 nanohttpd라는 것을 사용한 것 같다.
확실히 nanohttpd git을 보니 몇년 전까지만 업데이트되었다.
kotlin으로 구현된 http server api를 발견하였지만 난 java니까 패스...
빠르게 nanohttpd를 사용해본다.

 

1. build.gradle(Module)에 아래 내용 추가

implementation 'com.nanohttpd:nanohttpd-webserver:2.1.1'

이렇게 하면 android studio에서 해당 패키지를 빌드해준다.

 

2. nano httpd 코드구현
먼저 MainActivity class에 아래 내용을 추가.

/* tiny web server */
private WebServer server;
private static final String TAG = "tinyServer";
private static final int PORT = 8080;

private class WebServer extends NanoHTTPD {

        public WebServer()
        {
            super(PORT);
        }

        @Override
        public Response serve(String uri, Method method,
                              Map<String, String> header,
                              Map<String, String> parameters,
                              Map<String, String> files) {
            String answer = "nano test";


            return new NanoHTTPD.Response(answer);
        }
}

@Override
public void onDestroy()
{
    super.onDestroy();
    if (server != null)
        server.stop();
}

 

onCreate함수에 server를 생성하는 코드 추가

/* start tiny web server */
server = new WebServer();
try {
    server.start();
} catch(IOException ioe) {
    Log.w("Httpd", "The server could not start.");
}
Log.i("Httpd", "Web server initialized.");

 

이렇게 해서 어플 실행시키고 web browser에 http://localhost:8080/ 입력하면 http response에 입력한 내용이 나옴.

 

3. web hook 구현
motion eye -> django 에 web hook이 들어오면 django에서는 alarm on이 되어있는 mac address들에게 web hook을 전송해야 한다.
내가 놓친게 있네. 최초 webpage open시 ip address를 서버에 알려주고,
서버에서 ip address를 저장하고 있다가 alarm보낼 때 해당 ip로 보내도록 구현.

그래서 django server쪽 model에 ip address를 저장하도록 구현.

url에 ip address를 추가했고, android code에서도 ip address를 실어보낼 수 있도록 구현.

 

django로부터 web hook이 들어왔을 때 mac address와 매칭되는 ip address에 get request를 보내도록 구현.

 

4. notification 구현
build.gradle dependency에 아래 내용 추가

implementation "com.android.support:support-compat:28.0.0"

 

MainActivity.java에 추가할 내용.

먼저 MainActivity class에 추가해준다.
android 몇버전 이상부터는 channel이 필요하다는데, 그래서 필요한 id를 적어줌.
그리고 알람이 울릴 때 필요한 sound도 추가.

String CHANNEL_ID = "ch1";
Uri alarm_sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);



다음으로 필요한 함수 두개.
위에서 언급한대로 channel이 필요하므로 channel 생성하는 함수 구현.
너무 복붙한 티 남.ㅋㅋㅋ

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = "ch1";
        String description = "noti channel";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

 

다음으로 notification을 띄우는 함수 구현.
역시 복붙의 냄새..ㅋㅋ

protected void showNotification(String alarm_category) {
    Log.i("Start", "notification !!!! ");

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(androidx.transition.R.drawable.notification_action_background)
            .setContentTitle(alarm_category + "detected !!!!")
            .setSound(alarm_sound)
            .setPriority(NotificationCompat.PRIORITY_HIGH);

    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

    // notificationId is a unique int for each notification that you must define
    Integer notificationId = 1;
    notificationManager.notify(notificationId, builder.build());
}

 

아무튼 이렇게 해서 channel을 생성하는 함수는 onCreate에 넣어주고,
notification을 띄워주는 함수는 get request가 왔을 때 처리하도록 넣어주었다.
아래는 최종 response 함수의 모양이다.

public Response serve(String uri, Method method,
                      Map<String, String> header,
                      Map<String, String> parameters,
                      Map<String, String> files) {

    uri = uri.split("/")[1];

    if(uri.compareTo("motion") == 0)
        showNotification("motion");
    else if(uri.compareTo("sound") == 0)
        showNotification("sound");
    else
        Log.w("response", "alarm is not in category");

    String answer = "nano test";

    return new NanoHTTPD.Response(answer);
}

uri에 get request시 입력한 url이 들어와서 구분할 수 있도록 분기문을 넣어주었다.

이렇게 해서 알람이 오면 핸드폰에 notification으로 뜬다.

아이콘도 없고 초라하지만 알람 소리는 나서 제 기능은 할 것 같다.
notification 기본 sound여서 좀 구별될 수 있는 소리로 바꿔봐야겠다.

LIST

댓글