Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support of ONVIF event such as visitor (ring bell), face detect, person detect, car detect, pet detect #26

Merged
merged 4 commits into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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