I am trying to convert some c++/qt code to Python/qt.
Using QDBusInterface in c++:
auto qi = make_unique<QDBusInterface>("org.freedesktop.UPower", /org/freedesktop/UPower, "org.freedesktop.UPower", QDBusConnection::systemBus());
at this point I can already read values from it's properties:
auto prop = qi.property("OnBattery");
Unfortunately it does not work that way while doing the same in Python:
qi = QDBusInterface(serviceObject, path, interface, QDBusConnection.systemBus())
qi.isValid() returns True but reading property:
onBattery = qi.property("OnBattery")
returns None.
Also calling methods like EnumerateDevices works on both C++ and Python
Is there a way to make it work?
The problem here is lack of good examples:
from PyQt5.QtDBus import QDBusConnection, QDBusInterface, QDBusMessage
# DBus connection and Interface.
dbus_service = 'org.freedesktop.UPower'
dbus_path = '/org/freedesktop/UPower'
interface = QDBusInterface(dbus_service, dbus_path, 'org.freedesktop.DBus.Properties', QDBusConnection.systemBus())
# Get all properties.
msg = interface.call('GetAll', 'org.freedesktop.UPower')
print(msg.arguments())
for k, v in msg.arguments()[0].items():
print('{}: {}'.format(k, v))
# Get just the requested property.
msg = interface.call('Get', 'org.freedesktop.UPower', 'OnBattery')
print(msg.arguments()[0])
I found indirect solution on my own.
It was resigning from using QDBusInterface and switching to Python's dbus which API can be used like in this link
Related
I am new to ROS and rospy, and I am not familiar with non-simple data type as topic.
I want to build a ROS node as both a subscriber and publisher: it receives a topic (a list of two float64), and uses a function (say my_function) which returns a list of lists of float64, then publish this list of list as a topic.
To do this, I built a node as following:
from pymongo import MongoClient
from myfile import my_function
import rospy
import numpy as np
pub = None
sub = None
def callback(req):
client = MongoClient()
db = client.block
lon = np.float64(req.b)
lat = np.float64(req.a)
point_list = my_function(lon, lat, db)
pub.publish(point_list)
def calculator():
global sub, pub
rospy.init_node('calculator', anonymous=True)
pub = rospy.Publisher('output_data', list)
# Listen
sub = rospy.Subscriber('input_data', list, callback)
print "Calculation finished. \n"
ros.spin()
if __name__ == '__main__':
try:
calculator()
except rospy.ROSInterruptException:
pass
I know clearly that list in Subscriber and Publisher is not a message data, but I cannot figure out how to fix it since it is not an integer nor list of integer.
This post on the ROS forums gives you most of what you need. This is also useful. You can define a new message type FloatList.msg with the following specification:
float64[] elements
And then a second message type FloatArray.msg defined as:
FloatList[] lists
Then your function could look like:
def callback(req):
client = MongoClient()
db = client.block
lon = np.float64(req.b)
lat = np.float64(req.a)
point_list = my_function(lon, lat, db)
float_array = FloatArray()
for i in range(len(point_list)):
float_list = FloatList()
float_list.elements = point_list[i]
float_array.lists[i] = float_list
pub.publish(float_array)
And then you can unpack it with:
def unpack_callback(float_array_msg):
for lst in float_array_msg.lists:
for e in lst.elements:
print "Here is an element: %f" % e
In general, it is recommended you put ROS related questions on the ROS Forums since you are way more likely to get an answer to your question there.
You can complicate yourself by defining a new ros Type in the msg OR use the default and easy to implement std_msgs Type, maybe will be useful to use a json module, so you serialize the data before publishing and deserialize it back on the other side after receiving...
the rest Pub/Sub , topic and handlers remain the same :)
I agree with the solution, I thought about organizing it a bit more
Create a file FloatArray.msg in your catkin_ws in the src folder where you have all your other message files.
Build your env using catkin_make or catkin build.
In your script (e.g. Python script) import the message type and use it in the subscriber e.g.
joint_state_publisher_Unity = rospy.Publisher("/joint_state_unity", FloatArray , queue_size = 10)
specific case (bonus :)): if you are using Unity and ROS# build the message in Unity
I'm trying to set the mac address of the eth0 interface of a system on my cobbler server using the xmlrpcapi.
I can set simple fields like "comment", but I can't seem to set mac address, probably because I don't know the path to refer to. So this works:
handle = server.get_system_handle(system, token)
server.modify_system(handle, 'comment', 'my comment', token)
server.save_system(handle, token)
But if I want to set interfaces['eth0'][mac_address'] what property name do I use?
Found an example in the documentation that happens to show the creation of a new system:
server.modify_system(handle, 'modify_interface', {
'macaddress-eth0': args.mac
}, token)
I'm still not sure of a generic way though to determine what the path is to various properties, just got lucky with this example
I actually had to work around this same issue when developing the prov utility we use internally at Wolfram. I'm not sure why Cobbler's data representation isn't bidirectional. I effectively do the following:
system_name = '(something)' # The name of the system.
system_data = {} # The desired final state of the system data here.
# Pull out the interfaces dictionary.
if 'interfaces' in system_data:
interfaces = system_data.pop('interfaces')
else:
interfaces = {}
# Apply the non-interfaces data.
cobbler_server.xapi_object_edit('systems', system_name, 'edit', system_data, self.token)
# Apply interface-specific data.
handle = cobbler_server.get_system_handle(system_name, self.token)
ninterfaces = {}
for iname, ival in interfaces.items():
for k, v in ival.items():
if k in ['dns_name', 'ip_address', 'mac_address']:
if v:
ninterfaces[k.replace('_', '') + '-' + iname] = v
else:
ninterfaces[k + '-' + iname] = v
cobbler_server.modify_system(
handle,
'modify_interface',
ninterfaces,
self.token
)
cobbler_server.save_system(handle, self.token)
going off of the suggestion by abarnert in Python: Change Windows 7 master volume
I'm trying to write a python script to control the master volume in windows 7
I understand that in C++ this can be done like so:
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
mmde = CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pEnumerator);
mmd = mmde.GetDefaultAudioEndpoint(eRender, eMultimedia);
mgr = mmd.Activate(IID_IAudioSessionManager);
sav = mgr.GetSimpleAudioVolume(None, True);
sav.SetMasterVolume(0.5);
I'm trying to get that functionality in python using pywin32, but I find myself stuck. The code I have so far is:
import pythoncom
CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator)
IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator)
mmde = pythoncom.CoCreateInstance(CLSID_MMDeviceEnumerator, None, CLSCTX_ALL, IID_IMMDeviceEnumerator)
mmd = mmde.GetDefaultAudioEndpoint(eRender, eMultimedia)
mgr = mmd.Activate(IID_IAudioSessionManager)
sav = mgr.GetSimpleAudioVolume(None, True)
sav.SetMasterVolume(0.5)
CoCreateInstance wants the class ID (CLSID) of the MMDeviceEnumerator, but doesn't seem to have any function like __uuidof() to use to get the class ID. (Not that I could find anyway.)
Does anyone have any ideas / suggestions? I'm new to both COM/OLE programming and pywin32 and feeling a little lost.
From the documentation
PyIUnknown = CoCreateInstance(clsid, unkOuter , context , iid )
where
clsid : PyIID
Class identifier (CLSID) of the object
A PyIID object is used whenever a COM GUID is used. PyIID objects can be created using the pywintypes.IID() function, although all functions that accept a GUID also accept a string in the standard GUID format.
PyIID = IID(iidString, is_bytes )
where iidString is a string representation of an IID, or a ProgID.
MMDeviceEnumerator CLSID is BCDE0395-E52F-467C-8E3D-C4579291692E
so try this
PyIID = IID("BCDE0395-E52F-467C-8E3D-C4579291692E", is_bytes )
I've been trying to unpickle some dictionaries from the database. I've reverted to using the marshal module, but was still wondering why pickle is having such a difficult time unserializing some data. Here is a command line python session showing essentially what I am trying to do:
>>> a = {'service': 'amazon', 'protocol': 'stream', 'key': 'lajdfoau09424jojf.flv'}
>>> import pickle; import base64
>>> pickled = base64.b64encode(pickle.dumps(a))
>>> pickled
'KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu'
>>> unpickled = pickle.loads(base64.b64decode(pickled))
>>> unpickled
{'protocol': 'stream', 'service': 'amazon', 'key': 'lajdfoau09424jojf.flv'}
>>> unpickled['service']
'amazon'
This works all fine, but when I try this inside of a factory method for a class, it seems like the pickle.loads part errors out. The strings I am trying to load are pickled the same way as above. I've even tried copying the exact string that is pickled in the command line session above and just trying to unpickle that, but with no success. Here is the code for this latter attempt:
class Resource:
_service = 'unknown'
_protocol = 'unknown'
_key = 'unknown'
'''
Factory method that creates an appropriate instance of one of Resource’s subclasses based on
the type of data provided (the data being a serialized dictionary with at least the keys 'service',
'protocol', and 'key').
#param resource_data (string) -- the data used to create the new Resource instance.
'''
#staticmethod
def resource_factory(resource_data):
# Unpack the raw resource data and then create the appropriate Resource instance and return.
resource_data = "KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu" #hack to just see if we can unpickle this string
logging.debug("Creating resource: " + resource_data)
unencoded = base64.b64decode(resource_data)
logging.debug("Unencoded is: " + unencoded)
unpacked = pickle.loads(unencoded)
logging.debug("Unpacked: " + unpacked)
service = unpacked['service']
protocol = unpacked['protocol']
key = unpacked['key']
if (service == 'amazon'):
return AmazonResource(service=service, protocol=protocol, key=key)
elif (service == 'fs'):
return FSResource(service=service, protocol=protocol, key=key)
Your code works. How are you testing it?
import logging
import base64
import pickle
class Resource:
#staticmethod
def resource_factory(resource_data):
resource_data = "KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu" #hack to just see if we can unpickle this string
# logging.debug("Creating resource: " + resource_data)
unencoded = base64.b64decode(resource_data)
# logging.debug("Unencoded is: " + unencoded)
unpacked = pickle.loads(unencoded)
logging.debug("Unpacked: " + repr(unpacked))
service = unpacked['service']
protocol = unpacked['protocol']
key = unpacked['key']
logging.basicConfig(level=logging.DEBUG)
Resource.resource_factory('')
yields
# DEBUG:root:Unpacked: {'protocol': 'stream', 'service': 'amazon', 'key': 'lajdfoau09424jojf.flv'}
I was able to solve this after making some simplifications and then debugging in django. The main issue was that there were some errors in the Resource class itself that were preventing the correct completion of the resource_factory method. First, I was trying to concatenate a string and dictionary, which was throwing an error. I also had some errors elsewhere in the class where I was referring to the instance variables _service, _protocol, and key withouth the '' (typos).
In any case, the interesting thing was that when I used this code within Django's custom field infrastructure, the errors would get caught and I did not see any actual message indicating the problem. The debug statements suggested it was a problem with loads, but actually it was a problem with the debug statement itself and some code that came later. When I tried to implement this behavior using model properties instead of custom model fields for the data I was saving, the errors actually got printed out correctly and I was able to quickly debug.
I'm trying to use a feature of the Microsoft WinHttp library that has been exposed by the developers of Win32com. Unfortunately most of the library does not seem to be documented and there are no example of the correct way to use the win32inet features via the win32com library.
This is what I have so far:
import win32inet
hinternet = win32inet.InternetOpen("foo 1.0", 0, "", "", 0)
# Does not work!!!
proxy = win32inet.WinHttpGetProxyForUrl( hinternet, u"http://www.foo.com", 0 )
As you can see, all I am trying to do is use the win32inet feature to find out which proxy is the appropriate one to use for a given URL, int his case foo.com.
Can you help me correct the syntax of the last line? MSN has some good documentation for the function being wrapped but the args do not seem to map the to those of the python library perfectly.
The fixed version of this script should:
Be able to look up which proxy to use
for any given URL.
It should always do exactly what Internet Explorer would do (i.e. use the same proxy)
It should be valid on any valid Windows XP set-up. That means it should work with an explicitly configured proxy and also no proxy at all.
It only needs to work on Windows XP 32bit with Python 2.4.4. It can use any official released version of win32com.
I'm using Python2.4.4 with Win32Com on Windows XP.
UPDATE 0:
OR... can you give me an alternative implementation in cTypes? As long as I can make it work I'm happy!
Here is the code which creates HINTERNET session and uses that to get proxy details, using ctypes to directly access winhttp DLL.
It works without any error but I have no proxy set on my machine, you may have to tweak few constants to get it right. Go thru the msdn links in code, from where I have seen the API.
import ctypes
import ctypes.wintypes
winHttp = ctypes.windll.LoadLibrary("Winhttp.dll")
# http://msdn.microsoft.com/en-us/library/aa384098(VS.85).aspx
# first get a handle to HTTP session
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY=0
WINHTTP_NO_PROXY_NAME=WINHTTP_NO_PROXY_BYPASS=0
WINHTTP_FLAG_ASYNC=0x10000000
HINTERNET = winHttp.WinHttpOpen("PyWin32", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC)
print HINTERNET
# now get proxy using HTTP session
# http://msdn.microsoft.com/en-us/library/aa384097(VS.85).aspx
"""
BOOL WinHttpGetProxyForUrl(
__in HINTERNET hSession,
__in LPCWSTR lpcwszUrl,
__in WINHTTP_AUTOPROXY_OPTIONS *pAutoProxyOptions,
__out WINHTTP_PROXY_INFO *pProxyInfo
);
"""
# create C structure for WINHTTP_AUTOPROXY_OPTIONS
#http://msdn.microsoft.com/en-us/library/aa384123(VS.85).aspx
"""
typedef struct {
DWORD dwFlags;
DWORD dwAutoDetectFlags;
LPCWSTR lpszAutoConfigUrl;
LPVOID lpvReserved;
DWORD dwReserved;
BOOL fAutoLogonIfChallenged;
} WINHTTP_AUTOPROXY_OPTIONS;
"""
class WINHTTP_AUTOPROXY_OPTIONS(ctypes.Structure):
_fields_ = [("dwFlags", ctypes.wintypes.DWORD),
("dwAutoDetectFlags", ctypes.wintypes.DWORD),
("lpszAutoConfigUrl", ctypes.wintypes.LPCWSTR),
("lpvReserved", ctypes.c_void_p ),
("dwReserved", ctypes.wintypes.DWORD),
("fAutoLogonIfChallenged",ctypes.wintypes.BOOL),]
WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001;
WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001;
WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002;
options = WINHTTP_AUTOPROXY_OPTIONS()
options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT
options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP|WINHTTP_AUTO_DETECT_TYPE_DNS_A
options.lpszAutoConfigUrl = 0
options.fAutoLogonIfChallenged = False
# create C structure for WINHTTP_AUTOPROXY_OPTIONS
# http://msdn.microsoft.com/en-us/library/aa383912(VS.85).aspx
"""
struct WINHTTP_PROXY_INFO {
DWORD dwAccessType;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
};
"""
class WINHTTP_PROXY_INFO(ctypes.Structure):
_fields_ = [("dwAccessType", ctypes.wintypes.DWORD),
("lpszProxy", ctypes.wintypes.LPCWSTR),
("lpszProxyBypass", ctypes.wintypes.LPCWSTR),]
info = WINHTTP_PROXY_INFO()
ret = winHttp.WinHttpGetProxyForUrl(HINTERNET, "http://www.google.com", ctypes.pointer(options), ctypes.pointer(info) )
print "proxy success?",ret
if not ret:
# some error lets see what is that?
import win32api
import win32con
errorCode = win32api.GetLastError()
print "win32 Error:",errorCode
s = ""
print win32api.FormatMessage(errorCode)
print info.dwAccessType, info.lpszProxy, info.lpszProxyBypass
Unless there is a strong reason for using win32inet (which is messy in this area due to limitations of SWIG), I recommend that you use ctypes instead.
At least with Python 2.7.6 and Pywin 218 on Windows XP x86 and Windows 8 x64, it works:
import win32inet
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa384098(v=vs.85).aspx
hinternet = win32inet.WinHttpOpen("foo", 0, "", "", 0)
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa384123(v=vs.85).aspx
autoproxy_options = (2, 0, u"http://your-proxy-script-path", None, 0, 1)
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa384097(v=vs.85).aspx
proxy = win32inet.WinHttpGetProxyForUrl(hinternet, u"http://www.google.com",
autoproxy_options)
print proxy
Worth to mention that the example uses the autoproxy option WINHTTP_AUTOPROXY_CONFIG_URL in order to pass in an explicit URL. You can use other options, for instance, if you want to autodetect using DNS or DHCP you can do:
autoproxy_options = (1, 1|2, u"", None, 0, 1)
You can find other options in the link showed above (in the code)