#include <zephyr.h>
#include <zephyr/types.h>
#include <sys/printk.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/gpio.h>
#include <modem/lte_lc.h>
#include <net/socket.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#define SERVER_ADDR "52.78.123.53"
#define SERVER_PORT 39634 // server increase first byte
static int sock;
static struct pollfd fds;
static struct sockaddr_storage server_addr;
static uint8_t tx_buf[512]; // we have a lot of ram space!!!!
static uint8_t rx_buf[512]; // me too
// return 0: we got the packet
// return -EAGAIN : no packet
static int wait(int timeout)
{
int ret = poll(&fds, 1, timeout);
if (ret == 0) return -EAGAIN; // no packet
if (ret < 0)
{
printk("@modem.wait:poll err=%d\n", errno);
return -errno;
}
if ((fds.revents & POLLERR) == POLLERR) {
printk("@modem.wait:POLLERR\n");
return -EIO;
}
if ((fds.revents & POLLNVAL) == POLLNVAL) {
printk("@modem.wait:POLLNVAL\n");
return -EBADF;
}
if ((fds.revents & POLLIN) != POLLIN) return -EAGAIN;
return 0; // packet exsist
}
// return -1 : error
// return 0 :no packet
// return >0 :recv packet size
int udp_recv(uint8_t *buf, int maxlen, int timeout_ms)
{
int ret;
if(maxlen <= 0) return -1; // parameter error:maxlen must be larger then 0
if(timeout_ms <= 0) return -1; // parameter error:timeout_ms must be larger then 0
ret = wait(timeout_ms);
if (ret < 0)
{
if (ret == -EAGAIN) return 0; // no packet
printk("@modem.recv:wait err=%d\n", ret);
return ret; // error on 'wait'
}
ret = recv(sock, buf, maxlen, MSG_DONTWAIT);
if (ret < 0)
{
if (errno == EAGAIN || errno == EWOULDBLOCK) return 0;
else
{
printk("@modem.recv:recv err=%d\n", ret);
return ret;
}
}
if (ret == 0) return 0; // no packet
return ret; // recv length
}
// return:sent bytes
int udp_send(uint8_t *buf, int len)
{
int ret;
ret = send(sock, buf, len, 0);
if (ret < 0)
{
printk("@modem.send:err.%d\n", errno);
}
return ret;
}
void main()
{
int err, firstByte;
int tx_ret, rx_ret;
struct sockaddr_in *server4 = ((struct sockaddr_in *)&server_addr);
printk("\n****** Hello. GettingStarted - mySooniUDP ******\n");
// #1. LTE link
printk("lte:init and connect...\n"); // takes about 10~30seconds
err = lte_lc_init_and_connect();
if (err)
{
printk("@lte:error=%d\n", err);
return;
}
printk("lte:connected.\n");
// #2. UDP Socket
// address parse
server4->sin_family = AF_INET;
server4->sin_port = htons((uint16_t)SERVER_PORT);
inet_pton(AF_INET, SERVER_ADDR, &server4->sin_addr);
// socket create
printk("socket:create...\n");
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
{
printk("@socket:create err=%d\n", errno);
(void)close(sock);
return;
}
printk("socket:create ok.\n");
// socket connect
printk("socket:connect...\n");
err = connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));
if(err != 0)
{
printk("@socket:connect err=%d\n", errno);
(void)close(sock);
return;
}
printk("socket:connect ok.\n");
/* Initialize FDS, for poll. */
fds.fd = sock;
fds.events = POLLIN;
printk("let's send/recv packet\n");
// #3. while
firstByte = 0;
while(true)
{
tx_buf[0] = (uint8_t)firstByte;
rx_buf[0] = 0;
printk("packet-%d:send at %u\n", firstByte, k_uptime_get_32());
tx_ret = udp_send(tx_buf, 4);
rx_ret = udp_recv(rx_buf, 512, 5000);
if((tx_ret > 0) && (rx_ret > 0))
{
tx_buf[0]++;
if(tx_buf[0] == rx_buf[0]) printk("packet-%d:recv at %u, okay\n", firstByte, k_uptime_get_32());
else printk("packet-%d:recv at %u, wrong\n", firstByte, k_uptime_get_32());
}
else
{
printk("@packet-%d:error\n", firstByte);
// do something for exception.
}
firstByte++;
printk("sleep:8000ms...\n");
k_msleep(8000);
}
}