nnnLik
@nnnLik
Capybara god

Как вывести список всех подключенных onvif камер?

У меня есть 2 ip камеры с поддержкой onvif, моя задача, вывести в списке их ip.

у меня есть такой вариант и он рабочий.
import re
import netifaces
from typing import List

from wsdiscovery.discovery import ThreadedWSDiscovery as WSDiscovery


def find(scope=None):
    if scope == None:
        ips = list()
        for iface in netifaces.interfaces():
            if netifaces.AF_INET in netifaces.ifaddresses(iface):
                ips.append(netifaces.ifaddresses(iface)[netifaces.AF_INET][0]["addr"])
        scope = [".".join(ip.split(".")[:2]) for ip in ips]
    wsd = WSDiscovery()
    wsd.start()
    ret = wsd.searchServices()
    wsd.stop()
    onvif_services = [s for s in ret if str(s.getTypes()).find("onvif") >= 0]
    urls = [ip for s in onvif_services for ip in s.getXAddrs()]
    ips = [ip for url in urls for ip in re.findall(r"\d+\.\d+\.\d+\.\d+", url)]
    lst = [ip for ip in ips if any(ip.startswith(sp) for sp in scope)]
    return sorted(lst)

Проблема заключается в том, что я не могу использовать этот скрипт в приложении фастапи. Если делаю 1 запрос, то результат приходит, но если сделать второй, после, то получаю следующую ошибку

INFO: Started server process [58321]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on 127.0.0.1:8000 (Press CTRL+C to quit)
INFO: 127.0.0.1:54781 - "GET /cameras HTTP/1.1" 200 OK
INFO: 127.0.0.1:54801 - "GET /cameras HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/fastapi/applications.py", line 270, in __call__
await super().__call__(scope, receive, send)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
raise exc
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/routing.py", line 706, in __call__
await route.handle(scope, receive, send)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/routing.py", line 276, in handle
await self.app(scope, receive, send)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/routing.py", line 66, in app
response = await func(request)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/fastapi/routing.py", line 237, in app
raw_response = await run_endpoint_function(
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/fastapi/routing.py", line 165, in run_endpoint_function
return await run_in_threadpool(dependant.call, **values)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/starlette/concurrency.py", line 41, in run_in_threadpool
return await anyio.to_thread.run_sync(func, *args)
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/anyio/to_thread.py", line 31, in run_sync
return await get_asynclib().run_sync_in_worker_thread(
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 937, in run_sync_in_worker_thread
return await future
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 867, in run
result = context.run(func, *args)
File "fastapi_wed.py", line 18, in find_cameras
wsd.start()
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/wsdiscovery/threaded.py", line 285, in start
self._startThreads()
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/wsdiscovery/threaded.py", line 265, in _startThreads
self._networkingThread.start()
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/wsdiscovery/threaded.py", line 239, in start
self._multiInSocket = self._createMulticastInSocket()
File "/Users/macbook/Python-Proj/test/fastapi-onvif/venv/lib/python3.8/site-packages/wsdiscovery/threaded.py", line 109, in _createMulticastInSocket
sock.bind(('', MULTICAST_PORT))
OSError: [Errno 48] Address already in use


Думаю ,что это не получиться так просто исправить, так как тут ошибка с самой библиотекой wsdiscovery и просто найти новый способ без этой библиотеки и чтобы работало с фастапи.
  • Вопрос задан
  • 202 просмотра
Решения вопроса 1
nnnLik
@nnnLik Автор вопроса
Capybara god
Не понял почему это так работает, но если создать экземпляр класса с методом и вызывать то все будет работать...
Вот результат:

from fastapi import FastAPI
import re
import netifaces

from wsdiscovery.discovery import ThreadedWSDiscovery as WSDiscovery

app = FastAPI()


class Finder:
    def __init__(self):
        self.ips = list()
        for iface in netifaces.interfaces():
            if netifaces.AF_INET in netifaces.ifaddresses(iface):
                self.ips.append(
                    netifaces.ifaddresses(iface)[netifaces.AF_INET][0]["addr"]
                )
        self.scope = [".".join(ip.split(".")[:2]) for ip in self.ips]
        self.wsd = WSDiscovery()

    def start(self):
        self.wsd.start()
        self.ret = self.wsd.searchServices()
        self.wsd.stop()
        self.onvif_services = [
            s for s in self.ret if str(s.getTypes()).find("onvif") >= 0
        ]
        self.urls = [ip for s in self.onvif_services for ip in s.getXAddrs()]
        self.ips = [
            ip for url in self.urls for ip in re.findall(r"\d+\.\d+\.\d+\.\d+", url)
        ]
        self.lst = [
            ip for ip in self.ips if any(ip.startswith(sp) for sp in self.scope)
        ]
        return {"results": self.lst}


finder = Finder()


@app.get("/cameras")
def find_cameras():
    return {"cameras": finder.start()}


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app)


Если кто-то знает почему так, пожалуйста, обьясните
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы