Echo dot commands Raspberry pi to execute a script on my computer - python

Looking for a coding guru to explain me what direction I need to take now:
I use an Amazon Echo Dot which is currently connected to my Raspberry Pi.
I can now say "Alexa turn device on/off" which returns a true/false to my Raspberry Pi using this excellent repository: https://github.com/toddmedema/echo.
Could anyone explain me how I can replace this 'true' in this python script with a script that sends a request to execute a batch file on my windows computer using RDP?. I think it is here but it doesn't work:
def act(self, client_address, state, name):
print "State", state, "from client #", client_address
GPIO.setmode(GPIO.BOARD) ## Use board pin numbering
GPIO.setup(str(sys.argv[3]), GPIO.OUT) ## Setup GPIO Pin to OUTPUT
GPIO.output(str(sys.argv[3]), not state) ## State is true/false
GPIO.cleanup(str(sys.argv[3]))
return True ## after this line add the command the execute?
Extra question: How do I add more voice commands?
Would really appreciate it.

Related

Bind Bluetooth device programmatically to rfcomm via python in

i wrote a script in python for serial communication between my M5Stack Stick C (like raduino) and the raspberry pi.
all work fine. i can send "X","Y" or "Z" from raspberry py to the stick and he will reply the value (G-Force) back to the raspi! so far so good
Codes:
Python on raspy:
import serial
import time
import threading
ser = serial.Serial('/dev/rfcomm5') #init serial port
input_line = []#init input char array
def process_data(_data):
#called every time a sream is terminated by \n
#and the command string is ready to use
command = convert(_data)
print(command)
def convert(s): #convert the char list in a string
new = "" #init string to append all chars from char array
for x in s: # traverse in the string
new += str(x)
return new # return string
def processIncomingByte(inByte):#adding incoming chars to input_line
global input_line# globalize the input_line
if(inByte == '\n'):#if \n is incoming, end the chararray and release process data method
process_data(input_line)
input_line = []#reset input_line for next incoming string
elif(inByte == '\r'):
pass
else:#put all incoming chars in input_line
input_line.append(inByte)
while True:
while(ser.in_waiting > 0):#while some data is waiting to read....
processIncomingByte(ser.read())#.... process bytes whit method
ser.write(b'X\n')
time.sleep(0.5)
before the script work, i have to manually bind the m5Stak Stick-C over Blueman
to /dev/Rfcomm5. it work just fine over GUI or Console....
but now i would like to connect the stick via python to rfcomm5 (just by know the MAC adress, will be found in a config file later on...)
i startet to investigate a bit, but the more i research the more confused i am!!
i read some stuff over sockets and server-client aproaches. over a seperated script and so on....
i tested this code:
from bluetooth import *
target_name = "M5-Stick-C"
target_address = None
nearby_devices = discover_devices()
for address in nearby_devices:
if (target_name == lookup_name( address )):
target_address = address
break
if (target_address is not None):
print ("found target bluetooth device with address ", target_address)
else:
print ("could not find target bluetooth device nearby")
and indeed it found the device (just testing)!
but do i realy need to make a second script/process to connect to from my script?
is the the M5stack Stick-C the server? (i think so)
im so confused about all that stuff. i coded a lot, but never whit sockets, server-client stuff.
basically the communication (server/client?) works.
i just need to connect the device i found in the second script via macadress to rfcomm5 (or whatever rfcomm).
do i need a bluetooth socket? like in this example
https://gist.github.com/kevindoran/5428612
isnt the rfcomm the socket or am i wrong?
There are a number of layers that are used in the communication process and depending where you tap into that stack will depend what coding you need to do. The other complication is that BlueZ (the Bluetooth stack on linux) changed how it works over recent times leaving a lot of out of date information on the internet and easy for people to get confused.
With two Bluetooth devices, they need to establish a pairng. This is typically a one off provisioning step. This can be done with tools like Blueman or on the command line with bluetoothctl. Once you have a pairing established between your RPi and the M5Stack Stick, you shouldn't need to discover nearby devices again. Your script should just be able to connect if you tell it which device to connect to.
The M5Stack stick is advertising as having a Serial Port Profile (SPP). This is a layer on top of rfcomm.
There is a blog post about how this type of connection can be done with the standard Python3 installation: http://blog.kevindoran.co/bluetooth-programming-with-python-3/
My expectation is that you will only have to do the client.py on your RPi as the M5Stack Stick is the server. You will need to know its address and which port to connect on. Might be some trial and error on the port number (1 and 3 seem to be common).
Another library that I find helpful for SPP, is bluedot as it abstracts away some of the boilerplate code: https://bluedot.readthedocs.io/en/latest/btcommapi.html#bluetoothclient
So in summary, my recommendation is to use the standard Python Socket library or Bluedot. This will allow you to specify the address of the device you wish to connect to in your code and the underlying libraries will take care of making the connection and setting up the serial port (as long as you have already paired the two devices).
Example of what the above might look like with Bluedot
from bluedot.btcomm import BluetoothClient
from signal import pause
from time import sleep
# Callback to handle data
def data_received(data):
print(data)
sleep(0.5)
c.send("X\n")
# Make connection and establish serial connection
c = BluetoothClient("M5-Stick-C", data_received)
# Send initial requests
c.send("X\n")
# Cause the process to sleep until data received
pause()
Example using the Python socket library:
import socket
from time import sleep
# Device specific information
m5stick_addr = 'xx:xx:xx:xx:xx:xx'
port = 5 # This needs to match M5Stick setting
# Establish connection and setup serial communication
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.connect((m5stick_addr, port))
# Send and receive data
while True:
s.sendall(b'X\n')
data = s.recv(1024)
print(data)
sleep(0.5)
s.close()

How to run Neopixel without sudo permissions for use in an alexa app

I am creating an Alexa app that will allow the user to turn on a set of NeoPixels (WS2812) LEDs using a simple voice command. The app is hosted on a raspberry pi 4 and currently works for turning on GPIO pins. The issue I am having is that the code to turn on the NeoPixels needs sudo permissions, so when using the alexa app and it will simply error instead of turning on the lights.
due to the fact that sudo is needed the only way I have been able to run the script is to
sudo python3 LEDTest2.py
which works fine
here is the implementation for the alexa app turning on the GPIO pin and calling the python program
#ask.intent('GpioIntent', mapping = {'status':'status'})
def Gpio_Intent(status,room):
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(17,GPIO.OUT)
if status in STATUSON:
GPIO.output(17,GPIO.HIGH)
LEDTest2.func() ###Problem Point###
return statement('turning {} lights'.format(status))
This works fine for turning on the GPIO pin
Here is the LEDTest2.func()
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.D18,60)
def func():
print("func() in LEDtest2.py")
pixels.fill((255, 197, 143))
time.sleep(5)
pixels.fill((0,0,0))
if __name__ == "__main__": #same as file one
print("LEDtest2.py is being run directly")
for x in range(2):
pixels.fill((0, 255, 0))
time.sleep(.1)
pixels.fill((0, 0, 0))
time.sleep(.1)
else:
print("LEDtest2.py is being imported into another module")
how can i run this code without needing sudo permissions? is there an alternative way to control WS2812 LEDs using python?
Edit: Just to clarify i am not having any problems with the GPIO pins it is the NeoPixel library that cannot be used without sudo permissions
I was able to control it without sudo.
You should enable SPI interface from raspi-config.
Of course, first physically move LED connection to GPIO10 and change the pin in code.
I tried it and this works for me.

Can't get Kodi to accept keys emitted from python-uinput?

I'm emitting keys from a python script using python-uinput. Basic stuff such as up / down / enter / esc.
As far as I can see this works fine on my desktop, in the terminal, and with the browser. But when I run Kodi, it doesn't seem to respond at all. Is this something to do with it being a fullscreen application?
NB: I'm running Raspbian on model 3 Raspberry Pi.
Maybe you need to do: sudo modprobe uinput
The following script works for me to send Function key 12 to vice (a C64 emulator) based on a button press on a GPIO:
import uinput
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
wasPressed=False
# set up keystroke input
device = uinput.Device([uinput.KEY_F12])
while True:
button_inactive = GPIO.input(21)
if not button_inactive and not wasPressed:
device.emit_click(uinput.KEY_F12)
print "sending F12"
wasPressed=True
if button_inactive:
wasPressed=False
time.sleep(0.1)
Note that I used uinput.KEY_F12 twice. The script should be run as root.

How to use Arduino Uno analog pins as digital pins with pyfirmata

I am trying to use Arduino analog pins (A0-A5) as digital pins (D14-D19) with pyfirmata. I'm doing a simple blink test with D14 (or A0) to test this:
#!/usr/bin/python
# Blink test with analog as digital pins
# Import required libraries
from pyfirmata import Arduino, util
from pyfirmata import INPUT, OUTPUT, PWM
from time import sleep
# Associate port and board with pyFirmata
port = '/dev/cu.usbmodem1451'
board = Arduino(port)
# Pause to sync
sleep(1)
led = board.get_pin('d:14:o')
time = 1
while True:
led.write(1)
print ("On")
sleep(time)
led.write(0)
print ("Off")
sleep(time)
To enable analog pins to act as digital pins, I've gone into pyfirmata's boards.py file (as show in the github repo at https://github.com/tino/pyFirmata/blob/master/pyfirmata/boards.py) and changed line #3 from
digital': tuple(x for x in range(14)),
to
digital': tuple(x for x in range(20)),
I don't get an error when I run my python script, but the LED doesn't blink (don't worry, I'm positive the LED was in the right way).
Does anyone know how I can effectively instantiate digital pin 14 as an output pin with pyfirmata (as in the line led = board.get_pin('d:14:o'))
By the way (not that I think this affects anything) but I'm running Mac OSX with Yosemite.
Thank you!
The standard firmata that we use in Arduino, makes all analog pins input by default. So instead of changing anything in boards.py file, go to standard firmata file in arduino ide and find this ...
switch (mode) {
case PIN_MODE_ANALOG:
if (IS_PIN_ANALOG(pin)) {
if (IS_PIN_DIGITAL(pin)8) {
pinMode(PIN_TO_DIGITAL(pin), INPUT);
Now comment the pinMode line so that the firmata does not make any analog pin input
Now go to void setup() function and explicitly define nature of analog pins as shown below.
Firmata.begin(57600);
while (!Serial) {
}
pinMode(14,OUTPUT);
pinMode(15,INPUT);
pinMode(16,INPUT);
pinMode(17,INPUT);
pinMode(18,INPUT);
pinMode(19,INPUT);
digitalWrite(14,LOW);

LCD commands not working inside threads

I hooked up a 16X2 LCD to the pi via a MCP23017 GPIO expander. The problem that I am facing is that the LCD code below works inside normal functions or when I call it individually. But it does not work inside any of the threads in my program.
#!/usr/bin/python
# Example script to show usage of MCP230xx GPIO extender to drive character LCD.
from Adafruit_CharLCD import Adafruit_CharLCD
from Adafruit_MCP230xx import MCP230XX_GPIO
bus = 1 # Note you need to change the bus number to 0 if running on a revision 1 Raspberry Pi.
address = 0x20 # I2C address of the MCP230xx chip.
gpio_count = 8 # Number of GPIOs exposed by the MCP230xx chip, should be 8 or 16 depending on chip.
# Create MCP230xx GPIO adapter.
mcp = MCP230XX_GPIO(bus, address, gpio_count)
# Create LCD, passing in MCP GPIO adapter.
lcd = Adafruit_CharLCD(pin_rs=1, pin_e=2, pins_db=[3,4,5,6], GPIO=mcp)
lcd.clear()
lcd.message(" Adafruit 16x2\n Standard LCD")
links to library programs,
https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_CharLCD/Adafruit_CharLCD.py
https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_MCP230xx/Adafruit_MCP230xx.py
part of my actual program:
def switch():
mcp.config(0, mcp.INPUT)
mcp.pullup(1,1)
if ((mcp.input(1)>>1))
lcd.clear()
lcd.message("Switch open")
switchthread=threading.thread(target=switch)
switchthread.start()
Can anyone please tell me how to get the LCD commands working in the threads ?

Categories

Resources