Python program disregards button input - python

I'm new to python and linux, and I recently set up a twitter bot with my Raspberry Pi to mess around and have fun with. I want to set up a system where my RasPi sends a tweet every time I press a button. I followed the instructions on https://raspberrypihq.com/use-a-push-button-with-raspberry-pi-gpio to set up the basic input.
I have two .py files, tweet_test.py and buttonPress.py
tweet_test:
#!/usr/bin/env python
import os
import random
from twython import Twython
# your twitter consumer and access information goes here
apiKey = ''
apiSecret = ''
accessToken = ''
accessTokenSecret = ''
api = Twython(apiKey,apiSecret,accessToken,accessTokenSecret)
messages = [
"A button was pressed!!",
"My creator pressed a button.",
"This tweet was triggered by a button press.",
]
message = random.choice(messages)
api.update_status(status=message)
print("Tweeted: " + message)
buttonPress:
import tweet_test
import RPi.GPIO as GPIO #Import Raspberry Pi GPIO library
def button_callback(channel):
tweet_test
print("Button was pushed!")
GPIO.setwarnings(False) #Ignore warning for now
GPIO.setmode(GPIO.BOARD) #Use physical pin numbering
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #Set pin 10 to be an
input pin and set initial value to be pulled low (off)
GPIO.add_event_detect(10,GPIO.RISING,callback=button_callback) #Set up
event on pin 10 rising edge
message = input("Press enter to quit\n\n") #Run until someone presses
enter
GPIO.cleanup() #Clean Up
However, when I run buttonPress.py in the command line, the first thing it does is tweet, without even having received any input from the button. Then, it begins receiving button inputs, but doesn't tweet anything. Please help!
Sample output:
user1#raspberrypi:~/TwitterBot $ sudo python buttonPress.py
Tweeted: A button was pressed!!
Press enter to quit
Button was pushed!
Button was pushed!
Button was pushed!

You import tweet_test.py at the very beginning and it will run first, which will run as exactly it is supposed to do, i.e. to send a tweet. You need to wrap the tweeting part as a function so that it only run when it is called:
In tweet_test.py
def tweet():
message = random.choice(messages)
api.update_status(status=message)
print("Tweeted: " + message)
In buttonPress.py
Call the tweet() function in your button_callback like this:
def button_callback(channel):
tweet()
print("Button was pushed!")
Alternatively, just move the tweeting part to the button_call function, and combined both into your button_callback:
def button_callback(channel):
message = random.choice(messages)
api.update_status(status=message)
print("Button was pushed! Tweeted: %s" % message)
Update
Please also change the line import tweet_test to from tweet_test import *

Related

Python output insists I need "tkinter", yet none of the modules I have called use it

Being very new to Python, any help at all is greatly appreciated.
I'm trying to make a spammer thing to mess with my friends, and the output keeps insisting that I need "tkinter".
The modules that I'm using are pyautogui, time, and subprocess and some Googling has told me that none of those have to use tkinter for anything.
When I try to actually install tkinter it won't install (apt-get or pacman) What can I do?
Here is my code:
import pyautogui
import time
import subprocess
def sendNotif(title, message):
subprocess.run(['notify-send', title, message])
message = input("Enter message (leave blank to paste clipboard")
repeats = int(input("Number of times to send the message:"))
delay = int(input("Number of ms between each message (seconds x 1000): "))
isLoaded = input("Open your messaging application and press Enter when it's ready")
print("You have 5 seconds to refocus the message entering area of your chat application.")
time.sleep(5)
for i in range(0,repeats):
if message != "":
pyautogui.typewrite(message)
pyautogui.press("enter")
else:
pyautogui.hotkey('ctrl', 'v')
pyautogui.press("enter")
time.sleep(delay/1000)
sendNotif('Finished Sending Flood', 'Now we play the waiting game......')
print("Done")

Change OBS Filename before replay buffer is saved using obspython

I am writing an OBS python script to add your current active window to the filename formatting before saving with replay buffer. So far, I've gotten it to update the active window name in the filename, but it's updating the filename after I press "save replay buffer"
Here's the working code I have so far:
import win32gui
import obswebsocket
import obspython
from obswebsocket import obsws, events, requests
def on_event(event):
if event == obspython.OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
print("Setting file name to active window title...")
windowTitle = win32gui.GetWindowText (win32gui.GetForegroundWindow())
print("Window Title: " + windowTitle)
client = obswebsocket.obsws("localhost", 4444, "")
client.connect()
client.call(obswebsocket.requests.SetFilenameFormatting("%CCYY-%MM-%DD %hh:%mm:%ss - " + windowTitle))
client.disconnect()
print("Done!")
def script_load(settings):
obspython.obs_frontend_add_event_callback(on_event)
print("get-window-title.py Loaded!")
I've thought of trying a different approach where I set up a keypress listener to run "save replay buffer" after the title change in the code. I wanted to see if there was a simpler way using the obspython.OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED event handler.

How to open a program using keyboard input?

My project is to make a program that you can run while you are playing games or other programs in the background.
When you press a certain key, your notepad should open and also close after you press the same key again.
I have managed to open notepad with subprocess and that works fine but I have no idea to make it open only when a certain key is pressed.
Thanks for any help!
EDIT:
What I tried already:
import subprocess
import keyboard
if keyboard.is_pressed('k'):
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
input()
here it just doesn't detect any keyboard input, the input() at the end makes the program not close instantly
import subprocess
import keyboard
keyboard.add_hotkey('ctrl+k', print,args=("hello", "test"))
input()
Here if I press "ctrl+k it" will print hello test that means the hotkey works fine. When I switch this part "print,args=("hello", "test")" to "subprocess.Popen('C:\Windows\System32\notepad.exe')"(it should open the program instead of printing hello test) the notepad opens instantly after I run the program and when I press "ctrl+k" I get a big error.
A more complex, but still working example could be the following. With this code your program will be always listening the keyboard, not only when you are focused on the input, so may be mre practical in your case
from pynput import keyboard
import subprocess
import threading
class MyException(Exception): pass
class Listening:
"""Is allways waiting for the keyboard input"""
def __init__(self):
self.notepad_open = False # to know the state
with keyboard.Listener(
on_press=self.on_press) as listener:
try:
listener.join()
except:
pass
def on_press(self, key):
try:
if key.char == "k":
if not self.notepad_open:
self.subprocess = \
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
self.notepad_open = True # update state
else:
self.subprocess.kill()
self.notepad_open = False # update state
except: # special key was pressed
pass
thread = threading.Thread(target=lambda: Listening())
thread.start()
The problem is that you check for the key 'k' only once at the beginning. If you want the program to correctly work then you should try this:
import time
import subprocess
import keyboard
while True:
if keyboard.is_pressed('k'):
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
time.sleep(5)
-I used the time so that you can only open the program once 5 seconds(If you're curious, see what happens without it)-

Simulate "button pressed" an rise an event in gpiozero

I try to develop some code on a machine without GPIO. As GPIO library I selected a gpiozero to be able to write my code without access to gpio of raspberry pi.
My problem, I cant get ride of .when_pressed event in the code.
I simulate state change of the button, but the function is not called.
Device.pin_factory = MockFactory()
def interrupt_Event(channel):
print("%s puted in the queue", channel)
InputPin.Device.pin_factory.pin(channel)
InputPin.when_pressed = interrupt_Event
def main():
try:
while True:
time.sleep(1)
InputPins[channel].pull=drive_high()
time.sleep(0.1)
print("State CHANNEL %s" % channel)
print(InputPins[channel].state)
InputPins[channel].drive_low()
Till now I have no Idea what is wrong.
when_pressed function should not have arguments (see 2.7 in https://gpiozero.readthedocs.io/en/stable/recipes.html).
You could define the callback using a loop :Creating functions in a loop
(use channel=channel to force early binding of channel value as in example below)
for channel in channels:
def onpress(channel=channel):
print("%s puted in the queue", channel)
InputPins[channel].when_pressed = onpress
I am not convinced that you are using drive_high and drive_low to simulate the button pushing.
I have a almost identical problem. using Mock pins to develop a Pi program on windows, I find that the callback routines are not called.
from gpiozero.pins.mock import MockFactory
from gpiozero import Device, Button, LED
from time import sleep
Device.pin_factory = MockFactory() # set default pin
factory
btn = Button(16)
# Get a reference to mock pin 16 (used by the button)
btn_pin = Device.pin_factory.pin(16)
def pressed(): # callback
print('pressed')
def released(): # callback
print('released')
btn.when_pressed = pressed
btn.when_released = released # callback routine
for i in range(3): # now try to signal sensor
print('pushing the button')
btn_pin.drive_high
sleep(0.1)
btn_pin.drive_low
sleep(0.2)
The output has no callbacks, just
pushing the button
pushing the button
pushing the button
>>>

How to return to command line from script running in the background

I have this panic button, and a script that responds to the button press.
if I send the process to the background, using the command $sudo python3 ./Panicbutton.py & I get the command line back. when I press the panic button, the script responds, and prints the message corresponding to the number of times the button was pressed. What I want it to do is go back to the background, whilst it waits for more button presses. pressing ctrl+c returns me to the command line, but I don’t want to need to press ctrl+c each time after the button is pressed. is there a way to return the script to the background while it awaits further key presses? How can I send the ctrl+c command to the terminal from the script? I don't want to terminate the process, I just want the command line prompt to return after the message is printed.
I am using Linux, and python3.4. Please assist.
heres the script:
# USB Panic Button interface code
# Copyright 2010 Ken Shirriff
# http://arcfn.com
import usb.core
x = 0
comment0 = """ PanicButton - interface to USB Panic Button This code requires PyUSB."""
class PanicButton:
def __init__(self):
# Device is: ID 1130:0202 Tenx Technology, Inc.
self.dev = usb.core.find(idVendor=0x1130, idProduct=0x0202)
if not self.dev:
raise ValueError("Panic Button not found")
try:
self.dev.detach_kernel_driver(0) # Get rid of hidraw
except Exception as e:
pass # already unregistered
def read(self):
comment1 = """ Read the USB port. Return 1 if pressed and released, 0 otherwise."""
#Magic numbers are from http://search.cpan.org/~bkendi/Device-USB-PanicButton-0.04/lib/Device/USB/PanicButton.pm
return self.dev.ctrl_transfer(bmRequestType=0xA1, bRequest=1, wValue=0x300, data_or_wLength=8, timeout=500)[0]
if __name__ == "__main__":
import time
button = PanicButton()
while 1:
if button.read():
global x
x = x + 1
if x < 5:
print(x)
elif x == 5:
print("Baby just screem if you want some more!")
elif x == 6:
print("Like AH!")
elif x == 7:
print("push it, push it.")
elif x == 8:
print("watch me work it.")
elif x == 9:
print("I'm PERFECT")
else:
x = 0
print("")
time.sleep(.5)
The script is always in the background, and does not go to the foreground at any point. It just looks that way because the script's output has the purely cosmetic effect of appearing to mess up the prompt.
Instead of pressing Ctrl-C, you can just write ls and press enter. You'll see that the shell works just fine and that your script is not in the foreground.
Bash can't really redraw the prompt because it doesn't control which other programs write to the screen. Consider finding a less invasive way of reporting button presses such as:
printing a bel character to make the terminal play a sound
changing the xterm's title
using tmux or screen to have a window or status bar message
using xmessage or similar to pop up a dialog box
having your bash prompt include messages from the script every time it redraws

Categories

Resources