python通过onvif协议搜索局域网所有摄像头ip,并获取摄像头rtsp,mac地址...
python通过onvif协议搜索局域⽹所有摄像头ip,并获取摄像头rtsp,mac地址等
相关服务
这⾥⽤到模块
pip install camera_discovery
from camera_discovery import CameraDiscovery
camera_ip = CameraDiscovery.ws_discovery()
print(camera_ip)
成功的话会返回⼀个摄像头ip列表
自我工作评价
不过笔者在使⽤过程中遇到了⼀个莫名其妙的问题erro 101 network is unreachable(⽹络不可达)可我ping的通⽹络,连接也没问题。查询后也没个准确的答案,只知道报错的py⽂件下有个sock.sendto函数,这个函数发送会有timeout时长,超过就会报上⾯的错误,我的⽅法是直接try:下运⾏sock.sendto函数,报错信息忽略掉,就解决问题了。
try:
sock.sendto()
except:
pass
这是Ubuntu的解决⽅法,Windows下会报hostname的错误,其实也不是这个错误,Windows下没有hostname -i这个命令,所以⽆法获取到本机ip,直接这样输⼊就可以了(Ubuntu也同样适⽤)CameraDiscovery.ws_discovery(‘192.’),原本以为⾃⼰添加ip就可以了,可后⾯运⾏时⼜报了怎么⼀个错误 AttributeError: module 'select' has no attribute 'poll',查了下是说这个模块只适⽤于Linux 2.5+,并不⽀持其他系统。poll机制是Linux内核的⼀种内核微调机制,由此可以说这个搜索ip的功能只能适⽤于Ubuntu了,但是如果你已知摄像头ip的话,下⾯的摄像头信息获取功能你也能在Windows使⽤
另外此模块还可以对摄像头做其他操作,如获取摄像头mac地址等,官⽹提供的导⼊⽅式如下:
from camera_discovery import CameraONVIF
Class = CameraONVIF(camera_ip, user, password)小学家长会教师发言稿
上⾯的导⼊其实是不对的,导⼊⽅式应该改为这样
from camera_discovery.CameraDiscovery import CameraONVIF
camera = CameraONVIF(camera_ip, user, password)
camera.camera_start()#初始化摄像头相关信息,不改源码会出错
这样⽣成camera对象是成功了,但是初始化相关信息还是会报如下错误
相关获取功能还是不能使⽤,这个库这是bug多多,还得改改源码,改动其实很简单的,就是 import zeep ,加了个 zeep_pythonvalue 函数以及 在 camera_start 函数下 加上句 zeep.xsd.simple.AnySimpleType.pythonvalue = p_pythonvalue,整体改后的CameraONVIF类如下:
import subprocess
from typing import List
import WSDiscovery
from onvif import ONVIFCamera
import zeep #额外加的
def ws_discovery(scope =None)-> List:
"""Discover cameras on network using onvif discovery.
Returns:
List: List of ips found in network.
"""
lst =list()
if(scope ==None):
if(scope ==None):
cmd ='hostname -I'
scope = subprocess.check_output(cmd, shell=True).decode('utf-8')
wsd = WSDiscovery.WSDiscovery()
wsd.start()
ret = wsd.searchServices()
for service in ret:
get_ip =XAddrs())
get_types =Types())
for ip_scope in scope.split():
result = get_ip.find(ip_scope.split('.')[0]+'.'+ ip_scope.split('.')[1])
if result >0and get_types.find('onvif')>0:
string_result = get_ip[result:result+13]
string_result = string_result.split('/')[0]
lst.append(string_result)
wsd.stop()
lst.sort()
return lst
class CameraONVIF:
"""This class is used to get the information from all cameras discovered on this specific
network."""
def__init__(self, ip, user, password):
"""Constructor.
Args:
激励上进正能量句子ip (str): Ip of the camera.
user (str): Onvif login.
password (str): Onvif password.
"""
self.cam_ip = ip
self.cam_user = user
self.cam_password = password
def zeep_pythonvalue(self, xmlvalue):#额外加的
return xmlvalue
def camera_start(self):
"""Start module.
"""
mycam = ONVIFCamera(self.cam_ip,80, self.cam_user, self.cam_password, no_cache =True)        media = ate_media_service()
zeep.xsd.simple.AnySimpleType.pythonvalue = p_pythonvalue  #额外加的
media_profile = media.GetProfiles()[0]
self.camera_media = media
self.camera_media_profile = media_profile
def get_hostname(self)->str:
"""Find hostname of camera.
Returns:
str: Hostname.
"""
resp = am.devicemgmt.GetHostname()
return resp.Name
def get_manufacturer(self)->str:
"""Find manufacturer of camera.
Returns:
str: Manufacturer.无法获取ip地址
"""
resp = am.devicemgmt.GetDeviceInformation()
resp = am.devicemgmt.GetDeviceInformation()
return resp.Manufacturer
def get_model(self)->str:
"""Find model of camera.
Returns:
str: Model.
"""
resp = am.devicemgmt.GetDeviceInformation()
return resp.Model
def get_firmware_version(self)->str:
最省电的智能手机
"""Find firmware version of camera.
Returns:
str: Firmware version.
"""
resp = am.devicemgmt.GetDeviceInformation()
return resp.FirmwareVersion
def get_mac_address(self)->str:
"""Find serial number of camera.
Returns:
str: Serial number.
"""
resp = am.devicemgmt.GetDeviceInformation()
return resp.SerialNumber
def get_hardware_id(self)->str:
"""Find hardware id of camera.
Returns:
str: Hardware Id.
"""
resp = am.devicemgmt.GetDeviceInformation()
return resp.HardwareId
def get_resolutions_available(self)-> List:
"""Find all resolutions of camera.
Returns:
tuple: List of resolutions (Width, Height).
"""
request = self.ate_type('GetVideoEncoderConfigurationOptions')        request.ProfileToken = self.camera_ken
config = self.camera_media.GetVideoEncoderConfigurationOptions(request) return[(res.Width, res.Height)for res in config.H264.ResolutionsAvailable]
def get_frame_rate_range(self)->int:
"""Find the frame rate range of camera.
Returns:
int: FPS min.
int: FPS max.
"""
request = self.ate_type('GetVideoEncoderConfigurationOptions')        request.Profi
leToken = self.camera_ken
config = self.camera_media.GetVideoEncoderConfigurationOptions(request) return config.H264.FrameRateRange.Min, config.H264.FrameRateRange.Max
def get_date(self)->str:
"""Find date configured on camera.
Returns:
str: Date in string.
女孩子学什么专业好
"""
datetime = am.devicemgmt.GetSystemDateAndTime()
return datetime.UTCDateTime.Date
return datetime.UTCDateTime.Date
def get_time(self)->str:
"""Find local hour configured on camera.
Returns:
str: Hour in string.
"""
datetime = am.devicemgmt.GetSystemDateAndTime()
return datetime.UTCDateTime.Time
def is_ptz(self)->bool:
"""Check if camera is PTZ or not.
Returns:
bool: Is PTZ or not.
"""
resp = am.devicemgmt.GetCapabilities()
return bool(resp.PTZ)
然⽽虽然整体模块是能⽤了,可是⾥⾯并没有获取rtsp地址的功能,这可让我太⽆奈了,因为我本来就是想图省事不想写的,既然没有没办法就写⼀个了
def get_rtsp(self):
obj = self.ate_type('GetStreamUri')
obj.StreamSetup ={'Stream':'RTP-Unicast','Transport':{'Protocol':'RTSP'}}
obj.ProfileToken = self.camera_ken
res_uri = self.camera_media.GetStreamUri(obj)['Uri']
return res_uri
把上述函数加到CameraONVIF类中就有获取rtsp流地址的功能了,这⾥我测了⼀下有些获取到的地址直接能⽤,有些还得在ip前⾯加上⽤户名和密码,奇奇怪怪。
到此为⽌这个库就完全可⽤了,也很奇怪为什么python关于onvif协议调⽤摄像头的资料那么少,让我耽搁了好多天学习关于onvif的知识
第三次bug更新
将ws_discovery函数的ip返回机制更改⼀下,源代码返回的ip会有的结尾会带:,⽽且有些摄像头端⼝并不是默认的80,所以我们将端⼝也⼀并返回
def ws_discovery(scope =None)-> List:
"""Discover cameras on network using onvif discovery.
Returns:
List: List of ips found in network.
"""
lst =list()
if(scope ==None):
cmd ='hostname -I'
scope = subprocess.check_output(cmd, shell=True).decode('utf-8')
wsd = WSDiscovery.WSDiscovery()
wsd.start()
ret = wsd.searchServices()
for service in ret:
get_ip =XAddrs())
get_types =Types())
for ip_scope in scope.split():
result = get_ip.find(ip_scope.split('.')[0]+'.'+ ip_scope.split('.')[1])
if result >0and get_types.find('onvif')>0:
#下⾯是更改的代码
#string_result = get_ip[result:result+13]
string_result = get_ip[result:].split('/')[0]
string_result = string_result.split(':')
if len(string_result)>1:
lst.append([string_result[0],string_result[1]])
else:
lst.append([string_result[0],'80'])
wsd.stop()
lst.sort()
return lst
之后改⼀下CameraONVIF类的init函数,将port参数也初始化
def__init__(self, ip,user, password, port):
"""Constructor.
Args:
ip (str): Ip of the camera.
user (str): Onvif login.
password (str): Onvif password.
"""
self.cam_ip = ip
self.cam_user = user
self.cam_password = password
self.cam_port = port#加⼊port参数
并在camera_start函数⾥将默认的80端⼝改为self.cam_port
mycam = ONVIFCamera(self.cam_ip, self.cam_port, self.cam_user, self.cam_password, no_cache =True)这样基本上所有ip的rtsp地址你都能获取到了,少数问题是摄像头鉴权问题

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。