alexshpilkin / dvrip Goto Github PK
View Code? Open in Web Editor NEWPython DVRIP (Xiongmai, XMEye, Sofia protocol) library and tools
License: Creative Commons Zero v1.0 Universal
Python DVRIP (Xiongmai, XMEye, Sofia protocol) library and tools
License: Creative Commons Zero v1.0 Universal
Hi,
Can you add capability to change settings of camera?
I have the communication between XMeye and Camera recorded, and this is how it goes:
..... ...........I...{ "Camera.Param.[0]" : { "AeSensitivity" : 7, "ApertureMode" : "0x00000001", "BLCMode" : "0x00000001", "DayNightColor" : "0x00000000", "Day_nfLevel" : 3, "DncThr" : 30, "ElecLevel" : 50, "EsShutter" : "0x00000006", "ExposureParam" : { "LeastTime" : "0x00000064", "Level" : 0, "MostTime" : "0x00010000" }, "GainParam" : { "AutoGain" : 0, "Gain" : 50 }, "IRCUTMode" : 1, "IrcutSwap" : 0, "Night_nfLevel" : 3, "PictureFlip" : "0x00000001", "PictureMirror" : "0x00000001", "RejectFlicker" : "0x00000000", "WhiteBalance" : "0x00000000" }, "Name" : "Camera.Param.[0]", "SessionID" : "0x9" }
Binary:
ff000000060000001800000000001004490200007b202243616d6572612e506172616d2e5b305d22203a207b2022416553656e736974697669747922203a20372c202241706572747572654d6f646522203a202230783030303030303031222c2022424c434d6f646522203a202230783030303030303031222c20224461794e69676874436f6c6f7222203a202230783030303030303030222c20224461795f6e664c6576656c22203a20332c2022446e6354687222203a2033302c2022456c65634c6576656c22203a2035302c202245735368757474657222203a202230783030303030303036222c20224578706f73757265506172616d22203a207b20224c6561737454696d6522203a202230783030303030303634222c20224c6576656c22203a20302c20224d6f737454696d6522203a20223078303030313030303022207d2c20224761696e506172616d22203a207b20224175746f4761696e22203a20302c20224761696e22203a203530207d2c202249524355544d6f646522203a20312c202249726375745377617022203a20302c20224e696768745f6e664c6576656c22203a20332c202250696374757265466c697022203a202230783030303030303031222c2022506963747572654d6972726f7222203a202230783030303030303031222c202252656a656374466c69636b657222203a202230783030303030303030222c2022576869746542616c616e636522203a20223078303030303030303022207d2c20224e616d6522203a202243616d6572612e506172616d2e5b305d222c202253657373696f6e494422203a202230783622207d0a
Receive after
.... ...........:...{ "Name" : "", "Ret" : 100, "SessionID" : "0x00000009" }
PEP8 clearly says Spaces are the preferred indentation method.. And large majority of Python project follow. But dvrip uses tabs. That's in sharp contrast to having a testsuite, using type annotations, etc. Is there a reason for that?
Looks good from peeking into the code - but how to use? I don't seem to even be able to install it (on Ubuntu 20 - I don't have much idea with python personally).
Appreciate there have been a couple of issues raised about the readme but in the absence of a readme maybe someone else can just leave a comment saying basically how to install and run it?
Hi Alex,
thank you for great job. Awsame!
I'm trying to integrate this library with Home-Assistant. My concern is to make it work async. Home Assistant is using asyncio and I'm trying to send stream from camera using monitor to pipe then read it with ffmped and then process.
Do you have time to make it async?
Can you give an example to use your code ?
Failing with #6, we're proceeding with python3.7 -m venv ...
. Looking at setup.py there're bunch of dvr-*
entrypoint. But running them have no effect:
(.venv) dvrip$ dvr-info
Usage: info
(.venv) dvrip$ dvr-info 192.168.1.10
Usage: info
(.venv) dvrip$ dvr-info -h 192.168.1.10
Usage: info
That's apparently because "calling conventions" for subcommands have changed, and nowadays
if host() is None:
usage()
is always true.
hello! i've wrote example code of core features from this project, so you can just use it as a wiki.
the snapshoting function now relies on PyAV library which costs additional 45MB when code compiled,
but i'm in progress of writing my own h264 decoder in python3, which i would be glad to share either.
import socket
import traceback
from io import BytesIO
from PIL import Image
from av.packet import Packet
from av.codec.context import CodecContext
from dvrip.monitor import Stream
from dvrip.io import DVRIPClient
Status = {
None: 0,
'Wrong password': -1,
'Banned': 2
}
class XMEye:
def __init__(self, ip=None, port=None):
self.ip = ip
self.port = port
self.login = None
self.password = None
def auth(self, login, password):
global Status
self.Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.Socket.settimeout(4)
self.conn = DVRIPClient(self.Socket)
log_in = self.conn.connect((self.ip, self.port), login, password)
return Status[log_in]
def get_snapshot(self, ch):
self.Socket2 = socket.create_connection((self.ip, self.port), 11)
h264 = self.conn.monitor(self.Socket2, channel=ch, stream=Stream.HD)
data = b''
while True:
if chunk := h264.read(1024):
data += chunk
if len(chunk) < 1024:
break
self.codec_264 = CodecContext.create("h264", "r")
frame = self.codec_264.decode(Packet(data)):
# frame[0].to_image().save(f'frame_{frame.index}.jpg')
jpeg = BytesIO()
frame[0].to_image().save(jpeg, format='JPEG')
if ch == self.channels:
self.conn.logout()
self.Socket2.close()
return jpeg.getvalue()
def sys_info(self):
info = self.conn.systeminfo()
self.channels_count = int(info.videoin)
self.model = f'{info.chassis}_{info.board}'
try:
ptz = self.conn.button(channel=0, button=PTZButton.MENU)
except DVRIPRequestError:
ptz = None
if int(info.audioin) > 0 and ptz is None:
self.model = f'{self.model}-Sound'
elif ptz is not None:
self.model = f'{self.model}-PTZ'
return
# def debug(self):
# self.conn.keepalive()
Hi alex
I have installed your dvrip via pip but i am struggling to run your code pass this error
File "C:\Python36\lib\site-packages\dvrip\typing.py", line 80, in json_to
return type.json_to # type: ignore
AttributeError: 'tuple' object has no attribute 'json_to'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "dvrip_test.py", line 8, in
from dvrip.io import DVRIPClient
File "C:\Python36\lib\site-packages\dvrip\io.py", line 8, in
from .info import GetInfo, Info
File "C:\Python36\lib\site-packages\dvrip\info.py", line 72, in
class DiskInfo(Object):
File "C:\Python36\lib\site-packages\dvrip\typing.py", line 360, in new
member.set_name(self, mname)
File "C:\Python36\lib\site-packages\dvrip\typing.py", line 301, in set_name
self.pipe = (jsontype(get_args(ann)[0]),)
File "C:\Python36\lib\site-packages\dvrip\typing.py", line 138, in jsontype
return (json_to(type), for_json)
File "C:\Python36\lib\site-packages\dvrip\typing.py", line 87, in json_to
if issubclass(type, bool): # needs to come before 'int'
TypeError: issubclass() arg 1 must be a class
when you print whats happening it getting stuck on
(typing.List, <class 'dvrip.info.PartitionInfo'>)
i am using python 3.6.7 on windows
many thanks
jon
I'm not sure if I find empathy here, but my system is not made of rubber. If I'll install all the things I try (even in virtualenv), it will be a mess. That's pretty much why I use Python - that I can clone, review code, run, and hack on it, all without extra unneeded motions.
Let's try it here:
$ python3.7 -m dvrip.cmd
/usr/bin/python3.7: No module named dvrip.cmd.__main__; 'dvrip.cmd' is a package and cannot be directly executed
Oops. Following an observation in #5, looks like some contrast with depending on features which aren't available in default Python installed in many distro nowadays (3.5-3.6), and not having old good (by now) __main__.py
.
Following patch allows to proceed further:
diff --git a/dvrip/cmd/__main__.py b/dvrip/cmd/__main__.py
new file mode 100644
index 0000000..e7d3e76
--- /dev/null
+++ b/dvrip/cmd/__main__.py
@@ -0,0 +1,4 @@
+from . import main
+
+
+main()
Hi,
thank you for the project.
I am trying to download all video files which I list with conn.files()
This is the function I am using:
def download(file):
socket = Socket(AF_INET, SOCK_STREAM)
conn = DVRIPClient(socket)
conn.connect((argv[1], DVRIP_PORT), argv[2], argv[3])
sock = Socket(AF_INET, SOCK_STREAM)
sock.connect((argv[1], DVRIP_PORT))
namepart = file.name.split('/')
print(namepart)
newname = "{}-{}".format(namepart[2], namepart[4])
if os.path.exists(newname):
have = os.path.getsize(newname)
if have == file.length*1024:
print("file complete")
return
sz = 0
lastping = 0
rdr = conn.download(sock, file.name)
with open(newname, 'wb') as out:
while True:
chunk = rdr.read(16)
sz += len(chunk)
#print(sz)
if not chunk: break
out.write(chunk)
out.flush()
if time.time() > lastping + 10:
lastping = time.time()
print(conn.storageinfo())
sock.close()
this only started working after I patched playback like this:
diff --git a/dvrip/playback.py b/dvrip/playback.py
index 6668ce5..4ad296f 100644
--- a/dvrip/playback.py
+++ b/dvrip/playback.py
@@ -26,6 +26,7 @@ class PlaybackParams(Object):
# TODO there are more
name: member[str] = member('FileName')
transport: fixedmember = fixedmember('TransMode', 'TCP') # TODO
+ playmode: fixedmember = fixedmember('PlayMode', 'ByName')
class Playback(Object):
action: member[PlaybackAction] = member('Action')
I took the parameter from a capture I made during download using the original activeX plugin:
"Name" : "OPPlayBack", "OPPlayBack" : { "Action" : "Claim", "EndTime" : "2023-10-26 08:28:41", "Parameter" : { "FileName" : "/idea0/2023-10-26/001/08.25.00-08.28.41[R][@355c][0].h264", "IntelligentPlayBackEvent" : "", "IntelligentPlayBackSpeed" : -1, "PlayMode" : "ByName", "StreamType" : 0, "TransMode" : "TCP", "Value" : 0 }, "StartTime" : "2023-10-26 08:25:00" }, "SessionID" : "0x763" }
Before this, the downloaded file didn't match the FileSize parameter (maybe related to #9 ?)
There is one weird thing though, I need to keep "pinging" the api using some command (see conn.storageinfo() in my code) to prevent the download from freezing. This helps but it still freezes sometimes.
Do you have some idea how to make this flawless?
I start it with following command:
dvr -h 192.168.117.101 -u admin cat '/idea0/2020-10-24/001/08.28.17-08.28.45[M][@2d10][0].h264'
and get video from 2020-10-01
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.