Script not running on startup when using crontab -e - python

I have a raspberry pi and an RFID reader. I have a python script that uses RFID and spotipy to read RFID tags and plays a song/song when a certain RFID tag is scanned. I'm trying to make this python script run on startup using crontab -e so I don't have to run it everytime. I followed a tutorial online and used an example script. The example runs on start up. When I substitute it for the player script however it does not work. This is what I had in the crontab -e #reboot python3 /home/pi/Documents/rfidspotify/player.py. Here's the player python script I was using.(script works fine when I run it)
#!/usr/bin/env python
from mfrc522 import SimpleMFRC522
import RPi.GPIO as GPIO
import spotipy
from spotipy.oauth2 import SpotifyOAuth
from time import sleep
DEVICE_ID="YOUR_DEVICE_ID"
CLIENT_ID="YOUR_CLIENT_ID"
CLIENT_SECRET="YOUR_CLIENT_SECRET"
while True:
try:
reader=SimpleMFRC522()
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
redirect_uri="http://localhost:8080",
scope="user-read-playback-state,user-modify-playback-state"))
# create an infinite while loop that will always be waiting for a new scan
while True:
print("Waiting for record scan...")
id= reader.read()[0]
print("Card Value is:",id)
sp.transfer_playback(device_id=DEVICE_ID, force_play=False)
# DONT include the quotation marks around the card's ID value, just paste the number
if (id=='RFID-CARDVALUE-1'):
# playing a song
sp.start_playback(device_id=DEVICE_ID, uris=['spotify:track:2vSLxBSZoK0eha4AuhZlXV'])
sleep(2)
elif (id=='RFID-CARDVALUE-2'):
# playing an album
sp.start_playback(device_id=DEVICE_ID, context_uri='spotify:album:0JGOiO34nwfUdDrD612dOp')
sleep(2)
# continue adding as many "elifs" for songs/albums that you want to play
# if there is an error, skip it and try the code again (i.e. timeout issues, no active device error, etc)
except Exception as e:
print(e)
pass
finally:
print("Cleaning up...")
GPIO.cleanup()

Related

Python SetThreadExecutionState: How do I prevent screen display from turning off?

I am on Windows. I want to run a Python Script that involves keyboard activity hence my PC mustn't lock screen or go to sleep. Instead of changing my PC Sleep Setting, I want to use Python code to keep my Screen Display On for the whole duration of my Python Script.
I modified the code here Prevent sleep mode python (Wakelock on python) but it doesn't work. My screen display still offs automatically. MY modified code as below:
class WindowsInhibitor:
'''Prevent OS sleep/hibernate in windows; code from:
https://github.com/h3llrais3r/Deluge-PreventSuspendPlus/blob/master/preventsuspendplus/core.py
API documentation:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa373208(v=vs.85).aspx'''
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
ES_DISPLAY_REQUIRED= 0x00000002
def __init__(self):
pass
def inhibit(self):
import ctypes
print("Preventing Windows from going to sleep")
ctypes.windll.kernel32.SetThreadExecutionState(
WindowsInhibitor.ES_CONTINUOUS | \
WindowsInhibitor.ES_DISPLAY_REQUIRED)
def uninhibit(self):
import ctypes
print("Allowing Windows to go to sleep")
ctypes.windll.kernel32.SetThreadExecutionState(
WindowsInhibitor.ES_CONTINUOUS)
import os
osSleep = None
# in Windows, prevent the OS from sleeping while we run
if os.name == 'nt':
osSleep = WindowsInhibitor()
osSleep.inhibit()

How can I prevent my python program from loading when using pyngrok?

I have the following function in my script
import os, re
from pyngrok import ngrok
def server():
os.system('kill -9 $(pgrep ngrok)')
ngrok.connect(443, "tcp")
while True:
ngrok_tunnels = ngrok.get_tunnels()
url = ngrok_tunnels[0].public_url
if re.match("tcp://[0-9]*.tcp.ngrok.io:[0-9]*", url) is not None:
print "your url is : " + url
break
This is responsible for generating a ngrok tcp link and it works, but it gets stuck like in the image below.
enter image description here
How can I prevent it from being charged? And just print the link, they told me about the monitor_thread mode in False but I don't know how to configure it in my function, thank you very much in advance.
The reason the script is “stuck” is because pyngrok starts ngrok with a thread to monitor logs, and the Python process can’t exit until all threads have been dealt with. You can stop the monitor thread, as shown here in the documentation, or, if you have no use for it, you can prevent it from starting in the first place:
import os, re
from pyngrok import ngrok
from pyngrok.conf import PyngrokConfig
def server():
os.system('kill -9 $(pgrep ngrok)')
ngrok_tunnel = ngrok.connect(443, "tcp", pyngrok_config=PyngrokConfig(monitor_thread=False))
print("your url is : " + ngrok_tunnel.public_url)
However, this still won’t do what you want. If you do this, yes, you will be returned back to the console, but with that the ngrok process will also be stopped, as it is a subprocess of Python at this point. To leave the tunnels open, you need to leave the process running.

Can't run file on boot-up with Raspberry Pi

I have tried multiple ways (crontab and rc.local) of going about this. I have triple checked my code and processes each time but to no avail.
I am making a father's day gift with a button that says his favorite word, "No!".
Every time I reboot, my program does not respond at all to the GPIO and the button attached.
Is it how I have things structured in my sloppy code?
I'm not native in Python so I beg of you to help me.
When ran from the terminal or through Thonny, it runs perfectly. But no matter what, doesn't boot at start-up!
Here is my rc.local
Here's my code for the program:
import pygame
from random import randint
import RPi.GPIO as GPIO
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)
pygame.mixer.init()
#pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
continue
proverbFile = 'proverbs/Pro1.mp3'
num = 5
def randNo ():
noFile = '/home/pi/Desktop/audio/no/No1.mp3'
print('Executed!')
default = 1
global num
pulled = 1
while num == pulled:
pulled = randint(1,4)
print('Same!')
num = pulled
print(num)
noFile = noFile.replace(str(default), str(num), 1)
print(noFile)
pygame.mixer.music.load(noFile)
pygame.mixer.music.play()
default = num
def button_callback(channel):
print("Button was pushed!")
randNo()
GPIO.add_event_detect(10,GPIO.RISING,callback=button_callback)
#while True:
# keyPress = input('Press q to quit: ')
# if keyPress == 'q':
# break;
#GPIO.add_event_detect(10,GPIO.RISING,callback=button_callback) # Setup event on pin 10 rising edge
If you want a script to run when you boot into the LXDE environment, you could take a look at this Raspberry Pi forum post:
Navigate to ~/.config/lxsession/LXDE-pi
Open the autostart file in that folder:
$ sudo nano autostart
Add #midori on a new line. If you want to run something like a python script, put something like #python mypython.py on a new line. Running a script file would be #./superscript, but for some reason the script runs in an infinite loop (perhaps this will stop that).
Save and exit: Ctrl+X, Y, Enter
Restart your Raspberry Pi into the LXDE environment.
answer from here

Django Celery: Function only runs once within True While Loop

Background: I am using celery to run a python script within a django environment to measure weight from a load cell using a raspberry pi. I am measuring a bottle of water and it relays the information to the webserver.
The python code below runs perfectly when ran in a python environment outside of celery, but when it is ran by a celery worker, the value from the hx.get_weight(5) function within the while loop never changes after the first iteration.
This coded runs fine and the hx.get_weight(5) returns a different value everytime (weight is changing) when not ran by a celery worker. So, I believe it is celery that is causing this issue.
import RPi.GPIO as GPIO
import time
import sys
from .hx711 import HX711, L287
app = Celery('robobud', broker='redis://localhost:6379/0')
log = logging.getLogger(__name__)
#app.task
async def pump(program_id, amount1, amount2):
def cleanAndExit():
print ("Cleaning...")
GPIO.cleanup()
print ("Bye!")
sys.exit()
### Weight Class
hx = HX711(5, 6 )
hx.set_reading_format("LSB", "MSB")
hx.set_reference_unit(112)
hx.reset()
hx.tare()
### Weight
while True:
try:
val = hx.get_weight(5)
print val
hx.power_down()
hx.power_up()
time.sleep(1)

Waiting for user input when controlling 3rd party application via python script

I am writing a script intended to be used by members of a project team. As part of the script, I am launching a 3rd party proprietary application run through Citrix. I am going to use the script mostly to send keys to this application, but the first step once it launches is for the user to log in.
Because I would like the user to log in while the script is running, rather than asking for user/pass from some kind of GUI input earlier, and because the time it takes Citrix to launch varies, I would like to include some kind of logic that detects when the user has logged in and then resume the script from there, rather than including an obnoxiously long implicit wait or risking the script timing out.
Is there a way to detect user keystrokes using win32com.client (or to detect a change in state of the application itself)? See below for the relevant code to launch the app:
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
shell.Run('C:\Citrix\[rest of path])
EDIT:
Per Vasily's suggestion in the comments below, I attempted to adapt the "hook and listen" code to my scenario, but was unsuccessful. When I launch my file, I don't even get an exception message in my terminal, I get a Windows pop-up that says Python encountered a problem and needs to quit.
This is how I adapted it:
#[omitting import lines for brevity]
def on_timer():
"""Callback by timer out"""
win32api.PostThreadMessage(main_thread_id, win32con.WM_QUIT, 0, 0);
def on_event(args):
"""Callback for keyboard and mouse events"""
if isinstance(args, KeyboardEvent):
for i in range(1,100):
time.sleep(1)
if args.pressed_key == 'Lcontrol':
break
def init():
hk = Hook()
hk.handler = on_event
main_thread_id = win32api.GetCurrentThreadId()
t = Timer(55.0, on_timer) # Quit after 55 seconds
t.start()
hk.hook(keyboard=True, mouse=True)
At the point when the 3rd party Citrix app begins to launch in my main script, I call hookandlisten.init().
As a reminder, my goal is to wait until the user sends a certain keystroke (here I chose Control) before proceeding with the rest of the main script.
Solved this by eliminating the timer and unhooking the keyboard upon the correct keystroke:
import win32api
import win32con
from pywinauto.win32_hooks import Hook
from pywinauto.win32_hooks import KeyboardEvent
from pywinauto.win32_hooks import MouseEvent
def on_event(args):
"""Callback for keyboard and mouse events"""
if isinstance(args, KeyboardEvent):
if args.current_key == 'Lcontrol' and args.event_type == 'key down':
print("Success")
hk.unhook_keyboard()
return
def init():
hk.handler = on_event
hk.hook(keyboard=True, mouse=False)
hk = Hook()

Categories