格安30倍光学ネットワークカメラをハックする

## 格安2万円代の30倍光学ネットワークカメラをPCから制御出来るように。
本IPカメラの基本設定(ネットワーク設定等)や、付属アプリケーションの説明は、記載していません。

![IP-Camera.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/4da3dd9f-529b-8dad-61ea-1de71e91aae9.png)

### 調査内容
対象とするネットワークカメラは、Ctronins(クロニクス）中華製の防犯カメラです。
- チルトパン制御
- ズームアウト・ズームイン制御
- 映像の取り込み

### 1. チルト・パン制御
チルト・パン制御は、http-getで制御ができます。

カメラを右側へ向ける
```
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=right&-speed=63
この間に右側へ向く
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=stop&-speed=63
```
カメラを左側へ向ける
```
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=left&-speed=63
この間に左側へ向く
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=stop&-speed=63
```
カメラを下側へ向ける
```
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=down&-speed=63
この間に下側へ向く
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=stop&-speed=63
```
カメラを上側へ向ける
```
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=up&-speed=63
この間に上側へ向く
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=stop&-speed=63
```
### 2. ズームアウト・ズームイン制御
ズームアウト・ズームイン制御は、http-getで制御ができます。

ズームイン
```
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=zoomin&-speed=63
この間にズームインする
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=stop&-speed=63
```
ズームアウト
```
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=zoomout&-speed=63
この間にズームアウトする
http://admin:admin@192.168.0.20/web/cgi-bin/hi3510//ptzctrl.cgi?-step=0&-act=stop&-speed=63
```

### 3. 映像の取り込み
RTSP映像をPCに取り込めるようです。

first streame　　rtsp://ネットワークカメラのIP/11
second streame rtsp://ネットワークカメラのIP/12
注意:second streameの場合、openCVで文字を合成すると、表示文字列が、大ききなります。

pythonでRTSPをopenCVで取り込む
```
video_capture = VideoCaptureWrapper('rtsp://192.168.0.20/11')
```

(1)50m先の車映像を静止画で出力
![IP-Camera-2024-0107.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/df72d95f-28ab-9ae3-7ddb-26ba8ea12ec2.jpeg)

(2)50m先のアルコマーカを認識してみた
![IP-Camera-2024-0108-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/075803a4-e4db-98c2-3142-d7ddde968d70.png)

openCVでデジタル拡大：左側の写真が、認識されているアルコマーカNo=1,No=0
![IP-Camera-2024-0108-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/f74801c2-6591-0e8f-0de4-16252347fd0f.png)

(3)飛行機撮影
![waseda_20240210173705.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/b0ba800d-7735-e4ba-b03f-703ffd6544ed.jpeg)

### 4. ネットワークカメラ制御クラス python
(1)ネットワーク制御クラス
```
import requests
from enum import Enum
from time import sleep
"""
Ctronins(クロニクス中華) 防犯カメラ 500万画素 30倍光学ズーム:制御クラス
 - ズームイン、ズームアウト制御
 - チルトパン制御
"""
class IPcmd(Enum):
    LEFT = 'left'
    RIGHT = 'right'
    UP = 'up'
    DOWN = 'down'
    IN = 'zoomin'
    OUT = 'zoomout'
    UPLEFT = 'upleft'   # UPと同じ
    UPRIGHT = 'upright' # 
    DOWNLEFT = 'downleft'
    DOWNRIGHT = 'downright'  # RIGTH と同じ
    HOME = 'home'       # ない

class IPcamera():
    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&amp;-number={}".format(self.__url, num))

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

    def param(self, cmdStr):
        _res = requests.get("{}/param.cgi?cmd={}".format(self.__url, cmdStr))
        return _res

def main():
    host = "192.168.0.20"
    user = "admin"
    password = "admin"
    cam = IPcamera(host, user, password)
    WAIT = 3

    print("上へ移動 3sec")
    cam.ptz(IPcmd.UP, 3)
    sleep(WAIT)

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

    print("右へ移動 5sec")
    cam.ptz(IPcmd.RIGHT, 5)
    sleep(WAIT)
    print("左へ移動 5sec")
    cam.ptz(IPcmd.LEFT, 5)
    sleep(WAIT)

    print("下へ移動 3sec")
    cam.ptz(IPcmd.DOWN, 3)
    sleep(WAIT)

    print("ズームアウト3sec")
    cam.ptz(IPcmd.OUT, 3)
    sleep(WAIT)

if __name__ == "__main__":
    main()
```
(2)実験
情報取得系のAPIのテストですが、あくまでも参考です。
```
    print("getmotorattr..")
    res = cam.param('getmotorattr')
    print(res.text)
    sleep(10)
    print("getmotorrange..")
    res = cam.param('getmotorrange')
    print(res.text)
    print("getinfrared..")
    res = cam.param('getinfrared')
    print(res.text)
    print("getlanguage..")
    res = cam.param('getlanguage')
    print(res.text)

結果
getmotorattr..
var pandir="0";
var tiltdir="0";
var panspeed="0";
var tiltspeed="0";
var panscan="1";
var tiltscan="1";
var movehome="off";
var movesteptimeout="1000";
var presettimeout="30";
var ptzalarmmask="on";
var alarmpresetindex="1";
var poweronpresetindex="0";
var watchpresetindex="0";
var poweronscanenable="0";
var limitleft="-1";
var limitright="-1";
var tourinterval="5;10;15;20;30;60;90;120";

getmotorrange..
var panrange="1006";
var tiltrange="144";
var panhome="503";
var tilthome="55";
var pangap="24";
var tiltgap="32";
var peripheral="0";
var selfcheckspeed="45";
var lenstype="3";
var trackpreset="31";
var trackhtimems="700";
var trackvtimems="300";

getinfrared..
var infraredstat="auto";

getlanguage..
var lancode="1";
```