一种动态联动的实现方法

安防领域中的联动规则

有安防领域相关的开发经历的人知道,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_ = 0
        link_tval_ = link_tval_ + ex_var1
        link_tval_ = link_tval_ + ex_var3
        link_tval_ = link_tval_ + ex_var5
        link_tval_ = link_tval_ + ex_var2
        link_tval_ = link_tval_ + ex_var4
        return 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) >= 16

The 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++实现复杂的联动规则是否为真的判断逻辑了。这不仅仅是提高了开发效率,而且还避免过多的编码可能会引入的缺陷。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

P1042 [NOIP2003 普及组] 乒乓球

题目描述&#xff1a; AC代码&#xff1a; #include<iostream> #include<cmath>using namespace std;const int N 25*250010; int a[N],b[N]; int k[2] {11,21};int main() {int n0;while(1){char c;cin >> c;//方便后面去做计算 if(c W) a[n] 1;if(c…

牛市下 AI + Web3 叙事引关注,Verasity 或成又一黑马项目?

事实上&#xff0c;在 ChatGPT 以及 Sora 大模型被相继提出后&#xff0c;AI 就成为了科技领域重点关注的板块&#xff0c;并引发了一轮又一轮的 AI 投资热潮。在传统科技领域引发的 AI 热潮&#xff0c;正在向加密行业拓展&#xff0c;Web3 领域也涌现出了不少 AIWeb3 概念的项…

单模场哈密顿量推导

满足麦克斯韦方程和边界条件的单模场又下式&#xff08;1&#xff09;&#xff0c;&#xff08;2&#xff09;给出 --------&#xff08;1&#xff09; ---------&#xff08;2&#xff09; , 单模场的经典场能或者哈密顿量又下式给出&#xff1a; &#xff08;3&#xff09…

编译esp32s3的ncnn,并运行mnist 手写数字识别

东哥科技&#xff0c;专注科技研发&#xff0c;wx交流&#xff1a;dg_i688 我的项目代码 https://github.com/cdmstrong/ncnn_on_esp32s3 下载ncnn git clone https://github.com/Tencent/ncnn.git安装idf 环境 这里直接按官网的可执行文件来就好了&#xff0c;直接安装完…

嵌入式Linux 内核的内存管理方法

内存管理的主要工作就是对物理内存进行组织,然后对物理内存的分配和回收。但是Linux引入了虚拟地址的概念。 虚拟地址的作用 如果用户进程直接操作物理地址会有以下的坏处: 1、 用户进程可以直接操作内核对应的内存,破坏内核运行。 2、 用户进程也会破坏其他进程的运行 …

传统电力运维企业的数字化转型案例

一. 传统电力运维企业面临的主要问题 上海某电力集团企业下属有成套设备公司、电力工程公司&#xff0c;依托于自身的设备制造和工程服务能力&#xff0c;以及多年积累的终端客户资源&#xff0c;几年前该公司成立了电力运维服务公司进入用户侧电力托管运维服务行业。 该公司…

【Linux系统编程】进程程序替换

介绍&#xff1a; 进程程序替换是指将一个进程中正在运行的程序替换为另一个全新的程序的过程&#xff0c;但替换不是创建新进程&#xff0c;只是将对应程序的代码和数据进行替换。具体来说&#xff0c;这个替换过程涉及将磁盘中的新程序加载到内存结构中&#xff0c;并重新建立…

Leetcode 31. 删除无效的括号

心路历程&#xff1a; 一开始看到有点懵&#xff0c;后来发现有点像按照一定规则穷举所有可能情况&#xff0c;想到了排列组合问题&#xff0c;再结合问题长度不固定&#xff0c;无法用已知个for循环表示&#xff0c;从而想到了回溯。这个题相当于需要在一定规则下枚举。 按照…

桌面云解决方案

桌面云解决方案是一种基于云计算的服务&#xff0c;它将用户的桌面环境托管在云端&#xff0c;允许用户通过互联网访问自己的虚拟桌面。这种解决方案为企业和个人用户提供了一种灵活、可扩展且成本效益高的桌面计算方式。以下是一些桌面云解决方案的关键特点和优势&#xff1a;…

MusicHiFi: Fast High-Fidelity Stereo Vocoding

文章目录 abstract abstract demo: https://musichifi.github.io/web/主要用于高精度的音乐场景文章主要做了两件事&#xff1a;&#xff08;1&#xff09;低频mel谱输入&#xff0c;生成更高频率的语音&#xff1b;&#xff08;2&#xff09;单声道音频生成立体声&#xff1b…

AI工具快速部署

演示站见文章底部 部署教程 搭建一键整合包&#xff0c;你需要的东西有&#xff1a; 一个最低1h1g的海外服务器 推荐服务器系统为&#xff1a;CentOS-7.9.2111-x64 一份NineAI一件整合包代码 一定的linux指令知识第一步 通过ssh工具连接服务器 同时打开宝塔面板至文件区域 将…

代码随想录算法训练营第二十五天|● 216.组合总和III ● 17.电话号码的字母组合(JS写法)

216 组合总和Ⅲ 题目链接/文章讲解&#xff1a;https://programmercarl.com/0216.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CIII.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1wg411873x 方法一&#xff1a;自己写的 自己写的&#xff0c;本题和77很像&#xf…

连号区间数c++

题目 输入样例1&#xff1a; 4 3 2 4 1输出样例1&#xff1a; 7输入样例2&#xff1a; 5 3 4 2 5 1输出样例2&#xff1a; 9样例解释 第一个用例中&#xff0c;有 77 个连号区间分别是&#xff1a;[1,1],[1,2],[1,3],[1,4],[2,2],[3,3],[4,4][1,1],[1,2],[1,3],[1,4],[2,2…

关于Oracle Primavera P6的各数据库帐号用途

在使用/维护P6时&#xff0c;经常会用到各种不同的P6数据库用户&#xff0c;如在连接配置P6 Professional时用到的公共帐号pubuser&#xff0c;进入后台维护p6配置信息(adminpv)或开发常连接的privuser&#xff0c;亦或是配置BI Report/BUSINESS Intelligence报表套件用到的pxr…

Axure 中继器的Item属性介绍及使用

item.列名 获取数据行中指定列的值。 index 获取索引编号&#xff0c;编号起始值为1 isFirst 判断数据是否为第一行 isLast 判断是否为最后一行 isEven 判断是否为偶数行 isOdd 判断是否为奇数行 isMarked 判断行是否被标记 isVisible 改行是否为显示

8年测试总结,自动化测试必要注意点+自动化测试框架(汇总)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、开始自动化测试…

工具精灵--超级好用的在线工具网站

工具精灵是一个超级好用的在线工具网站&#xff0c;它有这些功能&#xff1a;json格式化、xml格式化、markdown在线编辑、sql格式化、json转Java、xml转Java等。 虽然有很多这种类似的网站了&#xff0c;但它们并不好用&#xff0c;很粗糙。工具精灵超级好用&#xff0c;细节方…

详解Python中的缩进和选择

缩进 Python最具特色的是用缩进来标明成块的代码。我下面以if选择结构来举例。if后面跟随条件&#xff0c;如果条件成立&#xff0c;则执行归属于if的一个代码块。 先看C语言的表达方式&#xff08;注意&#xff0c;这是C&#xff0c;不是Python!&#xff09; if ( i > 0 …

el-upload的多个文件与单个文件上传

样式图&#xff1a; 场景多个&#xff1a; 使用el-upload上传多个文件 <el-upload class"upload-demo" :action"uploadUrl" :on-remove"handleRemove1":on-success"handleAvatarSuccess1" multiple :limit"5" :on-exc…

gma 2.0.7 (2024.03.16) 更新日志

安装 gma 2.0.7 pip install gma2.0.7网盘下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1P0nmZUPMJaPEmYgixoL2QQ?pwd1pc8 提取码&#xff1a;1pc8 注意&#xff1a;此版本没有Linux版&#xff01; 编译gma的Linux虚拟机没有时间修复&#xff0c;本期Linux版继…