How can I find out what IP address my Photon has?

Hi. I have a few devices installed in a remote location behind a NATed ADSL connection. The router is configured to update my DynDNS server periodically. However, it seems to have stopped updating, so I’ve lost contact with the mother ship so to speak. My Photon is still alive and continuously updating a registered variable. Is there any way I can easily find the remote IP address through the Particle.io servers? I guess a last resort could be to have the Photon open a connection to an external port or something on one of my servers that I could log onto, but it seems a little overkill and outside of the scope of what I’m using this Photon for. Any other ideas? Thanks.

I would try so: https://docs.particle.io/reference/firmware/photon/#get-public-ip

Thanks @antdem, I tried it, but can’t get it to work. Here’s the code:

char *ipAddress;

void handler(const char *topic, const char *data) {
    ipAddress = (char *) data;
}

void setup() {
  Particle.variable("IP address", ipAddress);
  Particle.subscribe("spark/", handler);
}

int loopCount = 0;

void loop() {
  // Publish my external IP address
  Particle.publish("spark/device/ip");
  delay(120000);
}

First I tried with just publishing, and setting up an IFTTT recipe that would trigger when the event was published. But I never saw it publish anything in the device log. So then I set up a variable to monitor that would be updated when the handler method is called. However, I don’t ever get anything published and the variable doesn’t seem to change. Am I doing something wrong? Thanks.

1 Like

Hi @Bluzcat

It is not a good idea to have your handler just use the pointer handed to you by the subscribe command. That pointer points to a part of an internal circular buffer that will change as other messages flow to and from the cloud.

The best thing to do is to copy that data in to a globally allocated char array using strcpy or similar that you manage.

Your variable can share the global char array, of course.

1 Like

@bko, Can you get this ip address from another device or the CLI, or can only the sending device get this info? I notice that if I subscribe via the CLI, the data received is a string of 64 hex characters. Is that an encrypted version of the ip address?

Thanks @bko, good point. It was just a simple test, so I’ll definitely clean the code up once I’m done.

Hi @Ric. I haven’t been able to publish anything with Particle.publish(“spark/device/ip”) call. My handler never gets called. I read somewhere in the subscribe() documentation that the “spark/” path was reserved and that it wasn’t possible to subscribe to those system events. Or maybe I misunderstood the docs. I ended up using a simple TCPClient to just connect to a remote Linux server so at least the IP address ends up in the log file. That’s really all I need for now.

It works for me. How do you know the handler isn’t called? Did you test with a print statement?

@Ric, no I don’t have access to the console. The device is thousands of miles away. I was trying to assign the value to a variable that gets monitored. Also, aren’t all system type variables always logged in the device log on the Particle.io site? I see other “spark/…” variables show up there.

I think the problem might be due to what @bko said in his post. Try updating the variable like so,

char ipAddress[65];


void setup() {
    Particle.subscribe("spark/", handler);
    Particle.variable("ipAddress", ipAddress);
}

void loop() {
    Particle.publish("spark/device/ip");
    delay(10000);
}

void handler(const char *topic, const char *data) {
    strcpy(ipAddress, data);
}
2 Likes
void handler(const char *topic, const char *data) {
    ipAddress = (char *) data;
}

void setup() {
  Particle.variable("IP address", ipAddress);
  Particle.subscribe("spark/", handler);
}

The reason why this doesn’t work is two fold.
Once as @bko said, you are only shifting your pointer to a temporary available string but additionally the reason why you don’t see any change in your Particle.variable() is due to the fact that Particle.variable() does not expose the value of your pointer but only the mem space the pointer pointed to at the time of registration and since this will be a null pointer at startup you will always ever see the contents there.

So deriving that the handler is never called just by looking at the variable is not working this way.

1 Like

Thanks @ScruffR. Based on the previous replies, I had already rewritten the code and deployed it, and it’s working fine now as far as I can tell. I’m keeping the IP address in a variable so I can monitor it with an HTTPS request. I’m also using a straight up TCPClient to connect to a cloud server that I have, only so I can catch the remote IP address in the log file. Seems to work fine. The “poor man’s dynamic DNS client” :smile:

The code looks something like this now:

int sGnd = D0;
int moisture = -1;
int loopCount = 0;
TCPClient client;
byte server[] = { // my server IP address here };
char ipAddress[128];
char cachedIpAddress[128];

void handler(const char *topic, const char *data) {
    strncpy(ipAddress, (char *) data, 128);
    if (strcmp(cachedIpAddress, ipAddress) != 0) {
        // IP address has changed, so publish the event
        Particle.publish("ipAddress", ipAddress);
        strcpy(cachedIpAddress, ipAddress);
    }
}

void setup() {
  pinMode(sGnd, OUTPUT);
  digitalWrite(sGnd, HIGH); // Turn sensor on
  Particle.variable("Moisture", moisture);
  Particle.variable("IPAddress", ipAddress);
  Particle.subscribe("spark/", handler);
}

void loop() {
  digitalWrite(sGnd, HIGH); // Turn sensor on
  delay(1000); // Wait one second
  moisture = analogRead(A0);
  digitalWrite(sGnd, LOW); // Turn sensor off
  
  // Report IP address roughly every 16m
  if (loopCount % 8 == 0) {
    if (client.connect(server, 123)) {
          client.println("Hello from Photon");
          client.stop();
    }
    // Report IP address
    Particle.publish("spark/device/ip");
  }

  loopCount++;
  delay(120000);
}

BTW, my logic above in the handler() method doesn’t seem to work. My thought was to cache the current IP address and only call Particle.publish() when it changes. I’ve noticed it change several times, but I don’t see the event being published. Since I don’t have access to the serial port, I guess I can debug by using variables or something. I thought doing a strcmp() on the cached IP address with the one getting passed into the handler() method would be sufficient, but it doesn’t seem to work. What’s the easiest way of debugging Arduino Wiring stuff? I have the Arduino IDE installed, but I’m not sure if works with the Photon. Thanks.

Why have you not got access to your serial port? The serial monitor of Arduino IDE should work.
No USB port free or the device not accessible?
Why would your public IP change several times? The remote IP should be the one your AP receives from your provider. Does your ISP only have a very short lease time or what service are you on?

Hi @ScruffR. The device is located on the other side of the Atlantic ocean :smile:
I do have a few other Photons laying around in the house, so I could use one of those to debug I guess. The ISP changes the external IP address for the ADSL router several times a day. Not sure why, but that’s how it is. Does the code look OK for what I described? Thanks.

I have flashed your code to one of my Electrons and it seems to run OK.
I just altered some things to get more publishes for testing.

Update:
I’ve also added this in order to test the behaviour if the IP changes

void setup()
{
  ...
  Particle.function("reset", res);
}

int res(String cmd)
{
    cachedIpAddress[0] = '\0'; // reset the cached IP to retrigger a publish next time
    return 0;
}
1 Like

It seems to work now, I’m seeing the data getting published in the device log. I added your function so I could reset it, which is a nice feature. Thanks!

1 Like

Hello Bluzcat (And @ScruffR )

I was trying your code:

I discovered

Particle.variable(“IPAddress”, ipAddress);

returns the public ip address of the router to which my particle photon is connected to .
Why not local LAN ip assigned by router to the particle photon?

hence its local IP wouldn't be of much use to access the device from this side of it :wink:
You need to get to the gateway which in turn needs to forward the request to the desired device (e.g. via port forwarding).

If you only wanted the local IP things are much simpler. You'd just use WiFi.localIP().

1 Like