Register a Bluetooth agent with Python DBus to hci1 (not hci0) - bluez

I have been using copy, paste, and magic to register a Bluetooth agent via Python DBUs which works great for hci0, but I cannot for the life of me see how I can get this agent to work for other Bluetooth controllers, i.e hci1. I have tried selecting the controller and setting it as default in bluetoothctl and other side channels.
Can someone please show me where the agent is associated with the controller. This is all too magical.
I am also unable to find the agent or anything on it with D-Feet - How should or could I find it please?
A dumb toy example is as:
import dbus
import dbus.service
AGENT_PATH = "/org/bluez/anAgent"
class Agent(dbus.service.Object):
#dbus.service.method(AGENT_INTERFACE,
in_signature="os", out_signature="")
def AuthorizeService(self, device, uuid):
print("Some stuff and things")
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
capability = "DisplayYesNo"
agent = Agent(bus, AGENT_PATH)
obj = bus.get_object("org.bluez", "/org/bluez")
# Create the agent manager
manager = dbus.Interface(obj, "org.bluez.AgentManager1")
manager.RegisterAgent(AGENT_PATH, capability)
manager.RequestDefaultAgent(AGENT_PATH)

When Bluetooth needs an agent it looks at the org.bluez.AgentManager1 interface at the /org/bluez D-Bus object path for the location of the agent that has been registered. It then calls the relevant method on the org.bluez.Agent1 interface at that registered object path (/org/bluez/anAgent in your example). The methods that need to be implemented for the org.bluez.Agent1 interface are documented at:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/agent-api.txt
There is only one agent irrespective of how many adapters there are on your system.
Could the issue be that the device being paired is associated with the "wrong" adapter?
The Device API has an Adapter property which tracks the object path of the adapter the device belongs to.
To find the agent that you have created it can be useful to use busctl. Using busctl list will list all the available SystemBus services. As you are not claiming a bus name for the agent it will be anonymous so in the format of :x.xxx. This can be a long list so busctl list | grep python is what I usually do to narrow the list down.
To introspect what was there you would do something like:
$ busctl introspect :1.174 /org/bluez/anAgent
To test the agent service that has been published:
$ busctl call :1.174 /org/bluez/anAgent org.bluez.Agent1 AuthorizeService os /org/bluez/hci1/dev_12_34_56_78 1234
This service will need to be asynchronous so you will need to start the MainLoop event loop.
Below is a full example of creating an Agent using pydbus D-Bus bindings.
The only place that the adapter is mentioned is the instruction to start discovery.
If you had another device trying to discover your device with the agent, then it will depend on which adapter is discoverable and/or the other device tries to connect to.
import threading
import pydbus
from gi.repository import GLib
BUS_NAME = 'org.bluez'
AGENT_IFACE = 'org.bluez.Agent1'
AGNT_MNGR_IFACE = 'org.bluez.AgentManager1'
ADAPTER_IFACE = 'org.bluez.Adapter1'
AGENT_PATH = '/org/bluez/anAgent'
AGNT_MNGR_PATH = '/org/bluez'
DEVICE_IFACE = 'org.bluez.Device1'
CAPABILITY = 'KeyboardDisplay'
bus = pydbus.SystemBus()
class Agent:
"""
<node>
<interface name="org.bluez.Agent1">
<method name="Release" />
<method name="RequestPinCode">
<arg name="device" direction="in" type="o" />
<arg name="pincode" direction="out" type="s" />
</method>
<method name="DisplayPinCode">
<arg name="device" direction="in" type="o" />
<arg name="pincode" direction="in" type="s" />
</method>
<method name="RequestPasskey">
<arg name="device" direction="in" type="o" />
<arg name="passkey" direction="out" type="u" />
</method>
<method name="DisplayPasskey">
<arg name="device" direction="in" type="o" />
<arg name="passkey" direction="in" type="u" />
<arg name="entered" direction="in" type="q" />
</method>
<method name="RequestConfirmation">
<arg name="device" direction="in" type="o" />
<arg name="passkey" direction="in" type="u" />
</method>
<method name="RequestAuthorization">
<arg name="device" direction="in" type="o" />
</method>
<method name="AuthorizeService">
<arg name="device" direction="in" type="o" />
<arg name="uuid" direction="in" type="s" />
</method>
<method name="Cancel" />
</interface>
</node>
"""
def Release(self):
print('Release')
def RequestPinCode(self, device):
print('RequestPinCode', device)
return '1234'
def DisplayPinCode(self, device, pincode):
print('DisplayPinCode', device, pincode)
def RequestPasskey(self, device):
print('RequestPasskey', device)
return 1234
def DisplayPasskey(self, device, passkey, entered):
print('DisplayPasskey', device, passkey, entered)
def RequestConfirmation(self, device, passkey):
print('RequestConfirmation', device, passkey)
def RequestAuthorization(self, device):
print('RequestAuthorization', device)
def AuthorizeService(self, device, uuid):
print('AuthorizeService', device, uuid)
def Cancel(self):
return
def pair_reply(*args):
print('reply', args)
def pair_error(*args):
print('error', args)
def dbus_path_up(dbus_obj):
return '/'.join(dbus_obj.split('/')[:-1])
def device_found(dbus_obj, properties):
adapter = bus.get(BUS_NAME, dbus_path_up(dbus_obj))
device = bus.get(BUS_NAME, dbus_obj)
print('Stopping discovery')
adapter.StopDiscovery()
if device.Paired:
device.Connect()
else:
print('Pairing procedure starting...')
device.Pair()
def interface_added(path, ifaces):
if DEVICE_IFACE in ifaces.keys():
dev_name = ifaces[DEVICE_IFACE].get('Name')
print('Device found:', dev_name)
if dev_name == 'HC-06':
device_found(path, ifaces[DEVICE_IFACE])
def publish_agent():
bus.register_object(AGENT_PATH, Agent(), None)
aloop = GLib.MainLoop()
aloop.run()
print('Agent Registered')
def create_agent():
thread = threading.Thread(target=publish_agent, daemon=True)
thread.start()
print('Agent running...')
def my_app(hci_idx=0):
adapter_path = f'/org/bluez/hci{hci_idx}'
mngr = bus.get(BUS_NAME, '/')
mngr.onInterfacesAdded = interface_added
create_agent()
agnt_mngr = bus.get(BUS_NAME, AGNT_MNGR_PATH)[AGNT_MNGR_IFACE]
agnt_mngr.RegisterAgent(AGENT_PATH, CAPABILITY)
print('Agent registered...')
adapter = bus.get(BUS_NAME, adapter_path)
# adapter.StartDiscovery()
mainloop = GLib.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
adapter.StopDiscovery()
if __name__ == '__main__':
my_app()

Related

WSO2 ESB property incorrect scope

I have next sequence:
<payloadFactory>
<format>
<cb:accounts/>
</format>
<args/>
</payloadFactory>
<property name="accounts" type="OM" expression="//cb:accounts" />
...
<iterate id="accountIterator" continueParent="true" sequential="true" expression="//cb:accounts/cb:accountId">
<target>
<sequence>
...
<property name="accounts" type="OM" expression="//*" />
</sequence>
</target>
</iterate>
<aggregate id="accountIterator">
<onComplete expression="$body/child::*[fn:position()=1]">
<log level="custom" />
</onComplete>
</aggregate>
<enrich>
<source type="custom" xpath="get-property('accounts')"/>
<target type="body" />
</enrich>
Why property named "accounts" which was set inside "iterate" mediator has null value outside "iterate" mediator ?
Thanks
The flow inside the iterator runs on a separate thread and it is not visible out side. Therefore you can't access a property which is set inside the iterator mediator, outside but vice versa is possible.
Before calling each iteration cycle message context will be cloned and it will only be available in the context inside iterator target. Hence, by default can not get the things doing in synapse/default scope outside the iterator. If you want to store something global, use property with operation scope.
Before iterator assign your property to operation scope
Inside iterator - do modifications
Outside the iterator - assign your property to default scope (if you want to take it back to default scope)
use below structure for example:
<!--assign your property to operation scope-->
<property name="ITERATOR_DATA_PAYLOAD"
expression="get-property('DATA_PAYLOAD')"
scope="operation"
type="OM"/>
<iterate xmlns:ns="http://org.apache.synapse/xsd"
continueParent="true"
expression="//bookstore/book"
sequential="true">
<target>
<sequence>
<!--if you want to assign the property-->
<property name="DATA_PAYLOAD"
expression="get-property('operation','ITERATOR_DATA_PAYLOAD')"
type="OM"/>
</sequence>
</target>
</iterate>
<!--Outside the iterator-->
<property xmlns:ns="http://org.apache.synapse/xsd"
name="NEW_DATA_PAYLOAD"
expression="get-property('operation','ITERATOR_DATA_PAYLOAD')"
type="OM"/>

Error at server side while executing dss query

I'm using wso2dss 3.1.0 and wso2esb 4.7.0.I wish to fire select from esb.I have write select query in dss and dbs for this is like :
<query id="Capp_select_emercontactid" useConfig="default">
<sql>select userid,mailid,phonenumber from muser where phonenumber = ? or mailid = ?</sql>
<result element="Entries" rowName="Entry">
<element column="userid" name="userid" xsdType="string"/>
<element column="mailid" name="mailid" xsdType="string"/>
<element column="phonenumber" name="phonenumber" xsdType="string"/>
</result>
<param name="phonenumber" ordinal="1" sqlType="STRING"/>
<param name="mailid" ordinal="2" sqlType="STRING"/>
</query>
<operation disableStreaming="true" name="Capp_select_emercontactid_op">
<call-query href="Capp_select_emercontactid">
<with-param name="phonenumber" query-param="phonenumber"/>
<with-param name="mailid" query-param="mailid"/>
</call-query>
</operation>
It's working fine in dss.
Now i have write a payload in esb like :
<payloadFactory>
<format>
<p:Capp_select_emercontactid_op xmlns:p="http://ws.wso2.org/dataservice">
<p:phonenumber>$1</p:phonenumber>
<p:mailid>$2</p:mailid>
</p:Capp_select_emercontactid_op>
</format>
<args>
<arg expression="get-property('phoneno1')" evaluator="xml"/>
<arg expression="get-property('mailid1')" evaluator="xml"/>
</args>
</payloadFactory>
<log level="full"/>
<send>
<endpoint>
<address uri="http://localhost:9764/services/Capp_MuserDataservice/" format="soap11"/>
</endpoint>
</send>
When i'm hiting this proxy it didn't give responce..Why so?Is it correct configuration?Please let me know
I never had any luck using the send mediator with the DSS. Could you consider using the CalloutMediator instead (it's a synchronous send/response call so you may need to use a respond mediator after if you're wanting an immediate response to your client).
It'd look something like:
<callout xmlns="http://ws.apache.org/ns/synapse" action="Capp_select_emercontactid_op">
<source xmlns:p="http://ws.wso2.org/dataservice" xpath="//p:Capp_select_emercontactid_op"/>
<target xmlns:p="http://ws.wso2.org/dataservice" xpath="//p:Capp_select_emercontactid_op"/>
</callout>

Image upload component for OpenLaszlo with drag & drop support and preview

I haven't seen any good file upload component for OpenLaszlo. Is there an open source version of a file upload component, which supports drag & drop for DHTML and Adobe AIR, and a preview functionality for both runtimes?
Technically it is possible to support the following features:
drag and drop file upload in DHTML for all desktop browsers http://caniuse.com/#feat=dragndrop
preview of images for Webkit browsers and Firefox in DHTML, and for all browsers using a SWF runtime
drag and drop support for Adobe Air applications
Maybe someone has an existing component which could be made open source, and maintained or improved by the community.
There is currently no way to do a File Upload in DHTML (aka HTML5) mode of an OpenLaszlo application since unfortunately there is no way to set the form type to enctype=multipart/form-data in that run-time.
However, you can do a File Upload with the SWF(Flash) mode of an OpenLaszlo application by accessing the low-level Flash API. It is not obvious how to do this so I wrote a class to do this myself a while back, it will work under (Flash) SWF8, SWF9 and SWF10 mode of OpenLaszlo.
I have never tried compiling an OpenLaszlo application to AIR but I believe the Flash Upload will probably work for that case too.
Here is my class, feel free to use it:
( The code is also avaiable here: http://forum.openlaszlo.org/showthread.php?t=14566&highlight=fileReference )
<library>
<switch>
<when property="$as3"><!-- SWF9/SWF10 -->
<!---
CLASS: <fileuploadhelper>
EXTENDS: <node> (lz.node)
DESCRIPTION:
This is the ActionScript3 (AS3) (SWF9/SWF8) version of the Flash file
upload object.
This allows users to upload files when compiled to a Flash Version that
uses ActionScript3 such as Flash 9 or Flash 10.
-->
<class name="fileuploadhelper" extends="node">
<!---
#param string uploadurl: (optional) default upload url to use if none
passed to this.upload()
-->
<attribute name="uploadurl" type="string" />
<!-- #keywords private -->
<!--- #param flash.net.FileReference file_reference: Flash file reference object -->
<attribute name="file_reference" type="expression" value="null" />
<!-- Imports Required for SWF9/SWF10 -->
<passthrough>
import flash.net.FileReference;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLRequest;
</passthrough>
<!-- *** METHODS *** -->
<handler name="oninit">
<![CDATA[
#passthrough {
this.file_reference = new FileReference();
file_reference.addEventListener(Event.SELECT,this.onSelect);
file_reference.addEventListener(Event.COMPLETE, this.onComplete);
file_reference.addEventListener(ProgressEvent.PROGRESS, this.progressHandler);
file_reference.addEventListener(IOErrorEvent.IO_ERROR, this.ioErrorHandler);
file_reference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.securityErrorHandler);
}#
]]>
</handler>
<!---
Displays file browsing window and allows the user to select a file (or
cancel to close the window).
-->
<method name="browse">
<![CDATA[
#passthrough {
file_reference.browse();
}#
]]>
</method>
<!---
Return name of selected file
#returns string: the filename of the selected file
-->
<method name="getName">
return this.file_reference.name;
</method>
<!--- #keywords private -->
<!---
#param string submit_url: SWF9/10 #passthrough{...} requires URL to be
referenced in an attribute rather than a
locally defined OpenLaszlo variable or
a compilation error occurs.
-->
<attribute name="submit_url" type="string" />
<!---
Uploads the currently selected file.
#param string strURL: (optional) If defined upload the file to this
URL, otherwise upload to this.uploadurl
Note: required if this.uploadurl is not defined.
-->
<method name="upload" args="strURL = false">
<![CDATA[
if (strURL === false)
var strURL = this.uploadurl; // workaround for SWF9/10 compatibility
this.setAttribute('submit_url', strURL);
#passthrough {
var request:URLRequest = new URLRequest(submit_url);
file_reference.upload(request);
}#
]]>
</method>
<!-- * ABSTRACT handlers: Override to do something useful in instance * -->
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when user selects a file.
#param flash.events.Event ev: the select event
-->
<method name="onSelect" args="ev=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onSelect(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when progress event is captured.
#param {anything} objDummy: SWF8 requires file_reference object here, does nothing in SWF9/10
#param number bytesLoaded: the number of bytes of the file uploaded
#param number bytesTotal: the number of total bytes of the file to be uploaded
-->
<method name="onProgress" args="objDummy, bytesLoaded, bytesTotal">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onProgress(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when a file upload is complete.
#param flash.events.Event ev: the complete event
-->
<method name="onComplete" args="ev=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onComplete(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when the file upload fails.
#param flash.events.IOErrorEvent/flash.events.securityErrorEvent ev: the Flash Error Event
-->
<method name="onError" args="ev=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onError(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!-- * Internal Private Handlers * -->
<!--- #keywords private -->
<!---
This will pass the progress values to method this.onProgress()
#param flash.events.ProgressEvent ev: the Flash Progress Event
-->
<method name="progressHandler" args="ev=null">
this.onProgress(false, ev.bytesLoaded, ev.bytesTotal);
</method>
<!--- #keywords private -->
<!---
This will catch an ioError and call method this.onError()
#param flash.events.IOErrorEvent ev: the Flash Error Event
-->
<method name="ioErrorHandler" args="ev=null">
if ($debug) Debug.error('as3 (SWF9/10): fileuploadhelper.ioErrorHandler(): ERROR: ioError detected, could not upload file.');
this.onError(ev);
</method>
<!--- #keywords private -->
<!---
This will catch a securityError and call method this.onError()
#param flash.events.securityErrorEvent ev: the Flash Error Event
-->
<method name="securityErrorHandler" args="ev=null">
if ($debug) Debug.error('as3 (SWF9/10): fileuploadhelper.securityErrorHandler(): ERROR: securityError detected. Are you sure you are uploading to same domian as this application is being served from?');
this.onError(ev);
</method>
</class>
</when>
<when property="$as2"><!-- SWF8 -->
<!---
CLASS: <fileuploadhelper>
EXTENDS: <node> (lz.node)
DESCRIPTION:
This is the ActionScript2(AS2) (SWF8) version of the Flash file
upload object.
This allows users to upload files when compiled to a Flash Version that
uses ActionScript2 such as Flash 8
-->
<class name="fileuploadhelper" extends="node">
<!---
#param string uploadurl: (optional) default upload url to use if none
passed to this.upload()
-->
<attribute name="uploadurl" />
<!--- #keywords private -->
<!--- #param flash.net.FileReference file_reference: Flash file reference object -->
<attribute name="file_reference" />
<!-- *** METHODS *** -->
<handler name="oninit" args="invoker">
fr = new flash.net.FileReference();
this.setAttribute('file_reference', fr);
fr.addListener(invoker);
</handler>
<!-- *** METHODS *** -->
<!---
Displays file browsing window and allows the user to select a file (or
cancel to close the window).
-->
<method name="browse">
this.file_reference.browse();
</method>
<!---
Return name of selected file
#returns string: the filename of the selected file
-->
<method name="getName">
return this.file_reference.name;
</method>
<!---
Uploads the currently selected file.
#param string strURL: (optional) If defined upload the file to this
URL, otherwise upload to this.uploadurl
Note: required if this.uploadurl is not defined.
-->
<method name="upload" args="strURL">
if (strURL == null)
var strURL = this.uploadurl;
this.file_reference.upload(strURL);
</method>
<!-- * ABSTRACT HANDLERS * -->
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when user selects a file.
#param flash.events.Event ev: the select event
-->
<method name="onSelect" args="ev=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onSelect(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when progress event is captured.
#param flash.net.fileReference fr: file_reference object here
#param number bytesLoaded: the number of bytes of the file uploaded
#param number bytesTotal: the number of total bytes of the file to be uploaded
-->
<method name="onProgress" args="fr, bytesLoaded, bytesTotal">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onProgress(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when a file upload is complete.
#param flash.events.Event fr: the file_reference object
-->
<method name="onComplete" args="fr=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onComplete(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when the file upload fails.
#param flash.events.Event fr: the file_reference object
-->
<method name="onError" args="fr=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onError(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
</class>
</when>
</switch>
</library>
Note: This works similar to an HTML form where you post the file upload to a receiving script on the backend (could be in PHP, ASP, etc.) which would process the file and store it somewhere, there are many tutorials on the web on how to do that so I have not included it. As for drag and drop and preview you would have to write a fairly complicated application in OpenLaszlo yourself to do this, I suggest you view the tutorials and OpenLaszlo documentation to learn how to do that.

Problems with WCF deserialising SOAP array containing polymorphic objects

I have a problem with a WCF web services that is deserialising an array of polymorphic objects. The server side is not WCF, but I created the stubs from WSDL. The important parts in WSDL are
<complexType name="NodeList">
<sequence>
<element name="data" type="cmtypes:Node" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
</sequence>
</complexType>
and
<complexType name="Device">
<sequence>
<element name="uniqueKey" type="xsd:unsignedLong" minOccurs="1" maxOccurs="1"/>
<element name="revision" type="xsd:string" minOccurs="1" maxOccurs="1"/>
[...}
</sequence>
</complexType>
<complexType name="Node">
<complexContent>
<extension base="cmtypes:Device">
<sequence>
<element name="cmdaemonUrl" type="xsd:string" minOccurs="1" maxOccurs="1"/>
<element name="networks" type="cmtypes:NetworkInterfaceList" minOccurs="0" maxOccurs="1" nillable="true"/>
[...]
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="MasterNode">
<complexContent>
<extension base="cmtypes:Node">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
VS created the following type for the list:
[System.Xml.Serialization.SoapIncludeAttribute(typeof(MasterNode))]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(SlaveNode))]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(VirtualSMPNode))]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(VirtualNode))]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(PhysicalNode))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.233")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace="http://www.brightcomputing.com/cmtypes.xsd")]
public partial class Node : Device {
private string cmdaemonUrlField;
[...]
}
However, if I receive a message containing a master node like
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cmtypes="http://www.brightcomputing.com/cmtypes.xsd" xmlns:cmdevice="http://www.brightcomputing.com/cmdevice.wsdl">
<s:Header xmlns:s="http://www.w3.org/2003/05/soap-envelope"></s:Header>
<SOAP-ENV:Body>
<cmdevice:getNodesResponse SOAP-ENV:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<nodes xsi:type="cmtypes:NodeList" xmlns="">
<data xsi:type="cmtypes:MasterNode">
<uniqueKey xsi:type="xsd:unsignedLong">38654705666</uniqueKey>
<revision xsi:type="xsd:string"></revision>
<modified xsi:type="xsd:boolean">false</modified>
<toBeRemoved xsi:type="xsd:boolean">false</toBeRemoved>
[...]
the whole stuff explodes with a System.ServiceModel.CommunicationException saying "Error in deserializing body of reply message for operation 'getNodes'." and "Object cannot be stored in an array of this type." in the inner exception. Why? What can I do to fix this (the stub generation)?
I have absolutely no clue due to very limited WCF/SOAP knowledge, so any help is appreciated.
Best regards,
Christoph
Edit: It might be relevant that the response actually contains "data" elements of different, polymorphic types, i.e. cmtypes:MasterNode and cmtypes:PhysicalNode.
Edit: Could it be that the Stub and the Message do not go together? As I understand, the stub expects a data property, which is an array:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.233")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace="http://www.brightcomputing.com/cmtypes.xsd")]
public partial class NodeList : object, System.ComponentModel.INotifyPropertyChanged {
private Node[] dataField;
/// <remarks/>
[System.Xml.Serialization.SoapElementAttribute(IsNullable=true)]
public Node[] data {
get {
return this.dataField;
}
set {
this.dataField = value;
this.RaisePropertyChanged("data");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
However, in my answer I get a NodeList directly containing a sequence of data elements, which are actually nodes or derived from nodes:
<cmdevice:getNodesResponse SOAP-ENV:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<nodes xsi:type="cmtypes:NodeList" xmlns="">
<data xsi:type="cmtypes:MasterNode">
<uniqueKey xsi:type="xsd:unsignedLong">38654705666</uniqueKey>
[...]
</data>
<data xsi:type="cmtypes:PhysicalNode">
<uniqueKey xsi:type="xsd:unsignedLong">38654705669</uniqueKey>
[...]
</data>
[...]
Do you think I can fix that somehow by injecting a behavior in WCF? My big problem is that I have absolutely no possibility of chaning the server side...
Troubleshooting this is going to be hard. One thing I would try is using XmlSerializer to see if it can deserialize then start reducing the message until you get the offending type.

GUI using Pygtk and glade

i am trying to build a GUI using pygtk and glade on Windows. I am a noob at python GUI building so please excuse my noobness. I Looked up this tutorial and did exactly as it said. The only difference was that I am on Windows 7 Home Premium x64 .
I put a Label and a button in a window using glade as in the tutorial and then i got a libglade xml file. Then i typed the following code
import sys
import pygtk
import gtk
import gtk.glade
pygtk.require("2.0")
class HellowWorldGTK:
def __init__(self):
#Set the Glade file
self.gladefile = "Hello_World.glade"
self.wTree = gtk.glade.XML(self.gladefile)
#Get the Main Window, and connect the "destroy" event
self.window = self.wTree.get_widget("MainWindow")
if (self.window):
self.window.connect("destroy", gtk.main_quit)
if __name__ == "__main__":
hwg = HellowWorldGTK()
gtk.main()
I put both the files in the same folder and then i run a python interpreter from the command line into the folder.Apparently The program runs but the thing is that i'm unable to get the interface all i get on the command line is that that the Program is running. I dont even get an error or something.Is it due to the fact that i'm on Windows?? I thought that GTK was cross-platform and the same code should run on windows as well as on Linux??
Also here is the .glade file generated by GLADE GUI designer
<?xml version="1.0" encoding="UTF-8"?>
<glade-interface>
<!-- interface-requires gtk+ 2.24 -->
<!-- interface-naming-policy project-wide -->
<widget class="GtkWindow" id="Hello world!">
<property name="can_focus">False</property>
<property name="resizable">False</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<widget class="GtkLabel" id="Click Here!">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="Please Click on the Button!">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
self.window.show()
At the end of __init__ should do it I think.
EDIT AFTER COMMENT...
self.window = self.wTree.get_widget("MainWindow")
but there is no window called "MainWindow", I think you've called your window "Hello world!", try loading that instead (or renaming your window in glade).
It may be a good idea to check that your window is actially found in the glade file as well.
window_name="Hello World!"
self.window = self.wTree.get_widget(window_name)
if (self.window):
self.window.connect("destroy", gtk.main_quit)
else:
raise Exception("I couldn't find the window called "+window_name+"!")