【问题标题】:How to detect how often a button has been pushed consecutively?如何检测按钮连续按下的频率?
【发布时间】:2016-11-17 07:21:19
【问题描述】:

我想监视一个命令的输出,该命令一直无限运行并时不时地打印一行。它显示一个硬件按钮的事件,每行表示一次按下。

我的脚本应该在接收到行时运行其他命令,但问题是,不是这些行的内容决定必须运行哪个命令,而是给定延迟内的行数。

换句话说,用户可以多次按下这个被监控的按钮,并且根据按下按钮的频率执行不同的命令。用户在两次按下之间有 2 秒的时间,然后将根据连续按下的次数选择命令。

我目前有一个具有这种结构的 Bash 脚本:

#!/bin/bash
lasttouch="0"

MONITORING_COMMAND
| while read line; do     
    if [ $(date +%s --date="2 seconds ago") -lt $lasttouch ]       
    then
        COMMAND2
    else
        lasttouch=$(date +%s)
        COMMAND1
    fi    
done

然而,这最多只能处理两次连续按下,并且它在每个事件上执行COMMAND1,即使随后及时按下并且应该运行COMMAND2

我实际上不知道如何在 Bash 中正确实现这一点。我想我需要某种多线程,一个线程监听传入的行并增加一个计数器,另一个线程在每个事件后运行 2 秒倒计时,并在倒计时超时后重置计数器并执行适当的命令而无需其他事件。

【问题讨论】:

    标签: linux multithreading bash


    【解决方案1】:

    你可以为你的单推设置一个函数,在执行COMMAND1之前等待所需的时间,用$!记录它的pid,并在你在所需时间之前真正收到双推时将其杀死。

    这是一个延迟 700 毫秒的示例:

    #!/bin/bash
    
    MONITORING_COMMAND="your monitoring command here"
    PUSH_NUM=1         #1 => until double push detection | 2 => until triple push detection etc...
    MAX_DELAY=700      #the delay in between push in milliseconds
    
    inc=0
    remaining_delay=0
    
    # wait_push <command value> <time left to sleep before taking the push>
    wait_push()
    {
        if [ ! -z "$2" ]; then
            sleep $2
        fi
        inc=0
        #switch between all your command here
        #COMMAND0 : normal push
        #COMMAND1 : double push
        #COMMAND2 : triple push etc..
        echo "push is detected here: execute $1 here"
        pid=""
        lasttouch=""
    }
    
    $MONITORING_COMMAND | while read line ; do 
    
        current=$(($(date +%s%N)/1000000))
    
        if [ ! -z "$lasttouch" ]; then
    
            diff=`expr $current - $lasttouch`
    
            if test $diff -lt $MAX_DELAY
            then
    
                inc=$((inc+1))
    
                if [ "$inc" -lt $PUSH_NUM ]; then
    
                    if [ ! -z "$pid" ]; then
                        kill $pid 2>/dev/null
                        wait $pid 2>/dev/null
                    fi
                    remaining_delay=$((remaining_delay-diff))
                    time=`awk -v delay=$remaining_delay 'BEGIN { print (delay / 1000) }'`
                    #normal push
                    wait_push "COMMAND${inc}" $time &
                    pid=$!
                    continue
    
                elif  [ "$inc" == $PUSH_NUM ]; then
    
                    if [ ! -z "$pid" ]; then
                        kill $pid 2>/dev/null
                        wait $pid 2>/dev/null
                    fi
                    wait_push "COMMAND${inc}"
                    continue
    
                fi
            else
                inc=0
            fi
        fi
    
        if [ "$inc" == 0 ]; then
            remaining_delay=$MAX_DELAY
            time=`awk -v delay=$MAX_DELAY 'BEGIN { print (delay / 1000) }'`
            #normal push
            wait_push "COMMAND${inc}" $time &
            pid=$!
        fi
    
        lasttouch=$current
    done
    

    可以增加推送号编辑变量PUSH_NUM

    • 双推:PUSH_NUM=1
    • 三次推送:PUSH_NUM=2

    您将在wait_push 函数中进行所有命令处理。这考虑了所有连续推送事件之间的剩余时间(不超过MAX_DELAYms)

    【讨论】:

    • 有趣的方法。对于任意数量的推送,我将如何修改它,而不仅仅是 2?
    • 我已经用动态推送次数更新了答案
    • 对不起,有误会。我不希望 command1 运行一次,而 command2 在更多次推送后运行,但我有很多命令(例如 5 个),并且每个按钮按下次数对应一个不同的命令。
    • 我已经更新了动态数量的命令绑定到你想要的推送事件的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多