Menu

Probe-Listener

Help
Robert B.
2014-05-28
2014-07-16
  • Robert B.

    Robert B. - 2014-05-28

    Hello dear community,

    Is it possible to implement a kind of listener for Probe-Messages? I touhgt of something like the helloReceived()-function. Or do I have to implement a extra Message-Listener in my Device-Class with a handle-function?

    Regards,
    Robert

     
  • Robert B.

    Robert B. - 2014-06-02

    I'm trying to implement my own IncomingMessageListener in my device-class now. It looks like this:

    private final class DPWSMessageListener extends DefaultIncomingMessageListener
    {
        public DPWSMessageListener(CredentialInfo credentialInfo)
        {    
            super(credentialInfo);
        }
    
        @Override
        public void handle(HelloMessage hello, ConnectionInfo connectionInfo)
        {
            //logRequest(hello);
        }
    
        @Override
        public void handle(ByeMessage bye, ConnectionInfo connectionInfo)
        {
            //logRequest(bye);
        }
    
        @Override
        public ProbeMatchesMessage handle(ProbeMessage probe, ConnectionInfo connectionInfo) throws SOAPException
        {
        }
        return null;
        }
    }
    

    How can I achieve to use this listener instead of the DeviceMessageListener?

     

    Last edit: Robert B. 2014-06-02
  • Jannis Müthing

    Jannis Müthing - 2014-06-04

    Hi Robert

    for this there is the MessageInformer. It takes a MessageListener and a MessageSelector to register to be informed about incoming/outgoing messages. The MessageSelector decides if the message will be delivered to the supplied MessageListener.

    Here is some sample code:

    public class Example {
    
        public static void main(String[] args) throws WS4DIllegalStateException, IOException {
            JMEDSFramework.start(null);
    
            Log.setLogLevel(Log.DEBUG_LEVEL_ERROR);
            DefaultDevice testDevice = new DefaultDevice(DPWSCommunicationManager.COMMUNICATION_MANAGER_ID);
            testDevice.start();
    
            MessageListener yourDPWSMessageListener = new DPWSMessageListener();
    
            // Registering our listener with a selector that only accepts Probe messages. There is also the
            // AllMessageSelector. It can be used when we want to receive all messages
            MessageInformer.getInstance().addMessageListener(yourDPWSMessageListener, new MessageSelector() {
    
                @Override
                public boolean matches(Message msg) {
                    return msg.getType() == MessageConstants.PROBE_MESSAGE;
                }
            });
        }
    }
    
    class DPWSMessageListener implements MessageListener {
    
        @Override
        public void receivedInboundMessage(Message msg, ConnectionInfo connectionInfo, AttributedURI optionalMessageId) {
            // Our message selector has already determined that the message is a probe
            Log.error("Received Probe Message: " + msg.toString());
        }
    
        @Override
        public void receivedOutboundMessage(Message msg, ConnectionInfo connectionInfo, AttributedURI optionalMessageId) {
            // we do not really care about those
        }
    }
    

    I hope this helps you.

    Best,

    Jannis

     

    Last edit: Jannis Müthing 2014-06-04
  • Robert B.

    Robert B. - 2014-06-06

    Hello Jannis,

    thank you very much! This advice was very helpful. But if I use the AllMessageSelector I don't get Hello-Messages, is that right? So I need the DefultClient with helloReceived, too.

    Regards
    Robert

     
  • Jannis Müthing

    Jannis Müthing - 2014-06-11

    Hi Robert!

    The MessageInformer only farwards all messages processed by JMEDS. Without anyone registered for hello message listening the stack will not process them and the message informer will not get its callback. So you could either make a default client and register it for hello listening:

    ...
            JMEDSFramework.start(null);
    
            Log.setLogLevel(Log.DEBUG_LEVEL_ERROR);
            DefaultDevice testDevice = new DefaultDevice("DPWS");
            testDevice.start();
    
            DefaultClient client = new DefaultClient();
            client.registerHelloListening();
    
            MessageListener yourDPWSMessageListener = new DPWSMessageListener();
    
            // Registering our listener with a selector that only accepts hello messages. There is also the
            // AllMessageSelector. It can be used when we want to receive all messages
            MessageInformer.getInstance().addMessageListener(yourDPWSMessageListener, new MessageSelector() {
    
                @Override
                public boolean matches(Message msg) {
                    return msg.getType() == MessageConstants.HELLO_MESSAGE;
                }
            });
    ...
    

    Or if you want to register yourself directly you could do it without going through the message informer. It is a little more code though:

    public class Example {
    
        public static void main(String[] args) throws WS4DIllegalStateException, IOException {
            JMEDSFramework.start(null);
    
            CommunicationManager communicationManager = CommunicationManagerRegistry.getCommunicationManager(DPWSCommunicationManager.COMMUNICATION_MANAGER_ID);
    
            // the default auto bindings from the communication manager
            DiscoveryAutoBinding discoveryAutobinding = communicationManager.getAutoBindingFactory().createDiscoveryMulticastAutobinding();
    
            // an autobinding keeps its listener informed about changes on the network. We only need the listener to get to the actual discovery bindings.
            Listener listener = new Listener();
            discoveryAutobinding.addAutoBindingListener(listener);
    
            // the message listener
            DefaultIncomingMessageListener helloReceiver = new DefaultIncomingMessageListener(null) {
    
                public void handle(HelloMessage hello, ConnectionInfo connectionInfo) {
                    Log.error("Received hello: " + hello);
                }
            };
    
            // registering our interest in hello messages on all bindings in the autobinding. The autobinding can contain multiple bindings for multiple interfaces
            Iterator it = discoveryAutobinding.getDiscoveryBindings(listener);
            while (it.hasNext()) {
                DiscoveryBinding b = (DiscoveryBinding) it.next();
                communicationManager.registerDiscovery(new int[] { MessageConstants.HELLO_MESSAGE }, b, helloReceiver, null);
            }
    
            OutDispatcher.getInstance().registerHelloListener(helloReceiver);
        }
    }
    
    /**
     * Listener
     * We use this just to get the bindings from the autobinding.
     * In production code you might want to handle network changes (an interface going away or coming back etc.) in this listener!
     * 
     * @author jmuethin
     */
    class Listener implements NetworkChangeListener, AutoBindingAndOutgoingDiscoveryInfoListener {
        public void announceNewCommunicationBindingAvailable(Binding binding, boolean isDiscovery) {}
        public void announceNewDiscoveryBindingAvailable(DiscoveryBinding binding, DiscoveryAutoBinding dab) {}
        public void announceNewOutgoingDiscoveryInfoAvailable(OutgoingDiscoveryInfo outgoingDiscoveryInfo) {}
        public void announceCommunicationBindingDestroyed(Binding binding, boolean isDiscovery) {}
        public void announceDiscoveryBindingDestroyed(DiscoveryBinding binding, DiscoveryAutoBinding dab) {}
        public void announceOutgoingDiscoveryInfoDestroyed(OutgoingDiscoveryInfo outgoingDiscoveryInfo) {}
        public String getPath() {return null;}
        public void announceNewInterfaceAvailable(Object iface) {}
        public void startUpdates() {}
        public void stopUpdates() {}
    }
    

    Best,

    Jannis

     

    Last edit: Jannis Müthing 2014-06-11
  • Jannis Müthing

    Jannis Müthing - 2014-06-11

    We found an even better way to do this without using autobindings:

    JMEDSFramework.start(null);
    
            CommunicationManager communicationManager = CommunicationManagerRegistry.getCommunicationManager(DPWSCommunicationManager.COMMUNICATION_MANAGER_ID);
    
            // the message listener
            DefaultIncomingMessageListener messageListener = new DefaultIncomingMessageListener(null) {
    
                public void handle(HelloMessage hello, ConnectionInfo connectionInfo) {
                    Log.error("Received hello: " + hello);
                }
            };
    
            Iterator it = communicationManager.getAvailableOutgoingDiscoveryInfos(true, CredentialInfo.EMPTY_CREDENTIAL_INFO).iterator();
            while (it.hasNext()) {
                DiscoveryBinding b = communicationManager.getDiscoveryBinding((OutgoingDiscoveryInfo) it.next());
                communicationManager.registerDiscovery(new int[] { MessageConstants.HELLO_MESSAGE }, b, messageListener, null);
            }
    
            OutDispatcher.getInstance().registerHelloListener(messageListener);
    

    Best,

    Jannis

     
  • Robert B.

    Robert B. - 2014-06-15

    Great! Thanks a lot for the support!

     
  • Robert B.

    Robert B. - 2014-07-09

    Ok this works fine now.

    Next question is how to send a probeMatch manually? (if at all possible)
    I built a message like this:

    ProbeMatch pm = new ProbeMatch(device.getDiscoveryData());
    ProbeMatchesMessage res = new ProbeMatchesMessage();
    res.addProbeMatch(pm);
    res.setResponseTo(probeMsg);
    

    But how can I send this now?

     
  • Jannis Müthing

    Jannis Müthing - 2014-07-16

    Hi Robert!

    You can send any message using the internal send(...) methods in the communication manager (in your case the DPWSCommunicationManager). Specifically

    public void send(Message message, XAddressInfo targetXAddrInfo, CredentialInfo credentialInfo) throws WS4DIllegalStateException
    

    should do the job for you. That being said, this is not really an application the stack was designed for. As mentioned the send methods are internal and should be used with extreme care or better not at all. It looks like you are trying to reimplement functionality that should be the stacks responsibility.

    Best,

    Jannis

     

Log in to post a comment.