This project has moved. For the latest updates, please go here.

Xbee API Send Working fine - OnDataReceived never fires

May 20, 2013 at 4:27 AM
I programming Xbee Pro Series 2 devices using your wonderful C#.net API Library.

I have configured Coordinator and router properly. I can issue commands to Coordinator and it responds to commands properly.

but When I send data basically a string, I get no response.

Here is my code. Please have a look and guide me in finding where things are going wrong.
        IXBeeConnection xbConn = new SerialConnection("COM15", 9600);

        IPacketListener listener = new PacketListener();

        XBeeApi xBee = new XBeeApi(xbConn);

        xBee.EnableDataReceivedEvent();

        xBee.EnableAddressLookup();

        xBee.EnableModemStatusEvent();

        xBee.AddPacketListener(listener);

        xBee.DataReceived += new XBeeApi.XBeeDataReceivedEventHandler(OnDataReceived);

        xBee.Open();

        var nodes = xBee.DiscoverNodes();

        var results = xBee.SendAPI_ATcommand(); // This works fine.

        var response = xBee.Send("#AA").To(0x0013A2004048A146).GetResponse(); // This gives status as success

        NodeInfo nodeInfo = new NodeInfo();

        nodeInfo = nodes[0].NodeInfo;

        var response132 = xBee.Send("7E 00 0A 01 01 13 A2 20 0 00 48 65 6C 6C 6F B8").To(nodeInfo).GetResponse();// Here also I get Delivery success

        listener.ProcessPacket(response132); // I get not data here


        Application.Run();
// This event never fires This is the main issue
    public static void OnDataReceived(XBeeApi receiver, byte[] data, XBeeAddress sender)
    {
        Console.WriteLine("Received: " + new string(Encoding.UTF8.GetChars(data)));
    }
Please help me in this. Thanks a lot
Coordinator
May 20, 2013 at 7:05 AM
Hi,

Could you please share the whole source code for both the router and coordinator? If its confidential then please extract the xbee part to some other project and share that one.
May 20, 2013 at 10:30 AM
Hi Gralin,

Here is my Complete code. I have a console app. And in that I have set Reference of your XBee.PC Project. So The custom code that I have written is below. If you Copy this in a Console App and Set ref to XBee.PC in that project this code will work fine. Though you may need devices too, to actually issue commands.

More On How We are trying to use the devices : We are having this electric meter component which is connected to Xbee Router. Then we have one Xbee Coordinator connected to PC via serial port. Coordinator has got router's SH and SL and vice-versa. These two devices work fine with X-TCU and With two separate Custom Apps. I have tried that.

Now So far I can set some parameters of Meter using this code below. But When I query the meter using its command "#AA".
Which has been provided to me by our technical person who do the set up. Its does not return anything on "OnDataReceived" or rather the event itself does not get fired.

I did not write any other code for Router to respond. Since I believe its going to be at remote location and we can communicate to it via Coordinator only which is connected to PC. So there should be code for Coordinator only.

I am Suppose to use Xbee. Recieve(); method for this? I Have tried that too but it did not work.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NETMF.OpenSource.XBee;
using System.Diagnostics;
using NETMF.OpenSource.XBee.Api;
using NETMF.OpenSource.XBee.Api.Common;
using NETMF.OpenSource.XBee.Api.Zigbee;
using System.Windows.Forms;
using NETMF.OpenSource.XBee.Util; 

namespace Xbee.PunchLine
{
    class Program
    {
        public static IXBeeConnection xbConn = new SerialConnection("COM15", 9600);

        public static  IPacketListener listener = new PacketListener();

        public static XBeeApi xBee;

        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine("This is Coordinator Console");

            xBee = new XBeeApi(xbConn);

            xBee.EnableDataReceivedEvent();

            xBee.EnableAddressLookup();

            xBee.EnableModemStatusEvent();

            xBee.AddPacketListener(listener);

            xBee.DataReceived += new XBeeApi.XBeeDataReceivedEventHandler(OnDataReceived);

            xBee.Open();

            SendDataToDevice(listener, xBee);

            Application.Run();
        }

        private static void SendDataToDevice(IPacketListener listener, XBeeApi xBee)
        {
            // Find Node connected to Coordinator
            var nodes = xBee.DiscoverNodes();

            NodeInfo nodeInfo = new NodeInfo();

            // Get Router Address or router node info
            nodeInfo = nodes[0].NodeInfo;

            // Want to read data from meter via xbee router - This code does not give any data in return, 
            // Where as The response to this command is supposed to be a 9 char string from router.
            // Status of Response come as Success, which means data/string is sent to router, but response is not comming.
            var response = xBee.Send("H01#AA").To(nodeInfo).GetResponse(); 

            // This command sets time on meter, This works fine
            var response1321 = xBee.Send("#BB1111$").To(nodeInfo).GetResponse();

            // This command sets Number of Units on meter, This works fine
            var response1322 = xBee.Send("#CC1111$").To(nodeInfo).GetResponse();

            // This Command Sets Load Status on/Off on Meter, This too works fine.
            var response1323 = xBee.Send("#CC0111$").To(nodeInfo).GetResponse();

            listener.ProcessPacket(response1321);
        }

        public static void OnDataReceived(XBeeApi receiver, byte[] data, XBeeAddress sender)
        {
            Console.WriteLine("Received: " + new string(Encoding.UTF8.GetChars(data)));
            SendDataToDevice(listener, xBee);
        }
    }
}
Note : All Xbee Commands that are there in Xbee Manual work fine in this code. I have tried them all. The text/string that I am sending in this code. Its kind of custom commands set by the technical team here for the devices to read and write relevant data.

Also please advise on : How to Read data that a router send in response to a
Coordinator
May 20, 2013 at 11:29 AM
Edited May 20, 2013 at 11:31 AM
Could you please analyze the code below, run it and tell me what is the output?
using System;
using System.Text;
using NETMF.OpenSource.XBee;
using NETMF.OpenSource.XBee.Api;
using NETMF.OpenSource.XBee.Api.Common;
using System.Windows.Forms;
using NETMF.OpenSource.XBee.Util;

namespace Xbee.PunchLine
{
    class Program
    {
        public static IXBeeConnection xbConn = new SerialConnection("COM15", 9600);
        public static XBeeApi xBee;

        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine("This is Coordinator Console");

            // this will give as debug info in the console from xbee
            Logger.Initialize(Console.WriteLine);

            xBee = new XBeeApi(xbConn);

            // our listener will be invoked for every incoming frame
            xBee.AddPacketListener(new MyListener());

            // OnData should be invoked for every incoming TX frame
            xBee.DataReceived += OnData;

            xBee.Open();
            
            // OnNodeDiscovered method will be invoked 
            // for every discovered node in the network
            xBee.DiscoverNodes(OnNodeDiscovered);

            Application.Run();
        }

        private static void OnNodeDiscovered(DiscoverResult node)
        {
            Console.WriteLine("Discovered node: {0}", node);

            var nodeInfo = node.NodeInfo;
            var response = xBee.Send("H01#AA").To(nodeInfo).GetResponse();
            var response1321 = xBee.Send("#BB1111$").To(nodeInfo).GetResponse();
            var response1322 = xBee.Send("#CC1111$").To(nodeInfo).GetResponse();
            var response1323 = xBee.Send("#CC0111$").To(nodeInfo).GetResponse();
        }

        public static void OnData(XBeeApi receiver, byte[] data, XBeeAddress sender)
        {
            var dataStr = new string(Encoding.UTF8.GetChars(data));
            Console.WriteLine("Data received: {0}", dataStr);
        }
    }

    public class MyListener: IPacketListener
    {
        public void ProcessPacket(XBeeResponse packet)
        {
            // This will write a line in console for every incoming frame
            Console.WriteLine("<- {0} {1}", packet.GetType().Name, packet);
        }

        public XBeeResponse[] GetPackets(int timeout)
        {
            throw new NotSupportedException();
        }

        public bool Finished { get { return false; } }
    }
}
May 21, 2013 at 5:06 AM
Hi Gralin,

I have tried running this code. I got Two issue one in the logger I fixed it by adding another Hash Table.
            foreach (var level in LogWritters.Keys)
            {
                LogWritters2[level] = logWritter; // If we update LogWritters here then it gives an exception. So I have added another varibale LogWritters2 
            }

            foreach (var level in LogWritters2.Keys)
            {
                LogWritters[level] = logWritter; // Then putting the values from LogWritters2 to LogWritters. This works fine now. I could have commented it but tried to solve it. This is not major issue for me.
            }
Now the second issue is When the following code gets executed.

var response = xBee.Send("H01#AA").To(nodeInfo).GetResponse(); // This gives me timeout exception as below (Screen shot of exception)

Image

I have not done any modification to the code you gave after re factoring my code.

Note : If I comment this line // var response = xBee.Send("H01#AA").To(nodeInfo).GetResponse();

Then subsequent code run without error.

Here is screen shoot of Console output

Image

Thanks a ton for the help and re factoring the code. I am really stuck in this.
Coordinator
May 21, 2013 at 7:40 AM
Indeed there was a bug in the Logger class - in regular .NET you can't modify collection inside foreach. Apparently I haven't used Logger in PC app before. I have pushed a fix to the repo.

As you can see in the console output the first 6 received AtResponse frames are responses to the initialization of your local XBee. This way the library knows what module its using. Next line is the summary of your module. Following two lines are the response for the discovery start and first discovered node. Next line is the summary of the discovered node - the router. What we do next is we are trying to send the data packets to the router. You get timeout exception with the first attempt but you seem to get a response to at least one request (the TxStatusResponse). Could you please surround each Send with try catch so that we see in the output which requests get a response?

Two things bother me.

1) The disovery process should also find your end device that is connected to the router.
2) If you want to send and receive data from the end-device why do you send the data to the router.

If the discovery process doesn't find your end device you can try to communicate with it using serial numer.
May 25, 2013 at 4:57 AM
Hi Gralin,

1 - I am back on this. Yes you are right that discovery process should find the end device. But we are using router and end device as per digi.
2- Actually the idea is to send and receive data from end device. but we are keeping it to last phase. For now what we are trying to achieve is:
set the communication between devices.

I have tried to use Try and catch for every send. as below.
            try
            {
                xBee.Send("#BB4444$").To(nodeInfo).GetResponse();
            }
            catch (Exception ex)
            { 
                Console.WriteLine("Error : " + ex.Message.ToString());
            }

            try
            {
                var response1322 = xBee.Send("#AA").To(nodeInfo).GetResponse();
            }
            catch (Exception Ex) { Console.WriteLine("Error : " + Ex.Message.ToString()); }
And then here is the console output

Image


Another thing I noted down is If I use .Getresponse() then only I get error. And if I use .NoResponse() the error does not come. Although I do not get data also.

One more thing to Note : First command xBee.Send("#BB4444$") Sets values on the meter successfully. After debugging i came to know that its the .getResponse() method which is throwing exception. Also you can see in the console out put that TxResponse of delivery of commands is coming up.

I have been looking on internet for the Timeout issue. Found that many people facing it. I too believe that its something related to reading the data at right time. May be we are trying to read data before or after its coming on the port. and its getting lost.

Please let me know your thoughts.
May 25, 2013 at 5:12 AM
Sorry - I mean We are using Router as End Device as per instructions from Digi
May 25, 2013 at 5:20 AM
There one more thing that I tried.
  • Set both the devices in command mode.
  • Issue the commands on terminal.
  • Set commands successfully set values on meter. #BB4444$ works fine on terminal in command mode.
  • Get command get the data on terminal immediately. #AA works fine on terminal in command mode, it returns a string of data.
And I type these commands on Coordinator Terminal.

That means in Command mode everything works fine. In API mode is the issue.
Coordinator
May 25, 2013 at 8:03 AM
The GetResponse() method is used when you want to send packet and you are expecting a response in return. It throws TimeoutException if response is not received after some given period of time. You can extend that timout time by invoking Timeout(int) before GetResponse(). If you use NoResponse() it will send the request and return without waiting for the response so no TimeoutException. Maybe if you wait for the response longer it will be received. You could also just not wait for the response as it should be received by the MyListener class object and reported to the console. Just Thread.Sleep(Timeout.Infinite) and wait for it...

When you say 'command mode' you mean AT mode? If so you must have changed the firmware for that am I right?

How can you tell if some command work fine? You have any visual indication of that? If so it means that some commands issued using API work and some don't right?
May 25, 2013 at 8:28 AM
Yes When I say command mode It means AT Mode.

And yes I do write/Change firmware on device to change the mode.

Regarding Visual indication.
  • In AT mode I can see the results in terminal window.
  • In API mode I can see the changes on a LCD display connected to meter. This display show me data present in the Micro controller of Meter.
So when I set value by xBee.Send("#BB4444$") I can see the changes on LCD screen.

Thanks for the help. I will try the timeout option. And may will get back to you. How it goes.
May 27, 2013 at 9:48 AM
I tried Using Thead.Sleep(Timeout.Infinite). I get do not get any data. Tried it for 30 Mins, 1 Hr and 2 Hrs.

Looks like Router is Not transmitting Data back to Coordinator.

Any thoughts. please let me know
Coordinator
May 27, 2013 at 1:03 PM
But did you set the Timeout before sending the request? Thead.Sleep() is only needed so your app doesn't close before receiving the async response. I will try to think what else could be the problem and will get back to you.
May 28, 2013 at 4:05 AM
No I set is after sending the request.

If I set it before sending request then it does not move to next line of execution. Code execution halts.

I tried changing timeout value here
    public XBeeResponse[] GetPackets(int timeout = -1)
    {
        FinishedFlag.WaitOne(1000, false); // TImeout is 100 here by default

        if (Packets.Count == 0)
            return new XBeeResponse[0];

        return (XBeeResponse[])Packets.ToArray(typeof(XBeeResponse));
    }
Before Issuing command I set a sleep 1000 Ms like this
            Thread.Sleep(1000);
                xBee.Send("#AA").To(address).GetResponse();
Now I do not Timeout get Exception

I get <TxResponseStatus .. .. > response.

Now I have a question in my mind. Q : Is there a chance of data being lost before listener gets free to read it?

After #AA is issued listener goes to read TxresponseStatus data. By the time it finishes reading it may happen that #AA Response is lost.

But then since it is doing async reading then all data that comes to port will be read. Is that right?
Coordinator
May 28, 2013 at 6:51 AM
Don't use Thread.Sleep between calls. What i meant by using timeout is this:
xBee.Send("#AA").To(address).Timeout(5000).GetResponse();
This is a fluent API so you invoke method on the result of previous method. You start with Send and end with GetResponse, GetResponses, NoResponse or Invoke.

You shouldnt miss any packets since you add your custom packet listener (MyListener) at the beginning. This listener should catch all incoming packets. Maybe try broadcasting you messages (blind guess).
Jun 7, 2013 at 10:54 AM
Hi Gralin,

The Communication has been established now. The devices are working fine with the existing code.

The issue was : We were not sending a Tx Request from MCU.

Xbee Router needs data in Tx(0x10) format from MCU. Or It will not understand and will not route it. We have to change the program in MCU. And it worked fine.

Thanks for the Support. The problem is solved. We can close this thread now.

Regards,
Lalit
Coordinator
Jun 12, 2013 at 5:42 PM
It's great to hear that you resolved this issue. So no changes were needed in the codebase to get it working? If you had to make any send me the changes or make a pull request.