使用python模拟Raspbian中的击键

时间:2017-03-09 06:02:45

标签: python python-3.x raspbian raspberry-pi3

当我试图找出如何让按钮按下后使用GPIO引脚发送左或右按键时,我偶然发现了this question

似乎所选择的链接问题的答案是我需要让我继续但是在安装xautomation之后,尝试将代码调整到我的脚本并阅读Popen的文档(我甚至尝试运行新文件随着代码逐字)我不断收到以下错误:

Traceback (most recent call last):
  File "/home/zdistaging/Documents/xte test.py", line 17, in <module>
    keypress(shift_a_sequence)
  File "/home/zdistaging/Documents/xte test.py", line 15, in keypress
    p.communicate(input=sequence)
  File "/usr/lib/python3.4/subprocess.py", line 941, in communicate
    self.stdin.write(input)
TypeError: 'str' does not support the buffer interface

我正在使用Pixel的Raspbian Jessie(从raspberrypi.org下载)在Pi 3模型B上运行Python3

任何想法为什么会出错?

如果它有所帮助,我所要做的就是允许用户在FEH幻灯片中左右滚动......考虑到这个看起来很简单的任务,我可能完全不合适。我不是在寻找有人为我彻底解决这个问题 - 我喜欢与编码相关的挑战 - 我只是对python的新手;在正确的方向上推动我会非常有帮助。

非常感谢任何帮助!!!

编辑:很抱歉不包含该代码!

from subprocess import Popen, PIPE

control_f4_sequence = '''keydown Control_L
key F4
keyup Control_L
'''

shift_a_sequence = '''keydown Shift_L
key A
keyup Shift_L
'''

def keypress(sequence):
    p = Popen(['xte'], stdin=PIPE)
    p.communicate(input=sequence)

keypress(shift_a_sequence)
keypress(control_f4_sequence)

编辑编辑:

这是我的更新代码......它实际上是为按下左右按钮打印空格。

import time
import RPi.GPIO as GPIO
from subprocess import Popen, PIPE
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

leftArrow = '''key \x1B[D'''  # I've tried '''key Left'''
rightArrow = '''key \x1B[C''' # and '''key Right''' with the same results

offButton   = 26     # Black wire
onButton    = 19     # White wire
leftButton  = 13     # Red wire
rightButton =  6     # Green wire


def keypress(sequence):
    if isinstance(sequence, str):
        sequence = sequence.encode('ascii')
    p = Popen(['xte'], stdin=PIPE)
    p.communicate(input=sequence)


GPIO.setup( offButton, GPIO.IN, GPIO.PUD_UP )
GPIO.setup( onButton, GPIO.IN, GPIO.PUD_UP )
GPIO.setup( leftButton, GPIO.IN, GPIO.PUD_UP )
GPIO.setup( rightButton, GPIO.IN, GPIO.PUD_UP )


while True:
    offButton_state = GPIO.input( offButton )
    onButton_state = GPIO.input( onButton )
    leftButton_state = GPIO.input( leftButton )
    rightButton_state = GPIO.input( rightButton )

    if offButton_state == GPIO.LOW:
        print( "Off button pressed" )

    if onButton_state == GPIO.LOW:
        print( "On button pressed" )

    if leftButton_state == GPIO.LOW:
        keypress(leftArrow)
        print( "Left button pressed" )

    if rightButton_state == GPIO.LOW:
        keypress(rightArrow)
        print( "Right button pressed" )

    time.sleep( 1 )

我已经阅读了subprocess and Popen.communicate(),但无法确定问题是与该问题有关还是与xte is expecting as an argument有关。想法?

2 个答案:

答案 0 :(得分:1)

错误表明您的控制序列是字符串(即unicode),但Subprocess似乎期望字节。

在函数 protected void ReaderFPMachine() { _readerCollection = ReaderCollection.GetReaders(); foreach (Reader Reader in _readerCollection) { _fPMachineID = Reader.Description.SerialNumber; break; } this.CheckFingerPrint(); } protected void CheckFingerPrint() { try { _finger = null; _reader = _readerCollection[0]; if (!OpenReader()) { //this.Close(); } if (!StartCaptureAsync(this.OnCaptured)) { //this.Close(); } } catch (Exception ex) { } } private void OnCaptured(CaptureResult captureResult) { try { _finger = null; // Check capture quality and throw an error if bad. if (!CheckCaptureResult(captureResult)) return; //SendMessage(Action.SendMessage, "A finger was captured."); DataResult<Fmd> resultConversion = FeatureExtraction.CreateFmdFromFid(captureResult.Data, Constants.Formats.Fmd.ANSI); if (resultConversion.ResultCode != Constants.ResultCode.DP_SUCCESS) { _reset = true; throw new Exception(resultConversion.ResultCode.ToString()); } _finger = resultConversion.Data; _fingerPrintID = Fmd.SerializeXml(_finger); //MsVisitorHd _msVisitorHd = this._vMSBL.GetSingleMsVisitorHdByFingerPrintID(_fingerXML); //List<MsVisitorHd> _listMsVisitorHd = this._vMSBL.GetListMsVisitorHd(); bool _exist = false; //foreach (var _item in _listMsVisitorHd) //{ // Fmd _fmd = Fmd.DeserializeXml(_fingerPrintID); // Fmd _fmd2 = Fmd.DeserializeXml(_item.FingerPrintID); // CompareResult compareResult = Comparison.Compare(_fmd, 0, _fmd2, 0); // if (compareResult.ResultCode != Constants.ResultCode.DP_SUCCESS) // { // _reset = true; // throw new Exception(compareResult.ResultCode.ToString()); // } // else // { // if (compareResult.Score < (PROBABILITY_ONE / 100000)) // { // //_visitorExist = new MsVisitorHd(); // //_visitorExist = _item; // _exist = true; // break; // } // else // { // } // } //} if (!CheckCaptureResult(captureResult)) return; // Create bitmap foreach (Fid.Fiv fiv in captureResult.Data.Views) { this.FingerPictureBox.BackgroundImage = CreateBitmap(fiv.RawImage, fiv.Width, fiv.Height); } if (_exist) { _fgMember = "Y"; //MessageBox.Show("Sidik jadi terdaftar sebagai " + _visitorExist.VisitorName); } else { _fgMember = "N"; } //SendMessage(Action.SendMessage, secondFinger.Bytes.ToString() + "Comparison resulted in a dissimilarity score of " + compareResult.Score.ToString() + (compareResult.Score < (PROBABILITY_ONE / 100000) ? " (fingerprints matched)" : " (fingerprints did not match)")); //SendMessage(Action.SendMessage, "Place a finger on the reader."); // count = 0; //} } catch (Exception ex) { // Send error message, then close form //SendMessage(Action.SendMessage, "Error: " + ex.Message); } } public bool OpenReader() { _reset = false; Constants.ResultCode result = Constants.ResultCode.DP_DEVICE_FAILURE; // Open reader result = _reader.Open(Constants.CapturePriority.DP_PRIORITY_COOPERATIVE); if (result != Constants.ResultCode.DP_SUCCESS) { MessageBox.Show("Error: " + result); _reset = true; return false; } return _reset; } public void GetStatus() { Constants.ResultCode result = _reader.GetStatus(); if ((result != Constants.ResultCode.DP_SUCCESS)) { _reset = true; throw new Exception("" + result); } if ((_reader.Status.Status == Constants.ReaderStatuses.DP_STATUS_BUSY)) { Thread.Sleep(50); } else if ((_reader.Status.Status == Constants.ReaderStatuses.DP_STATUS_NEED_CALIBRATION)) { _reader.Calibrate(); } else if ((_reader.Status.Status != Constants.ReaderStatuses.DP_STATUS_READY)) { throw new Exception("Reader Status - " + _reader.Status.Status); } } public bool CheckCaptureResult(CaptureResult captureResult) { if (captureResult.Data == null) { if (captureResult.ResultCode != Constants.ResultCode.DP_SUCCESS) { _reset = true; throw new Exception(captureResult.ResultCode.ToString()); } // Send message if quality shows fake finger if ((captureResult.Quality != Constants.CaptureQuality.DP_QUALITY_CANCELED)) { throw new Exception("Quality - " + captureResult.Quality); } return false; } return true; } public bool CaptureFingerAsync() { try { GetStatus(); Constants.ResultCode captureResult = _reader.CaptureAsync(Constants.Formats.Fid.ANSI, Constants.CaptureProcessing.DP_IMG_PROC_DEFAULT, _reader.Capabilities.Resolutions[0]); if (captureResult != Constants.ResultCode.DP_SUCCESS) { _reset = true; throw new Exception("" + captureResult); } return true; } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); return false; } } public Bitmap CreateBitmap(byte[] bytes, int width, int height) { byte[] rgbBytes = new byte[bytes.Length * 3]; for (int i = 0; i <= bytes.Length - 1; i++) { rgbBytes[(i * 3)] = bytes[i]; rgbBytes[(i * 3) + 1] = bytes[i]; rgbBytes[(i * 3) + 2] = bytes[i]; } Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); for (int i = 0; i <= bmp.Height - 1; i++) { IntPtr p = new IntPtr(data.Scan0.ToInt64() + data.Stride * i); System.Runtime.InteropServices.Marshal.Copy(rgbBytes, i * bmp.Width * 3, p, bmp.Width * 3); } bmp.UnlockBits(data); return bmp; } public bool StartCaptureAsync(Reader.CaptureCallback OnCaptured) { // Activate capture handler _reader.On_Captured += new Reader.CaptureCallback(OnCaptured); // Call capture if (!CaptureFingerAsync()) { return false; } return true; } #endregion 中,将序列转换为字节,如下所示:

keypress

有关字节,字符串和unicode的非常好的文章可以在这里找到:https://nedbatchelder.com/text/unipain.html

答案 1 :(得分:0)

我一直在查看相同的示例,这是我的6个按钮的工作示例:(它有些混乱,但我的调试行也可以帮助其他人)

import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
from Xlib import X
from subprocess import Popen, PIPE

buttons = [18,         23,         24,         25,        8,     7 ]
opcodes = ['next', 'enter', 'alt tab', 'previous', 'spacebar', 'shift' ]
opcodes2 = ['key Left ', 'key Up ', 'key Down ', 'key Right ', 'key Enter ', 'key Shift_L ']

# set the gpio pins 
for button in buttons:
    GPIO.setup(button, GPIO.IN, GPIO.PUD_UP )

def keypress(sequence):
    #if isinstance(sequence, str):
    #sequence = sequence.encode('ascii')
    p = Popen(['xte', '-x:0'], stdin=PIPE)
    p.communicate(input=sequence)

def main():
    while True:
        button_state = []
        for button in buttons:
            button_state.append(GPIO.input(button))

        for item in range(len(button_state)):
            if button_state[item] == 0:
                print (opcodes2[item] ) #debugging
           # send X key for keystroke in (for the given iteration of the loop) opcodes[button.output(index)]
                #print (repr(str(opcodes2[item]).encode('ascii')))
                keypress(str(opcodes2[item]).encode('ascii'))
        print (repr(button_state)) #for debugging
        time.sleep(0.3)
        del button_state

if __name__ == '__main__':
    main()

注意每个命令的opcodes2中的尾随空格(可以是任何字符)。 ascii编码放弃了我的最后一个字符,所以这是我有点难看的解决方法。