Désolé pour cette réponse tardive mais j'ai essayé de rendre ce script PHP le plus lisible possible.
Je suis parti d'un script récupéré quelque part sur internet (désolé pour son auteur mais je ne me souviens pas de son nom).
Je l'ai customisé en ajoutant des fonctions d'envoi de mail et de communication avec l'API domoticz.
Selon les évènements détecté je positionne des device domoticz à ON ou OFF, ou l'inverse je teste l'état de device domoticz pour, par exemple, décider des actions du script.
Voici le script "tel que" si tu as des questions n'hésites pas.
Code : Tout sélectionner
<?PHP
$debug = true;
// mail parameters
// Recipient
$to = 'detinataire des mails';
// Sender
$from = 'expediteur des messages';
$fromName = 'identité expediteur';
// Email subject
$subject = 'Appel Interphone !!!';
// Email body content
$htmlContent = '
<h3>Appel interphone pendant absence</h3>
<p>Verifier photo jointe.</p>
';
$Attach="";
echo "<** Dahua VTO Eventempfaenger START **>\n";
$Dahua = new Dahua_Functions("adresseIPmon interphone", "username mon interphone", "pwd mon interphone",$to,$from,$fromName,$subject,$htmlContent,$Attach); # VTO's IP and user/pwd
$status = $Dahua->Main();
logging("All done");
function logging($text){
list($ts) = explode(".",microtime(true));
$dt = new DateTime(date("Y-m-d H:i:s.",$ts));
$logdate = $dt->format("Y-m-d H:i:s.u");
echo $logdate.": ";
print_r($text);
echo "\n";
}
class Dahua_Functions
{
private $sock, $host, $port, $credentials;
private $ID = 0; # Our Request / Responce ID that must be in all requests and initated by us
private $SessionID = 0; # Session ID will be returned after successful login
private $SID = 0; # SID will be returned after we called <service>.attach with 'Object ID'
private $FakeIPaddr = '(null)'; # WebGUI: mask our real IP
private $clientType = ''; # WebGUI: We do not show up in logs or online users
private $keepAliveInterval = 60;
private $lastKeepAlive = 0;
#private $to, $from, $fromName, $subject, $htmlContent, $Attach; #mail parameters
function Dahua_Functions($host, $user, $pass,$to,$from,$fromName,$subject,$htmlContent,$Attach)
{
$this->host = $host;
$this->username = $user;
$this->password = $pass;
$this->to = $to;
$this->from = $from;
$this->fromname = $fromName;
$this->subject=$subject;
$this->htmlcontent=$htmlContent;
$this->attach=$Attach;
}
function Gen_md5_hash($Dahua_random, $Dahua_realm, $username, $password)
{
$PWDDB_HASH = strtoupper(md5($username.':'.$Dahua_realm.':'.$password));
$PASS = $username.':'.$Dahua_random.':'.$PWDDB_HASH;
$RANDOM_HASH = strtoupper(md5($PASS));
return $RANDOM_HASH;
}
function KeepAlive($delay)
{
$DomoticzKeepAliveok="http://domoticz?svalue=keepAlive%20back";
$DomoticzKeepAliveFailed="http://domoticz?svalue=keepAlive%20failed";
global $debug;
logging("Started keepAlive thread");
while(true){
$query_args = array(
'method'=>"global.keepAlive",
'magic'=>"0x1234",
'params'=>array(
'timeout'=>$delay,
'active'=>true
),
'id'=>$this->ID,
'session'=>$this->SessionID);
$this->Send(json_encode($query_args));
$lastKeepAlive = time();
$keepAliveReceived = false;
while($lastKeepAlive + $delay > time()){
$data = $this->Receive();
if (!empty($data)){
foreach($data as $packet) {
$packet = json_decode($packet, true);
if (array_key_exists('result', $packet)){
if($debug) logging("keepAlive back");
$this->SendDomoticz($DomoticzKeepAliveok);
$keepAliveReceived = true;
}
elseif ($packet['method'] == 'client.notifyEventStream'){
$status = $this->EventHandler($packet);
}
}
}
}
if (!$keepAliveReceived){
//logging("keepAlive failed");
$this->SendDomoticz($DomoticzKeepAliveFailed);
return false;
}
}
}
function Send($packet)
{
if (empty($packet)){
$packet = '';
}
$header = pack("N",0x20000000);
$header .= pack("N",0x44484950);
$header .= pack("V",$this->SessionID);
$header .= pack("V",$this->ID);
$header .= pack("V",strlen($packet));
$header .= pack("V",0);
$header .= pack("V",strlen($packet));
$header .= pack("V",0);
if (strlen($header) != 32){
logging("Binary header != 32 ({})");
return;
}
$this->ID += 1;
try{
$msg = $header.$packet;
$result = fwrite($this->sock, $msg);
} catch (Exception $e) {
logging($e);
}
}
function Receive($timeout = 5)
{
#
# We must expect there is no output from remote device
# Some debug cmd do not return any output, some will return after timeout/failure, most will return directly
#
$data = "";
$P2P_header = "";
$P2P_data = "";
$P2P_return_data = [];
$header_LEN = 0;
try{
$len = strlen($data);
$read = array($this->sock);
$write = null;
$except = null;
$ready = stream_select($read, $write, $except, $timeout);
if ($ready > 0) {
$data .= stream_socket_recvfrom($this->sock, 8192);
}
} catch (Exception $e) {
return "";
}
if (strlen($data)==0){
#logging("Nothing received anything from remote");
return "";
}
$LEN_RECVED = 1;
$LEN_EXPECT = 1;
while (strlen($data)>0){
if (substr($data,0,8) == pack("N",0x20000000).pack("N",0x44484950)){ # DHIP
$P2P_header = substr($data,0,32);
$LEN_RECVED = unpack("V",substr($data,16,4))[1];
$LEN_EXPECT = unpack("V",substr($data,24,4))[1];
$data = substr($data,32);
}
else{
if($LEN_RECVED > 1){
$P2P_data = substr($data,0,$LEN_RECVED);
$P2P_return_data[] = $P2P_data;
}
$data = substr($data,$LEN_RECVED);
if ($LEN_RECVED == $LEN_EXPECT && strlen($data)==0){
break;
}
}
}
return $P2P_return_data;
}
function Login()
{
logging("Start login");
$query_args = array(
'id'=>10000,
'magic'=>"0x1234",
'method'=>"global.login",
'params'=>array(
'clientType'=>$this->clientType,
'ipAddr'=>$this->FakeIPaddr,
'loginType'=>"Direct",
'password'=>"",
'userName'=>$this->username,
),
'session'=>0
);
$this->Send(json_encode($query_args));
$data = $this->Receive();
if (empty($data)){
logging("global.login [random]");
return false;
}
$data = json_decode($data[0], true);
$this->SessionID = $data['session'];
$RANDOM = $data['params']['random'];
$REALM = $data['params']['realm'];
$RANDOM_HASH = $this->Gen_md5_hash($RANDOM, $REALM, $this->username, $this->password);
$query_args = array(
'id'=>10000,
'magic'=>"0x1234",
'method'=>"global.login",
'session'=>$this->SessionID,
'params'=>array(
'userName'=>$this->username,
'password'=>$RANDOM_HASH,
'clientType'=>$this->clientType,
'ipAddr'=>$this->FakeIPaddr,
'loginType'=>"Direct",
'authorityType'=>"Default",
)
);
$this->Send(json_encode($query_args));
$data = $this->Receive();
if (empty($data)){
return false;
}
$data = json_decode($data[0], true);
if (array_key_exists('result', $data) && $data['result']){
logging("Login success");
$this->keepAliveInterval = $data['params']['keepAliveInterval'];
return true;
}
logging("Login failed: ".$data['error']['code']." ".$data['error']['message']);
return false;
}
function Main($reconnectTimeout=60)
{
$AlertDomoticzOn="http://Domoticz?&svalue=%20Plus%20reseau%20interphone";
$AlertDomoticzOSocketError="http://domoticz&nvalue=4&svalue=Socket%20open%20failed";
$AlertDomoticzFailure="http://domoticz&svalue=Failure%20eventManager.attach";
$error = false;
while (true){
if($error){
sleep($reconnectTimeout);
}
$error = true;
$this->sock = @fsockopen($this->host, 5000, $errno, $errstr, 5);
if($errno){
logging("Socket open failed");
$this->SendDomoticz($AlertDomoticzOSocketError);
continue;
}
if (!$this->Login()){
continue;
}
#Listen to all events
$query_args = array(
'id'=>$this->ID,
'magic'=>"0x1234",
'method'=>"eventManager.attach",
'params'=>array(
'codes'=>["All"]
),
'session'=>$this->SessionID
);
$this->Send(json_encode($query_args));
$data = $this->Receive();
if (!count($data) || !array_key_exists('result', json_decode($data[0], true))){
logging("Failure eventManager.attach");
$this->SendDomoticz($AlertDomoticzFailure);
continue;
}
else{
unset($data[0]);
foreach($data as $packet) {
$packet = json_decode($packet, true);
if ($packet['method'] == 'client.notifyEventStream'){
$status = $this->EventHandler($packet);
}
}
}
$this->KeepAlive($this->keepAliveInterval);
logging("Failure no keep alive received");
$this->SendDomoticz($AlertDomoticzOn);
}
}
function EventHandler($data)
{
global $debug;
$eventList = $data['params']['eventList'][0];
$eventCode = $eventList['Code'];
$eventData = $eventList['Data'];
$DomoticzURlBoutonportail="http://domoticz";//Message quand appui sur bouton interphone
$DomoticzURLDetecteurPassage="http://domoticz";//message quand detecteur de passage activé
$DomoticzURLInterphoneEffraction="http://domoticz"; //Message si effraction sur interphone
$DomoticzURLSonnerieExterne="http://domoticz"; //message pour activer sonnerie externe
$DomoticzURLMouvementPortail="http://domoticz"; //mesasge pour indiquer un mouvement du portail
if(count($data['params']['eventList'])>1){
logging("Event Manager subscription reply");
}
elseif($eventCode == 'CallNoAnswered'){
logging("Event Call from VTO");
logging("Call domoticz !!!!");
$this->SaveSnapshot();
if ($this->QueryDomoticz())
{
$this->SendMail();
}
$this->SendDomoticz($DomoticzURlBoutonportail);
}
elseif($eventCode == 'IgnoreInvite'){
logging("Event VTH answered call from VTO");
}
elseif($eventCode == 'VideoMotion'){
logging("Event VideoMotion");
$this->SaveSnapshot();
}
elseif($eventCode == 'RtspSessionDisconnect'){
if($eventList['Action'] == 'Start'){
logging("Event Rtsp-Session from ".str_replace("::ffff:","",$eventData['Device'])." disconnected");
}
elseif($eventList['Action'] == 'Stop'){
logging("Event Rtsp-Session from ".str_replace("::ffff:","",$eventData['Device'])." connected");
}
}
elseif($eventCode == 'BackKeyLight'){
logging("Event BackKeyLight with State ".$eventData['State']." ");
}
elseif($eventCode == 'TimeChange'){
logging("Event TimeChange, BeforeModifyTime: ".$eventData['BeforeModifyTime'].", ModifiedTime: ".$eventData['ModifiedTime']."");
}
elseif($eventCode == 'NTPAdjustTime'){
if($eventData['result']) logging("Event NTPAdjustTime with ".$eventData['Address']." success");
else logging("Event NTPAdjustTime failed");
}
elseif($eventCode == 'KeepLightOn'){
if($eventData['Status'] == 'On'){
logging("Event KeepLightOn");
}
elseif($eventData['Status'] == 'Off'){
logging("Event KeepLightOff");
}
}
elseif($eventCode == 'VideoBlind'){
if($eventList['Action'] == 'Start'){
logging("Event VideoBlind started");
}
elseif($eventList['Action'] == 'Stop'){
logging("Event VideoBlind stopped");
}
}
elseif($eventCode == 'FingerPrintCheck'){
if($eventData['FingerPrintID'] > -1){
$finger=($eventData['FingerPrintID']);
$users = array( #From VTO FingerprintManager/FingerprintID
"0" => "Papa",
"1" => "Mama",
"2" => "Kind1",
"3" => "Kind2");
$name=$users[$finger];
logging("Event FingerPrintCheck success, Finger number ".$eventData['FingerPrintID'].", User ".$name."");
}
else{
logging("Event FingerPrintCheck failed, unknown Finger");
}
}
elseif($eventCode == 'DoorCard'){
if($eventList['Action'] == 'Pulse'){
$cardno=($eventData['Number']);
logging("DoorCard ".$cardno." was used at door");
}
}
elseif($eventCode == 'SIPRegisterResult'){
if($eventList['Action'] == 'Pulse'){
if($eventData['Success']) logging("Event SIPRegisterResult, Success");
else logging("Event SIPRegisterResult, Failed)");
}
}
elseif($eventCode == 'AccessControl'){
#Method:4=Remote/WebIf/SIPext,6=FingerPrint; UserID: from VTO FingerprintManager/Room Number or SIPext;
logging("Event: AccessControl, Name ".$eventData['Name']." Method ".$eventData['Method'].", ReaderID ".$eventData['ReaderID'].", UserID ".$eventData['UserID']);
logging("Door open, call domoticz !!!");
$url=$DomoticzURLMouvementPortail."On";
SendDomoticz($url);
}
elseif($eventCode == 'CallSnap'){
logging("Event: CallSnap, DeviceType ".$eventData['DeviceType']." RemoteID ".$eventData['RemoteID'].", RemoteIP ".$eventData['RemoteIP']." CallStatus ".$eventData['ChannelStates'][0]);
}
elseif($eventCode == 'Invite'){
logging("Event: Invite, Action ".$eventList['Action'].", CallID ".$eventData['CallID']." Lock Number ".$eventData['LockNum']);
}
elseif($eventCode == 'AlarmLocal'){
logging("Event: AlarmLocal, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'AccessSnap'){
logging("Event: AccessSnap, FTP upload to ".$eventData['FtpUrl']);
}
elseif($eventCode == 'RequestCallState'){
logging("Event: RequestCallState, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
logging("call domoticz stop ringing");
}
elseif($eventCode == 'PassiveHungup'){
logging("Event: PassiveHungup, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'ProfileAlarmTransmit'){
logging("Event: ProfileAlarmTransmit, Action ".$eventList['Action'].", AlarmType ".$eventData['AlarmType']." DevSrcType ".$eventData['DevSrcType'].", SenseMethod ".$eventData['SenseMethod']);
if ($eventData['AlarmType'] == 'PreventRemove'){
if ($eventList['Action'] == 'Start'){
logging("call domoticz alerte effraction");
$url=$DomoticzURLInterphoneEffraction."On";
SendDomoticz($url);
}
elseif ($eventList['Action'] == 'Stop'){
logging("call domoticz fin alerte effraction");
$url=$DomoticzURLInterphoneEffraction."Off";
SendDomoticz($url);
}
}
}
elseif($eventCode == 'NewFile'){
logging("Event: NewFile, Action ".$eventList['Action'].", File ".$eventData['File'].", Folder ".$eventData['Filter'].", LocaleTime ".$eventData['LocaleTime'].", Index ".$eventData['Index']);
}
elseif($eventCode == 'UpdateFile'){
logging("Event: UpdateFile, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'Reboot'){
logging("Event: Reboot, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'SecurityImExport'){
logging("Event: SecurityImExport, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime'].", Status ".$eventData['Status']);
}
elseif($eventCode == 'DGSErrorReport'){
logging("Event: DGSErrorReport, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'Upgrade'){
logging("Event: Upgrade, Action ".$eventList['Action'].", with State".$eventData['State'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'SendCard'){
logging("Event: SendCard, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'AddCard'){
logging("Event: AddCard, Action ".$eventList['Action'].": CardNo ".$eventData['Data'][0]['CardNo'].", UserID ".$eventData['Data'][0]['UserID'].", UserName ".$eventData['Data'][0]['UserName'].", CardStatus ".$eventData['Data'][0]['CardStatus'].", CardType ".$eventData['Data'][0]['CardType'].", Doors: Door 0=".$eventData['Data'][0]['Doors'][0].", Door1=".$eventData['Data'][0]['Doors'][1]);
}
elseif($eventCode == 'DoorStatus'){
logging("Event: DoorStatus, Action ".$eventList['Action'].", Status: ".$eventData['Status'].", LocaleTime ".$eventData['LocaleTime']);
if ($eventData['Status'] == 'Open'){
logging("call domoticz detecteur passage activé");
$url=$DomoticzURLDetecteurPassage."On";
SendDomoticz($url);
}
elseif ($eventData['Status'] == 'Close'){
logging("call domoticz detecteur passage désactivé");
$url=$DomoticzURLDetecteurPassage."Off";
SendDomoticz($url);
}
}
elseif($eventCode == 'DoorControl'){
logging("Event: DoorControl, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'DoorNotClosed'){
logging("Event: DoorNotClosed, Action ".$eventList['Action'].", Name".$eventData['Name'].", LocaleTime ".$eventData['LocaleTime']);
}
elseif($eventCode == 'NetworkChange'){
logging("Event: NetworkChange, Action ".$eventList['Action'].", LocaleTime ".$eventData['LocaleTime']);
}
else{
logging("Unknown event received");
if($debug) var_dump($data);
}
return true;
}
function SaveSnapshot($path="/tmp/")
{
$filename = $path."/DoorBell_".date("Y-m-d_H-i-s").".jpg";
$fp = fopen($filename, 'wb');
$url = "http://".$this->host."/cgi-bin/snapshot.cgi";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, $this->username . ":" . $this->password);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPGET, 1);
curl_exec($ch);
curl_close($ch);
fclose($fp);
copy($filename, $path."/Doorbell.jpg");
$this->attach=$filename;
$this->purge_jpg();
}
function QueryDomoticz()
{
// check if device "Envoi photo" is ON
$DomoticzURLPhotoInterphone="http://domoticz"; //mesage pour tester si dummy "envoi photo " = on
// create a new cURL resource
$ch = curl_init();
//query domoticz to retrieve dummy state
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $DomoticzURLPhotoInterphone);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
// grab URL and pass it to the browser
$tt=curl_exec($ch);
// close cURL resource, and free up system resources
curl_close($ch);
$data = json_decode($tt,true);
//var_dump($data["result"]);
logging("Status dummy domoticz : ".$data["result"][0]["Data"]);
if ($data["result"][0]["Data"] == "On" or $data["result"][0]["Data"]== false)
{
return true;
}
else
{
return false;
}
}
function SendMail()
{
logging("Debut Sendmail");
// Recipient
$to = $this->to;
// Sender
$from = $this->from;
$fromName = $this->fromname;
logging("to : ".$to);
logging("from :".$from);
logging("fromname :".$fromName);
// Email subject
$subject = $this->subject;
// Attachment file
//$file = "/tmp/DoorBell_2021-06-28_20-17-26.jpg";
$file=$this->attach;
logging("file :".$file);
// Email body content
//$htmlContent = '
// <h3>PHP Email with Attachment by CodexWorld</h3>
// <p>This email is sent from the PHP script with attachment.</p>
//';
$htmlContent=$this->htmlcontent;
// Header for sender info
$headers = "From: $fromName"." <".$from.">";
//$headers = "From:".$this->fromName." <".$this.from.">";
// Boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// Headers for attachment
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";
// Multipart boundary
$message = "--{$mime_boundary}\n" . "Content-Type: text/html; charset=\"UTF-8\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" . $htmlContent . "\n\n";
// Preparing attachment
if(!empty($file) > 0){
if(is_file($file)){
$message .= "--{$mime_boundary}\n";
$fp = @fopen($file,"rb");
$data = @fread($fp,filesize($file));
@fclose($fp);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: application/octet-stream; name=\"".basename($file)."\"\n" .
"Content-Description: ".basename($file)."\n" .
"Content-Disposition: attachment;\n" . " filename=\"".basename($file)."\"; size=".filesize($file).";\n" .
"Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
}
}
$message .= "--{$mime_boundary}--";
$returnpath = "-f" . $from;
// Send email
$mail = @mail($to, $subject, $message, $headers, $returnpath);
// Email sending status
echo $mail?"<h1>Email Sent Successfully!</h1>":"<h1>Email sending failed.</h1>";
}
function purge_jpg()
{
$fileList = glob('/tmp/DoorBell_*');
foreach($fileList as $filename){
if(is_file($filename)){
//echo $filename."\n";
//echo filemtime($filename)."\n";
$today=time();
$today=date("Ymd", $today);
//echo $today."\n";
$datefile=filemtime($filename);
$datefile=date("Ymd", $datefile);
//echo $datefile."\n";
$interval = $today-$datefile;
//echo $interval."\n";
if ($interval > 9)
{
echo "delete ".$filename."\n";
unlink($filename);
}
}
}
}
function SendDomoticz($url)
{
// create a new cURL resource
logging("Domoticz : ".$url."\n");
$ch = curl_init();
//query domoticz to retrieve dummy state
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
// grab URL and pass it to the browser
$tt=curl_exec($ch);
// close cURL resource, and free up system resources
curl_close($ch);
}
}
?>