【小ネタ】 監視カメラをPythonで操作してみました

2020.07.30

1 はじめに

CX事業本部の平内(SIN)です。

店舗内の商品をComputerVisionで確認するために、前回、監視カメラをONVIFで操作してみました。

監視カメラには、専用の操作アプリがあり、その画面からカメラの操作は出来ます。

こちらは、ONVIFを無効化しても利用可能なので、どうやって操作をしているのか確認してみた所、簡単なHTTPで動作していることを確認できたので、今回は、それをラップするクラスを作ってみました。

2 監視カメラ

使用したのは、前回と同じ、ANRANの防犯カメラです。
https://www.amazon.co.jp/gp/product/B07VD693ND/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

3 専用アプリ

専用アプリは、下記のような画面になっています。

左側の矢印ボタン等で、上下左右の回転や、ズームが可能になっています。

4 パケットモニタ

操作中のパケットをモニタすると、画面の画像についてはUDP、操作については、TCP(HTTP)で行われていることが分かります。

以下は、左回転の操作をした際の、TCPストリームを確認している様子です。

結果、カメラの動作は、以下のような、HTTPのGETだけで操作されていることが分かります。

左回転の操作開始

GET /web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=left&-speed=45 HTTP/1.1
Host: 10.0.0.12
Connection: keep-alive
Authorization: Basic YWRtaW46YWRtaW4=
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://10.0.0.12/web/mainpage.html
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8

HTTP/1.1 200 OK
Server: Hipcam
Cache-Control: no-cache
Content-Type:text/html
Connection: close
Content-Length: 16

[Succeed]set ok.

左回転の操作停止

GET /web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=stop&-speed=45 HTTP/1.1
Host: 10.0.0.12
Connection: keep-alive
Authorization: Basic YWRtaW46YWRtaW4=
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://10.0.0.12/web/mainpage.html
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8

HTTP/1.1 200 OK
Server: Hipcam
Cache-Control: no-cache
Content-Type:text/html
Connection: close
Content-Length: 16

[Succeed]set ok.

5 監視カメラ操作クラス

以下は、コマンド(GETリクエスト)を送って、UP, DOWN, RIGHT, LEFT, ZOOM及び、プリセットへの移動の操作を行うクラスです。 (speed=63は、最大スピードです)

cam.py

import requests
from enum import Enum
from time import sleep

class Cmd(Enum):
    LET = 'left'
    RIGHT = 'right'
    UP = 'up'
    DOWN = 'down'
    IN = 'zoomin'
    OUT = 'zoomout'

class Cam():
    def __init__(self, host, user, password):
        self.__url = "http://{}:{}@{}/web/cgi-bin/hi3510/".format(user, password, host) 
        self.__ptzctrl('stop')

    def ptz(self, cmd, sec):
        self.__ptzctrl(cmd.value)
        sleep(sec)
        self.__ptzctrl('stop')

    def preset(self, num):
        num = str(num - 1)
        requests.get("{}/preset.cgi?-act=goto&-number={}".format(self.__url, num))

    def __ptzctrl(self, cmdStr):
        requests.get("{}/ptzctrl.cgi?-step=0&-act={}&-speed=63".format(self.__url, cmdStr))

上記のクラスを利用している例です。

index.py

from time import sleep
from cam import Cam,Cmd

# 防犯カメラ
host = "10.0.0.12"
user = "admin"
password = "admin"
cam = Cam(host, user, password)

# コマンドの操作間隔(sec)
WAIT = 3



while(True):
    print("プリセット50に移動")
    cam.preset(50)
    sleep(WAIT)

    print("ズームイン")
    cam.ptz(Cmd.IN, 3)
    sleep(WAIT)

    print("右へ移動")
    cam.ptz(Cmd.RIGHT, 0.5)
    sleep(WAIT)

    print("下へ移動")
    cam.ptz(Cmd.DOWN, 0.2)
    sleep(WAIT)

    print("ズームアウト")
    cam.ptz(Cmd.OUT, 2)
    sleep(WAIT)

    for i in range(6):
        print("プリセット{}に移動".Format(i+1))
        cam.preset(i+1)
        sleep(WAIT)

6 最後に

今回は、監視カメラをHTTPで操作してみました。ONVIFで操作するより、非常にシンプルなコードになったかも知れません。