一种动态联动的实现方法

安防领域中的联动规则

有安防领域相关的开发经历的人知道,IPCamera可以配置使能“侦测”功能,并且指定仅针对图像传感器的某个区载进行侦测。除了基本的“移动侦测"外,侦测的功能点还有细化的类别,如人员侦测、车辆侦测、烟雾侦测等。这些侦测配置后若被触发,会在IPCamera内部产生一些事件;这事件发生时,IPC内部会有相应的动作,例如:邮件报告、图片上传、视频上传等;还可以配置IPC蜂鸣器报警、外置LED灯闪烁等(若有相应的硬件外设)。在IPC的Web界面,用户可以方便地配置这些选项:

IPCamera动态联动配置

如何实现这一功能呢?笔者咨询过相关在安防产业工作的朋友,得到的方案有两种:

  • IPC内部产生的事件种类是固定的,能够做出动作也是有限的,那么直接使用C/C++编码实现这些逻辑;
  • 将事件与动作分别独立为应用中的子模块,使用“胶水”语言Lua将二者联动起来;

朋友也坦言,第一种方案在代码库中存在很久了,代码逻辑错踪复杂;尤其是一些定制类的IPCamera项目,需求不同会造成开发人员花费不少的时间在动态联动的代码修改上。而第二种方案,虽然在项目开发上可以缩短时间,但只有少部分项目中有,接口也不一样,帮助不大:第一种方案仍是团队内部项目开发的主要方法。

动态联动的问题抽象

本文中,笔者将此类动态联动的问题抽象化,并提供上面提到的第二种方法的演示实现。假设IPCamera内部的图像处理会产生五个维度的状态量,名称分别为:
ex_var1/ex_var2/ex_var3/ex_var4/ex_var5

这五个状态量,与三个联动规则相关(即事件,当判定条件为真时会触发);也可能会产生另外三个联动规则不为真时的动作。也就是说,三个联动规则需要这五个变量来决定是否为真。笔者将这些信息写入到配置文件中由演示应用读取:

{"linked-vars": {"ex_var1": 1,"ex_var2": 2,"ex_var3": 3,"ex_var4": 4.2,"ex_var5": 5},"linked-action": [{"rule": "(ex_var1 + ex_var2 * 2 + ex_var3 * 3) > 14","true": "echo 'The planet Earth is freaking too hot'","false": "echo 'The planet Earth is freaking too cold'"},{"rule": "math.floor(ex_var4 * 5 / 4) > ex_var5","true": "echo 'Note that floor(ex_var4 * 5 / 4) > ex_var5'","false": "echo 'Note that floor(ex_var4 * 5 / 4) <= ex_var5'"},{"rule": "(ex_var1 + ex_var2 + ex_var3 + ex_var4 + ex_var4) >= 16","true": "echo 'All example values summed up greater or equal to 16.'","false": "echo 'All example values summed up less than 16'"}]
}

注意,上面的rule即一个动态联动规则是否判定为真的条件。它是一个Lua语句;这里只一行语句,在具体的实践层面上,可以是多行的计算(这里只支持一个语句)。上面还给出当事件联动为真时要执行的动作,例如,当全球平均温度大于14(度)时,就会触发事件:

echo 'The planet Earth is freaking too hot'

也就是简单地调用/bin/sh输出一行信息。当该条件为假时,则会触发另一个动作(可选)。

动态联动规则的实现

上面的JSON配置文件描述了我们抽象化的动态联动问题。笔者编写的演示例子,会根据上面的信息构造一个Lua脚本,用于计算三个联动规则是否成立:

local ex_var1 = 1
local ex_var3 = 3
local ex_var5 = 5
local ex_var2 = 2
local ex_var4 = 4.2
function rulefunc_1()return (ex_var1 + ex_var2 * 2 + ex_var3 * 3) > 14
end
function rulefunc_2()return math.floor(ex_var4 * 5 / 4) > ex_var5
end
function rulefunc_3()return (ex_var1 + ex_var2 + ex_var3 + ex_var4 + ex_var4) >= 16
end
function rulefunc_all()local link_tval_ = 0link_tval_ = link_tval_ + ex_var1link_tval_ = link_tval_ + ex_var3link_tval_ = link_tval_ + ex_var5link_tval_ = link_tval_ + ex_var2link_tval_ = link_tval_ + ex_var4return link_tval_
end

根据Lua的引用规则说明,五个演示变量都是上面构造的四个函数的上级变量(upvalue)。注意,上面的Lua函数rulefunc_2只引用了两个变量;也就是说,一些联动规则并不需要全部的状态量。当上面的代码编译为Lua字节码后,如何通一个函数的上级变量索引来更新所有的上级变量呢?这正是rulefunc_all函数的用处:它引用了全部五个变量,它的名称是固定的,虽然它不会被调用,但我们可以通过它来更新该构造脚本的全部上级变量。之后,这个脚本会使用luaL_dostring API预编译为一个Lua状态机:

rext_any_t rext_lua_new(const struct rext_var * lvar, int * errp) {...luaL_openlibs(L); /* load standard library */if (script != NULL && script[0] != '\0') {int ret;ret = luaL_dostring(L, script);if (ret != 0) {*errp = EINVAL;lua_close(L);L = NULL;}}

注意到,上面的配置信息给出了五个演示变量的初始值。这些值在判定一个联动规则是否被触发前,需要被更新。笔者采用的方法,正是上面提到的,通过函数rulefunc_all来更新:

int rext_upval_set(rext_any_t anyt, const struct rext_var * rfunc,int upindex, const struct rext_var * rval)
{...ret = rext_pushval(anyt, rval);if (ret < 0) {lua_settop(L, oldtop);return -7;}valp = lua_setupvalue(L, ntop, upindex);if (valp == NULL) {lua_settop(L, oldtop);return -8;}

之后,笔者简单编了5个变量的值,来测试演示动态联动:

    let t_map: HashMap<&str, f64> = HashMap::from([("ex_var1", 1f64),("ex_var2", 2f64),("ex_var3", 3f64),("ex_var4", 4f64),("ex_var5", 5f64),]);linked.act(&t_map);let t_map: HashMap<&str, f64> = HashMap::from([("ex_var1", 2f64),("ex_var2", 3f64),("ex_var3", 4f64),("ex_var4", 5f64),("ex_var5", 6f64),]);linked.act(&t_map);

动态联动的演示代码与结果

笔者提供了联动规则的演示代码,感兴趣的可以从此处获取。它的正常运行需要Ubuntu系统下安装Lua5.1开发库及Rust编译器:

sudo apt install lua5.1 liblua5.1-0-dev rust-full bindgen

笔者运行的结果如下:

Created Lua-state machine: 0x562e74aecfc0
Inserting ex_var5 => 1
Inserting ex_var4 => 2
Inserting ex_var3 => 3
Inserting ex_var1 => 4
Inserting ex_var2 => 5
Lua upvalues found: 5
The planet Earth is freaking too cold
false: 0 => (ex_var1 + ex_var2 * 2 + ex_var3 * 3) > 14
Note that floor(ex_var4 * 5 / 4) <= ex_var5
false: 0 => math.floor(ex_var4 * 5 / 4) > ex_var5
All example values summed up less than 16
false: 0 => (ex_var1 + ex_var2 + ex_var3 + ex_var4 + ex_var4) >= 16The planet Earth is freaking too hot
true : 0 => (ex_var1 + ex_var2 * 2 + ex_var3 * 3) > 14
Note that floor(ex_var4 * 5 / 4) <= ex_var5
false: 0 => math.floor(ex_var4 * 5 / 4) > ex_var5
All example values summed up greater or equal to 16.
true : 0 => (ex_var1 + ex_var2 + ex_var3 + ex_var4 + ex_var4) >= 16

至此,我们就可以避免使用C/C++实现复杂的联动规则是否为真的判断逻辑了。这不仅仅是提高了开发效率,而且还避免过多的编码可能会引入的缺陷。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/751698.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《手把手教你》系列技巧篇(三十七)-java+ selenium自动化测试-日历时间控件-上篇(详解教程)

1.简介 我们在实际工作中&#xff0c;有可能遇到有些web产品&#xff0c;网页上有一些时间选择&#xff0c;然后支持按照不同时间段范围去筛选数据。网页上日历控件一般&#xff0c;是一个文本输入框&#xff0c;鼠标点击&#xff0c;就会弹出日历界面&#xff0c;可以选择具体…

upload文件上传漏洞复现

什么是文件上传漏洞&#xff1a; 文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷&#xff0c;而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马&#xff0c;病毒&#xff0c;恶意脚本或者WebShell等。“…

Qt入门之概述

1.1 介绍 Qt&#xff1a;它是一套基于C的跨平台开发框架&#xff0c;包括GUI、字符串、多线程处理、文件IO、网络IO、3D渲染等时间&#xff1a;它诞生于1991年&#xff0c;由Haavard Nord和Eirik Chambe-Eng共同缔造发展&#xff1a;历经Qt Company、Nokia、Digia多个公司开发…

Seata 2.x 系列【9】事务会话存储模式

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Seata 版本 2.0.0 本系列Spring Boot 版本 3.2.0 本系列Spring Cloud 版本 2023.0.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 概述2. 存储模…

ubuntu安装docker的详细教程

检查卸载老版本docker ubuntu下自带了docker的库&#xff0c;不需要添加新的源。 但是ubuntu自带的docker版本太低&#xff0c;需要先卸载旧的再安装新的。 注&#xff1a;docker的旧版本不一定被称为docker&#xff0c;docker.io 或 docker-engine也有可能&#xff0c;所以卸…

有关整数和浮点数在内存中存储

1. 整数在内存中的存储 整数的2进制表⽰⽅法有三种&#xff0c;即原码、反码和补码 三种表⽰⽅法均有符号位和数值位两部分&#xff0c;符号位都是⽤0表⽰“正”&#xff0c;⽤1表⽰“负”&#xff0c;⽽数值位最 ⾼位的⼀位是被当做符号位&#xff0c;剩余的都是数值位。 正…

常用芯片学习——BME280芯片

BME280 温湿度气压传感器 芯片介绍 BME280是基于成熟传感原理的组合数字湿度、压力和温度传感器。该传感器块采用极为紧凑的金属盖LGA封装&#xff0c;占地面积仅为2.5x2.5mm2&#xff0c;高度为0.93mm。该传感器提供I2C以及SPI接口。它的小尺寸和低功耗允许在电池驱动的设备…

TCP-IP 知识汇总

开放式系统互联模型------国际化标准组织ISO提出----协议组&#xff08;协议模型&#xff09; 应用层&#xff1a;接收用户数据&#xff0c;人机交互的接口 表示层&#xff1a;将编码转换为二进制&#xff08;加密、解密&#xff09;---统一格式 会话层&#xff1a;针对传输…

springboot279基于javaweb的影院订票系统的设计与实现

影院订票系统 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本影院订票系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大…

2024.4.17周报

目录 摘要 Abstract 文献阅读&#xff1a;耦合时间和非时间序列模型模拟城市洪涝区洪水深度 现有问题 提出方法 创新点 XGBoost和LSTM耦合模型 XGBoost算法 ​编辑 LSTM&#xff08;长短期记忆网络&#xff09; 耦合模型 研究实验 数据集 评估指标 研究目的 洪水…

Orbit 使用指南 03 | 与刚体交互 | Isaac Sim | Omniverse

如是我闻&#xff1a; “在之前的指南中&#xff0c;我们讨论了独立脚本&#xff08; standalone script&#xff09;的基本工作原理以及如何在模拟器中生成不同的对象&#xff08;prims&#xff09;。在指南03中&#xff0c;我们将展示如何创建并与刚体进行交互。为此&#xf…

48、C++/堆区动态内存管理 类中特殊成员函数学习20240313

一、设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 代码&#xff1a; #include <iostream>us…

走进volatile的世界,探索它与可见性,有序性,原子性之间的爱恨情仇!

写在开头 在之前的几篇博文中&#xff0c;我们都提到了 volatile 关键字&#xff0c;这个单词中文释义为&#xff1a;不稳定的&#xff0c;易挥发的&#xff0c;在Java中代表变量修饰符&#xff0c;用来修饰会被不同线程访问和修改的变量&#xff0c;对于方法&#xff0c;代码…

Arduino RP2040 LittleFS的使用介绍

Arduino RP2040 LittleFS的使用 &#x1f4cc;RP2040基于Earle F. Philhower, III的开发核心固件&#xff1a;https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json&#x1f388;相关开发文档在线说明&#xff1a;https://ardu…

每日一题——LeetCode2789.合并后数组中的最大元素

方法一 倒序遍历&#xff1a; 将数组倒序过来看&#xff0c;就是从最后一个数开始&#xff0c;如果它前面一个数小于等于它就可以把前面一个数吃掉同时加上前一个数的值形成一个新的数&#xff0c;如果碰到一个更大的数就吃不动了&#xff0c;那么就换那个更大的数去继续吃前面…

ts版本微信小程序在wxml保存文件不刷新页面的解决办法

将project.config.json中的skylineRenderEnable改为false "skylineRenderEnable": false

惯导系统静止初始化方法与代码实现并在gazebo中测试

惯导系统静止初始化方法与代码实现并在gazebo中测试 前言静止初始化方法惯导静止初始化实现代码在gazebo中进行测试 前言 在进行GPS加IMU的组合导航或者Lidar加IMU的组合导航时&#xff0c;用EKF或者ESKF的滤波方法时&#xff0c;需要提前知道惯导的测量噪声、初始零偏、重力方…

POJO简介

文章目录 简介POJO与ELB的区别POJO真正的意思 常见的POJO类DTODAOPOVOEntity 简介 什么是POJO&#xff1f;POJO&#xff08;Plain Ordinary Java Object&#xff09;简单的Java对象&#xff0c;实际就是普通JavaBeans&#xff0c;是为了避免和EJB(EJB是Enterprise Java Beans技…

Ubuntu 22.04 Nvidia Audio2Face Error:Failed to build TensorRT engine

背景 1.在Ubuntu22.04上安装Audio2Face后启动&#xff0c;嘴形不会实时同步。控制台显示如【图一】&#xff1a; 【图一】 2.log日志如下: Error: Error during running command: [‘/home/admin/omniverse/libs/deps/321b626abba810c3f8d1dd4d247d2967/exts/omni.audio2fac…

【论文阅读】DiffSpeaker: Speech-Driven 3D Facial Animation with Diffusion Transformer

DiffSpeaker: 使用扩散Transformer进行语音驱动的3D面部动画 code&#xff1a;GitHub - theEricMa/DiffSpeaker: This is the official repository for DiffSpeaker: Speech-Driven 3D Facial Animation with Diffusion Transformer paper&#xff1a;https://arxiv.org/pdf/…