DNS problem with Photons (via 3G router and using WiFi.off() to save power)

My company is working on a project where several Photon are installed in the street. We would like to connect to the Internet via a 3/4G router. First I connected the router via a fixed wired WAN connection. My simple slightly adapted Blink code works fine. When I discconect the router from the wired connection and enable the 3G connection I can no longer use WiFi.off() as the Photon keeps complaining about unable to resolve device.spark.io:
0000069004 [system] ERROR: Cloud: unable to resolve IP for device.spark.io
When I connect my own laptop to the same router I can resolve device.spark.io. So this seems to be a timing issue.

Here is my code:

// ------------
// Blink an LED
// ------------

/*-------------

We've heavily commented this code for you. If you're a pro, feel free to ignore it.

Comments start with two slashes or are blocked off by a slash and a star.
You can read them, but your device can't.
It's like a secret message just for you.

Every program based on Wiring (programming language used by Arduino, and Particle devices) has two essential parts:
setup - runs once at the beginning of your program
loop - runs continuously over and over

You'll see how we use these in a second. 

This program will blink an led on and off every second.
It blinks the D7 LED on your Particle device. If you have an LED wired to D0, it will blink that LED as well.

-------------*/


// First, we're going to make some variables.
// This is our "shorthand" that we'll use throughout the program:

int led1 = D0; // Instead of writing D0 over and over again, we'll write led1
// You'll need to wire an LED to this one to see it blink.

int led2 = D7; // Instead of writing D7 over and over again, we'll write led2
// This one is the little blue LED on your board. On the Photon it is next to D7, and on the Core it is next to the USB jack.

// Having declared these variables, let's move on to the setup function.
// The setup function is a standard part of any microcontroller program.
// It runs only once when the device boots up or is reset.

// added proper logger here, such that we see much more details
SerialLogHandler logHandler(LOG_LEVEL_TRACE);

int looped = 0;

void setup() {

  // some time to get our serial line running and connected to a terminal
  delay(5000);

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  
  Log.trace(WiFi.SSID());
   
  delay(5000);
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.dnsServerIP());

}

// Next we have the loop function, the other essential part of a microcontroller program.
// This routine gets repeated over and over, as quickly as possible and as many times as possible, after the setup function is called.
// Note: Code that blocks for too long (like more than 5 seconds), can make weird things happen (like dropping the network connection).  The built-in delay function shown below safely interleaves required background activity, so arbitrarily long delays can safely be done if you need them.

void loop() {
  // To blink the LED, first we'll turn it on...
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);

  // We'll leave it on for 1 second...
  delay(10000);
  Log.trace("Trying particle connect");
  Particle.connect();

  // Then we'll turn it off...
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);

  delay(200);
  Log.trace("Connected to WLAN: %s", WiFi.SSID());

  Log.trace("Publish loop count");
  Particle.publish("lwup", String(looped));

  // Wait 2 seconds...
  delay(3000);
  
  looped++;

  Log.trace("Wifi off");
  WiFi.off();
  // And repeat!
}

And here the log from the serial output:

cat /tmp/3g.log 
0000023607 [app] TRACE: Trying particle connect
0000023807 [app] TRACE: Connected to WLAN: SensorHub_AFORT1
0000023807 [app] TRACE: Publish loop count
0000026808 [app] TRACE: Wifi off
0000026808 [system] INFO: Cloud: disconnecting
0000026808 [system] INFO: Cloud: disconnected
0000036811 [app] TRACE: Trying particle connect
0000036813 [hal.wlan] INFO: Using external antenna
0000036825 [system] INFO: ARM_WLAN_WD 1
0000037672 [system] INFO: ARM_WLAN_WD 2
0000037672 [hal.wlan] INFO: Bringing WiFi interface up with DHCP
0000037694 [system] INFO: CLR_WLAN_WD 1, DHCP success
0000037695 [system] INFO: Cloud: connecting
0000037695 [system] INFO: Read Server Address = type:1,domain:device.spark.io
0000052699 [system] ERROR: Cloud: unable to resolve IP for device.spark.io
0000052699 [system] WARN: Cloud socket connection failed: -1
0000052999 [system] WARN: Internet available, Cloud not reachable!
0000053000 [system] WARN: Handling cloud error: 3
0000053000 [app] TRACE: Connected to WLAN: SensorHub_AFORT1
0000053000 [app] TRACE: Publish loop count
0000054001 [system] INFO: Cloud: connecting
0000054001 [system] INFO: Read Server Address = type:1,domain:device.spark.io
0000069004 [system] ERROR: Cloud: unable to resolve IP for device.spark.io
0000069004 [system] WARN: Cloud socket connection failed: -1
0000069004 [system] WARN: Resetting WLAN due to 2 failed connect attempts
0000069146 [system] WARN: Internet available, Cloud not reachable!
0000069147 [system] WARN: Handling cloud error: 3
0000069147 [app] TRACE: Wifi off
0000079150 [app] TRACE: Trying particle connect
0000079350 [app] TRACE: Connected to WLAN: 
0000079351 [app] TRACE: Publish loop count
0000082351 [app] TRACE: Wifi off
0000092351 [app] TRACE: Trying particle connect
0000092551 [app] TRACE: Connected to WLAN: 
0000092551 [app] TRACE: Publish loop count
0000095552 [app] TRACE: Wifi off
0000105552 [app] TRACE: Trying particle connect
0000105752 [app] TRACE: Connected to WLAN: 
0000105752 [app] TRACE: Publish loop count
0000108752 [app] TRACE: Wifi off
0000118753 [app] TRACE: Trying particle connect
0000118953 [app] TRACE: Connected to WLAN: 
0000118953 [app] TRACE: Publish loop count

I would like to add that a full power cycle does enable the Photon to send data using Particle.publish() one time. As soon as WiFi.off() is called, the complaints about “unable to resolve…” start.

Another addition: it seems that the WiFi.dnsServerIP() is not working. Here an example from the output of this piece of code:

  Serial.println("Local network details:");
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.dnsServerIP());

0000023013 [app] TRACE: try… 0
Local network details:
192.168.1.100
255.255.255.0
192.168.1.1
0.0.0.0

I have made an additional discovery. I added the following to the test code:

  // ping test:
  Log.trace("Ping test....");
  
  // local WLAN gateway
  IPAddress localGW = WiFi.gatewayIP();
  
  int pingTries = 3;
  int pingCount = WiFi.ping(localGW, pingTries);
  Log.trace("Result of ping test to local gateway: %d", pingCount);
  
  // remote ping.xs4all.nl
  IPAddress externalIP(194,109,6,8);
  pingCount = WiFi.ping(externalIP, pingTries);

  Log.trace("Result of ping test to ping.xs4all.nl: %d", pingCount);

And now in the log:
0000174404 [app] INFO: Cloud end Publish, status: 0
0000174405 [system] INFO: Cloud: connecting
0000174405 [system] INFO: Read Server Address = type:1,domain:device.spark.io
0000189408 [system] ERROR: Cloud: unable to resolve IP for device.spark.io
0000189408 [system] WARN: Cloud socket connection failed: -1
0000189550 [system] WARN: Internet available, Cloud not reachable!
0000189550 [system] WARN: Handling cloud error: 3
0000189550 [app] TRACE: Wifi off
0000199554 [app] TRACE: Trying to switch WiFi on…
0000199554 [hal.wlan] INFO: Using external antenna
0000199565 [system] INFO: ARM_WLAN_WD 1
0000200418 [system] INFO: ARM_WLAN_WD 2
0000200418 [hal.wlan] INFO: Bringing WiFi interface up with DHCP
0000200440 [system] INFO: CLR_WLAN_WD 1, DHCP success
0000201440 [app] TRACE: try… 0
Local network details:
192.168.1.100
255.255.255.0
192.168.1.1
0.0.0.0
0000201440 [app] TRACE: Ping test…
0000201445 [app] TRACE: Result of ping test to local gateway: 3
0000202145 [app] TRACE: Result of ping test to ping.xs4all.nl: 3
0000202346 [app] TRACE: Connected to WLAN: SensorHub_AFORT1
0000202346 [app] TRACE: Trying particle connect
0000202346 [app] TRACE: Total loop count 8
0000202346 [app] INFO: Loop Wakeup time: 2792
0000202347 [app] INFO: Cloud end Publish, status: 0
0000202348 [system] INFO: Cloud: connecting
0000202348 [system] INFO: Read Server Address = type:1,domain:device.spark.io
0000217351 [system] ERROR: Cloud: unable to resolve IP for device.spark.io
0000217351 [system] WARN: Cloud socket connection failed: -1
0000217351 [system] WARN: Resetting WLAN due to 2 failed connect attempts
0000217576 [system] WARN: Internet available, Cloud not reachable!
0000217576 [system] WARN: Handling cloud error: 3
0000217576 [app] TRACE: Wifi off

As you can see from the log, the ping tests connection to the local gateway and some remote IP (address is hard-coded) and they are succesfull. However, the photon is unable to resolve device.spark.io. To me this seems like the nameserver is not picked up correctly.

Because this piece of code works fine behind a wired Internet-connection, ti seems like a timing problem related to contacting the DNS.

When I connect with my laptop to the same WiFi access point that is connected via a 3G connection i get these ping results:

PING ping.xs4all.nl (194.109.6.8) 56(84) bytes of data.
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=1 ttl=59 time=131 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=2 ttl=59 time=225 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=3 ttl=59 time=191 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=4 ttl=59 time=214 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=5 ttl=59 time=243 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=6 ttl=59 time=82.4 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=7 ttl=59 time=78.7 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=8 ttl=59 time=77.2 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=9 ttl=59 time=78.1 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=10 ttl=59 time=74.9 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=11 ttl=59 time=73.8 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=12 ttl=59 time=94.8 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=13 ttl=59 time=95.7 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=14 ttl=59 time=82.2 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=15 ttl=59 time=80.0 ms

When I determine the DNS lookup time I get times between 40 and 250 msec.

I’d suggest you read up on SYSTEM_MODE and SYSTEM_THREAD(ENABLED) in connection with WiFi.scan() in the docs.

And waitFor()/waitUntil() in connection with Particle.connected may help too.

You may also sprinkle some Particle,process() statements between commands involving WiFi to allow for propagation of state change between WiFi module and µC.

2 Likes

That sounds like good suggestions. I did add a Particle.process() already, but will add more of them to test. Here is the present sketch I have created so far. Today I can’t test, but tomorrow I will check this. Thanks!

    #define SLEEPTIMESECS 15000     // SW: time seems best trade off
    #define CLOUD_ACK_SAFE 3000     // SW: in msec, Photon bug, have to wait for FW 0.7
    #define WAIT_CONNECT 10000      // SW: arbitrary wait on connect

    char version[]="1.0.4";
    // Toggle between LOG_LEVEL_TRACE (most verbose) or LOG_LEVEL_WARN or LOG_LEVEL_ERROR (least verbose)

    // NOTE: whe setting to LOG_LEVEL_TRACE a 5 sec delay in setup is added
    SerialLogHandler logHandler(LOG_LEVEL_TRACE);

    SYSTEM_MODE(SEMI_AUTOMATIC);
    STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));

    /*
    ############################################
       Let op de antenne!!
       ANT_INTERNAL of ANT_EXTERNAL
    ############################################
    */
    STARTUP(WiFi.selectAntenna(ANT_EXTERNAL));

    retained int Loopcount=0;
    retained int Setupcount=0;

    void goto_sleep() {

      Log.info("Bugger, unable to start WLAN in %d TIME.", WAIT_CONNECT);
      if (WiFi.ready()) {
        Log.info("Switching Wifi off 30 sec.");
        WiFi.off();
      }
      delay(30000);
      Log.info("Switching Wifi on again.");
      WiFi.on();
    }

    //Timer sleepTimer(WAIT_CONNECT, goto_sleep, true);

    void setup() {

       unsigned long starttime = millis();
       unsigned long endtime;

       Setupcount++;

       Log.warn("App version %s",version);

       Log.trace("########### SETUP: Cloud connect start #############");
       
       Log.trace("Before start timer");
       //sleepTimer.start();
       
       Log.trace("Before Particle connect");
       Particle.connect();
       
       Log.trace("Before stop timer");
       //sleepTimer.stop();
       
       Log.info("All good?");

       endtime = millis();
       
       Log.info("WIFI: %s", WiFi.SSID());
       Log.info("Cloud start Publish");
       int status=Particle.publish("setup",String(Setupcount), WITH_ACK);
       Log.info("Cloud setup Publish, status: %d", status);
       Log.info("Setup Wakeup time: %d", endtime-starttime);
       status = Particle.publish("swup",String(endtime-starttime), WITH_ACK);
       Log.info("Cloud end Publish, status: %d", status);

       // make sure connection done to cloud
       delay(CLOUD_ACK_SAFE);

       WiFi.clearCredentials();
       WiFi.setCredentials("SOME_WLAN", "SECRET");
       
       delay(5000);
       Serial.println(WiFi.localIP());
       Serial.println(WiFi.subnetMask());
       Serial.println(WiFi.gatewayIP());
       Serial.println(WiFi.dnsServerIP());
       
       Log.trace("########### SETUP: DONE #############");

    }



    void loop() {
      
      delay(SLEEPTIMESECS);
      
      Log.warn("App version %s",version);
      Log.trace("Wait time is: %d",SLEEPTIMESECS);

      // let's get to work
      unsigned long starttime = millis();
      unsigned long endtime;
       
      Loopcount++;
      
      if (Log.isTraceEnabled()) {
        if (WiFi.ready()) {
            Log.trace("WEIRD, wifi is on!");
        } else {
            Log.trace("OK, wifi is off!");
        }

      }
      
      Log.trace("########### LOOP: Cloud connect start #############");
      
      Log.trace("Before start timer");
      //sleepTimer.start();
      WiFi.on();
      
      delay (2000);
      
      Log.trace("WIFI: %s", WiFi.SSID());
      
      Log.trace("after delay 2 sec");
      
      if (Log.isTraceEnabled()) {

        Serial.println(WiFi.localIP());
        Serial.println(WiFi.subnetMask());
        Serial.println(WiFi.gatewayIP());
        
        Serial.println(WiFi.dnsServerIP());
      }
      
      IPAddress ip = WiFi.resolve("device.spark.io");
      
      if (ip) {
        Log.trace("IP address was resolved");
      } else {
        Log.trace("Unable to resolve IP address");
      }
       
      Log.trace("Before Particle connect");
      Particle.connect();
       
      Log.trace("Before stop timer");
      //sleepTimer.stop();
       
      Log.trace("All good?");

      endtime = millis();
      
      Log.info("Cloud start Publish");
      
      int status=Particle.publish("loop",String(Loopcount), WITH_ACK);
      Log.info("Cloud setup Publish, status: %d", status);
      
      Log.info("Loop Wakeup time: %d", endtime-starttime);
      
      status = Particle.publish("lwup",String(endtime-starttime), WITH_ACK);
      Log.info("Cloud end Publish, status: %d", status);
      
      delay(CLOUD_ACK_SAFE);

      // WiFi off for real life test
      WiFi.off();
      
      Log.warn("Loop count: %d", Loopcount);
      
      Log.trace("########### LOOP: DONE #############");
      
    }
2 Likes

This morning I tested with mode in semi_automatic, but the connection to the cloud keeps on failing (“could not resolve device.spark.io”). I will execute more testing tomorrow and publish the results.

Does anyone know what timeout is used for DNS resolution?

Thanks.

Ok, I just finished additional testing. Sparying the code with Particle.process() does not help. Actually I tested the DNS issue by switching from 3G back to wired Internet. The Photon seems to hang on ot being able to resolve. I need a reboot/reset make the Photon connect again.

This is the latest code I use for testing:
#define WAIT_CONNECT 5000 // SW: arbitrary wait on connect

SYSTEM_MODE(SEMI_AUTOMATIC);

int led1 = D0;

int led2 = D7;

SerialLogHandler logHandler(LOG_LEVEL_TRACE);

void goto_sleep() {

  Log.info("Bugger, unable to start WLAN in %d TIME.", WAIT_CONNECT);
  if (WiFi.ready()) {
    Log.info("Disconnecting from Particle cloud.");
    Particle.disconnect();
    Log.info("Switching Wifi off %d msec.",WAIT_CONNECT);
    WiFi.off();
  }
  delay(WAIT_CONNECT);
  Log.info("Done with extra delay. Back to the loop");
}

Timer sleepTimer(WAIT_CONNECT, goto_sleep, true);

int looped = 0;

void setup() {
    
  // some time to get our serial line running and connected to a terminal
  delay(5000);

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  
  Log.trace(WiFi.SSID());
   
  delay(5000);
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.dnsServerIP());

}

// Next we have the loop function, the other essential part of a microcontroller program.
// This routine gets repeated over and over, as quickly as possible and as many times as possible, after the setup function is called.
// Note: Code that blocks for too long (like more than 5 seconds), can make weird things happen (like dropping the network connection).  The built-in delay function shown below safely interleaves required background activity, so arbitrarily long delays can safely be done if you need them.

void loop() {
  // To blink the LED, first we'll turn it on...
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  
  // let's get to work
  unsigned long starttime = millis();
  unsigned long endtime;
  
  delay(WAIT_CONNECT);
  
  Log.trace("Trying to switch WiFi on....");
  
  sleepTimer.start();
  
  WiFi.on();
  WiFi.connect();
  
  for(int i=0;i<5;i++) {
    delay(200);
    if (WiFi.ready()) {
    Log.trace(" try... %d",i);
        break;
    }
  }
  
  Particle.process();
  
  Serial.println("Local network details:");
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.dnsServerIP());
  
  // ping test:
  Log.trace("Ping test....");
  
  // local WLAN gateway
  IPAddress localGW = WiFi.gatewayIP();
  
  int pingTries = 3;
  int pingCount = WiFi.ping(localGW, pingTries);
  Log.trace("Result of ping test to local gateway: %d", pingCount);
  
  // remote ping.xs4all.nl
  IPAddress externalIP(194,109,6,8);
  pingCount = WiFi.ping(externalIP, pingTries);

  Log.trace("Result of ping test to ping.xs4all.nl: %d", pingCount);
  // Then we'll turn it off...
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);

  delay(200);
  Log.trace("Connected to WLAN: %s", WiFi.SSID());

  Log.trace("Trying particle connect");
  Particle.process();
  Particle.connect();
  
  sleepTimer.stop();

  Log.trace("Total loop count %d", looped);
  
  endtime = millis();
  
  Log.info("Loop Wakeup time: %d", endtime-starttime);
  Particle.process();
  int status = Particle.publish("lwup",String(endtime-starttime), WITH_ACK);
  Log.info("Cloud end Publish, status: %d", status);

  Particle.process();
  Serial.println(WiFi.dnsServerIP());

  // Wait 2 seconds...
  delay(200);
  Particle.disconnect();
  
  looped++;

  Log.trace("Wifi off");
  WiFi.off();
  // And repeat!
}

Does this problem happen if you just connect the Photon to the 3G router with the router in 3G mode, not starting in wired mode? Lots of folks are able to use hotspots with Photons.

Is that switching between wired/3G the same way you did the laptop experiment? Did you first connect the laptop to the router with wired internet and then switch the router to 3G? Is the laptop renegotiating a DHCP address, gateway, and DNS server when you do this?

If it is possible for this workflow to work with a Photon, my feeling is that you will have to use manual mode and completely manage the connection, including possibly rebooting when you discover that the DNS settings have gone stale.

1 Like

bko,
Thanks for trying to help me out here. When I connect to the router and switch from wired to 3G, the Wifi on the router goes down and my laptop reconnects. But when I have connection again, my laptop works fine including DNS resolution. But even when I start the Photon with conection to the router that has a 3G WAN connection, the problem is immediately there, so switching is not the issue and also involves for the photon a new lease from the router.

I was actually planning to rewrite my code into manual mode. Will try to do that in the next 30 min.

Keep you posted on this.
Edge

When your laptop connects to the hotspot in 3G mode, it would be good to see what the DNS server is. Normally on Windows you use ipconfig -all in a cmd shell to get this.

If you can’t get the DNS to work with Photon on the 3G router in 3G mode, something on one side or the other is not configured right.

1 Like

I am a Linux user. I just ran MANUAL mode. You can actually see the DNS is the problem:

000447171 [app] TRACE: Trying to switch WiFi on…
0000447172 [hal.wlan] INFO: Using external antenna
0000447184 [system] INFO: ARM_WLAN_WD 1
0000448002 [system] INFO: ARM_WLAN_WD 2
0000448002 [hal.wlan] INFO: Bringing WiFi interface up with DHCP
0000448034 [system] INFO: CLR_WLAN_WD 1, DHCP success
0000448234 [app] TRACE: try… 0
Local network details:
192.168.1.100
255.255.255.0
192.168.1.1
0.0.0.0
0000448234 [app] TRACE: Ping test…
0000448240 [app] TRACE: Result of ping test to local gateway: 3
0000449046 [app] TRACE: Result of ping test to ping.xs4all.nl: 3
0000449246 [app] TRACE: Connected to WLAN: SensorHub_AFORT1
0000449246 [app] TRACE: Trying particle connect
0000449247 [system] INFO: Cloud: connecting
0000449247 [system] INFO: Read Server Address = type:1,domain:device.spark.io
0000464250 [system] ERROR: Cloud: unable to resolve IP for device.spark.io
0000464250 [system] WARN: Cloud socket connection failed: -1
0000464250 [system] WARN: Resetting WLAN due to 2 failed connect attempts
0000464331 [system] WARN: Internet available, Cloud not reachable!
0000464331 [system] WARN: Handling cloud error: 3
0000464331 [app] TRACE: Total loop count 46
0000464331 [app] INFO: Loop Wakeup time: 22160
0000464332 [system] WARN: Resetting WLAN due to SPARK_WLAN_RESET
0000464335 [app] INFO: Cloud end Publish, status: 0
0000464336 [hal.wlan] INFO: Using external antenna
0000464338 [system] INFO: ARM_WLAN_WD 1
0000465001 [system] INFO: ARM_WLAN_WD 2
0000465001 [hal.wlan] INFO: Bringing WiFi interface up with DHCP
0000465023 [system] INFO: CLR_WLAN_WD 1, DHCP success
0.0.0.0
0000465224 [app] TRACE: Wifi off
0000470230 [app] TRACE: Trying to switch WiFi on…
0000470230 [hal.wlan] INFO: Using external antenna
0000470243 [system] INFO: ARM_WLAN_WD 1
0000471043 [system] INFO: ARM_WLAN_WD 2
0000471043 [hal.wlan] INFO: Bringing WiFi interface up with DHCP
0000471064 [system] INFO: CLR_WLAN_WD 1, DHCP success
0000471264 [app] TRACE: try… 0
Local network details:
192.168.1.100
255.255.255.0
192.168.1.1
0.0.0.0
0000471264 [app] TRACE: Ping test…
0000471269 [app] TRACE: Result of ping test to local gateway: 3
0000471558 [app] TRACE: Result of ping test to ping.xs4all.nl: 3
0000471758 [app] TRACE: Connected to WLAN: SensorHub_AFORT1
0000471758 [app] TRACE: Trying particle connect
0000471759 [system] INFO: Cloud: connecting
0000471759 [system] INFO: Read Server Address = type:1,domain:device.spark.io

See the bold line. That IP address is outside. So it does have Internet connectivity. My laptop is now on 3G as well:

time dig device.spark.io

; <<>> DiG 9.10.3-P4-Ubuntu <<>> device.spark.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13985
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;device.spark.io. IN A

;; ANSWER SECTION:
device.spark.io. 60 IN CNAME device.nodes.spark.io.
device.nodes.spark.io. 59 IN A 54.90.239.114

;; Query time: 131 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Fri May 19 17:25:22 CEST 2017
;; MSG SIZE rcvd: 87

real 0m0,170s
user 0m0,028s
sys 0m0,004s

and my ping test:
ping ping.xs4all.nl
PING ping.xs4all.nl (194.109.6.8) 56(84) bytes of data.
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=1 ttl=59 time=62.5 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=2 ttl=59 time=83.7 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=3 ttl=59 time=79.4 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=4 ttl=59 time=88.0 ms
64 bytes from ping.xs4all.nl (194.109.6.8): icmp_seq=5 ttl=59 time=88.8 ms
^C
— ping.xs4all.nl ping statistics —
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 62.562/80.559/88.876/9.613 ms

My latest code:

#define WAIT_CONNECT 5000      // SW: arbitrary wait on connect

SYSTEM_MODE(MANUAL);
//SYSTEM_MODE(SEMI_AUTOMATIC);


int led1 = D0;

int led2 = D7;

SerialLogHandler logHandler(LOG_LEVEL_TRACE);

void goto_sleep() {

  Log.info("Bugger, unable to start WLAN in %d TIME.", WAIT_CONNECT);
  if (WiFi.ready()) {
    Log.info("Disconnecting from Particle cloud.");
    Particle.disconnect();
    Log.info("Switching Wifi off %d msec.",WAIT_CONNECT);
    WiFi.off();
  }
  delay(WAIT_CONNECT);
  Log.info("Done with extra delay. Back to the loop");
}

Timer sleepTimer(WAIT_CONNECT, goto_sleep, true);

int looped = 0;

void setup() {
    
  // some time to get our serial line running and connected to a terminal
  delay(5000);

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  
  Log.trace(WiFi.SSID());
   
  delay(5000);
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.dnsServerIP());

}

// Next we have the loop function, the other essential part of a microcontroller program.
// This routine gets repeated over and over, as quickly as possible and as many times as possible, after the setup function is called.
// Note: Code that blocks for too long (like more than 5 seconds), can make weird things happen (like dropping the network connection).  The built-in delay function shown below safely interleaves required background activity, so arbitrarily long delays can safely be done if you need them.

void loop() {
  // To blink the LED, first we'll turn it on...
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  
  // let's get to work
  unsigned long starttime = millis();
  unsigned long endtime;
  
  delay(WAIT_CONNECT);
  
  Log.trace("Trying to switch WiFi on....");
  
  sleepTimer.start();
  
  WiFi.on();
  WiFi.connect();
  
  for(int i=0;i<5;i++) {
    delay(200);
    if (WiFi.ready()) {
    Log.trace(" try... %d",i);
        break;
    }
  }
  
  Serial.println("Local network details:");
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.dnsServerIP());
  
  // ping test:
  Log.trace("Ping test....");
  
  // local WLAN gateway
  IPAddress localGW = WiFi.gatewayIP();
  
  int pingTries = 3;
  int pingCount = WiFi.ping(localGW, pingTries);
  Log.trace("Result of ping test to local gateway: %d", pingCount);
  
  // remote ping.xs4all.nl
  IPAddress externalIP(194,109,6,8);
  pingCount = WiFi.ping(externalIP, pingTries);

  Log.trace("Result of ping test to ping.xs4all.nl: %d", pingCount);
  // Then we'll turn it off...
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);

  delay(200);
  Log.trace("Connected to WLAN: %s", WiFi.SSID());

  Log.trace("Trying particle connect");
  Particle.connect();
  
  if (Particle.connected) {
    
    sleepTimer.stop();
    
    Particle.process();

    Log.trace("Total loop count %d", looped);
  
    endtime = millis();
  
    Log.info("Loop Wakeup time: %d", endtime-starttime);
    Particle.process();
    int status = Particle.publish("lwup",String(endtime-starttime), WITH_ACK);
    Log.info("Cloud end Publish, status: %d", status);

    Particle.process();
    Serial.println(WiFi.dnsServerIP());

    // Wait 2 seconds...
    delay(200);
    Particle.disconnect();
    
  }
  
  looped++;

  Log.trace("Wifi off");
  WiFi.off();
  // And repeat!
}

This is weird. This says your laptop is using a local host (on the 127.0.0.0 subnet) as a DNS server. When I do that on a regularly connected machine, the SERVER and DNS server (use nmcli) are the same and are not on a private subnet.

There is something fishy about the 3g router setup in my opinion.

Well, that is the modern way they pass DNS requests on Linux via a localhost socket. Via systemd.

http://manpages.ubuntu.com/manpages/xenial/man1/systemd-resolve.1.html

Wow, it seems you were right…
I changed the DNS servers via DHCP to Google DNS 8.8.8.8 and 8.8.4.4 and that … works!

Likely I have caching in my laptop and the photon does not.

Anyway, I am very happy this is solved now!!!

Thanks for helping along.

1 Like

New details from the DHCP lease. Not sure if the issue is with the router or my 3G ISP.

1 Like

Hi @edge_support

I think your laptop likely has more than one DNS server listed in resolv.conf and that is why DNS works there. The Photon can only have exactly one DNS server.

Actually I also discovered that my “3G Only” setting on the TP-Link MR6400 does not works in a stable manner. I switched to “4G preferred” and that seems like a stable connection. Here are my settings from the UI where you can see the “4G preferred”.