I've been working on getting Google Assistant working on my Raspberry Pi 3.
It is working but I'm having problems getting this specific step to work:
https://developers.google.com/assistant/sdk/guides/library/python/extend/handle-device-commands
This step covers sending an on/off command to the Pi to turn a LED bulb on or off.
I have confirmed the Bread board and LED is setup correctly because I can turn the LED on or off via a python script.
However, after following the steps in that page and trying to run the following command "python hotword.py --device_model_id my-model"
(which is actually: python hotword.py --device_model_id assistantraspi-1d671-pigooglev2-8n98u3)
I get the following error:
ImportError: No module named pathlib2
I am including a copy of that file (hotword.py)
#!/usr/bin/env python
# Copyright (C) 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import print_function
import argparse
import json
import os.path
import pathlib2 as pathlib
import RPi.GPIO as GPIO
import google.oauth2.credentials
from google.assistant.library import Assistant
from google.assistant.library.event import EventType
from google.assistant.library.file_helpers import existing_file
from google.assistant.library.device_helpers import register_device
try:
FileNotFoundError
except NameError:
FileNotFoundError = IOError
WARNING_NOT_REGISTERED = """
This device is not registered. This means you will not be able to use
Device Actions or see your device in Assistant Settings. In order to
register this device follow instructions at:
https://developers.google.com/assistant/sdk/guides/library/python/embed/register-device
"""
def process_event(event):
"""Pretty prints events.
Prints all events that occur with two spaces between each new
conversation and a single space between turns of a conversation.
Args:
event(event.Event): The current event to process.
"""
if event.type == EventType.ON_CONVERSATION_TURN_STARTED:
print()
print(event)
if (event.type == EventType.ON_CONVERSATION_TURN_FINISHED and
event.args and not event.args['with_follow_on_turn']):
print()
if event.type == EventType.ON_DEVICE_ACTION:
for command, params in event.actions:
print('Do command', command, 'with params', str(params))
if command == "action.devices.commands.OnOff":
if params['on']:
print('Turning the LED on.')
GPIO.output(25, 1)
else:
print('Turning the LED off.')
GPIO.output(25, 0)
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('--device-model-id', '--device_model_id', type=str,
metavar='DEVICE_MODEL_ID', required=False,
help='the device model ID registered with Google')
parser.add_argument('--project-id', '--project_id', type=str,
metavar='PROJECT_ID', required=False,
help='the project ID used to register this device')
parser.add_argument('--device-config', type=str,
metavar='DEVICE_CONFIG_FILE',
default=os.path.join(
os.path.expanduser('~/.config'),
'googlesamples-assistant',
'device_config_library.json'
),
help='path to store and read device configuration')
parser.add_argument('--credentials', type=existing_file,
metavar='OAUTH2_CREDENTIALS_FILE',
default=os.path.join(
os.path.expanduser('~/.config'),
'google-oauthlib-tool',
'credentials.json'
),
help='path to store and read OAuth2 credentials')
parser.add_argument('-v', '--version', action='version',
version='%(prog)s ' + Assistant.__version_str__())
args = parser.parse_args()
with open(args.credentials, 'r') as f:
credentials = google.oauth2.credentials.Credentials(token=None,
**json.load(f))
device_model_id = None
last_device_id = None
try:
with open(args.device_config) as f:
device_config = json.load(f)
device_model_id = device_config['model_id']
last_device_id = device_config.get('last_device_id', None)
except FileNotFoundError:
pass
if not args.device_model_id and not device_model_id:
raise Exception('Missing --device-model-id option')
# Re-register if "device_model_id" is given by the user and it differs
# from what we previously registered with.
should_register = (
args.device_model_id and args.device_model_id != device_model_id)
device_model_id = args.device_model_id or device_model_id
with Assistant(credentials, device_model_id) as assistant:
events = assistant.start()
device_id = assistant.device_id
print('device_model_id:', device_model_id)
print('device_id:', device_id + '\n')
GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.OUT, initial=GPIO.LOW)
# Re-register if "device_id" is different from the last "device_id":
if should_register or (device_id != last_device_id):
if args.project_id:
register_device(args.project_id, credentials,
device_model_id, device_id)
pathlib.Path(os.path.dirname(args.device_config)).mkdir(
exist_ok=True)
with open(args.device_config, 'w') as f:
json.dump({
'last_device_id': device_id,
'model_id': device_model_id,
}, f)
else:
print(WARNING_NOT_REGISTERED)
for event in events:
process_event(event)
if __name__ == '__main__':
main()
Have you tried installing pathlib2 with pip or pip3? Please try
pip install pathlib2
if you're using Python2, and
pip3 install pathlib2
if you're using Python3. However, If pip is not found, then try installing it with
apt-get install python-pip python3-pip
Thanks for the suggestions. Turns out the solution was pretty simple.
The solution is two fold:
1: I have to run the following command first:
source env/bin/activate
Then I could run the python script without getting an error
(env) pi#raspberrypi:~/assistant-sdk-python/google-assistant-sdk/googlesamples/assistant/library $ python hotword.py --device_model_id assistantraspi-1d671-pigooglev2-8n98u3
As I progressed through the articles, the source becomes deactivated per se and returns to a normal prompt with first starting with (env).
Trying to run the python script without first loading the source command was the problem.
I still haven't wrapped my head around how this all works but I'll keep plugging along and hopefully understand what running this command first does
source env/bin/activate
This is the command that the script uses.
sudo apt-get install python-psutil
Make sure that you are working inside the virtual environment.
If not enter into the virtual environment and give a try.
If you are still having trouble execute the following command inside the virtual environment and try again:
sudo pip3 install pathlib2
This worked for me
Related
I need to login to IBM i System using Python without entering the username and password manually.
I used py3270 library but it is not able to detect the Emulator wc3270. The emulator I use has .hod extension and opens with IBM i Launcher.
Can anyone help me with this? what could be the possible solution for this?
os.system() is a blocking statement. That is, it blocks, or stops further Python code from being executed until whatever os.system() is doing has completed. This problem needs us to spawn a separate thread, so that the Windows process executing the ACS software runs at the same time the rest of the Python code runs. subprocess is one Python library that can handle this.
Here is some code that opens an ACS 5250 terminal window and pushes the user and password onto that window. There's no error checking, and there are some setup details that my system assumes about ACS which your system may not.
# the various print() statements are for looking behind the scenes
import sys
import time
import subprocess
from pywinauto.application import Application
import pywinauto.keyboard as keyboard
userid = sys.argv[1]
password = sys.argv[2]
print("Starting ACS")
cmd = r"C:\Users\Public\IBM\ClientSolutions\Start_Programs\Windows_x86-64\acslaunch_win-64.exe"
system = r'/system="your system name or IP goes here"'
# Popen requires the command to be separate from each of the parameters, so an array
result = subprocess.Popen([cmd, r"/plugin=5250",system], shell=True)
print(result)
# wait at least long enough for Windows to get past the splash screen
print("ACS starting - pausing")
time.sleep(5)
print("connecting to Windows process")
ACS = Application().connect(path=cmd)
print(ACS)
# debugging
windows = ACS.windows()
print(windows)
dialog = ACS['Signon to IBM i']
print(dialog)
print("sending keystrokes")
keyboard.send_keys(userid)
keyboard.send_keys("{TAB}")
keyboard.send_keys(password)
keyboard.send_keys("{ENTER}")
print('Done.')
Currently, I am facing the same issue. I was able to run the IBMi (ACS), however, once it run, my python script stop functioning as if the app is preventing the python from being running. In generally speaking, the app seems to not detecting the script.But once I closed the app, my python script continue to work.. I put some indication e.g timesleep, however as i mentioned earlier, it only continue to that line of code once IBM is closed. There will be few lines to be added to move the selection to 5250 and inject the credential.
*I tried with pyautogui, still facing the same issue. so now i tried pywinauto import keyboard .
#Variables
dir = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
x = dir.split("\\")
print(x[-1])
command = "cd \ && cd Users/Public/Desktop && " + '"' + x[-1] + '"'
print(command)
os.system(command)
------ FROM THIS LINE OF CODE ONWARDS, IT STOPPED RUNNING ONCE IBM IS LAUNCHED ---
print('TIME START')
time.sleep(5)
print('TIME END')
keyboard.send_keys(username)
keyboard.send_keys(password)
keyboard.send_keys("{ENTER}")
print('Done.')
Appreciate your help to look into this matter. Thanks
I am trying to make a server hardening script for my work, part of it is to install wazuh-agent on the servers that will be connected to a SIEM manager.
The script has 2 parts, one where it adds the repo entry - that works fine.
The second part installs the wazuh agent (code below). When I run the commands on the shell, they work fine but with the script it gives me the following error.
import os
import subprocess
wazuhrepofile = "/etc/yum.repos.d/wazuh.repo"
wazuh = "wazuh-agent"
wazuhmanager = 'WAZUHMANAGER="10.0.0.2"'
def install_wazuh(wazuh, wazuhmanager, wazuhrepofile):
subprocess.run([wazuhmgr ,'yum', 'install', '-y', wazuh], check=True)
print("Wazuh Agent Installed")
subprocess.run(['systemctl', 'daemon-reload'], check=True)
print("Daemon Reloaded")
subprocess.run(['systemctl', 'enable', wazuh])
print("Wazuh Agent Enabled")
subprocess.run(['systemctl', 'start', wazuh], check=True)
print("Wazuh-Agent Service Started!")
subprocess.run(['sed', '-i', '"s/^enabled=1/enabled=0/"', wazuhrepofile])
install_wazuh(wazuh, wazuhmgr, wazuhrepofile)
and the following is the error
[run error]
hj.
Thanks for choosing Wazuh.
As it was stated, subprocess.run accepts a series of parameters, but it seems that the first one needs to be an actual command instead of a variable assignment.
What you are doing is passing the Manager IP to have the Agent auto-enroll to the Manager. Another possible way, would be to install the Agent and then use the agent-auth located on the /var/ossec/bin/ folder. This commands also allows the Agent to pass an Agent Name to the Manager, so it will show with on the alerts and the UI, for easier identification.
the command is: /var/ossec/bin/agent-auth -m MANAGER-IP -A AGENT-NAME
For more information on agent registration visit here and for info on agent-auth tool, here
In case you have any further questions, don't hesitate to ask.
Cheers
I am able to write a script to checkout the code from SVN issue using "pysvn" module but just wanted to know is there any way I can do without pysvn also ? Because pysvn is third party library which I have to install separately on linux and windows both which I don't want. Please help me get alternate way in which I don't have to install any third party module code -
import pysvn,os,shutil
def getLogin(realm, username, may_save):
svn_user = '<my-username>'
svn_pass = '<my-password>'
return True, svn_user, svn_pass, False
def ssl_server_trust_prompt( trust_dict ):
return (True # server is trusted
,trust_dict["failures"]
,True) # save the answer so that the callback is not called again
def checkOut(svn_url,dest_dir):
if os.path.isdir(dest_dir):
shutil.rmtree(dest_dir)
os.mkdir(dest_dir)
client = pysvn.Client()
client.callback_ssl_server_trust_prompt = ssl_server_trust_prompt
client.callback_get_login = getLogin
client.checkout(svn_url,dest_dir)
else:
os.mkdir(dest_dir)
client = pysvn.Client()
client.callback_ssl_server_trust_prompt = ssl_server_trust_prompt
client.callback_get_login = getLogin
client.checkout(svn_url,dest_dir)
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','ABC')
print "checked out the code \n"
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','XYZ')
print "checked out the code\n"
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','MNP')
print "checked out the code \n”
You can pass username and password as arguments:
$ svn update --username 'user2' --password 'password'
You can make Executable of ur script which will include the pysvn into binary file, thus wouldn't need to import or pip install any library, n ur code will run on python-less machines too
Hi I've installed gridengine on a 4-node cluster using the following command:
sudo apt-get install gridengine-client gridengine-qmon gridengine-exec gridengine-master
sudo apt-get install gridengine-exec gridengine-client
And it returned:
SGE_ROOT: /var/lib/gridengine
SGE_CELL: bms
I've therefore done all the necessary step to configure the gridengine and it works.
However I want to run my job using python drmaa library and I've installed on the master node:
sudo apt-get install libdrmaa-dev
pip install drmaa
So if i query the system with following script:
#!/usr/bin/env python
import drmaa
def main():
"""Query the system."""
s = drmaa.Session()
s.initialize()
print 'A DRMAA object was created'
print 'Supported contact strings: ' + s.contact
print 'Supported DRM systems: ' + str(s.drmsInfo)
print 'Supported DRMAA implementations: ' + str(s.drmaaImplementation)
print 'Version ' + str(s.version)
print 'Exiting'
s.exit()
if __name__=='__main__':
main()
It returns:
A DRMAA object was created
Supported contact strings: session=NGS-1.9217.1679116461
Supported DRM systems: GE 6.2u5
Supported DRMAA implementations: GE 6.2u5
Version 1.0
Exiting
But if I try to run a job with the script suggested by the link:
http://code.google.com/p/drmaa-python/wiki/Tutorial#Running_a_Job
It returns
drmaa.errors.NoActiveSessionException: code 5: No active session
Could anyone help me?
What's wrong.
The drmaa library looks like is able to communicate with gridengine but it cannot run a job.
Why it raise this error?
I would really appreciate any kind of help.
you will find that the example of running job using DRMAA does not initialize the session so just add s.initialize() after creating new session s = drmaa.Session() as following:
#!/usr/bin/env python
import drmaa
import os
def main():
"""Submit a job.
Note, need file called sleeper.sh in current directory.
"""
s = drmaa.Session()
s.initialize()
print 'Creating job template'
jt = s.createJobTemplate()
jt.remoteCommand = os.getcwd() + '/sleeper.sh'
jt.args = ['42','Simon says:']
jt.joinFiles=True
jobid = s.runJob(jt)
print 'Your job has been submitted with id ' + jobid
print 'Cleaning up'
s.deleteJobTemplate(jt)
s.exit()
if __name__=='__main__':
main()
How would I go about getting a privilege elevation dialog to pop up in my Python app? I want the UAC dialog on Windows and the password authentication dialog on Mac.
Basically, I need root privileges for part of my application and I need to get those privileges through the GUI. I'm using wxPython. Any ideas?
On Windows you cannot get the UAC dialog without starting a new process, and you cannot even start that process with CreateProcess.
The UAC dialog can be brought about by running another application that has the appropriate manifest file - see Running compiled python (py2exe) as administrator in Vista for an example of how to do this with py2exe.
You can also programatically use the runas verb with the win32 api ShellExecute http://msdn.microsoft.com/en-us/library/bb762153(v=vs.85).aspx - you can call this by using ctypes http://python.net/crew/theller/ctypes/ which is part of the standard library on python 2.5+ iirc.
Sorry don't know about Mac. If you give more detail on what you want to accomplish on Windows I might be able to provide more specific help.
I know the post is a little old, but I wrote the following as a solution to my problem (running a python script as root on both Linux and OS X).
I wrote the following bash-script to execute bash/python scripts with administrator privileges (works on Linux and OS X systems):
#!/bin/bash
if [ -z "$1" ]; then
echo "Specify executable"
exit 1
fi
EXE=$1
available(){
which $1 >/dev/null 2>&1
}
platform=`uname`
if [ "$platform" == "Darwin" ]; then
MESSAGE="Please run $1 as root with sudo or install osascript (should be installed by default)"
else
MESSAGE="Please run $1 as root with sudo or install gksu / kdesudo!"
fi
if [ `whoami` != "root" ]; then
if [ "$platform" == "Darwin" ]; then
# Apple
if available osascript
then
SUDO=`which osascript`
fi
else # assume Linux
# choose either gksudo or kdesudo
# if both are avilable check whoch desktop is running
if available gksudo
then
SUDO=`which gksudo`
fi
if available kdesudo
then
SUDO=`which kdesudo`
fi
if ( available gksudo && available kdesudo )
then
if [ $XDG_CURRENT_DESKTOP = "KDE" ]; then
SUDO=`which kdesudo`;
else
SUDO=`which gksudo`
fi
fi
# prefer polkit if available
if available pkexec
then
SUDO=`which pkexec`
fi
fi
if [ -z $SUDO ]; then
if available zenity; then
zenity --info --text "$MESSAGE"
exit 0
elif available notify-send; then
notify-send "$MESSAGE"
exit 0
elif available xmessage notify-send; then
xmessage -buttons Ok:0 "$MESSAGE"
exit 0
else
echo "$MESSAGE"
fi
fi
fi
if [ "$platform" == "Darwin" ]
then
$SUDO -e "do shell script \"$*\" with administrator privileges"
else
$SUDO $#
fi
Basically, the way I set up my system is that I keep subfolders inside the bin directories (e.g. /usr/local/bin/pyscripts in /usr/local/bin), and create symbolic links to the executables. This has three benefits for me:
(1) If I have different versions, I can easily switch which one is executed by changing the symbolic link and it keeps the bin directory cleaner (e.g. /usr/local/bin/gcc-versions/4.9/, /usr/local/bin/gcc-versions/4.8/, /usr/local/bin/gcc --> gcc-versions/4.8/gcc)
(2) I can store the scripts with their extension (helpful for syntax highlighting in IDEs), but the executables do not contain them because I like it that way (e.g. svn-tools --> pyscripts/svn-tools.py)
(3) The reason I will show below:
I name the script "run-as-root-wrapper" and place it in a very common path (e.g. /usr/local/bin) so python doesn't need anything special to locate it. Then I have the following run_command.py module:
import os
import sys
from distutils.spawn import find_executable
#===========================================================================#
def wrap_to_run_as_root(exe_install_path, true_command, expand_path = True):
run_as_root_path = find_executable("run-as-root-wrapper")
if(not run_as_root_path):
return False
else:
if(os.path.exists(exe_install_path)):
os.unlink(exe_install_path)
if(expand_path):
true_command = os.path.realpath(true_command)
true_command = os.path.abspath(true_command)
true_command = os.path.normpath(true_command)
f = open(exe_install_path, 'w')
f.write("#!/bin/bash\n\n")
f.write(run_as_root_path + " " + true_command + " $#\n\n")
f.close()
os.chmod(exe_install_path, 0755)
return True
In my actual python script, I have the following function:
def install_cmd(args):
exe_install_path = os.path.join(args.prefix,
os.path.join("bin", args.name))
if(not run_command.wrap_to_run_as_root(exe_install_path, sys.argv[0])):
os.symlink(os.path.realpath(sys.argv[0]), exe_install_path)
So if I have a script called TrackingBlocker.py (actual script I use to modify the /etc/hosts file to re-route known tracking domains to 127.0.0.1), when I call "sudo /usr/local/bin/pyscripts/TrackingBlocker.py --prefix /usr/local --name ModifyTrackingBlocker install" (arguments handled via argparse module), it installs "/usr/local/bin/ModifyTrackingBlocker", which is a bash script executing
/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py [args]
e.g.
ModifyTrackingBlocker add tracker.ads.com
executes:
/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py add tracker.ads.com
which then displays the authentification dialog needed to get the privileges to add:
127.0.0.1 tracker.ads.com
to my hosts file (which is only writable by a superuser).
If you want to simplify/modify it to run only certain commands as root, you could simply add this to your script (with the necessary imports noted above + import subprocess):
def run_as_root(command, args, expand_path = True):
run_as_root_path = find_executable("run-as-root-wrapper")
if(not run_as_root_path):
return 1
else:
if(expand_path):
command = os.path.realpath(command)
command = os.path.abspath(command)
command = os.path.normpath(command)
cmd = []
cmd.append(run_as_root_path)
cmd.append(command)
cmd.extend(args)
return subprocess.call(' '.join(cmd), shell=True)
Using the above (in run_command module):
>>> ret = run_command.run_as_root("/usr/local/bin/pyscripts/TrackingBlocker.py", ["status", "display"])
>>> /etc/hosts is blocking approximately 16147 domains
I'm having the same problem on Mac OS X. I have a working solution, but it's not optimal. I will explain my solution here and continue looking for a better one.
At the beginning of the program I check if I'm root or not by executing
def _elevate():
"""Elevate user permissions if needed"""
if platform.system() == 'Darwin':
try:
os.setuid(0)
except OSError:
_mac_elevate()
os.setuid(0) will fail if i'm not already root and that will trigger _mac_elevate() which relaunch my program from the start as administrator with the help of osascript. osascript can be used to execute applescript and other stuff. I use it like this:
def _mac_elevate():
"""Relaunch asking for root privileges."""
print "Relaunching with root permissions"
applescript = ('do shell script "./my_program" '
'with administrator privileges')
exit_code = subprocess.call(['osascript', '-e', applescript])
sys.exit(exit_code)
The problem with this is if I use subprocess.call as above I keep the current process running and there will be two instances of my app running giving two dock icons. If I use subprocess.Popen instead and let the non-priviledged process die instantly I can't make use of the exit code, nor can I fetch the stdout/stderr streams and propagate to the terminal starting the original process.
Using osascript with with administrator privileges is actually just Apple Script wrapping a call to AuthorizationExecuteWithPrivileges().
But you can call AuthorizationExecuteWithPrivileges() directly from Python3 with ctypes.
For example, the following parent script spawn_root.py (run as a non-root user) spawns a child process root_child.py (run with root privileges).
The user will be prompted to enter their password in the OS GUI pop-up. Note that this will not work on a headless session (eg over ssh). It must be run inside the GUI (eg Terminal.app).
After entering the user's password into the MacOS challenge dialog correctly, root_child.py executes a soft shutdown of the system, which requires root permission on MacOS.
Parent (spawn_root.py)
#!/usr/bin/env python3
import sys, ctypes
import ctypes.util
from ctypes import byref
sec = ctypes.cdll.LoadLibrary(ctypes.util.find_library("Security"))
kAuthorizationFlagDefaults = 0
auth = ctypes.c_void_p()
r_auth = byref(auth)
sec.AuthorizationCreate(None,None,kAuthorizationFlagDefaults,r_auth)
exe = [sys.executable,"root_child.py"]
args = (ctypes.c_char_p * len(exe))()
for i,arg in enumerate(exe[1:]):
args[i] = arg.encode('utf8')
io = ctypes.c_void_p()
sec.AuthorizationExecuteWithPrivileges(auth,exe[0].encode('utf8'),0,args,byref(io))
Child (root_child.py)
#!/usr/bin/env python3
import os
if __name__ == "__main__":
f = open( "root_child.out", "a" )
try:
os.system( "shutdown -h now" )
f.write( "SUCCESS: I am root!\n" )
except Exception as e:
f.write( "ERROR: I am not root :'(" +str(e)+ "\n" )
f.close()
Security Note
Obviously, any time you run something as root, you need to be very careful!
AuthorizationExecuteWithPrivileges() is deprecated, but it can be used safely. But it can also be used unsafely!
It basically boils down to: do you actually know what you're running as root? If the script you're running as root is located in a Temp dir that has world-writeable permissions (as a lot of MacOS App installers have done historically), then any malicious process could gain root access.
To execute a process as root safely:
Make sure that the permissions on the process-to-be-launched are root:root 0400 (or writeable only by root)
Specify the absolute path to the process-to-be-launched, and don't allow any malicious modification of that path
Sources
https://github.com/cloudmatrix/esky/blob/master/esky/sudo/sudo_osx.py
https://github.com/BusKill/buskill-app/issues/14
https://www.jamf.com/blog/detecting-insecure-application-updates-on-macos/