Skip to content

Instantly share code, notes, and snippets.

@themactep
Forked from 667bdrm/ipcam-clock-set.pl
Created September 9, 2022 00:56
Show Gist options
  • Save themactep/f878e1103bfc6d4372715e9825404f29 to your computer and use it in GitHub Desktop.
Save themactep/f878e1103bfc6d4372715e9825404f29 to your computer and use it in GitHub Desktop.
Simple clock synchronization for some chinese DVRs supporting CMS with json-like protocol. Includes some other API commands. Fork at https://gitlab.com/667bdrm/sofiactl
#!/usr/bin/perl
# latest release at https://gitlab.com/667bdrm/sofiactl
#
# Simple clock synchronization for some chinese HiSilicon based DVRs supporting CMS (Sofia software) with json-like protocol. Tested with:
#
# HJCCTV HJ-H4808BW (XiongMai, Hi3520, MBD6304T)
# http://www.aliexpress.com/item/Hybird-NVR-8chs-H-264DVR-8chs-onvif-2-3-Economical-DVR-8ch-Video-4-AUDIO-AND/1918734952.html
#
#
# PBFZ TCV-UTH200 (XiongMai, Hi3518, 50H20L_S39)
# http://www.aliexpress.com/item/Free-shipping-2014-NEW-IP-camera-CCTV-2-0MP-HD-1080P-IP-Network-Security-CCTV-Waterproof/1958962188.html
#
# Additional protocol reference : https://github.com/charmyin/IPCTimeLapse
# vendor sdk: https://github.com/mondwan/cpp-surveillance-cli
# vendor: http://www.xiongmaitech.com
# vendor specifications: http://wiki.xm030.com:81/
package IPcam;
use Module::Load::Conditional qw[can_load check_install requires];
my $use_list = {
'IO::Socket' => undef,
'IO::Socket::INET' => undef,
'Time::Local' => undef,
JSON => undef,
'Data::Dumper' => undef,
};
if (!can_load( modules => $use_list, autoload => true )) {
die('Failed to load required modules: ' . join(', ', keys %{$use_list}));
}
use constant {
LOGIN_REQ1 => 999,
LOGIN_REQ2 => 1000,
LOGIN_RSP => 1000,
LOGOUT_REQ => 1001,
LOGOUT_RSP => 1002,
FORCELOGOUT_REQ => 1003,
FORCELOGOUT_RSP => 1004,
KEEPALIVE_REQ => 1006, # 1005
KEEPALIVE_RSP => 1007, # 1006
SYSINFO_REQ => 1020,
SYSINFO_RSP => 1021,
CONFIG_SET => 1040,
CONFIG_SET_RSP => 1041,
CONFIG_GET => 1042,
CONFIG_GET_RSP => 1043,
DEFAULT_CONFIG_GET => 1044,
DEFAULT_CONFIG_GET_RSP => 1045,
CONFIG_CHANNELTILE_SET => 1046,
CONFIG_CHANNELTILE_SET_RSP => 1047,
CONFIG_CHANNELTILE_GET => 1048,
CONFIG_CHANNELTILE_GET_RSP => 1049,
CONFIG_CHANNELTILE_DOT_SET => 1050,
CONFIG_CHANNELTILE_DOT_SET_RSP => 1051,
SYSTEM_DEBUG_REQ => 1052,
SYSTEM_DEBUG_RSP => 1053,
ABILITY_GET => 1360,
ABILITY_GET_RSP => 1361,
PTZ_REQ => 1400,
PTZ_RSP => 1401,
MONITOR_REQ => 1410,
MONITOR_RSP => 1411,
MONITOR_DATA => 1412,
MONITOR_CLAIM => 1413,
MONITOR_CLAIM_RSP => 1414,
PLAY_REQ => 1420,
PLAY_RSP => 1421,
PLAY_DATA => 1422,
PLAY_EOF => 1423,
PLAY_CLAIM => 1424,
PLAY_CLAIM_RSP => 1425,
DOWNLOAD_DATA => 1426,
TALK_REQ => 1430,
TALK_RSP => 1431,
TALK_CU_PU_DATA => 1432,
TALK_PU_CU_DATA => 1433,
TALK_CLAIM => 1434,
TALK_CLAIM_RSP => 1435,
FILESEARCH_REQ => 1440,
FILESEARCH_RSP => 1441,
LOGSEARCH_REQ => 1442,
LOGSEARCH_RSP => 1443,
FILESEARCH_BYTIME_REQ => 1444,
FILESEARCH_BYTIME_RSP => 1445,
SYSMANAGER_REQ => 1450,
SYSMANAGER_RSP => 1451,
TIMEQUERY_REQ => 1452,
TIMEQUERY_RSP => 1453,
DISKMANAGER_REQ => 1460,
DISKMANAGER_RSP => 1461,
FULLAUTHORITYLIST_GET => 1470,
FULLAUTHORITYLIST_GET_RSP => 1471,
USERS_GET => 1472,
USERS_GET_RSP => 1473,
GROUPS_GET => 1474,
GROUPS_GET_RSP => 1475,
ADDGROUP_REQ => 1476,
ADDGROUP_RSP => 1477,
MODIFYGROUP_REQ => 1478,
MODIFYGROUP_RSP => 1479,
DELETEGROUP_REQ => 1480,
DELETEGROUP_RSP => 1481,
ADDUSER_REQ => 1482,
ADDUSER_RSP => 1483,
MODIFYUSER_REQ => 1484,
MODIFYUSER_RSP => 1485,
DELETEUSER_REQ => 1486,
DELETEUSER_RSP => 1487,
MODIFYPASSWORD_REQ => 1488,
MODIFYPASSWORD_RSP => 1489,
GUARD_REQ => 1500,
GUARD_RSP => 1501,
UNGUARD_REQ => 1502,
UNGUARD_RSP => 1503,
ALARM_REQ => 1504,
ALARM_RSP => 1505,
NET_ALARM_REQ => 1506,
NET_ALARM_REQ => 1507,
ALARMCENTER_MSG_REQ => 1508,
UPGRADE_REQ => 1520,
UPGRADE_RSP => 1521,
UPGRADE_DATA => 1522,
UPGRADE_DATA_RSP => 1523,
UPGRADE_PROGRESS => 1524,
UPGRADE_INFO_REQ => 1525,
UPGRADE_INFO_RSQ => 1526,
IPSEARCH_REQ => 1530,
IPSEARCH_RSP => 1531,
IP_SET_REQ => 1532,
IP_SET_RSP => 1533,
CONFIG_IMPORT_REQ => 1540,
CONFIG_IMPORT_RSP => 1541,
CONFIG_EXPORT_REQ => 1542,
CONFIG_EXPORT_RSP => 1543,
LOG_EXPORT_REQ => 1544, #CONDIG_EXPORT_REQ
LOG_EXPORT_RSP => 1545, #CONFIG_EXPORT_RSP
NET_KEYBOARD_REQ => 1550,
NET_KEYBOARD_RSP => 1551,
NET_SNAP_REQ => 1560,
NET_SNAP_RSP => 1561,
SET_IFRAME_REQ => 1562,
SET_IFRAME_RSP => 1563,
RS232_READ_REQ => 1570,
RS232_READ_RSP => 1571,
RS232_WRITE_REQ => 1572,
RS232_WRITE_RSP => 1573,
RS485_READ_REQ => 1574,
RS485_READ_RSP => 1575,
RS485_WRITE_REQ => 1576,
RS485_WRITE_RSP => 1577,
TRANSPARENT_COMM_REQ => 1578,
TRANSPARENT_COMM_RSP => 1579,
RS485_TRANSPARENT_DATA_REQ => 1580,
RS485_TRANSPARENT_DATA_RSP => 1581,
RS232_TRANSPARENT_DATA_REQ => 1582,
RS232_TRANSPARENT_DATA_RSP => 1583,
SYNC_TIME_REQ => 1590,
SYNC_TIME_RSP => 1591,
PHOTO_GET_REQ => 1600,
PHOTO_GET_RSP => 1601,
};
sub new {
my $classname = shift;
my $self = {};
bless($self, $classname);
$self->_init(@_);
return $self;
}
sub DESTROY {
my $self = shift;
}
sub disconnect {
my $self = shift;
$self->{socket}->close();
}
sub _init {
my $self = shift;
$self->{host} = "";
$self->{port} = 0;
$self->{user} = "";
$self->{password} = "";
$self->{socket} = undef;
$self->{sid} = 0;
$self->{SystemInfo} = undef;
$self->{GenericInfo} = undef;
$self->{lastcommand} = undef;
$self->{sequence} = 0;
if (@_) {
my %extra = @_;
@$self{keys %extra} = values %extra;
}
}
sub getDeviceRuntime {
my $self = shift;
$self->getSystemInfo();
my $total_minutes = hex($self->{SystemInfo}->{DeviceRunTime});
my $total_hours = $total_minutes / 60;
my $total_days = $total_minutes / (60*24);
my $left_minutes = $total_minutes % (60*24);
my $hours = int($left_minutes / 60);
my $minutes = int($left_minutes % 60);
my $years = $total_days / 365;
my $left_days = $total_days % 365;
my $months = int( $left_days / 30);
my $days = $left_days % 30;
$total_minutes -= $months * 24 * 60;
$total_hours = int($total_hours);
$total_days = int($total_days);
$runtime = sprintf("%d day(s): %d year(s), %d month(s), %d day(s), %d hour(s), %d minute(s)", $total_days, $years, $months, $days, $hours, $minutes);
return $runtime;
}
sub BuildPacketSid {
my $self = shift;
return sprintf("0x%08x",$self->{sid});
}
sub BuildPacket {
my $self = shift;
my ($type, $params) = @_;
my @pkt_prefix_1;
my @pkt_prefix_2;
my $pkt_type;
my $json = JSON->new;
@pkt_prefix_1 = (0xff, 0x01, 0x00, 0x00); # (head_flag, version, reserved01, reserved02)
@pkt_prefix_2 = (0x00, 0x00, 0x00, 0x00); # (total_packets, cur_packet)
$pkt_type = $type;
#my $msgid = pack('c*', @$pkt_type);
my $msgid = pack('s', 0) . pack('s', $pkt_type);
my $pkt_prefix_data = pack('c*', @pkt_prefix_1) . pack('i', $self->{sid}) . pack('c*', @pkt_prefix_2). $msgid;
my $pkt_params_data = $json->encode($params);
my $pkt_data = $pkt_prefix_data . pack('i', length($pkt_params_data)) . $pkt_params_data;
$self->{lastcommand} = $params->{Name} . sprintf(" msgid = %d", $pkt_type);
return $pkt_data;
}
sub GetReplyHead {
my $self = shift;
my $data;
my @reply_head_array;
# head_flag, version, reserved
$self->{socket}->recv($data, 4);
my @header = unpack('C*', $data);
my ($head_flag, $version, $reserved01, $reserved02) = (@header)[0,1,2,3];
# int sid, int seq
$self->{socket}->recv($data, 8);
my ($sid,$seq) = unpack('i*', $data);
$reply_head_array[3] = ();
$self->{socket}->recv($data, 8);
my ($channel,$endflag,$msgid,$size) = unpack('CCSI', $data);
my $reply_head = {
Version => $version,
SessionID => $sid,
Sequence => $seq,
MessageId => $msgid,
Content_Length => $size,
};
$self->{sequence} = $reply_head->{Sequence};
printf("reply: head_flag=%x version=%d session=0x%x sequence=%d channel=%d end_flag=%d msgid=%d size = %d lastcommand = %s\n", $head_flag, $version, $sid, $seq, $channel, $end_flag, $msgid, $size, $self->{lastcommand});
return $reply_head;
}
sub GetReplyData {
my $self = shift;
my $reply = $_[0];
my $length = $reply->{'Content_Length'};
my $out;
for (my $downloaded=0; $downloaded < $length; $downloaded++) {
$self->{socket}->recv($data, 1);
$out .= $data;
}
return $out;
}
sub getSystemInfo {
my $self = shift;
if ($self->{SystemInfo} eq undef) {
$self->CmdSystemInfo();
}
return $self->{SystemInfo};
}
sub PrepareGenericCommandHead {
my $self = shift;
my $msgid = $_[0];
my $parameters = $_[1];
my $data;
my $pkt = $parameters;
if ($msgid ne LOGIN_REQ2) {
$parameters->{SessionID} = $self->BuildPacketSid();
}
my $cmd_data = $self->BuildPacket($msgid, $pkt);
$self->{socket}->send($cmd_data);
my $reply_head = $self->GetReplyHead();
return $reply_head;
}
sub PrepareGenericCommand {
my $self = shift;
my $msgid = $_[0];
my $parameters = $_[1];
my $reply_head = $self->PrepareGenericCommandHead($msgid, $parameters);
my $out = $self->GetReplyData($reply_head);
if ($msgid eq LOGIN_REQ2 and exists $reply_head->{SessionID}) {
$self->{sid} = hex($reply_head->{SessionID});
}
if ($out) {
return decode_json($out);
}
return undef;
}
sub PrepareGenericDownloadCommand {
my $self = shift;
my $msgid = $_[0];
my $parameters = $_[1];
my $file = $_[2];
my $reply_head = $self->PrepareGenericCommandHead($msgid, $parameters);
my $out = $self->GetReplyData($reply_head);
open(OUT, ">$file");
print OUT $out;
close(OUT);
return 1;
}
sub CmdLogin {
my $self = shift;
my $data;
my $pkt = {
EncryptType => "MD5",
LoginType => "DVRIP-Web",
PassWord => $self->{password},
UserName => $self->{user}
};
print Dumper $pkt;
$reply_json = $self->PrepareGenericCommand(LOGIN_REQ2, $pkt);
$self->{GenericInfo} = $reply_json;
return $reply_json;
}
sub CmdSystemInfo {
my $self = shift;
my $pkt = {
Name => 'SystemInfo',
};
my $systeminfo = $self->PrepareGenericCommand(SYSINFO_REQ, $pkt);
$self->{SystemInfo} = $systeminfo->{SystemInfo};
return $systeminfo;
}
sub CmdAlarmInfo {
my $self = shift;
my $parameters = $_[0];
my $pkt = {
Name => 'AlarmInfo',
AlarmInfo => $parameters,
};
return $self->PrepareGenericCommand(ALARM_REQ, $pkt);
}
sub CmdOPNetAlarm {
my $self = shift;
my $pkt = {
Name => 'OPNetAlarm',
NetAlarmInfo => {
Event => 0,
State => 1,
},
};
return $self->PrepareGenericCommand(NET_ALARM_REQ, $pkt);
}
sub CmdAlarmCenterMsg {
my $self = shift;
my $data;
my $pkt = {
Name => 'NetAlarmCenter',
NetAlarmCenterMsg => {
Address => "0x0B0A060A",
Channel => 0,
Descrip => "",
Event => "MotionDetect",
SerialID => "003344236523",
StartTime => "2010-06-24 17:04:22",
Status => "Stop",
Type => "Alarm",
},
};
my $cmd_data = $self->BuildPacket(ALARMCENTER_MSG_REQ, $pkt);
$self->{socket}->send($cmd_data);
my $reply_head = $self->GetReplyHead();
my $out = $self->GetReplyData($reply_head);
return decode_json($out);
}
sub CmdOPNetKeyboard {
my $self = shift;
my $parameters = $_[0];
my $pkt = {
Name => 'OPNetKeyboard',
OPNetKeyboard => $parameters,
};
return $self->PrepareGenericCommand(NET_KEYBOARD_REQ, $pkt);
}
sub CmdUsers {
my $self = shift;
my $pkt = {
};
return $self->PrepareGenericCommand(USERS_GET, $pkt);
}
sub CmdGroups {
my $self = shift;
my $pkt = {
};
return $self->PrepareGenericCommand(GROUPS_GET, $pkt);
}
sub CmdStorageInfo {
my $self = shift;
my $pkt = {
Name => 'StorageInfo',
};
return $self->PrepareGenericCommand(SYSINFO_REQ, $pkt);
}
sub CmdWorkState {
my $self = shift;
my $pkt = {
Name => 'WorkState',
};
return $self->PrepareGenericCommand(SYSINFO_REQ, $pkt);
}
sub CmdSnap {
my $self = shift;
my $pkt = {
Name => 'OPSNAP',
};
return $self->PrepareGenericCommand(NET_SNAP_REQ, $pkt);
}
sub CmdEmpty {
my $self = shift;
my $pkt = {
Name => '',
};
return $self->PrepareGenericCommand(SYSINFO_REQ, $pkt);
}
sub CmdKeepAlive {
my $self = shift;
my $pkt = {
Name => 'KeepAlive',
};
return $self->PrepareGenericCommand(KEEPALIVE_REQ, $pkt);
}
sub CmdOPMonitorClaim {
my $self = shift;
my $pkt = {
Name => 'OPMonitor',
SessionID => $self->BuildPacketSid(),
OPMonitor => {
Action => "Claim",
Parameter => {
Channel => 0,
CombinMode => "NONE",
StreamType => "Extra1",
TransMode => "TCP"
}
}
};
my $cmd_data = $self->BuildPacket(MONITOR_CLAIM, $pkt);
$self->{socket}->send($cmd_data);
my $reply = $self->GetReplyHead();
for my $k (keys %{$reply}) {
print "rh = $k\n";
}
my $out = $self->GetReplyData($reply);
my $out1 = decode_json($out);
# $self->{socket}->recv($data, 1);
return $out1;
}
sub CmdOPMonitorStop {
my $self = shift;
my $pkt = {
Name => 'OPMonitor',
SessionID => $self->BuildPacketSid(),
OPMonitor => {
Action => "Stop",
Parameter => {
Channel => 0,
CombinMode => "NONE",
StreamType => "Extra1",
TransMode => "TCP"
}
}
};
my $cmd_data = $self->BuildPacket(MONITOR_REQ, $pkt);
$self->{socket}->send($cmd_data);
my $reply = $self->GetReplyHead();
for my $k (keys %{$reply}) {
print "rh = $k\n";
}
my $out = $self->GetReplyData($reply);
my $out1 = decode_json($out);
# $self->{socket}->recv($data, 1);
return $out1;
}
sub CmdOPMonitorStart {
my $self = shift;
my $data;
my $pkt = {
Name => 'OPMonitor',
SessionID => $self->BuildPacketSid(),
OPMonitor => {
Action => "Start",
Parameter => {
Channel => 0,
CombinMode => "NONE",
StreamType => "Extra1",
TransMode => "TCP"
}
}
};
my $cmd_data = $self->BuildPacket(MONITOR_REQ, $pkt);
$self->{socket}->send($cmd_data);
open(OUT, ">> ".$self->{sid}.".h264");
$stop = 0;
while (defined( my $reply = $self->GetReplyHead()) and $stop == 0 ) {
if (sprintf("%x", $reply->{Data1}) ne "12ff") {
for my $k (keys %{$reply}) {
print "rh = $k\n";
}
print "Content_Length = " . $reply->{Content_Length} . "\n";
my $out = $self->GetReplyData($reply);
print OUT $out;
if ($reply->{Sequence} > 3) {
#$stop = 1;
$self->CmdKeepAlive();
}
} else {
$stop = 1;
break;
}
}
close(OUT);
return $out1;
}
sub CmdOPTimeSetting {
my $self = shift;
my $nortc = $_[0];
my $data;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
my $clock_cmd = 'OPTimeSetting';
my $pkt_type = SYSMANAGER_REQ;
if ($nortc eq 1) {
$clock_cmd .= 'NoRTC';
$pkt_type = SYNC_TIME_REQ;
}
my $pkt = {
Name => $clock_cmd,
SessionID => $self->BuildPacketSid(),
"$clock_cmd" => sprintf("%4d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec)
};
my $cmd_data = $self->BuildPacket($pkt_type, $pkt);
$self->{socket}->send($cmd_data);
my $reply = $self->GetReplyHead();
my $out = $self->GetReplyData($reply);
if ($out) {
return decode_json($out);
}
return undef;
}
#buggy
sub CmdSystemFunction {
my $self = shift;
my $pkt = {
Name => 'SystemFunction',
};
return $self->PrepareGenericCommand(ABILITY_REQ, $pkt);
}
sub CmdOPFileQuery {
my $self = shift;
my $parameters = $_[0];
my $pkt = {
Name => 'OPFileQuery',
OPFileQuery => $parameters,
};
return $self->PrepareGenericCommand(FILESEARCH_REQ, $pkt);
}
sub CmdOEMInfo {
my $self = shift;
my $pkt = {
Name => 'OEMInfo',
};
return $self->PrepareGenericCommand(SYSINFO_REQ, $pkt);
}
sub CmdOPPlayBack {
my $self = shift;
my $parameters = $_[0];
my $pkt = {
Name => 'OPPlayBack',
OPPlayBack => $parameters,
};
return $self->PrepareGenericCommand(PLAY_REQ, $pkt);
}
sub CmdOPLogQuery {
my $self = shift;
my $parameters = $_[0];
my $pkt = {
Name => 'OPLogQuery',
OPLogQuery => $parameters,
};
return $self->PrepareGenericCommand(LOGSEARCH_REQ, $pkt);
}
sub LogExport {
my $self = shift;
my $file = $_[0];
my $pkt = {
Name => '',
};
return $self->PrepareGenericDownloadCommand(LOG_EXPORT_REQ, $pkt, $file);
}
sub ConfigExport {
my $self = shift;
my $file = $_[0];
my $pkt = {
Name => '',
};
return $self->PrepareGenericDownloadCommand(CONFIG_EXPORT_REQ, $pkt, $file);
}
sub CmdOPStorageManager {
my $self = shift;
my $data;
my $parameters = $_[0];
my $pkt = {
Name => 'OPStorageManager',
'OPStorageManager' => $parameters,
SessionID => $self->BuildPacketSid(),
};
return $self->PrepareGenericCommand(DISKMANAGER_REQ, $pkt);
}
package main;
use IO::Socket;
use IO::Socket::INET;
use Time::Local;
use Getopt::Long;
use Pod::Usage;
use Data::Dumper;
my $cfgFile = "";
my $cfgUser = "";
my $cfgPass = "";
my $cfgHost = "";
my $cfgPort = "";
my $cfgCmd = undef;
my $help = 0;
my $result = GetOptions (
"help|h" => \$help,
"outputfile|of|o=s" => \$cfgFile,
"user|u=s" => \$cfgUser,
"pass|p=s" => \$cfgPass,
"host|hst=s" => \$cfgHost,
"port|prt=s" => \$cfgPort,
"command|cmd|c=s" => \$cfgCmd,
);
pod2usage(1) if ($help);
if (!($cfgHost or $cfgPort or $cfgUser)) {
print STDERR "You must set user, host and port!\n";
exit(0);
}
my $socket = IO::Socket::INET->new(
PeerAddr => $cfgHost,
PeerPort => $cfgPort,
Proto => 'tcp',
Timeout => 10000,
Type => SOCK_STREAM,
Blocking => 1
) or die "Error at line " . __LINE__. ": $!\n";
print "Setting clock for: host = $cfgHost port = $cfgPort\n";
my $dvr = IPcam->new(host => $cfgHost, port => $cfgPort, user => $cfgUser, password => $cfgPass, socket => $socket);
my $savePath = '/tmp';
my $decoded = $dvr->CmdLogin();
#Ret = 100 - login ok
#Ret = 205 - bad login
#Ret = 101 - ???
$aliveInterval = $decoded->{'AliveInterval'};
print sprintf("SessionID = 0x%08x\n",$dvr->{sid});
print sprintf("AliveInterval = %d\n",$aliveInterval);
my $decoded = $dvr->CmdSystemInfo();
print Dumper $dvr->{GenericInfo};
print Dumper $dvr->getSystemInfo();
print "System running:" . $dvr->getDeviceRuntime() ."\n";
if ($cfgCmd eq "OPTimeSetting") {
$decoded = $dvr->CmdOPTimeSetting(1);
$decoded = $dvr->CmdOPTimeSetting();
} elsif ($cfgCmd eq "Users") {
$decoded = $dvr->CmdUsers();
} elsif ($cfgCmd eq "Groups") {
$decoded = $dvr->CmdGroups();
} elsif ($cfgCmd eq "StorageInfo") {
$decoded = $dvr->CmdStorageInfo();
} elsif ($cfgCmd eq "WorkState") {
$decoded = $dvr->CmdWorkState();
} elsif ($cfgCmd eq "LogExport") {
$decoded = $dvr->LogExport($cfgFile);
} elsif ($cfgCmd eq "ConfigExport") {
$decoded = $dvr->ConfigExport($cfgFile);
} elsif ($cfgCmd eq "OEMInfo") {
$decoded = $dvr->CmdOEMInfo();
} elsif ($cfgCmd eq "OPStorageManagerClear") {
$decoded = $dvr->CmdOPStorageManager({
Action => "Clear",
PartNo => 0,
SerialNo => 0,
Type => "Data",
});
} elsif ($cfgCmd eq "OPStorageManagerPartition") {
$decoded = $dvr->CmdOPStorageManager({
Action => "Partition",
PartNo => 0,
PartitionSize => ( { "Record" => 853869 }, { "SnapShot" => 100000 } ),
SerialNo => 0 ,
});
} elsif ($cfgCmd eq "OPStorageManagerRecover") {
$decoded = $dvr->CmdOPStorageManager({
Action => "Recover",
PartNo => 0,
SerialNo => 0,
});
} elsif ($cfgCmd eq "OPStorageManagerRW") {
$decoded = $dvr->CmdOPStorageManager({
Action => "SetType",
PartNo => 0,
SerialNo => 0,
Type => "ReadWrite",
});
} elsif ($cfgCmd eq "OPStorageManagerRO") {
$decoded = $dvr->CmdOPStorageManager({
Action => "SetType",
PartNo => 0,
SerialNo => 0,
Type => "ReadOnly",
});
}
print Dumper $decoded;
#my $decoded = $dvr->CmdSystemFunction();
#my $decoded = $dvr->CmdOPFileQuery({
# BeginTime => "2016-07-01 22:00:00",
# EndTime => "2016-07-01 23:59:59",
# Channel => 1,
# # search all channels instead of single
# #HighChannel => 0,
# #LowChannel => 255,
# DriverTypeMask => "0x0000FFFF",
# Event => "*", # * - All; A - Alarm; M - Motion Detect; R - General; H - Manual;
# Type => "h264" #h264 or jpg
#});
#my $decoded = $dvr->CmdOPPlayBack({
# Action => "Claim",
# EndTime => '2015-05-04 17:59:24',
# StartTime => '2015-05-04 17:59:09',
# Parameter => {
# FileName => '/idea0/2015-05-04/002/17.59.09-17.59.24[M][@12480][0].h264',
# PlayMode => "ByName",
# TransMode => "TCP",
# Value => 0
# }
#});
my $decoded = $dvr->CmdAlarmInfo({
Channel => 0,
Event => "VideoMotion",
StartTime => "2016-07-03 03:36:11",
Status => "Start"
});
#my $decoded = $dvr->CmdOPNetAlarm(); #FIXME
#my $decoded = $dvr->CmdAlarmCenterMsg(); #FIXME
my $decoded = $dvr->CmdOPNetKeyboard({
Status => "KeyUp",
Value => "0",
});
#my $decoded = $dvr->CmdSnap(); #FIXME unsuppoted?
#my $decoded = $dvr->CmdOPLogQuery({
# BeginTime => "2014-01-01 00:00:00",
# EndTime => "2016-06-29 00:00:00",
# LogPosition => 0,
# Type => "LogAll",
#});
#my $pkt = {
# Name => '',
#};
#my $decoded = $dvr->PrepareGenericDownloadCommand(IPcam::PHOTO_GET_REQ, $pkt, "out.dat");
print Dumper $decoded;
$dvr->disconnect();
__END__
=head1 NAME
./dvr.pl - utility for working with nvr data
=head1 SYNOPSIS
./dvr.pl [options]
=head1 OPTIONS
=over 8
=item B<-help>
Print a brief help message and exits.
=item B<-of>
Path to output file filename.
=item B<-u>
username
=item B<-p>
password
=item B<-host>
nvr hostname or ip address
=item B<-port>
nvr CMS port
=item B<-c>
nvr command: OPTimeSetting, Users, Groups, WorkState, StorageInfo, OEMInfo, LogExport, ConfigExport, OPStorageManagerClear
=back
=head1 DESCRIPTION
B<This program> can control the NVR.
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment