Skip to content

Commit

Permalink
Merge pull request #26 from t0urista/master
Browse files Browse the repository at this point in the history
support of ONVIF event such as visitor (ring bell), face detect, person detect, car detect, pet detect
  • Loading branch information
Jezza34000 committed Mar 10, 2024
2 parents 405c96b + 302132d commit 1eea1eb
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 34 deletions.
96 changes: 96 additions & 0 deletions core/config/reolinkapicmd.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,102 @@
"isVisible": 1,
"logicalId": "MdState"
},


{
"abilityneed":"alarmMd",
"name": "event Motion (etat)",
"type": "info",
"subtype": "binary",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvMotion"
},
{
"abilityneed":"alarmMd",
"name": "event FaceDetect (etat)",
"type": "info",
"subtype": "binary",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvFaceDetect"
},
{
"abilityneed":"alarmMd",
"name": "event PeopleDetect (etat)",
"type": "info",
"subtype": "binary",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvPeopleDetect"
},
{
"abilityneed":"alarmMd",
"name": "event VehicleDetect (etat)",
"type": "info",
"subtype": "binary",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvVehicleDetect"
},
{
"abilityneed":"alarmMd",
"name": "event DogCatDetect (etat)",
"type": "info",
"subtype": "binary",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvDogCatDetect"
},
{
"abilityneed":"alarmMd",
"name": "event MotionAlarm (etat)",
"type": "info",
"subtype": "binary",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvMotionAlarm"
},
{
"abilityneed":"alarmMd",
"name": "event Visitor (etat)",
"type": "info",
"subtype": "binary",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvVisitor"
},

{
"abilityneed":"alarmMd",
"name": "last Onvif Event (full) ",
"type": "info",
"subtype": "string",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvLastOnvifFull"
},

{
"abilityneed":"alarmMd",
"name": "last Onvif Event (name) ",
"type": "info",
"subtype": "string",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvLastOnvifName"
},

{
"abilityneed":"alarmMd",
"name": "last Onvif Event (etat)",
"type": "info",
"subtype": "binary",
"IsHistorized": 0,
"isVisible": 1,
"logicalId": "EvLastOnvifState"
},

{
"abilityneed":"performance",
"name": "Débit codec (Kbps)",
Expand Down
27 changes: 24 additions & 3 deletions core/php/jeeReolink.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
die();
}

if (isset($result['message']) && $result['message'] == "motion") {
# BEGIN modified by t0urista to handle ONVIF events
if (isset($result['message']) && (($result['message']=="motion") || (strpos($result['message'], 'Ev') !== false) )) {
# END modified by t0urista to handle ONVIF events

$plugin = plugin::byId('reolink');
$eqLogics = eqLogic::byType($plugin->getId());

Expand All @@ -31,8 +34,26 @@
}

if ($camera_ip == $result['ip']) {
log::add('reolink', 'debug', 'Evènement MotionState reçu depuis le daemon. Cam IP='.$result['ip'].' état='.$result['motionstate']);
$eqLogic->checkAndUpdateCmd('MdState', $result['motionstate']);
if ($result['message'] == "motion") {
log::add('reolink', 'debug', 'Cam IP='.$result['ip']. ' Onvif event reçu depuis le daemon. name= MDstate, état='.$result['motionstate']);
$eqLogic->checkAndUpdateCmd('MdState', $result['motionstate']);
}

# BEGIN added by t0urista to handle ONVIF events

# catch any ONVIF events in the 3 genreic ONVIF commands, can cover unknown ONVIF events
$eqLogic->checkAndUpdateCmd('EvLastOnvifName', $result['message']);
$eqLogic->checkAndUpdateCmd('EvLastOnvifState', $result['motionstate']);
$eqLogic->checkAndUpdateCmd('EvLastOnvifFull', $result['message'] . '-' . $result['motionstate']);

# catch all pre-defined ONVIF events with their dedicated commands, does only cover knwon ONVIF events

if (strpos($result['message'], 'Ev') !== false) {
log::add('reolink', 'debug', 'Cam IP='.$result['ip']. ' Onvif event reçu depuis le daemon. name= ' . $result['message'] . ', etat='.$result['motionstate']);
$eqLogic->checkAndUpdateCmd($result['message'], $result['motionstate']);
}
# END added by t0urista to handle ONVIF events

#log::add('reolink', 'debug', 'IP : ' . $camera_contact_point . ' / IsCamAI : ' . $camera_AI . ' / EqId : ' . $EqId . ' / Channel : ' . $channel);
if ($camera_AI == "Oui") {
$camcnx = reolink::getReolinkConnection($eqLogic->getId());
Expand Down
116 changes: 85 additions & 31 deletions resources/demond/camhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,103 @@
import re

try:
from jeedom.jeedom import *
from jeedom.jeedom import *
except ImportError:
print("Error: importing module jeedom.jeedom")
sys.exit(1)
print("Error: importing module jeedom.jeedom")
sys.exit(1)

try:
f = open('jeedomcreds', 'r')
_callback = f.readline().rstrip("\n")
_apikey = f.readline().rstrip("\n")
f.close()
f = open('jeedomcreds', 'r')
_callback = f.readline().rstrip("\n")
_apikey = f.readline().rstrip("\n")
f.close()
except:
logging.error(f"Unable to read credentials jeedom file, retry...")
sys.exit(1)
logging.error(f"Unable to read credentials jeedom file, retry...")
sys.exit(1)

try:
os.remove("jeedomcreds")
os.remove("jeedomcreds")
except:
pass
pass

jeedom_cnx = jeedom_com(_apikey, _callback)
detect_state = 0
# BEGIN added by t0urista to handle ONVIF events
eventTable = {}
# END added by t0urista to handle ONVIF events
app = FastAPI()


@app.post("/inbound_events", status_code=200)
async def get_body(request: Request):
global detect_state
ip = request.client.host
logging.debug(f"Incoming XML camera event on webhook from IP={ip}")
xml_answer = await request.body()

new_detect_state = 0
if re.search('IsMotion" Value="true"', xml_answer.decode('utf-8')):
new_detect_state = 1

if detect_state != new_detect_state:
detect_state = new_detect_state
send_frame = {
"message": "motion",
"ip": ip,
"motionstate": detect_state
}
# convert into JSON:
message = json.dumps(send_frame)
jeedom_cnx.send_change_immediate(json.loads(message))
return

global detect_state

# BEGIN added by t0urista to handle ONVIF events
global eventTable
# END added by t0urista to handle ONVIF events


ip = request.client.host
logging.debug(f"Incoming XML camera event on webhook from IP={ip}")
xml_answer = await request.body()

new_detect_state = 0
if re.search('IsMotion" Value="true"', xml_answer.decode('utf-8')):
new_detect_state = 1
if detect_state != new_detect_state:
detect_state = new_detect_state
send_frame = {
"message": "motion",
"ip": ip,
"motionstate": detect_state
}
# convert into JSON:
message = json.dumps(send_frame)
jeedom_cnx.send_change_immediate(json.loads(message))


# BEGIN added by t0urista to handle ONVIF events
pattern=r'<wsnt:.*?ConcreteSet">(.*?)</wsnt:Topic>.*?<tt:Data>.*?Value="(.*?)" /></tt:Data>'
event_status_all=re.findall(pattern,xml_answer.decode('utf-8'))

# logging.debug(event_status_all)
for event_status in event_status_all:
# logging.debug(event_status)
event=re.findall(r'tns1:.*/(.*)', event_status[0])
event="Ev" + event[0]
# logging.debug(event[0])
status=0
if(event_status[1]!="false"):
status=1
logging.debug(f"received event {event} {status}")
eventFound=0
for eventName in eventTable:
# print(eventName)
if (eventName==event):
eventFound=1
if (eventTable[eventName]!=status):
logging.debug(f"{event} --> {status}")
eventTable[eventName]=status
send_frame = {
"message": event,
"ip": ip,
"motionstate": status
}
# convert into JSON:
message = json.dumps(send_frame)
jeedom_cnx.send_change_immediate(json.loads(message))
if (eventFound==0):
eventTable[event] = status
logging.debug(f"{event} --> {status}")
send_frame = {
"message": event,
"ip": ip,
"motionstate": status
}
# convert into JSON:
message = json.dumps(send_frame)
jeedom_cnx.send_change_immediate(json.loads(message))
# END added by t0urista to handle ONVIF events

return

0 comments on commit 1eea1eb

Please sign in to comment.