This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

UDP questions

Hello,

I work on nbiot evaluation and i try to send udp data from my basement.. I boot and attach network from ground-floor and when i'm on PSM mode im going on basement.

I wonder when i wake up from to PSM mode to send my udp data if my nbiot module need a reception phase (RX) from eNb to send data ? My test doesn't work and i wonder why i don't receive data on my server... It's possible my nrf9160 need reception phase from the eNb even if i deactivated message from RAI config?

I use control plane cIoT EPS optimisation.. maybe it's possible to send data without reception from eNb when i wake up from PSM ?

  • Hello,

    I use this FW to try to send udp trame from my basement but i have a bit modified for receive on my own serveur and see differently configuration like XRAI = 4 & CSCON Slight smile

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
     */
    
    #include <lte_lc.h>
    #include <net/socket.h>
    #include <stdio.h>
    #include <string.h>
    #include <uart.h>
    #include <zephyr.h>
    
    #define NTP_HOST "server url :)"
    #define NTP_PORT 41234
    #define RECV_BUF_SIZE 1024
    #define SEND_BUF_SIZE 1024
    
    /* Chapter 3: https://www.eecis.udel.edu/~mills/y2k.html 
     * Need to convert from 1900 -> 1970
     */
    #define NTP_TO_UNIX_OFFSET 2208988800ULL
    
    char recv_buf[RECV_BUF_SIZE];
    
    
    /* From NTP RFCs https://www.ietf.org/rfc/rfc5905.txt */
    struct ntp_format {
      u8_t flags;
      u8_t stratum;       /* stratum */
      u8_t poll;          /* poll interval */
      s8_t precision;     /* precision */
      u32_t rootdelay;    /* root delay */
      u32_t rootdisp;     /* root dispersion */
      u32_t refid;        /* reference ID */
      u32_t reftime_sec;  /* reference time */
      u32_t reftime_frac; /* reference time */
      u32_t org_sec;      /* origin timestamp */
      u32_t org_frac;     /* origin timestamp */
      u32_t rec_sec;      /* receive timestamp */
      u32_t rec_frac;     /* receive timestamp */
      u32_t xmt_sec;      /* transmit timestamp */
      u32_t xmt_frac;     /* transmit timestamp */
    };
    
    int blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags) {
      int err;
    
      do {
        err = recv(fd, buf, size, flags);
      } while (err < 0 && errno == EAGAIN);
    
      return err;
    }
    
    int blocking_recvfrom(int fd, void *buf, u32_t size, u32_t flags,
        struct sockaddr *src_addr, socklen_t *addrlen) {
      int err;
    
      do {
        err = recvfrom(fd, buf, size, flags, src_addr, addrlen);
      } while (err < 0 && errno == EAGAIN);
    
      return err;
    }
    
    int blocking_send(int fd, u8_t *buf, u32_t size, u32_t flags) {
      int err;
    
      do {
        err = send(fd, buf, size, flags);
      } while (err < 0 && errno == EAGAIN);
    
      return err;
    }
    
    int blocking_connect(int fd, struct sockaddr *local_addr, socklen_t len) {
      int err;
    
      do {
        err = connect(fd, local_addr, len);
      } while (err < 0 && errno == EAGAIN);
    
      return err;
    }
    
    void setup_psm(void) {
      /*
    	* GPRS Timer 3 value (octet 3)
    	*
    	* Bits 5 to 1 represent the binary coded timer value.
    	*
    	* Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
    	* Bits 
    	* 8 7 6
    	* 0 0 0 value is incremented in multiples of 10 minutes 
    	* 0 0 1 value is incremented in multiples of 1 hour 
    	* 0 1 0 value is incremented in multiples of 10 hours
    	* 0 1 1 value is incremented in multiples of 2 seconds
    	* 1 0 0 value is incremented in multiples of 30 seconds
    	* 1 0 1 value is incremented in multiples of 1 minute
    	* 1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
    	* 1 1 1 value indicates that the timer is deactivated (NOTE 2).
    	*/
      char psm_settings[] = CONFIG_LTE_PSM_REQ_RPTAU;
      printk("PSM bits: %c%c%c\n", psm_settings[0], psm_settings[1],
          psm_settings[2]);
      printk("PSM Interval: %c%c%c%c%c\n", psm_settings[3], psm_settings[4],
          psm_settings[5], psm_settings[6], psm_settings[7]);
      int err = lte_lc_psm_req(true);
      if (err < 0) {
        printk("Error setting PSM: %d Errno: %d\n", err, errno);
      }
    }
    
    void ntp_swap_endianess(struct ntp_format *ntp) {
      if (ntp) {
        ntp->org_frac = htonl(ntp->org_frac);
        ntp->org_sec = htonl(ntp->org_sec);
        ntp->reftime_frac = htonl(ntp->reftime_frac);
        ntp->reftime_sec = htonl(ntp->reftime_sec);
        ntp->rec_frac = htonl(ntp->rec_frac);
        ntp->rec_sec = htonl(ntp->rec_sec);
        ntp->xmt_frac = htonl(ntp->xmt_frac);
        ntp->xmt_sec = htonl(ntp->xmt_sec);
      }
    }
    
    void ntp_print(struct ntp_format *ntp) {
      if (ntp == NULL) {
        return;
      }
    
      printk("Flags: %u\n", ntp->flags);
      printk("Stratum: %u\n", ntp->stratum);
      printk("Poll: %u\n", ntp->poll);
      printk("Precision: %u\n", ntp->precision);
      printk("Root delay: %u\n", ntp->rootdelay);
      printk("Root dispersion: %u\n", ntp->rootdisp);
      printk("Ref ID: %u\n", ntp->refid);
      printk("Ref timestamp: %u", ntp->reftime_sec);
      printk("%u\n", ntp->reftime_frac);
      printk("Orig Timestamp: %u", ntp->org_sec);
      printk("%u\n", ntp->org_frac);
      printk("Receive timestamp: %u", ntp->rec_sec);
      printk("%u\n", ntp->rec_frac);
      printk("Transmit: %u", ntp->xmt_sec);
      printk("%u\n", ntp->xmt_frac);
    
      u32_t unix_time = ntp->xmt_sec - NTP_TO_UNIX_OFFSET;
      printk("Unix time: %d\n", unix_time);
    
      time_t time = unix_time;
      printf("Time: %s", ctime(&time));
    }
    
    /****************************************************************************************************
    *name: 
    *to do:  PSM mode
    *return: 
    ****************************************************************************************************/
    void PSM_etat(void) {
    
      const char *at_commandsOFF[] = {
          "AT+CSCON?",
      };
    
      /* Ouverture Socket */
      int at_socket_fd = socket(AF_LTE, 0, NPROTO_AT);
    
      if (at_socket_fd < 0) {
        printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
      }
      /* Envoi Commande AT */
      for (int i = 0; i < ARRAY_SIZE(at_commandsOFF); i++) {
        int bytes_written = send(at_socket_fd, at_commandsOFF[i],
            strlen(at_commandsOFF[i]), 0);
        if (bytes_written > 0) {
          int r_bytes =
              blocking_recv(at_socket_fd, recv_buf,
                  sizeof(recv_buf), MSG_DONTWAIT);
          if (r_bytes > 0) {
            printk("%s", recv_buf);
          }
        }
      }
      /* Fermeture Socket */
      (void)close(at_socket_fd);
    }
    
    void PSM_config(void) {
    
      const char *at_commandsOFF[] = {
          "AT+CSCON = 3"};
    
      /* Ouverture Socket */
      int at_socket_fd = socket(AF_LTE, 0, NPROTO_AT);
    
      if (at_socket_fd < 0) {
        printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
      }
      /* Envoi Commande AT */
      for (int i = 0; i < ARRAY_SIZE(at_commandsOFF); i++) {
        int bytes_written = send(at_socket_fd, at_commandsOFF[i],
            strlen(at_commandsOFF[i]), 0);
        if (bytes_written > 0) {
          int r_bytes =
              blocking_recv(at_socket_fd, recv_buf,
                  sizeof(recv_buf), MSG_DONTWAIT);
          if (r_bytes > 0) {
            printk("%s", recv_buf);
          }
        }
      }
      /* Fermeture Socket */
      (void)close(at_socket_fd);
    }
    
    void RAI_setup(void) {
    
      const char *at_commandsOFF[] = {
          "AT%XRAI=4"};
    
      /* Ouverture Socket */
      int at_socket_fd = socket(AF_LTE, 0, NPROTO_AT);
    
      if (at_socket_fd < 0) {
        printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
      }
      /* Envoi Commande AT */
      for (int i = 0; i < ARRAY_SIZE(at_commandsOFF); i++) {
        int bytes_written = send(at_socket_fd, at_commandsOFF[i],
            strlen(at_commandsOFF[i]), 0);
        if (bytes_written > 0) {
          int r_bytes =
              blocking_recv(at_socket_fd, recv_buf,
                  sizeof(recv_buf), MSG_DONTWAIT);
          if (r_bytes > 0) {
            printk("%s", recv_buf);
          }
        }
      }
      /* Fermeture Socket */
      (void)close(at_socket_fd);
    }
    
    void RAI_config(void) {
    
      const char *at_commandsOFF[] = {
          "AT%XRAI?"};
    
      /* Ouverture Socket */
      int at_socket_fd = socket(AF_LTE, 0, NPROTO_AT);
    
      if (at_socket_fd < 0) {
        printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
      }
      /* Envoi Commande AT */
      for (int i = 0; i < ARRAY_SIZE(at_commandsOFF); i++) {
        int bytes_written = send(at_socket_fd, at_commandsOFF[i],
            strlen(at_commandsOFF[i]), 0);
        if (bytes_written > 0) {
          int r_bytes =
              blocking_recv(at_socket_fd, recv_buf,
                  sizeof(recv_buf), MSG_DONTWAIT);
          if (r_bytes > 0) {
            printk("%s", recv_buf);
          }
        }
      }
      /* Fermeture Socket */
      (void)close(at_socket_fd);
    }
    
    void app_ntp_socket_start(void) {
      struct addrinfo *res;
      struct ntp_format ntp = {0x48};
      socklen_t addrlen = sizeof(struct sockaddr_storage);
    
      /* Just hard code the packet format */
    	//u8_t send_buf[sizeof(struct ntp_format)] = { 0x48,0x65,0x6c,0x6c,0x6f };
            u8_t send_buf[sizeof(struct ntp_format)] = { 0x48};
    
      ntp.flags = 0xe3;
      int err = getaddrinfo(NTP_HOST, NULL, NULL, &res);
    
      printk("getaddrinfo err: %d\n\r", err);
      ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(NTP_PORT);
      struct sockaddr_in local_addr;
    
      local_addr.sin_family = AF_INET;
      local_addr.sin_port = htons(0);
      local_addr.sin_addr.s_addr = 0;
    
      int client_fd = socket(AF_INET, SOCK_DGRAM, 0);
      printk("client_fd: %d\n\r", client_fd);
    
      err = bind(client_fd, (struct sockaddr *)&local_addr,
          sizeof(local_addr));
      printk("bind err: %d\n\r", err);
    
      err = blocking_connect(client_fd, (struct sockaddr *)res->ai_addr,
          sizeof(struct sockaddr_in));
      if (err < 0) {
        printk("connect err: %d\n\r", errno);
      }
    
      err = send(client_fd, send_buf, sizeof(send_buf), 0);
      printk("sendto ret: %d\n\r", err);
      // freeaddrinfo(res);
      //(void)close(client_fd);
    
      if (err < 0) {
        printk("sendto err: %d\n\r", errno);
      }
    
      //err = blocking_recvfrom(client_fd, &ntp, sizeof(struct ntp_format), 0,
      //(struct sockaddr *)res->ai_addr, &addrlen);
      if (err < 0) {
        printk("recvfrom err: %d\n\r", errno);
      }
    
      ntp_swap_endianess(&ntp);
      ntp_print(&ntp);
      freeaddrinfo(res);
      (void)close(client_fd);
    }
    
    static volatile bool run_udp;
    
    void app_timer_handler(struct k_timer *dummy) {
      static u32_t minutes;
    
      minutes++;
      /* This shall match the PSM interval */
      if (minutes % 10 == 0) {
        run_udp = true;
      }
      printk("Elapsed time: %d\n", minutes);
    }
    
    K_TIMER_DEFINE(app_timer, app_timer_handler, NULL);
    
    void timer_init(void) {
      k_timer_start(&app_timer, K_MINUTES(1), K_MINUTES(1));
    }
    int main(void) {
    
      if (!IS_ENABLED(CONFIG_AT_HOST_LIBRARY)) {
        /* Stop the UART RX for power consumption reasons */
        NRF_UARTE0_NS->TASKS_STOPRX = 1;
      }
    
      printk("DATA POST test with PSM\n");
    
      app_ntp_socket_start();
    
      PSM_config();
      RAI_config();
    
      RAI_setup();
      setup_psm();
    
      PSM_etat();
      RAI_config();
    
      timer_init();
      k_sleep(30000);
    
      PSM_etat();
      while (1) {
        k_sleep(5000);
        if (run_udp == true) {
          printk("Run HTTP POST\n");
          run_udp = false;
    
          app_ntp_socket_start();
        }
      }
      return 1;
    }

    And the log:

    (09:52:24.015) SPM: prepare to jump to Non-Secure image.
    (09:52:25.663) ***** Booting Zephyr OS build v2.0.99-ncs1-rc1-11-g9be97c63368a *****
    (09:52:54.821) +CEREG: 2,"C356","00124DD0",9,0,0,"11100000","11100000"
    (09:53:07.796) +CEREG: 1,"C356","00124DD0",9,,,"11100000","11100000"
    (09:53:07.818) DATA POST test with PSM
    (09:53:11.641) getaddrinfo err: 0
    (09:53:11.648) <CR>client_fd: 3
    (09:53:11.648) <CR>bind err: 0
    (09:53:11.648) <CR>sendto ret: 48
    (09:53:11.648) <CR>Flags: 227
    (09:53:11.718) Stratum: 0
    (09:53:11.718) Poll: 0
    (09:53:11.718) Precision: 0
    (09:53:11.718) Root delay: 0
    (09:53:11.718) Root dispersion: 0
    (09:53:11.718) Ref ID: 0
    (09:53:11.718) Ref timestamp: 00
    (09:53:11.718) Orig Timestamp: 00
    (09:53:11.718) Receive timestamp: 00
    (09:53:11.718) Transmit: 00
    (09:53:11.718) Unix time: 2085978496
    (09:53:11.718) Time: Thu Feb  7 06:28:16 2036<CR>
    (09:53:11.718) ERROR<CR>
    (09:53:11.718) %XRAI: 0<CR>
    (09:53:11.718) OK<CR>
    (09:53:11.718) OK<CR>
    (09:53:11.718) PSM bits: 101
    (09:53:11.718) PSM Interval: 01010
    (09:53:11.718) +CSCON: 0,1<CR>
    (09:53:11.718) OK<CR>
    (09:53:11.718) %XRAI: 4<CR>
    (09:53:11.718) OK<CR>
    (09:53:17.144) +CEREG: 1,"C356","00124DD0",9,,,"00000000","10010100"
    (09:53:41.690) +CSCON: 0,0<CR>
    (09:53:41.699) OK<CR>
    (09:54:11.681) Elapsed time: 1
    (09:55:11.677) Elapsed time: 2
    (09:56:11.677) Elapsed time: 3
    (09:57:11.677) Elapsed time: 4
    (09:58:11.675) Elapsed time: 5
    (09:59:11.668) Elapsed time: 6
    (10:00:11.671) Elapsed time: 7
    (10:01:11.663) Elapsed time: 8
    (10:02:11.669) Elapsed time: 9
    (10:03:11.669) Elapsed time: 10
    (10:03:11.760) Run HTTP POST
    (10:03:11.760) getaddrinfo err: 0
    (10:03:11.760) <CR>client_fd: 3
    (10:03:11.760) <CR>bind err: 0
    (10:03:11.760) <CR>sendto ret: 48
    (10:03:11.760) <CR>Flags: 227
    (10:03:11.760) Stratum: 0
    (10:03:11.760) Poll: 0
    (10:03:11.760) Precision: 0
    (10:03:11.760) Root delay: 0
    (10:03:11.760) Root dispersion: 0
    (10:03:11.760) Ref ID: 0
    (10:03:11.760) Ref timestamp: 00
    (10:03:11.760) Orig Timestamp: 00
    (10:03:11.760) Receive timestamp: 00
    (10:03:11.760) Transmit: 00
    (10:03:11.760) Unix time: 2085978496
    (10:03:11.760) Time: Thu Feb  7 06:28:16 2036<CR>
    (10:03:53.920) +CEREG: 1,"FFFE","FFFFFFFF",9,,,"00000000","10010100"
    (10:04:11.667) Elapsed time: 11
    

    As i said before, i send one udp trame, i configure modem to XRAI 4 and switch on psm mode (with verification) n ground floor.

    On "Elapsed time 5" i'm going to my basement and wait to send second udp trame. But we can see transmission with

    "(10:03:11.760) Run HTTP POST
    (10:03:11.760) getaddrinfo err: 0
    (10:03:11.760) <CR>client_fd: 3
    (10:03:11.760) <CR>bind err: 0
    (10:03:11.760) <CR>sendto ret: 48"

    But i don't get anything on my server...


    I have commented:
     //err = blocking_recvfrom(client_fd, &ntp, sizeof(struct ntp_format), 0,
    //(struct sockaddr *)res->ai_addr, &addrlen);
    to not get stuck

    To send an udp frame, does my device necessarily need to receive a request from the server?

  • Did you try running the udp_with_psm sample I showed you earlier? Also, where is the UDP server located? Are you hosting it on the nrf9160? Could you provide some context for what you are trying to do?

Related