Ad-hoc connection without router

Hi guys,
my project is very simple. I would like to use the arduino yun to send data from a sensor to a PC via wifi. However, I don't have a router and I want to use a the ad-hoc connection. I didn't find much information about it, I only found where I can set the ad-hoc configuration on the advance setting...ok.. and then.... I miss the next step.

Can you help me?? Thanks!!

This might help.

OpenWrt Recipes
http://wiki.openwrt.org/doc/recipes/start

Jesse

Thank you Jesse for your answer.
I read the different documentation but apart from the information about the setting configuration in LUCI interface.... unfortunally I have not solved the problem :frowning:

http://forum.arduino.cc/index.php?topic=255216.msg1815506#msg1815506

Plan B: Setup Yun as Access Point. leave PC as client

http://forum.arduino.cc/index.php?topic=256234.msg1813025#msg1813025

Plan C: Setup PC as Access Point. leave Yun as client

woodstock:
Thank you Jesse for your answer.
I read the different documentation but apart from the information about the setting configuration in LUCI interface.... unfortunally I have not solved the problem :frowning:

woodstock,
are you aware that the default settings for the Yun is to act as an AP (wireless Access Point)?
So, I'm puzzled as to your real problem. Do you want wifi as your primary network medium?
Or are you looking for a dependable network. Can you please give us more details.

Thanks
Jesse

Hi jesse, the picture linked may better explain the situation. It's very simple. :slight_smile:

https://drive.google.com/file/d/0B8SUiMN6PrauS0ZOUTRfbTFHX28/view?usp=sharing

Thanks,
Woodstock

From that picture, it sure seems like you want the default behavior of the Yun where it acts as the access point, and the computer connects to it as a client.

Does it specifically have to be "ad hoc" mode, or can the Yun be an access point? There is a subtle difference between the two, but either will accomplish what is in the picture.

Ok, either ways allow me to connect the Arduino Yun with the PC... but how can I read the data from sensor during the streaming? Thanks!

YunClient/YunServer may fit your bill. Check this discussion out: Enable Telnet? - #8 by ShapeShifter - Arduino Yún - Arduino Forum

Another alternative is to use the Bridge.put() to store the most recent sensor reading, for example:

char value[20];

// Convert the float "temperature" into a character string
dtostrf(temperature, 4, 1, value);

// Set the temperature string value under the key "Temperature"
Bridge.put("Temperature", value);

The PC can then make an HTTP call to "http://arduino.local/data/get/Temperature" to read the latest value from the Temperature key, or simply to "http://arduino.local/data/get" to read the latest values for all defined keys in one shot (useful if you have several sensors.)

The first idea (TCP socket) is better for streaming a lot of data, where you want to be sure to get every value. The second idea (Bridge.put) is good for when the PC wants to occasionally get the latest value, without having to maintain a connection (and without getting every single data item.)

ShapeShifter:
YunClient/YunServer may fit your bill. Check this discussion out: Enable Telnet? - #8 by ShapeShifter - Arduino Yún - Arduino Forum

Another alternative is to use ...
::::SNIP::::

Thanks ShapeShifter.

Thanks ShapeShifter, I think that the TCP communication should be better for my purposes. In your opinion, I have the possibility to set the arduino yun as a client and then the PC as a server? I checked the topic that you suggested me but in that case there was a multiple communication and it was quite complex than my project. The first object is to stream in real time the data from the sensor and read the value on the "serial monitor".

Yes, that thread was aiming to have multiple clients connect to the Yun. but the initial code in post #8 has the Yun acting as a server, and accepting only one connection at a time. Doing so is fairly straightforward: most of the extra code in post #8 is there to handle the client connecting and disconnecting at random times, while the sketch continues to run. (The sketch from which I condensed that code always sends data to the serial port, and also sends to the network socket if there is a client connected, therefore the sketch needs to keep running even if there is no client.)

If you have the PC act as the server, and the Yun is the client, it should be easier: you don't have to start a server object and keep trying to accept() a connection, and you don't have to worry about when a connection comes in. I've not tried it in that direction, but it still looks like you use YunClient. Call connect() with the PC server's IP address and port number, then call read() and write() on the client object to communicate. Call stop() when you are done and want to close the connection. Same I/O operations as in my example in post 8, but different connect/disconnect mechanism.

Thank you ShapeShifter for your advices!

I followed your steps and I read some references. I thought a simple way: using the Console command! To test this, I wrote a very simple program and I uploaded to the Yun:

#include <Console.h>

void setup () {
  Bridge.begin();
  Console.begin();
  
  while (!Console) {
    ;
  }
  
  Console.println("OK connected");
  
}

void loop() {
  int x = Console.read();
  for (x=0; x<10; x++){
    Console.println(x);
    delay(100);
    }
   delay(1000);
}

Using the TeraTerm I set Host--> ssh://root@name.local Port--> 6571 then I wrote 'telnet localhost 6571'
In this way I can see the values (0-9) printed to the monitor and using the IDE "serial monitor" I can see the same results.
Now, the next problem to solve is: how can I get this values in C#?!?...
Ok, now I used a router but the next-next step will be to use the ad-hoc connection.

woodstock:
I thought a simple way: using the Console command!

Interesting idea! Yes, the Console is just another TCP stream on a fixed port number, where all of the connection maintenance overhead is already done for you.

Now, the next problem to solve is: how can I get this values in C#?!?...

I just did this recently. I'm not at my computer at the moment, but when I get back to it I'll look for some sample code.

Ok, now I used a router but the next-next step will be to use the ad-hoc connection.

That shouldn't make ANY difference to the code. The way you connect to and associate with the network will change, but once you get connected and can ping from one to the other, this same code should work.

This is an extremely simple example of reading from a network socket in C#

I created a basic C# Windows Forms Application project, put a button on the form, and added a click event handler. In the handler, it opens a connection to my Yun, on socket 255 (since that's what the currently loaded sketch is using, you'll be using your different port number.) It then waits for 5 characters to be received, and adds them to a string as they come in. Finally, it closes the socket and pops up a message box displaying what it read.

Not very useful in and of itself, but shows the various steps of opening/reading/closing a socket. Of course, you will want to do something more sophisticated.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;

namespace NetTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Local data handling definitions
            int count = 5;
            int ch;
            StringBuilder str = new StringBuilder();

            // Declare the TcpClient that manages the connection, and the
            // NetworkStream that manages the commuincations over it.
            TcpClient tcpClient;
            NetworkStream netStrm;

            // Open the socket connection, and associate the network stream with the socket.
            tcpClient = new TcpClient();
            tcpClient.Connect("arduino.local", 255);
            netStrm = new NetworkStream(tcpClient.Client);

            // Read the fixed number of characters
            while (count > 0)
            {
                // Simple method to make the blocking call non-blocking.
                // Not really needed here since the while loop is blocking,
                // but added just to show the concept.
                if (netStrm.DataAvailable)
                {
                    // Read a character. Normally blocks, but we already know at least
                    // one byte is available because of the DataAvailable call.
                    ch = netStrm.ReadByte();

                    // Add the character to the string
                    str.Append((char)ch);

                    // One less character to read
                    count--;
                }
            }

            // Close the network stream, then the client. Closing the client does NOT close the stream!
            netStrm.Close();
            tcpClient.Close();

            // Pop up a message box showing what was received.
            MessageBox.Show(str.ToString(), "Received from socket");
        }
    }
}

While I had no need to do it in this application, data can also be sent back through the socket using the same NetworkStream object. For example:

        public void SendData(byte[] data)
        {
            if (tcpClient.Connected)
                netStrm.Write(data, 0, data.Length);
        }

Note that the NetworkStream read/write functions I used are blocking calls. I used DataAvailable() as a workaround in this example (even though it wasn't needed here) which makes it kind-of-sort-of non blocking, but if you need truly asynchronous reads/writes, there is a more complicated method to accomplish that: the NetworkStream documentation has some information on that.

I didn't do that. I already had some serial port code that ran in its own thread, and used delegate functions to send it the form where the incoming data could be caught by an event handler. Since this network socket was basically a replacement for the serial code in an existing application, I just created a copy of the class that encapsulated the serial thread code, and replaced the blocking serial I/O calls with blocking network I/O calls. I did that because it was expedient and minimized the changes to the existing code (it never realized that the underlying transport mechanism had changed.) I don't necessarily recommend going to all that work unless the NetworkStream native asynchronous calls are untenable for your application.

This is an extremely simple example of reading from a network socket in C#

The code is easy and clear. Thanks ShapeShifter! I have a doubt: with the Console command I need a ssh connection, in your opinion the C# code doesn't change?

if you need truly asynchronous reads/writes

I'll try to read some reference about NetworkStream and I'll report the result. Unfortunally, now I don't have with me Visual Studio to test the code :frowning:

I didn't do that. I already had some serial port code that ran in its own thread, and used delegate functions to send it the form where the incoming data could be caught by an event handler. Since this network socket was basically a replacement for the serial code in an existing application

Exactly, I wrote a C# code in which I used a serial port to read, process the data and plot them. I want to do this but... with the wifi communication (with Arduino Yun).

I just created a copy of the class that encapsulated the serial thread code, and replaced the blocking serial I/O calls with blocking network I/O calls.

Please, have you the code about it? I think that it should be a great solution!

woodstock:
I have a doubt: with the Console command I need a ssh connection, in your opinion the C# code doesn't change?

Oh... that would be a problem. This is a straight TCP stream socket. SSH adds an encrypted protocol layer on top of that. This was tested using the straight YunClient, but not tested with Console. I'm sure it won't work, and I've never looked into what it would take to make an SSH connection from C#. I'm afraid I can't be any help there. :frowning:

Hi guys... I finally completed my project. THANKS very much for your support. Now I want to share with you the code that I used.

  1. Sketch code: I didn't use the Console command but the TCP approach with YunClient. (Thanks to ShapeShifter)
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

#define PORT 255
YunServer server(PORT);
YunClient client;

static boolean clientActive = false;

void setup()
{
  // Bridge startup
  Bridge.begin();
  
  server.noListenOnLocalhost();
  server.begin();
  client = server.accept();
}



void loop()
{
  if (client.connected())
  {
    if (!clientActive)
      //Serial.println("New client connection.");
      
    clientActive = true;
    
    // Have a connection. Read and echo any input to the serial port
    if (client.available())
    {
      //Serial.print("From client: \"");
      
      //while (client.available())
        //Serial.print((char)client.read());
      
      //Serial.println("\"");
    }
    
    // Send to the client 350 349 348.... 301 350 349.....
    int x;
    
    for (x=350; x>300; x--){
        
      client.println(x);
      
      delay(100);
    }
    
   
  }
  else // No connection, try to accept one.
  {
    if (clientActive)
      Serial.println("Client disconnected.");
      
    clientActive = false;
    
    client = server.accept();
  }
}
  1. C# code: it was not very easy to create a socket and to control the sending data. However in with this code you will not have any problem :slight_smile:
using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Threading;
    using System.Net;

namespace readthat
{
        public class StateObject
        {
            // Client socket.
            public Socket workSocket = null;
            // Size of receive buffer.
            public const int BufferSize = 256;
            // Receive buffer.
            public byte[] buffer = new byte[BufferSize];
            // Received data string.
            public StringBuilder sb = new StringBuilder();
        }
        public class AsynchronousClient
        {
            // The port number for the remote device.
            private const int port = 255;
            // ManualResetEvent instances signal completion.
            private static ManualResetEvent connectDone =
            new ManualResetEvent(false);
            private static ManualResetEvent sendDone =
            new ManualResetEvent(false);
            private static ManualResetEvent receiveDone =
            new ManualResetEvent(false);
            // The response from the remote device.
            private static String response = String.Empty;
            public static void StartClient()
            {
                // Connect to a remote device.
                try
                {
                    // Establish the remote endpoint for the socket.
                    // The name of the
                    // remote device is "host.contoso.com".
                    //IPHostEntry ipHostInfo = Dns.GetHostEntry("192.168.43.102:255");
                    //IPAddress ipAddress = ipHostInfo.AddressList[0];
                    //
                    IPAddress ipAddress = IPAddress.Parse("192.168.43.102");
                    IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
                    // Create a TCP/IP socket.
                    Socket client = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);
                    // Connect to the remote endpoint.
                    client.BeginConnect(remoteEP,
                    new AsyncCallback(ConnectCallback), client);
                    connectDone.WaitOne();
                    // Send test data to the remote device.
                    Send(client, "This is a test<EOF>");
                    sendDone.WaitOne();
                    // Receive the response from the remote device.
                    Receive(client);
                    receiveDone.WaitOne();
                    // Write the response to the console.
                    Console.WriteLine("Response received : {0}", response);
                    // Release the socket.
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            private static void ConnectCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the socket from the state object.
                    Socket client = (Socket)ar.AsyncState;
                    // Complete the connection.
                    client.EndConnect(ar);
                    Console.WriteLine("Socket connected to {0}",
                    client.RemoteEndPoint.ToString());
                    // Signal that the connection has been made.
                    connectDone.Set();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            private static void Receive(Socket client)
            {
                try
                {
                    // Create the state object.
                    StateObject state = new StateObject();
                    state.workSocket = client;
                    // Begin receiving the data from the remote device.
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            private static void ReceiveCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the state object and the client socket
                    // from the asynchronous state object.
                    StateObject state = (StateObject)ar.AsyncState;
                    Socket client = state.workSocket;
                    // Read data from the remote device.
                    int bytesRead = client.EndReceive(ar);
                    if (bytesRead > 0)
                    {
                        // There might be more data, so store the data received so far.
                        response = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
                        Console.Write("{0}", response);
                        state.sb.Append(response);
                        // Get the rest of the data.
                        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);
                    }
                    else
                    {
                        // All the data has arrived; put it in response.
                        if (state.sb.Length > 1)
                        {
                            response = state.sb.ToString();
                        }
                        // Signal that all bytes have been received.
                        receiveDone.Set();
                        
                    }
                   
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }







            private static void Send(Socket client, String data)
            {
                // Convert the string data to byte data using ASCII encoding.
                byte[] byteData = Encoding.ASCII.GetBytes(data);
                // Begin sending the data to the remote device.
                client.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), client);
            }
            private static void SendCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the socket from the state object.
                    Socket client = (Socket)ar.AsyncState;
                    // Complete sending the data to the remote device.
                    int bytesSent = client.EndSend(ar);
                    Console.WriteLine("Sent {0} bytes to server.", bytesSent);
                    sendDone.Set();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
        }
    }

Thank you again and I hope that these code will be helpful for your project. :slight_smile: