使用Python读取Raspberry Pi RFSniffer的输出

3
我正在尝试运行RFSniffer进程以侦听传入的433mhz信号。如果我运行该进程,它只会输出来自433mhz接收器的值。我想用Python读取此输出,以便我可以执行特定的操作。我已找到许多使用Python运行并获取输出的方法,但这些命令都是自动终止的(例如`ls -ial`)。RFSniffer进程会一直运行,直到您手动停止它。这是我目前拥有的代码(无法正常工作):
#!/usr/bin/python
# -*- coding: utf-8 -*-
import subprocess, time, os, sys

cmd = ["sudo", "/home/pi/433Utils/RPi_utils/RFSniffer"]

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=1)
for line in iter(p.stdout.readline, b''):
    print line,
p.stdout.close()
p.wait()

你能更具体地说明哪里出了问题吗?是只得到了命令的部分输出吗?当你直接运行命令时,输出是什么样子的(在Python之外)? - Thibaut
当我在外部运行时,没有任何输出,Python 输出如下: 接收到 14446784 接收到 14446640 接收到 14446784 接收到 14446784 接收到 14446784 - user1232869
你也可以编辑RFSniffer.cpp并重新编译它,以便直接将数据写入文件或数据库中。 - Joe Platano
4个回答

1
如果符合您的需求,您也可以反过来做。我让我的Python脚本从RFSniffer中调用,将信号作为参数传递进去。
我的Python脚本类似于以下内容:
import sys, getopt
import uuid

fileEnding = "txt"
fileFolder = "./sniffed"

def main(argv):
    opts, args = getopt.getopt(argv,"s:")

    for opt, arg in opts:
        if opt == '-s':
            filename = fileFolder + "/" + str(uuid.uuid4()) + "." + fileEnding
            with open(filename, 'w') as outfile:
                outfile.write(arg)

if __name__ == "__main__":
    main(sys.argv[1:])

现在,您需要编辑RFSniffer.cpp,在每个接收到的信号后调用您的python脚本。以下代码片段将所有在短时间内接收到的信号代码连接在一起,因为有时一个遥控器上的按键会产生多个信号代码。因此,您的python脚本不是按信号而是按按钮按下来调用的。 我不是CPP开发人员,因此请原谅我的笨拙方法(但嘿,它能完成工作;))
//[...]
#include <iostream>
#include <string>
#include <sstream>
#include <unistd.h>
//[...]
while(1) {
          int count = 0;
          std::string signals;
          signals = "";

          while (count < 10000) {
              if (mySwitch.available()) {
                    int value = mySwitch.getReceivedValue();

                    if (value == 0) {
                        printf("Unknown encoding\n");
                    } else {
                        std::string signal;
                        std::stringstream signalStream;
                        signalStream << value;
                        signal = signalStream.str();

                        if (signals.length() > 0) {
                            signals.append(",");
                        }
                        else {
                            // first receive, so reset timeframe here
                            count = 0;
                        }
                        signals.append(signal);
                        printf("Received %s\n", signal.c_str() );
                    }
                    mySwitch.resetAvailable();
              }
              usleep(50);
              count += 1;
          }
          if (signals.length() > 0) {
            std::string command;
            command.append("python3 /home/pi/your_script.py -s ");
            command.append(signals);
            printf("Call %s\n", command.c_str());
            system(command.c_str());
          }
      }
      //[...]

它的作用是循环10k次,查找新的“ReceivedValue”,并等待50微秒。如果需要,您可以调整这些参数。这意味着一个时间框架至少需要半秒钟,并且应该覆盖遥控器上单个按钮按下所属的所有信号。这些一对多的信号代码作为逗号分隔的值传递给您的Python脚本(参数-s code1,code2,code3)。在脚本内部进行任何操作。祝玩得开心。

1
这个解决方案应该有效:
os.system("sudo /home/pi/433Utils/RPi_utils/RFSniffer >output.txt & pkill --signal SIGINT RFSniffer")
f = open("output.txt","r")
readf = f.read()
for line in readf:
    print line,
#close file
if f.closed == "False":
    f.close()

你可以将其放入while循环中,不断扫描直到找到参数为止。
这是我所知道的唯一一种方法,可以将实时扫描(无限制且不停止,不像ls -l)输出到文件中,然后读取值。
以下是我使用蓝牙进行实时扫描的一个示例:
sensortag=0
while sensortag != "B4:99:4C:64:33:E0":
    #call the command and write to scan.txt file and then fill the process.
    #loop to find if the MAC address given is available
    os.system("hcitool lescan> scan.txt & pkill --signal SIGINT hcitool")
    scan = open("scan.txt","r")
    readscan = scan.read()
    if "B4:99:4C:64:33:E0" in readscan:
        print "SensorTag found."
        sensortag = "B4:99:4C:64:33:E0"

无法工作 :-( 语法错误: 文件 "test2.py", 第8行 for line in readf ^ SyntaxError: 无效的语法 - user1232869
抱歉,在 for 语句后面我漏掉了一个冒号。我已经更新了代码。是我的笔误。 - Jonathan Davies
脚本已经启动,但是没有将任何数据写入output.txt文件中,即使我在终端中使用命令>output.txt运行。:( - user1232869
我修改了RFSniffer.cpp文件,使其记录到文件中,现在它可以工作了,感谢你一路上的帮助。 - user1232869

0
由于@user1232869没有分享他如何修改RFSniffer.cpp文件,而且因为我对C++不熟悉,所以这花费了我一些时间,现在我来分享一下:)。您只需要将这三行加粗的代码添加到您的文件中即可。
if (value == 0) {
      printf("Unknown encoding");
    } else {    

      printf("Received %i\n", mySwitch.getReceivedValue() );
      // These lines are the lines which interest you! :)
      FILE* pFile = fopen("/home/pi/logs.txt", "a");
      fprintf(pFile, "%i\n",mySwitch.getReceivedValue());
      fclose(pFile);
    }

    mySwitch.resetAvailable();

然后你可以正确使用@Jonathan Davies的回答,因为>output.txt在我的Pi上也失败了。


-1

我使用了一个名为pi-switch的Python库,它提供了rc-switch C++库的包装器。 该库可以在https://github.com/lexruee/pi-switch-python找到。

rc-switch是RFSniffer使用的库,因此使用pi-switch允许您从Python监听433mhz信号。

我正在使用它来检测无线门铃何时被按下。


尽管页面链接很有用,但了解在OP的问题背景下使用这种包装器的情况也很有趣。 - António Ribeiro
谢谢,我已经修改了我的答案。 - afreeman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接