I can't get the following code for Detecting USB Device Insertion to work on my Windows 10 (64 bit) computer with Python 3.7.
import win32serviceutil
import win32service
import win32event
import servicemanager
import win32gui
import win32gui_struct
struct = win32gui_struct.struct
pywintypes = win32gui_struct.pywintypes
import win32con
GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"
DBT_DEVICEARRIVAL = 0x8000
DBT_DEVICEREMOVECOMPLETE = 0x8004
import ctypes
#
# Cut-down clone of UnpackDEV_BROADCAST from win32gui_struct, to be
# used for monkey-patching said module with correct handling
# of the "name" param of DBT_DEVTYPE_DEVICEINTERFACE
#
def _UnpackDEV_BROADCAST (lparam):
if lparam == 0: return None
hdr_format = "iii"
hdr_size = struct.calcsize (hdr_format)
hdr_buf = win32gui.PyGetMemory (lparam, hdr_size)
size, devtype, reserved = struct.unpack ("iii", hdr_buf)
# Due to x64 alignment issues, we need to use the full format string over
# the entire buffer. ie, on x64:
# calcsize('iiiP') != calcsize('iii')+calcsize('P')
buf = win32gui.PyGetMemory (lparam, size)
extra = {}
if devtype == win32con.DBT_DEVTYP_DEVICEINTERFACE:
fmt = hdr_format + "16s"
_, _, _, guid_bytes = struct.unpack (fmt, buf[:struct.calcsize(fmt)])
extra['classguid'] = pywintypes.IID (guid_bytes, True)
extra['name'] = ctypes.wstring_at (lparam + struct.calcsize(fmt))
else:
raise NotImplementedError("unknown device type %d" % (devtype,))
return win32gui_struct.DEV_BROADCAST_INFO(devtype, **extra)
win32gui_struct.UnpackDEV_BROADCAST = _UnpackDEV_BROADCAST
class DeviceEventService (win32serviceutil.ServiceFramework):
_svc_name_ = "DevEventHandler"
_svc_display_name_ = "Device Event Handler"
_svc_description_ = "Handle device notification events"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__ (self, args)
self.hWaitStop = win32event.CreateEvent (None, 0, 0, None)
#
# Specify that we're interested in device interface
# events for USB devices
#
filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE (
GUID_DEVINTERFACE_USB_DEVICE
)
self.hDevNotify = win32gui.RegisterDeviceNotification (
self.ssh, # copy of the service status handle
filter,
win32con.DEVICE_NOTIFY_SERVICE_HANDLE
)
#
# Add to the list of controls already handled by the underlying
# ServiceFramework class. We're only interested in device events
#
def GetAcceptedControls(self):
rc = win32serviceutil.ServiceFramework.GetAcceptedControls (self)
rc |= win32service.SERVICE_CONTROL_DEVICEEVENT
return rc
#
# Handle non-standard service events (including our device broadcasts)
# by logging to the Application event log
#
def SvcOtherEx(self, control, event_type, data):
if control == win32service.SERVICE_CONTROL_DEVICEEVENT:
info = win32gui_struct.UnpackDEV_BROADCAST(data)
#
# This is the key bit here where you'll presumably
# do something other than log the event. Perhaps pulse
# a named event or write to a secure pipe etc. etc.
#
if event_type == DBT_DEVICEARRIVAL:
servicemanager.LogMsg (
servicemanager.EVENTLOG_INFORMATION_TYPE,
0xF000,
("Device %s arrived" % info.name, '')
)
elif event_type == DBT_DEVICEREMOVECOMPLETE:
servicemanager.LogMsg (
servicemanager.EVENTLOG_INFORMATION_TYPE,
0xF000,
("Device %s removed" % info.name, '')
)
#
# Standard stuff for stopping and running service; nothing
# specific to device notifications
#
def SvcStop(self):
self.ReportServiceStatus (win32service.SERVICE_STOP_PENDING)
win32event.SetEvent (self.hWaitStop)
def SvcDoRun(self):
win32event.WaitForSingleObject (self.hWaitStop, win32event.INFINITE)
servicemanager.LogMsg (
servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STOPPED,
(self._svc_name_, '')
)
if __name__=='__main__':
win32serviceutil.HandleCommandLine (DeviceEventService)
I start the script with the following command: python main.py start
Then the following error messages appear in the command prompt:
Starting service DevEventHandler
Error starting service: Access denied
I then ran the script with administrator privileges: runas /user:administrator "python main.py start"
Another error messages appear in the command prompt:
Starting service DevEventHandler
Error starting service: The specified service does not exist as an installed service.
How can the 'The specified service does not exist as an installed service' error be fixed?
I tested with Python 3.8.2 x64.
Install pywin32 (pip install pywin32)
Install the current/last version (1.5) of the WMI module from https://github.com/tjguk/wmi (pip install -e git+https://github.com/tjguk/wmi.git#egg=wmi)
run a script (test.py in my case), like:
import wmi
raw_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA \'Win32_USBHub\'"
c = wmi.WMI ()
watcher = c.watch_for(raw_wql=raw_wql)
while 1:
usb = watcher ()
print(usb)
plug in a USB device. Output looks like:
(wmi-py) C:\Users\USER\Source\wmi-py>py test.py
instance of Win32_USBHub
{
Caption = "USB Composite Device";
ConfigManagerErrorCode = 0;
ConfigManagerUserConfig = FALSE;
CreationClassName = "Win32_USBHub";
Description = "USB Composite Device";
...
Many thanks to the WMI module author, and the Windows nerds' discussion here Detecting USB drive insertion and removal using windows service and c#
I tried to run the script with debug argument and a message saying that service is not installed appeared.
Try first to type
python main.py install
then
python main.py start
Related
I am using a raspberry pi 4 mode B to interface communicate with a Teensy 4.0. I'm using ROS noetic on Ubuntu 20.04. I've flashed the code to the Teensy successfully using platformio. I have a problem, however, when I try and launch the calibration python script for the robot I'm working on. I'm interfacing the raspberry Pi with the Teensy through the GPIO pins (this is after I've flashed the code to the Teensy, I flashed it through usb). When I run the calibration script using roslaunch mini_ros spot_calibration I get the following error:
[servo_calibration-1] process has died [pid 4841, exit code 1, cmd /home/ubuntu/spark_ws/src/spot_mini_mini/mini_ros/src/servo_calibration __name:=servo_calibration __log:=/home/ubuntu/.ros/log/fa068172-32ea-11ec-b45a-513494152363/servo_calibration-1.log].
log file: /home/ubuntu/.ros/log/fa068172-32ea-11ec-b45a-513494152363/servo_calibration-1*.log
[ERROR] [1634874547.846356]: Mismatched protocol version in packet (b'\xf8'): lost sync or rosserial_python is from different ros release than the rosserial client
below is the python code in spot_calibration
#!/usr/bin/env python
"""
DESCRIPTION:
SUBSCRIBERS:
"""
from __future__ import division
import rospy
from mini_ros.srv import CalibServo, CalibServoResponse
from mini_ros.msg import JointPulse
import numpy as np
import sys
import rospkg
rospack = rospkg.RosPack()
sys.path.append(rospack.get_path('mini_ros') + '/../')
sys.path.append('../../')
class ServoCalibrator():
def __init__(self):
rospy.init_node('ServoCalibrator', anonymous=True)
self.serv = rospy.Service('servo_calibrator', CalibServo,
self.calib_service_cb)
self.jp_pub = rospy.Publisher('spot/pulse', JointPulse, queue_size=1)
def calib_service_cb(self, req):
""" Requests a servo to be moved to a certain position
Args: req
Returns: response
"""
try:
jp_msg = JointPulse()
jp_msg.servo_num = req.servo_num
jp_msg.servo_pulse = req.servo_pulse
self.jp_pub.publish(jp_msg)
response = "Servo Command Sent."
except rospy.ROSInterruptException:
response = "FAILED to send Servo Command"
return CalibServoResponse(response)
def main():
""" The main() function. """
srv_calib = ServoCalibrator()
rospy.loginfo(
"Use The servo_calibrator service (Pulse Width Unit is us (nominal ~500-2500))."
)
while not rospy.is_shutdown():
rospy.spin()
if __name__ == '__main__':
try:
main()
except rospy.ROSInterruptException:
pass
The package was supposedly made in ROS Melodic, so that might be why it's throwing the error, but I don't know what to change if the package is melodic exclusive.
The problem is indeed because the roslib package used by rosserial was build for Melodic. As you can guess this error is just caused because of mismatched version ids coming from the arduino side. The best option would be to rebuild ros_lib for Noetic.
To rebuild ros_lib all you have to do is navigate to your sketchbook and run make_libraries.py. Note that this will build up to the currently installed distro, so you need to run this on a machine that has Noetic installed.
cd <sketchbook>/libraries
rm -rf ros_lib
rosrun rosserial_arduino make_libraries.py .
If rebuilding isn't an option you can add the definitions manually. On the arduino side you'll have a ros_lib folder. You have two sub directories you need to change.
The first is ./ros/node_handle.h. At the top of the file you'll see a few protocol versions defined as const uint8_t. Add in the version id for noetic as const uint8_t PROTOCOL_VER6 = 0xfa; then change the line that states what version should be used. const uint8_t PROTOCOL_VER = PROTOCOL_VER6;.
Lastly, you just need to make this same change in ./ros_lib/ros/node_handle.h
I'm trying to run a python script that simulates traffic sensors sending in data in real time to PubSub on my Google Cloud Shell. I'm getting this error
Traceback (most recent call last):
File "./send_sensor_data.py", line 87, in <module>
psclient = pubsub.Client()
AttributeError: 'module' object has no attribute 'Client'
Tried running google.cloud.pubsub.__file__, no duplicates exist.
I've been searching everywhere and the popular consensus was to install the pubsub package into a virtual environment which I've tried to no avail.
What I've tried so far:
Set VM to clean state
Uninstalled and reinstalled all gcloud components
Updated all gcloud components to the latest version
uninsalled and reinstalled python pubsub library
Installed pubsub inside a virtualenv
Tried from a different project
Tried from a different GCP account
This is my script:
import time
import gzip
import logging
import argparse
import datetime
from google.cloud import pubsub
TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
TOPIC = 'sandiego'
INPUT = 'sensor_obs2008.csv.gz'
def publish(topic, events):
numobs = len(events)
if numobs > 0:
with topic.batch() as batch:
logging.info('Publishing {} events from {}'.
format(numobs, get_timestamp(events[0])))
for event_data in events:
batch.publish(event_data)
def get_timestamp(line):
# look at first field of row
timestamp = line.split(',')[0]
return datetime.datetime.strptime(timestamp, TIME_FORMAT)
def simulate(topic, ifp, firstObsTime, programStart, speedFactor):
# sleep computation
def compute_sleep_secs(obs_time):
time_elapsed = (datetime.datetime.utcnow() - programStart).seconds
sim_time_elapsed = (obs_time - firstObsTime).seconds / speedFactor
to_sleep_secs = sim_time_elapsed - time_elapsed
return to_sleep_secs
topublish = list()
for line in ifp:
event_data = line # entire line of input CSV is the message
obs_time = get_timestamp(line) # from first column
# how much time should we sleep?
if compute_sleep_secs(obs_time) > 1:
# notify the accumulated topublish
publish(topic, topublish) # notify accumulated messages
topublish = list() # empty out list
# recompute sleep, since notification takes a while
to_sleep_secs = compute_sleep_secs(obs_time)
if to_sleep_secs > 0:
logging.info('Sleeping {} seconds'.format(to_sleep_secs))
time.sleep(to_sleep_secs)
topublish.append(event_data)
# left-over records; notify again
publish(topic, topublish)
def peek_timestamp(ifp):
# peek ahead to next line, get timestamp and go back
pos = ifp.tell()
line = ifp.readline()
ifp.seek(pos)
return get_timestamp(line)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Send sensor data to Cloud Pub/Sub in small groups, simulating real-time behavior')
parser.add_argument('--speedFactor', help='Example: 60 implies 1 hour of data sent to Cloud Pub/Sub in 1 minute', required=True, type=float)
args = parser.parse_args()
# create Pub/Sub notification topic
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
psclient = pubsub.Client()
topic = psclient.topic(TOPIC)
if not topic.exists():
logging.info('Creating pub/sub topic {}'.format(TOPIC))
topic.create()
else:
logging.info('Reusing pub/sub topic {}'.format(TOPIC))
# notify about each line in the input file
programStartTime = datetime.datetime.utcnow()
with gzip.open(INPUT, 'rb') as ifp:
header = ifp.readline() # skip header
firstObsTime = peek_timestamp(ifp)
logging.info('Sending sensor data from {}'.format(firstObsTime))
simulate(topic, ifp, firstObsTime, programStartTime, args.speedFactor)
The pubsub.Client class exists until the 0.27.0 version of the pubsub python package. So I just created a virtual environment and installed the 0.27.0 version of pubsub into it.
Here are the commands:
virtualenv venv
source venv/bin/activate
pip install google-cloud-pubsub==0.27.0
Solution for Google Cloud Platforms is:
Modify the send_senor_data.py file as follows:
a. Comment the original import statement for pub_sub and use _v1 version
#from google.cloud import pubsub
from google.cloud import pubsub_v1
b. Find this code and replace it as follows:
#publisher = pubsub.PublisherClient()
publisher = pubsub_v1.PublisherClient()
Then execute your send_sensor_data.py as follows:
./send_sensor_data.py --speedFactor=60 --project=YOUR-PROJECT-NAME
There's no pubsub.Client class. You
need to choose a PublisherClient or SubscriberClient
see https://github.com/GoogleCloudPlatform/google-cloud-python/blob/master/pubsub/google/cloud/pubsub.py
Ok, so I wrote a python service that simply writes to a file. I packaged it all up with cx_freeze, and installed it as a Service via the command prompt. It ran fine, but then I realized that the file it was to writing was in some weird directory, so I changed the service code to write the file to my documents. Here's the code for my Python Service:
import win32service
import win32serviceutil
import win32event
class PySvc(win32serviceutil.ServiceFramework):
_svc_name_ = "PySvc"
_svc_display_name_ = "Python Test Service"
_svc_description_ = "This is a service that simply writes to a file"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self,args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcDoRun(self):
import servicemanager
f = open('C:/Users/Luke/Documents/test.dat', 'w+')
rc = None
while rc != win32event.WAIT_OBJECT_0:
f.write('TEST DATA\n')
f.flush()
rc = win32event.WaitForSingleObject(self.hWaitStop, 5000)
f.write('SHUTTING DOWN...\n')
f.close()
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
if __name__ == '__main':
win32serviceutil.HandleCommandLine(PySvc)
This line:
f = open('C:/Users/Luke/Documents/test.dat', 'w+')
Used to look like this (when it worked):
f = open('test.dat', 'w+')
This was the only change that I made to the code.
This time when I attempted to install it in the cmd, it returned this frustrating error:
Exception occurred while initializing the installation:System.BadImageFormatException: Could not load file or assembly 'file:///C:\PySvc\PySvc.exe' or one of its dependencies. The module was expected to contain an assembly manifest..
What Happened? Any Help?
I found the solution, and realized how amateur I truly am. Somewhere along the way, I accidently deleted the last 2 '_'s in if __name__ == '__main__': as you can see in the code. Just goes to show you that you should check all your code before you ask a SO question! So I changed this:
if __name__ == '__main':
To this:
if __name__ == '__main__':
I was just learning win32 modules and i try to reboot windows based on this but it doesn't work.
This is the code:
import win32security
import win32api
import sys
import time
from ntsecuritycon import *
def AdjustPrivilege(priv, enable=1):
# Get the process token
flags = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
htoken =win32security.OpenProcessToken(win32api.GetCurrentProcess(), flags)
# Get the ID for the system shutdown privilege.
idd = win32security.LookupPrivilegeValue(None, priv)
# Now obtain the privilege for this process.
# Create a list of the privileges to be added.
if enable:
newPrivileges = [(idd, SE_PRIVILEGE_ENABLED)]
else:
newPrivileges = [(idd, 0)]
# and make the adjustment
win32security.AdjustTokenPrivileges(htoken,0,newPrivileges)
def RebootServer(message='Rebooting', timeout=30,bForce=0,bReboot=1):
AdjustPrivilege(SE_SHUTDOWN_NAME)
try:
win32api.InitiateSystemShutdown(None,message,timeout,bForce,bReboot)
finally:
# Now we remove the privilege we just added.
AdjustPrivilege(SE_SHUTDOWN_NAME, 0)
def AbortReboot():
AdjustPrivilege(SE_SHUTDOWN_NAME)
try:
win32api.AbortSystemShotdown(None)
finally:
AdjustPrivilege(SE_SHUTDOWN_NAME, 0)
if __name__ == '__main__':
RebootServer()
time.sleep(10)
print ('Aborting shutdown')
AbortReboot()
I use python 3.4 version and my OS is windows 7(64)
and i get this error:
pywintypes.error: (1116, 'AbortSystemShutdown', 'Unable to abort the system shutdown because no shutdown was in progress.')
I apologise if the question is so stupid but I am new in linux and python.
The point is that I need to write a python script which will detect connected usb stick and write a file to it. I use opensuse(but script shoild work with any linux distro. in ideal case). Current version can detect usb and write a file if that usb is mounted. But on my machine usb is mounted only if I browse it in file manager. Until that usb detected as a partion but without mount point. So, how can I force the system to mount usb or how can I write a file using devname or devpath or another information what I can get from hal manager. I can not use "mount" command because it requires a root permission
Simplified Source code:
import dbus, gobject, os
class DeviceAddedListener:
def __init__(self):
self.bus = dbus.SystemBus()
self.hal_manager_obj = self.bus.get_object( "org.freedesktop.Hal", "/org/freedesktop/Hal/Manager")
self.hal_manager = dbus.Interface(self.hal_manager_obj, "org.freedesktop.Hal.Manager")
self.hal_manager.connect_to_signal("DeviceAdded", self.added)
def show(self, name, udi):
d_object = self.bus.get_object('org.freedesktop.Hal', udi)
d_interface = dbus.Interface(d_object,'org.freedesktop.Hal.Device')
if d_interface.QueryCapability("volume"):
print name
props = [ "block.device", "volume.label", "volume.is_mounted", "volume.mount_point", "volume.size"]
for p in props:
print '\t', p, " = ",
try:
print d_interface.GetProperty(p)
except:
print "Fail"
def added(self, udi):
self.show("DeviceAdded", udi)
self.bus.add_signal_receiver(self.property_modified,
"PropertyModified",
"org.freedesktop.Hal.Device",
"org.freedesktop.Hal",
udi,
path_keyword = "sending_device" )
def property_modified(self, numupdates, updates, sending_device = None):
self.show("PropertyModified", sending_device)
if __name__ == '__main__':
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
loop = gobject.MainLoop()
DeviceAddedListener()
print "running"
loop.run()
The output when usb plugged in
DeviceAdded
block.device = /dev/sdb1
volume.label = #
volume.is_mounted = 0
volume.mount_point =
volume.size = 4009722368
The output when usb plugged in and mounted
block.device = /dev/sdb1
volume.label = #
volume.is_mounted = 1
volume.mount_point = /media/#
volume.size = 4009722368
Thanks for any help!
You will have to use mount because the kernel controls mounting partitions within the operating system for security reasons. You can use mount without superuser/administrator privileges. Try something like this:
Make sure that the directory (/mnt/usb1/) you are mounting to already exists, and then
mount /dev/sdb1 /mnt/usb1 -o noauto,users,rw,umask=0
There's also something called autofs that does allow automatic mounting:
http://linuxconfig.org/automatically-mount-usb-external-drive-with-autofs
The HAL it's discontinued, I think so better use UDisks to work with pen USB. Then, you can use methods FilesystemMount and FilesystemUnmount, I create one example here (https://gist.github.com/3037221) and have oficial documantation here (http://hal.freedesktop.org/docs/udisks/Device.html#Device.FilesystemMount).