Integrate MQTT Event Intake 0.1

cron-addstorage-fix^2
Moe 2021-11-12 18:32:53 -08:00
parent 1d8ab96c9a
commit fbbe8fb0c7
6 changed files with 276 additions and 4 deletions

View File

@ -1344,5 +1344,9 @@
"scissors": "scissors",
"teddy bear": "teddy bear",
"hair drier": "hair drier",
"toothbrush": "toothbrush"
"toothbrush": "toothbrush",
"Frigate":"Frigate",
"Plain":"Plain",
"MQTT Error":"MQTT Error",
"MQTT Client":"MQTT Client"
}

187
libs/dropInEvents/mqtt.js Normal file
View File

@ -0,0 +1,187 @@
const mqtt = require('mqtt')
module.exports = (s,config,lang,app,io) => {
if(config.mqttClient === true){
const {
triggerEvent,
} = require('./events/utils.js')(s,config,lang)
function sendPlainEvent(options){
const groupKey = options.ke
const monitorId = options.mid || options.id
const subKey = options.subKey
const endpoint = options.host
triggerEvent({
id: monitorId,
ke: groupKey,
details: {
confidence: 100,
name: 'mqtt',
plug: endpoint,
reason: subKey
},
},config.mqttEventForceSaveEvent)
}
function sendFrigateEvent(data,options){
const groupKey = options.ke
const monitorId = options.mid || options.id
const subKey = options.subKey
const endpoint = options.host
const frigateMatrix = data.after || data.before
const confidenceScore = frigateMatrix.top_score * 100
const activeZones = frigateMatrix.entered_zones.join(', ')
const shinobiMatrix = {
x: frigateMatrix.box[0],
y: frigateMatrix.box[1],
width: frigateMatrix.box[2],
height: frigateMatrix.box[3],
tag: frigateMatrix.label,
confidence: confidenceScore,
}
triggerEvent({
id: monitorId,
ke: groupKey,
details: {
confidence: confidenceScore,
name: 'mqtt-'+endpoint,
plug: subKey,
reason: activeZones,
matrices: [shinobiMatrix]
},
},config.mqttEventForceSaveEvent)
}
function createMqttSubscription(options){
const mqttEndpoint = options.host
const subKey = options.subKey
const groupKey = options.ke
const onData = options.onData || function(){}
const client = mqtt.connect('mqtt://' + mqttEndpoint)
client.on('connect', function () {
client.subscribe(subKey, function (err) {
if (err) {
s.debugLog(err)
s.userLog({
ke: groupKey,
mid: '$USER'
},{
type: lang['MQTT Error'],
msg: err
})
}else{
client.on('message', function (topic, message) {
const data = s.parseJSON(message.toString())
onData(data)
})
}
})
})
return client
}
// const onEventTrigger = async () => {}
// const onMonitorUnexpectedExit = (monitorConfig) => {}
const loadMqttListBotForUser = function(user){
const groupKey = user.ke
const userDetails = s.parseJSON(user.details);
const mqttClientList = userDetails.mqttclient_list || []
if(!s.group[groupKey].mqttSubscriptions)s.group[groupKey].mqttSubscriptions = {};
const mqttSubs = s.group[groupKey].mqttSubscriptions
mqttClientList.forEach(function(n,row){
const mqttSubId = `${row.host} ${row.subKey}`
const messageConversionTypes = row.type || []
const monitorsToTrigger = row.monitors || []
const doActions = []
const onData = (data) => {
doActions.forEach(function(theAction){
theAction(data)
})
s.debugLog('MQTT Data',row,data)
}
if(mqttSubs[mqttSubId]){
mqttSubs[mqttSubId].end()
delete(mqttSubs[mqttSubId])
}
messageConversionTypes.forEach(function(type){
switch(type){
case'plain':
doActions.push(function(data){
// data is unused for plain event.
monitorsToTrigger.forEach(function(monitorId){
sendPlainEvent({
host: row.host,
subKey: row.subKey,
ke: groupKey,
mid: monitorId
})
})
})
break;
case'frigate':
// https://docs.frigate.video/integrations/mqtt/#frigateevents
doActions.push(function(data){
// this handler requires using frigate/events
// only "new" events will be captured.
if(data.type === 'new'){
monitorsToTrigger.forEach(function(monitorId){
sendFrigateEvent(data,{
host: row.host,
subKey: row.subKey,
ke: groupKey,
mid: monitorId
})
})
}
})
break;
}
})
mqttSubs[mqttSubId] = createMqttSubscription({
host: row.host,
subKey: row.subKey,
ke: groupKey,
onData: onData,
})
})
}
const unloadMqttListBotForUser = function(user){
const groupKey = user.ke
const mqttSubs = s.group[groupKey].mqttSubscriptions || {}
Object.keys(mqttSubs).forEach(function(n,mqttSubId){
mqttSubs[mqttSubId].end()
delete(mqttSubs[mqttSubId])
})
}
s.loadGroupAppExtender(loadMqttListBotForUser)
s.unloadGroupAppExtender(unloadMqttListBotForUser)
// s.onEventTrigger(onEventTrigger)
// s.onMonitorUnexpectedExit(onMonitorUnexpectedExit)
s.definitions["Account Settings"].blocks["MQTT Client"] = {
"evaluation": "$user.details.use_mqttclient !== '0'",
"name": lang['MQTT Client'],
"color": "green",
"info": [
{
"name": "detail=mqttclient",
"selector":"u_mqttclient",
"field": lang.Enabled,
"default": "0",
"example": "",
"fieldType": "select",
"possible": [
{
"name": lang.No,
"value": "0"
},
{
"name": lang.Yes,
"value": "1"
}
]
},
{
"id": "mqttclient_list",
"fieldType": "div",
}
]
}
//load front end js
s.customAutoLoadTree['LibsJs'].push('bs5.mqtt.js')
}
}

View File

@ -1,5 +1,3 @@
// - tab-return-accountSettings : currently does not function
$(document).ready(function(){
var accountSettingsWereSaved = false;
var theBlock = $('#tab-accountSettings')
@ -8,6 +6,17 @@ $(document).ready(function(){
var addStorageMaxAmounts = $('#add_storage_max_amounts')
var addStorageMaxAmountsField = theForm.find('[detail="addStorage"]')
var monitorGroups = $('#settings_mon_groups')
window.accountSettings = {
onLoadFieldsExtensions: [],
onLoadFields: function(...extender){
accountSettings.onLoadFieldsExtensions.push(...extender)
},
onSaveFieldsExtensions: [],
onSaveFields: function(...extender){
accountSettings.onSaveFieldsExtensions.push(...extender)
},
}
function drawAddStorageFields(){
try{
var addStorageData = JSON.parse($user.details.addStorage || '{}')
@ -89,6 +98,9 @@ $(document).ready(function(){
theForm.find(`[detail="${n}"]`).val(v).change()
})
reDrawMonGroupsInAccountSettings()
accountSettings.onLoadFieldsExtensions.forEach(function(extender){
extender(theForm)
})
}
addStorageMaxAmounts.on('change','[addStorageLimit]',function(){
var json = {}
@ -134,6 +146,9 @@ $(document).ready(function(){
})
var details = getDetailValues(theForm)
formData.details = details
accountSettings.onSaveFieldsExtensions.forEach(function(extender){
extender(formData)
})
$.post(getApiPrefix('accounts') + '/edit',{
data: JSON.stringify(formData)
},function(data){

View File

@ -372,7 +372,7 @@ window.getMonitorEditFormFields = function(){
monitorConfig.details = safeJsonParse(monitorConfig.details)
monitorConfig.details.substream = getSubStreamChannelFields()
monitorConfig.details.groups = getMonitorGroupsSelected()
// TODO : Input Maps and Stream Channels
// TODO : Input Maps and Stream Channels (does old way at the moment)
// if(monitorConfig.protocol=='rtsp'){monitorConfig.ext='mp4',monitorConfig.type='rtsp'}

View File

@ -840,6 +840,16 @@ function buildMiniMonitorCardBody(monitorAlreadyAdded,monitorConfigPartial,addit
`
return cardBody
}
function buildMonitorsListSelectFieldHtml(arrayOfSelected){
var monitorList = Object.values(loadedMonitors).map(function(item){
return {
value: item.mid,
label: item.name,
selected: (arrayOfSelected || []).indexOf(item.mid) > -1,
}
});
return createOptionListHtml(monitorList)
}
$(document).ready(function(){
$('body')
.on('click','[system]',function(){

56
web/assets/js/bs5.mqtt.js Normal file
View File

@ -0,0 +1,56 @@
$(document).ready(function(){
var mqttList = $('#mqttclient_list')
function drawMqttLsitRow(row,number){
var html = `<div class="d-flex flex-row mqtt-list-row">
<div class="flex-grow-1">
<input class="form-control form-control-sm" mqtt-param="host" value="${row.host || ''}">
</div>
<div>
<input class="form-control form-control-sm" mqtt-param="subKey" value="${row.subKey || ''}">
</div>
<div>
<select multiple class="form-control form-control-sm" mqtt-param="type">
${createOptionHtml({
value: 'plain',
label: lang['Plain'],
selected: row.type === 'plain',
})}
${createOptionHtml({
value: 'frigate',
label: lang['Frigate'],
selected: row.type === 'frigate',
})}
</select>
</div>
<div>
<select multiple class="form-control form-control-sm" mqtt-param="monitors">
<option value="${lang['All Monitors']}"></option>
<optgroup label="${lang.Monitors}">${buildMonitorsListSelectFieldHtml(row.monitors || [])}</optgroup>
</select>
</div>
</div>`
return html
}
accountSettings.onLoadFields(function(theForm){
var mqttClientList = $user.details.mqttclient_list ? $user.details.mqttclient_list : []
mqttList.empty()
$.each(mqttClientList,function(n,row){
mqttList.append(drawMqttLsitRow(row,n))
})
})
accountSettings.onSaveFields(function(theForm){
var mqttClientList = []
mqttList.find('.mqtt-list-row').each(function(n,v){
var el = $(v)
var rowFields = {}
el.find('[mqtt-param]').each(function(nn,param){
var paramEl = $(param)
var theKey = paramEl.attr('mqtt-param')
var value = paramEl.val()
rowFields[theKey] = value
})
mqttClientList.push(rowFields)
})
theForm.details.mqttclient_list = mqttClientList
})
})