Am I in physical proximity to my Particle device?

Is there any way to tell if I’m on the same router as my Particle device (Core/Photon)? I started out comparing the SSID of my mobile app with the SSID of my Particle device but quickly realized many people don’t change the default SSID of their router so there are probably thousands of Netgear (or whatever) SSID’s out there.

I want to create a product so I have no control over the naming of the SSID where the Particle device resides. But I want to restrict control of the Particle device in some situations to having the mobile app and the Particle device on the same router.

I’m not really a networking expert. Any ideas?

EDIT: Added “device” to make it more clear we are talking about a Core or Photon - BDub

Hi @steelydev,

The easiest way to do this (I think) would be to send small broadcasts from your Core / Photon via UDP. Your app could then listen for these messages on the local network, and would only see them if it were nearby. This is actually how the original mobile app detects when the Core has hopped on the nearby wifi. :smile:

http://docs.particle.io/core/firmware/#communication-udp

I hope that helps!

Thanks,
David

@Dave Thanks. Does that mean I’m bypassing the cloud? And is there any example code?

@Dave Have now be wrestling with UDP since your post 4 days ago and I’m blown away at the bugginess of it all. Has no action been take to resolve the bugs in the UDP firmware? I can’t broadcast from my cores without a hardware fault. I have written an IOS app that broadcasts and my core can pick it up. But I’m worried about the stability of the platform at this point. I’m working on a project that requires these devices to work!

Can you point me to any UDP code that will allow me to broadcast off the core?

@steelydev, the well known issues with UDP on the Core are primarily due to TI’s implementation on the CC3000. I can appreciate your frustration, however members have found workarounds and been able to use UDP successfully. Do a search on the Community for UDP workaround or such and you will most likely find what you need.

2 Likes

Hi @steelydev

@peekay123 is right on here–UDP has some quirks in the TI part but I am confident that it can work for you. I have used UDP in my NTP library and have debugged quite a few other UDP problems for others.

Please post your code and we will help. Are you trying subnet UDP broadcast or global broadcast? Is the cloud on or off?

2 Likes

When I ground out D0, the serial monitor reports ‘interrupt’ and I get SOS with one blink. Sometimes I can interrupt it two or three times. But no data over UDP ever gets to my IOS app.

//Reading works but sending causes hardware fault

unsigned int localPort = 51515;
char buffer[255];
unsigned char msg[10] = {70,70,70,70,70,70,70,70,70,70};
volatile bool interrupt = false;

UDP Udp;

void setup() {
  Udp.begin(localPort);

  Serial.begin(19200);
  Serial.println(WiFi.localIP());

  pinMode(D0,INPUT_PULLUP);
  attachInterrupt(D0,ISR,FALLING);

  blinkD7();
}

void loop() {
  //Serial.println("loop ");
  blinkD7();
  IPAddress ipAddress;
  int port;

  // Check if data has been received
  if (int len = Udp.parsePacket() > 0) {  // parsePacket must be bool
    Serial.print("Got packet. len=");
    Serial.println(len);
    blinkD7();

    // Read first char of data received
    //len = min(len,255);
   // Since len only comes back 0 or 1, force it to my packet size.
    len=24;
    char c = Udp.read(buffer,len);
    buffer[len] = 0;
    Serial.print("buffer =");
    Serial.print(buffer);
    Serial.print(" len = ");
    Serial.println(len);

    // Ignore other chars
   // I don't think this does anything
    Udp.flush();

    // Store sender ip and port
    ipAddress = Udp.remoteIP();
    port = Udp.remotePort();
    Serial.print("IP address=");
    Serial.print(ipAddress);
    Serial.print(" port=");
    Serial.println(port);  // Port comes back wrong.

  }

  if (interrupt) {
    Serial.println("interrupt");
    Udp.beginPacket(IPAddress(192,168,1,225), localPort+1);
    Udp.write(msg,10);
    Udp.endPacket();
    interrupt = false;   
    delay(100);
  }
}

void blinkD7() {
    pinMode(D7,OUTPUT);
    digitalWrite(D7,HIGH);
    delay(50);
    digitalWrite(D7,LOW);
    delay(50);
}

void ISR() {
  interrupt = true;
}

UDP.parsePacket() must be a bool because it only returns 0 or 1. UDP.remotePort() seems to return the wrong port. Since my IOS app is broadcasting on 51515 and the firmware is listening on 51515, shouldn’t the port returned be 51515? Again, I’m not a networking guy and this is my first time out with UDP.

@bko cloud is on AFAIK

Do you have a Linksys router? 192.168.1.225 is the magic configuration address for Linksys and a few other brands of router.

How do you know this address belongs to your iOS device?

UDP.parsePacket() does return the length of the packet so if you are getting a 1, that is a one byte packet and reading more can cause a crash. The remote port and IP address are set by parsePacket too, so when you say that the port comes back wrong, what do you mean? You are listening on port 51515 so for the other host, that is the destination port, but the sender can send on any source port and you would get that port number in the remote port.

1 Like

@bko Thanks for looking at this. Have a NetGear router. Have tried 255.255.255.255 and 192.168.1.255 no change.: SOS 1

In my code parsePacket() is returning only 0 or 1 no matter how long the message is. See where I force it to length of 24? I then get the 24 characters of my message from read(). My IOS app is sending 24 characters. Even when parsePacket() returns 1, I can still read the 24 character message. But if the messages were variable length, then I would be screwed. Luckily, I control both ends of the conversation.

I see what you’re saying about the sending port of the sender maybe not being the port I’m broadcasting to. I’ll have to look into that.

But the problem here is the Core sending a message back to me. It doesn’t work. At all. Is there a glaring error in my code? I basically pulled the code from this forum. And in any case SOS 1 happens all the time.

Also, Dave already pointed out the wikipedia UDP entry. There’s not much info there. Is there something I’m looking for?

1 Like

HI @steelydev

  • What remote port number do you get?
  • What remote IP address to you get?
  • Parse packet does not only return 1/0--it returns the number of bytes available to be read. That part of your code is wrong and could be causing the crash you are seeing.
  • UDP.read() returns an int not a char.
  • UDP.read() only copies available data so if UDP.available() returns 1, it only copies 1 byte.

You are going to have to fix these issues to make any progress.

1 Like

I think we're getting off topic. But I looked at your NTP code and you do not honor the return length from parsePacket() and instead use the known length of your expected message. Just as I'm doing. And I assume we both get the messages we want.

However, I'm reading OK. I can't seem to send. I looked at your code and can only assume I'm not using the correct data types for sending to the UDP object. I changed out

Udp.beginPacket(IPAddress(192,168,1,225), localPort+1);

For

Udp.beginPacket("255.255.255.255", localPort+1);

and no longer get SOS1 but there seems to be nothing coming up on port 51516. It seems the largest difference between what you're doing in the NTP code and what I'm doing is the language. You are using datatypes that are available in cpp and not in wiring. Am I barking up the wrong tree?

Does anybody out there have these three lines working in .ino? What should the data types be?

Udp.beginPacket(IPAddress(192,168,1,225), localPort+1);
Udp.write(msg,10);
Udp.endPacket();

And should I be looking for my devce on 255.255.255.255 or xxx.xxx.255.255 or what? I'm a little unclear.

1 Like

The DNS client inside the TI cc3000 does not understand this format and you will not be able to connect. There is a DNS reflection service that would let you write "255.255.255.255.xip.io" but I think you are better off with IPAddress.

Here's a program I pulled out of my debugging files for someone else and I just tested. It uses Serial1 for debug messages but you can obviously change that.

UDP udp;

IPAddress remoteIP(239,255,255,250);
int remotePort = 1900;
int count = 0;

unsigned char TxMsg[5] = { 'H', 'E', 'L', 'L', 'O'};

void setup() {
    udp.begin(5000);
    Serial1.begin(9600);
}

void loop() {
    Serial1.print("Run ");
    Serial1.print(count++);
    udp.beginPacket(remoteIP, remotePort);
    udp.write(TxMsg,5);
    udp.endPacket();
    delay(1000);
}
1 Like

@bko You are correct. I just figured out the same thing myself. I guess there’s no substitute for looking at the actual firmware code. The first parameter to beginPacket should be type IPAsdress to be safe. Thanks for the help. I can read and write! I still think there’s a bug in udp.parsePacket() although udp.available() does work.

Now back to the proximity question. Will sending UDP on 255.255.255.255 definitely restrict me to the local subnet? OK or should I parse my IP strip off the fourth octet and replace with 255? If what you’re saying is true of some routers interpreting 192.168.1.255 as magic the first would be preferable???

This is really a question of what your router does with broadcast packets. Most home routers do not forward them, but a managed switch or an enterprise router can be programmed to handle it in many different ways. They can forward or not forward plus do sophisticated port and address mapping so packets can land anywhere.

By the way, that magic address for router setup (over TCP) was 192.168.1.225 not 255, which I got out of the beginPacket in your code above! Maybe you meant 255 instead?

Yup. Just another bug OF MINE. And that may have cost me 6 hours or so. Pretty dum.