收拾屋子翻出一堆之前闲鱼捡的垃圾准备扔了,翻到一个海思Hi3516CV300+索尼IMX290的山寨摄像头模组。想起之前看到的开源摄像头固件OpenIPC,闲的时候可以刷来玩玩。

海思IPC SoC

海思的3516/3518系列SoC,在TI和安霸的H264时代后,2020年被制裁前在IPC行业是绝对的垄断地位,国内的大街小巷房前屋后的网络摄像头,里面可能80%都是海思的CPU。海思为最近几年安防行业的迅速扩张做出了巨大的贡献,人均几个摄像头无时不刻对着自己,也不知道是好事还是坏事。好日子直到美国的制裁戛然而止,海思目前可能还只剩下一点库存的高端3559系列芯片还在供应海康等VIP客户,剩下的中低端市场被其他国产作坊迅速分食,如君正、星宸、安凯和国科等。

Hi3516CV300发布于2016年,是一款中低端的产品,单核主频800MHz,支持1080P@30FPS H265编码 。

索尼安防图像传感器

索尼IMX290/IMX291就属于当时的高端安防图像传感器了,彼时号称星光级/黑光级的基本都用的这个传感器,后来又出了阉割版的IMX307和IMX327,成本降低,但弱光效果都不及前者。IMX290/IMX291到目前为止依然 是1/2.8英寸这个级别的安防夜视王者,更好的只有更大靶面的IMX385和IMX485了

天视通模组

这块模组的生产厂家是深圳天视通,型号TH38Q10,搜了下这个型号貌似很多摄像头组装作坊都曾用到过这款模块,淘宝依然在售,只要120元,挺值的。单板38x38mm,128M内存,16M SPI闪存,F1.2的M12镜头,可以自行替换,标称彩色模式下最低照度仅需0.0001Lux。家有网络摄像头觉得效果不好的,可以试试替换成这块模组,38x38mm的组装摄像头,配件基本都通用。

原厂固件

原厂固件目前能找到最新的是2018年的,来自组装作坊网站,之后就没再更新。默认开启了Telnet,root密码hdipc%No。原厂固件用着也丝毫没问题,甚至远程云服务四五年后依然可用,对山寨厂来说难能可贵了。RS485、ONVIF、RTSP等当然是标配了的

/mnt/nand # cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00040000 00010000 "boot"
mtd1: 00200000 00010000 "kernel"
mtd2: 00080000 00010000 "userdata"
mtd3: 00cc0000 00010000 "rootfs"
mtd4: 00080000 00010000 "userdata_bk"

连接TTL

这块板子没有单独留TTL串口,但在一个俄语的论坛发现有人标注了出来,感谢前人栽树。RX/TX的位置如图,GND直接接螺丝孔就行 TTL接口

OpenIPC

OpenIPC是一个半开源的摄像头固件,官网:https://openipc.org/,目前市面上常见的IPC SoC基本都已经支持或正在适配中,海思系列的SoC是最早适配的一批,目前已经基本堪用。OpenIPC的rootfs基于Buildroot,这一部分是开源的,但其中主要的ISP处理程序Majestic还是闭源状态,所以说他是半开源的固件。

目前已经实现的功能包括但不限于

  • RTSP视频流
  • HLS HTTP视频流
  • 静态图像生成
  • YouTube直播
  • ONVIF/NETIP/IPEYE等协议
  • 移动检测并且发送通知到EMAIL/FTP/Telegram/Yandex Disk/HTTP API/MQTT broker
  • 内置ZeroTier/WireGuard/Socks5等协议支持

我最想要的还是HLS视频流和send to webhook/MQTT功能,可以方便集成到HomeKit/HomeAssistant中

开始刷机

首先到Github上下载最新的固件,openipc.hi3516cv300-ultimate-br.tgz,官方提供了几个不同大小的固件,适配不同大小和类型的闪存,我有充足的16M SPI闪存,所以选择旗舰版固件。解压后把uImage.hi3516av300rootfs.squashfs.hi3516cv300放入到OpenTFTP的目录下。给模组接好TTL,通电后按任意键中断启动,进入uboot控制台

printenv看看环境参数

hisilicon # print
bootargs=mem=48M console=ttyAMA0,115200 root=/dev/mtdblock3 noinitrd rootfstype=squashfs mtdparts=hi_sfc:256K(boot),2048K(kernel),512K(userdata),13056K(rootfs),512K(userdata_bk)
bootcmd=sf probe 0;sf read 0x81000000 0x40000 0x200000;bootm 0x81000000
bootdelay=1
baudrate=115200
ethaddr=00:00:23:34:45:66
ipaddr=192.168.0.123
serverip=192.168.0.188
netmask=255.255.255.0
bootfile="uImage"
stdin=serial
stdout=serial
stderr=serial
verify=n
ver=U-Boot 2010.06 (Sep 20 2017 - 09:48:18)

设置好本机和TFTP服务器的IP

setenv ipaddr 192.168.2.2
setenv serverip 192.168.2.3
saveenv

能ping通电脑后首先备份闪存中原始固件,运行下面的命令将16M的闪存dump上传到OpenTFTP服务器上

mw.b 0x81000000 0xff 0x1000000
sf probe 0
sf read 0x81000000 0x0 0x1000000
tftp 0x81000000 th38q10_dump.bin 0x1000000

接下来就开始把OpenTFTP服务器上的OpenIPC固件写入到闪存中,首先规划一下闪存的分区,根据OpenIPC内核和rootfs分区的大小情况,我按照如下方式分配闪存

mtdparts=hi_sfc:256k(boot),64k(env),2048k(kernel),8192k(rootfs),-(rootfs_data)

然后下载kernel和rootfs镜像并写入到闪存中对应的位置

mw.b 0x81000000 0xff 0x200000
tftp 0x81000000 uImage.hi3516av300
sf probe 0
sf erase 0x50000 0x200000
sf write 0x81000000 0x50000 0x200000
mw.b 0x81000000 0xff 0x200000
tftp 0x81000000 rootfs.squashfs.hi3516cv300
sf probe 0
sf erase 0x250000 0x800000
sf write 0x81000000 0x250000 0x800000

然后修改bootargsbootcmd

setenv bootargs 'mem=48M totalmem=128M console=ttyAMA0,115200 panic=20 root=/dev/mtdblock3 init=/init rootfstype=squashfs mtdparts=hi_sfc:256k(boot),64k(env),2048k(kernel),8192k(rootfs),-(rootfs_data)'
setenv bootcmd 'sf probe 0;sf read 0x81000000 0x50000 0x200000;bootm 0x81000000'
setenv osmem 48M
setenv totalmem 128M
setenv soc hi3516cv300
setenv sensor imx290_i2c_lvds
saveenv

reset后重启应该就进入OpenIPC的系统了,默认root密码12345。检查下一切运行正常,再网页后台转悠看看新鲜下,接下来就该把他接入到HomeKit了

使用homebridge-camera-ui将RTSP视频流接入HomeKit

以下摘录于homebridge-camera-ui官网

homebridge-camera-ui allows you to expose cameras from camera.ui to HomeKit via Homebridge. camera.ui does not need to be installed separately. It is installed right away with homebridge-camera-ui
camera.ui is a NVR like PWA to control your RTSP capable cameras with:
	Live Streams on Web
	Camview: A resizable, drag & drop camera overview
	Web Application with almost full PWA support like push notification and more
	Multi-language: Easily expandable multi-language support
	Motion Detection via video analysis, MQTT, FTP, SMT or HTTP.
	Image Rekognition via AWS Rekognition
	Notifications via Alexa, Telegram, Webhook and WebPush
	Snapshot/Video: Save recording of snapshots/videos locally when motion is detected
	Prebuffering: See the seconds before the movement event
	User Interface: Beautiful and with love designed interface with 8 different color themes, dark mode and more
	HSV Support (HomeKit Secure Video)
	Config UI X Support
	and much more...

翻译下就是很牛逼的意思,可以将任意RTSP视频流通过homebridge接入到HomeKit系统中,并且支持苹果最新的HomeKit Secure Video录制(以下简称HKSV)。成品摄像头中支持这个功能的国内就Aqara的G3,卖749元,用不起。

安装参见官网,贴下我的config.json以防健忘。很多都可以省略的,这是camera ui的网页后台自动生成的配置文件,比较冗长。添加新摄像头在网页后台就行,比较方便

{
    "bridge": {
        "name": "Homebridge",
        "username": "ec🇩🇪2e:46:47:e3",
        "port": 12345,
        "pin": "111-22-333",
        "bind": "br-lan"
    },
    "mdns": {
        "interface": "192.168.2.1"
    },
    "platforms": [
        {
            "platform": "CameraUI",
            "name": "CameraUI",
            "port": 888,
            "cameras": [
                {
                    "name": "Test OpenIPC",
                    "manufacturer": "OpenIPC",
                    "model": "IMX290",
                    "serialNumber": "123456",
                    "excludeSwitch": false,
                    "privacySwitch": false,
                    "motion": true,
                    "doorbell": false,
                    "switches": false,
                    "useInterfaceTimer": true,
                    "motionTimeout": 15,
                    "motionDoorbell": false,
                    "unbridge": true,
                    "hsv": true,
                    "prebuffering": true,
                    "forcePrebuffering": false,
                    "prebufferLength": 8,
                    "videoConfig": {
                        "source": "-i rtsp://admin:[email protected]/stream=1",
                        "stillImageSource": "-i http://192.168.2.2/image.jpg",
                        "readRate": false,
                        "rtspTransport": "udp",
                        "maxStreams": 4,
                        "maxWidth": 1920,
                        "maxHeight": 1080,
                        "maxFPS": 25,
                        "maxBitrate": 2000,
                        "forceMax": true,
                        "vcodec": "copy",
                        "acodec": "libfdk_aac",
                        "stimeout": 10,
                        "encoderOptions": "-preset ultrafast -tune zerolatency",
                        "audio": false,
                        "debug": true
                    },
                    "mqtt": {
                        "motionTopic": "openipc/imx290",
                        "motionMessage": "Motion_detected",
                        "motionResetTopic": "livingroom/motion",
                        "motionResetMessage": "OFF",
                        "doorbellTopic": "",
                        "doorbellMessage": ""
                    },
                    "videoanalysis": {
                        "active": false
                    },
                    "smtp": {
                        "email": "Test OpenIPC"
                    }
                }
            ],
            "logLevel": "info",
            "atHomeSwitch": false,
            "options": {
                "videoProcessor": "/ffmpeg-for-homebridge/ffmpeg"
            },
            "ssl": {
                "active": false
            },
            "http": {
                "active": false,
                "port": 7272,
                "localhttp": false
            },
            "smtp": {
                "active": false,
                "port": 2727,
                "space_replace": "+"
            },
            "ftp": {
                "active": false,
                "useFile": false,
                "port": 5050
            },
            "mqtt": {
                "active": true,
                "tls": false,
                "host": "192.168.2.5",
                "port": 1883
            }
        }
    ]
}

启动后在HomeKit中添加新的设备,网关和摄像头是两个分开的设备,需要分开添加。摄像头配置移动侦测并发送通知Motion_detected到MQTT的openipc/imx290主题,camera ui则监听openipc/imx290主题,收到Motion_detected的消息时便会触发HomeKit中摄像头的动作传感器,苹果设备便会立即收到通知。通知的延迟非常低,实测从物体移动到设备收到提醒通知,时间不超过1秒

除了动作传感器外,HomeKit摄像头还可以给配置个门铃传感器,触发后HomePod会发出叮咚的门铃声,同时Apple TV右上角会以画中画的形式出现一个小预览窗口,播放摄像头的实时画面,不打断正在播放的节目,体验很赞

如果家中有HomeKit中枢网关设备,如HomePod和Apple TV,便可以远程观看摄像头,借此可以给不支持云功能的摄像头添加远程云功能,安全性和便利性比传统摄像头厂家的都更好,但实测远程播放会偶尔卡顿,没其他厂家的流畅

更棒的是还可以使用苹果的HomeKit Secure Video录制视频到iCloud云端,但这需要付费订阅iCloud+套餐,详见:https://support.apple.com/zh-cn/guide/icloud/mme054c72692/icloud 最低50G的套餐可以录制一台摄像头的视频,录制的视频不占用iCloud存储空间。开启HKSV录制后还可以在中枢网关上进行视频分析,识别人脸和物体,并和你相册中的人物做匹配,通知中可以直接显示人名

苹果官网说识别分析都是在本地中枢,但是开启分析功能的前提却是开启iCloud相册同步和录制视频到云端,这其中的逻辑似乎有点矛盾。我对云不感冒,没有花这个8块钱

说下几个踩的坑

  • HomeKit不支持H265,所以摄像头上得用H264编码,不然需要camera ui实时转码,非常卡
  • 在OpenWrt中安装的homebridge默认绑定eth0网卡,而我LAN侧的网卡是eth4,导致HomeKit无法搜索到homebridge,解决方法:在bridge后添加如下一段。虽然启动过程中会提示mdns已经被弃用让用bind参数替代,但千万别信,bind参数毫无作用,还是最后用mdns实现的绑定网卡
"mdns": {
  "interface": "192.168.2.1"
}