Telit WE310G4
Client_We310G4.c (created by ChatGPT)
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#define SERIAL_PORT "/dev/ttyUSB0"
#define BAUDRATE B115200
#define CMD_BUF_SIZE 2048
#define READ_BUF_SIZE 1024
// #define SERVER_ADDR "192.168.43.137"
#define SERVER_ADDR "192.168.2.37"
#define SERVER_PORT 8080
#define TEXT_FILE "messages.txt"
#define MAX_LINE 1024
#define MAX_SEND (MAX_LINE + 32) // extra space for =number
int serial_fd;
char cid_value[16] = {0};
char recv_data_len[16] = {0};
void tprintf(const char *format, ...);
// Helper function to print timestamped messages
void tprintf(const char *format, ...) {
time_t current_time;
struct tm *local_time;
char time_str[32];
time(¤t_time);
local_time = localtime(¤t_time);
strftime(time_str, sizeof(time_str), "[%Y-%m-%d %H:%M:%S]", local_time);
printf("%s ", time_str);
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
int configure_serial(const char *device) {
struct termios tty;
serial_fd = open(device, O_RDWR | O_NOCTTY);
if (serial_fd < 0) {
perror("Error opening serial port");
return -1;
}
if (tcgetattr(serial_fd, &tty) != 0) {
perror("tcgetattr");
return -1;
}
cfsetospeed(&tty, BAUDRATE);
cfsetispeed(&tty, BAUDRATE);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
tty.c_iflag &= ~IGNBRK;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 10;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag &= ~(PARENB | PARODD);
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr(serial_fd, TCSANOW, &tty) != 0) {
perror("tcsetattr");
return -1;
}
return 0;
}
// send_command now returns:
// 0 = OK
// -1 = timeout/error
// -2 = module returned ERROR
int send_command(const char *cmd, char *response, size_t resp_size,
int timeout_sec) {
char cmd_with_crlf[CMD_BUF_SIZE];
fd_set readfds;
struct timeval tv;
int n;
snprintf(cmd_with_crlf, sizeof(cmd_with_crlf), "%s\r\n", cmd);
write(serial_fd, cmd_with_crlf, strlen(cmd_with_crlf));
size_t total_read = 0;
memset(response, 0, resp_size);
while (1) {
FD_ZERO(&readfds);
FD_SET(serial_fd, &readfds);
tv.tv_sec = timeout_sec;
tv.tv_usec = 0;
int rv = select(serial_fd + 1, &readfds, NULL, NULL, &tv);
if (rv == -1) {
perror("select");
return -1;
} else if (rv == 0) {
tprintf("Timeout waiting for response to: %s\n", cmd);
return -1;
} else {
n = read(serial_fd, response + total_read, resp_size - total_read - 1);
if (n > 0) {
total_read += n;
response[total_read] = '\0';
// if (strstr(response, "OK")) {
// return 0; // Success
// }
// if (strstr(response, "ERROR")) {
// return -2; // Module ERROR
// }
if (strstr(cmd, "AT+SRR")) {
if (strstr(response, "+SRR:") && strstr(response, "OK")) {
return 0; // Valid AT+SRR response
}
if (strstr(response, "OK") && !strstr(response, "+SRR:")) {
tprintf("AT+SRR returned only OK, retry needed.\n");
return -1; // Treat as timeout/incomplete → force retry
}
} else {
if (strstr(response, "OK")) {
return 0; // Success
}
}
if (strstr(response, "ERROR")) {
return -2; // Module ERROR
}
} else if (n < 0) {
perror("read");
return -1;
}
}
}
return -1; // No valid result found before timeout
}
void extract_cid(const char *resp) {
char *p = strstr(resp, "+SC:");
if (p) {
int cid;
if (sscanf(p, "+SC:%d", &cid) == 1) {
snprintf(cid_value, sizeof(cid_value), "%d", cid);
tprintf("CID recorded: %s\n", cid_value);
}
}
}
void extract_recv_len(const char *resp) {
char *p = strstr(resp, "+SRR:");
if (p) {
int cid, port, len;
char ip[32];
if (sscanf(p, "+SRR:%d,%31[^,],%d,%d", &cid, ip, &port, &len) == 4) {
snprintf(recv_data_len, sizeof(recv_data_len), "%d", len);
tprintf("recv_data_len recorded: %s\n", recv_data_len);
}
}
}
#define CMD_CHECK_RETRY(cmd, resp, t, retries) \
do { \
int attempt = 0; \
while (attempt < retries) { \
int ret = send_command(cmd, resp, sizeof(resp), t); \
tprintf("[RX] %s", resp); \
if (ret == 0) \
break; /* Success */ \
if (ret == -1) { \
tprintf("TIMEOUT: %s (attempt %d/%d)\n", cmd, attempt + 1, retries); \
} else if (ret == -2) { \
tprintf("ERROR: %s (attempt %d/%d)\n", cmd, attempt + 1, retries); \
} \
attempt++; \
if (attempt < retries) { \
sleep(2); /* wait before retry */ \
} else { \
tprintf("Command failed after %d retries: %s\n", retries, cmd); \
goto recover; /* jump to recovery */ \
} \
} \
} while (0)
int main() {
char resp[READ_BUF_SIZE];
if (configure_serial(SERIAL_PORT) != 0)
return 1;
FILE *fp = fopen(TEXT_FILE, "r");
if (!fp) {
perror("Failed to open messages.txt");
return 1;
}
recover:
CMD_CHECK_RETRY("AT+WNI=0", resp, 15, 3);
CMD_CHECK_RETRY("AT+WNCN=1,\"UNEO_Pi4\",\"uneo1234\"", resp, 15, 3);
CMD_CHECK_RETRY("AT+SC=2,1,0", resp, 15, 3);
extract_cid(resp);
char cmd[CMD_BUF_SIZE];
snprintf(cmd, sizeof(cmd), "AT+SCO=%s,%s,%d", cid_value, SERVER_ADDR,
SERVER_PORT);
CMD_CHECK_RETRY(cmd, resp, 15, 3);
char line[MAX_LINE];
char send_str[MAX_SEND];
int i = 0;
for (;;) {
// Try reading next line
if (!fgets(line, sizeof(line), fp)) {
// If EOF, rewind file and read again
rewind(fp);
if (!fgets(line, sizeof(line), fp)) {
tprintf("No messages in file!\n");
break;
}
}
// Remove newline
line[strcspn(line, "\r\n")] = 0;
snprintf(send_str, sizeof(send_str), "%s", line);
int msg_len = strlen(send_str);
snprintf(cmd, sizeof(cmd), "AT+SN=%s,%s,%d,%d,%s", cid_value, SERVER_ADDR,
SERVER_PORT, msg_len, send_str);
// snprintf(cmd, sizeof(cmd), "AT+SN=%s,%s,%d,%ld,%s", cid_value,
// SERVER_ADDR,
// SERVER_PORT, strlen(send_str) + 1, send_str);
CMD_CHECK_RETRY(cmd, resp, 15, 3);
snprintf(cmd, sizeof(cmd), "AT+SRR=%s", cid_value);
CMD_CHECK_RETRY(cmd, resp, 15, 3);
extract_recv_len(resp);
snprintf(cmd, sizeof(cmd), "AT+SR=%s,%s", cid_value, recv_data_len);
CMD_CHECK_RETRY(cmd, resp, 15, 3);
sleep(1);
// i++;
}
fclose(fp);
snprintf(cmd, sizeof(cmd), "AT+SCL=%s", cid_value);
CMD_CHECK_RETRY(cmd, resp, 3, 3);
close(serial_fd);
return 0;
}
Server_Client.c (created by Gemini)
#include <arpa/inet.h>
#include <asm-generic/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>
#define BUFFER_SIZE 16384
#define RESPONSE_BUF_SIZE 128
#define TIMEOUT_SEC 300
void log_with_timestamp(const char *format, ...) {
time_t now = time(NULL);
struct tm *t = localtime(&now);
char timestamp[64];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", t);
printf("[%s] ", timestamp);
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
void server(int port) {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
char resp[RESPONSE_BUF_SIZE] = {0};
int keepalive = 1; // Enable keepalive
int keepidle =
TIMEOUT_SEC +
10; // Start keeplives after TIMEOUT_SEC + 10 seconds of idle time
int keepcnt = 3; // Send 3 keepalive probes
int keepintvl = 2; // Interval between keepalive probes: 2 seconds
struct timeval tv;
fd_set readfds;
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt,
sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// Enable keepalive on the server socket
if (setsockopt(server_fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
sizeof(keepalive)) < 0) {
perror("setsockopt SO_KEEPALIVE");
exit(EXIT_FAILURE);
}
// Set keepalive options (TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT)
if (setsockopt(server_fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle,
sizeof(keepidle)) < 0) {
perror("setsockopt TCP_KEEPIDLE");
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl,
sizeof(keepintvl)) < 0) {
perror("setsockopt TCP_KEEPINTVL");
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt,
sizeof(keepcnt)) < 0) {
perror("setsockopt TCP_KEEPCNT");
exit(EXIT_FAILURE);
}
log_with_timestamp("Server listening on port %d...\n", port);
int i = 0;
while (1) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t *)&addrlen)) < 0) {
perror("accept");
continue;
}
log_with_timestamp("Client connected.\n");
// Set socket to non-blocking
fcntl(new_socket, F_SETFL, O_NONBLOCK);
while (1) {
FD_ZERO(&readfds);
FD_SET(new_socket, &readfds);
tv.tv_sec = TIMEOUT_SEC;
tv.tv_usec = 0;
int retval = select(new_socket + 1, &readfds, NULL, NULL, &tv);
if (retval == -1) {
perror("select");
break;
} else if (retval == 0) {
// Timeout: No data received within TIMEOUT_SEC
log_with_timestamp("Client timeout (no data received).\n");
break;
} else {
memset(buffer, 0, BUFFER_SIZE);
ssize_t bytes_received = recv(new_socket, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0';
log_with_timestamp("Received from client: %s\n", buffer);
// Prepare and send response to client
char *response = "Message received successfully!Message received "
"successfully!Message received successfully!";
snprintf(resp, sizeof(resp), "%s-%d", response, i);
send(new_socket, resp, strlen(resp), 0);
log_with_timestamp("Sent response to client.\n");
i++;
if (i == 65534)
i = 0;
} else if (bytes_received == 0) {
printf("Client disconnected gracefully.\n");
break;
} else {
if (errno == ECONNRESET || errno == EPIPE) {
log_with_timestamp("Client disconnected unexpectedly.\n");
break;
} else {
perror("recv");
break;
}
}
}
}
close(new_socket);
}
close(server_fd);
}
void client(const char *ip_address, int port) {
int sock = 0;
struct sockaddr_in serv_addr;
char buffer[BUFFER_SIZE] = {0};
char message[BUFFER_SIZE];
int keepalive = 1; // Enable keepalive
int keepidle = 10; // Start keeplives after 10 seconds of idle time
int keepcnt = 3; // Send 3 keepalive probes
int keepintvl = 2; // Interval between keepalive probes: 2 seconds
fd_set readfds;
struct timeval tv;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket creation error");
return;
}
// Enable keepalive
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
sizeof(keepalive)) < 0) {
perror("setsockopt SO_KEEPALIVE");
close(sock);
return;
}
// Set keepalive options (TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT)
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle)) <
0) {
perror("setsockopt TCP_KEEPIDLE");
close(sock);
return;
}
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl,
sizeof(keepintvl)) < 0) {
perror("setsockopt TCP_KEEPINTVL");
close(sock);
return;
}
if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt)) <
0) {
perror("setsockopt TCP_KEEPCNT");
close(sock);
return;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip_address, &serv_addr.sin_addr) <= 0) {
perror("Invalid address/ Address not supported");
return;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("Connection Failed");
return;
}
log_with_timestamp(
"Connected to server. Enter messages (type 'exit' to quit):\n");
// Set socket to non-blocking
fcntl(sock, F_SETFL, O_NONBLOCK);
// Set stdin to non-blocking
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
while (1) {
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
FD_SET(STDIN_FILENO, &readfds);
tv.tv_sec = 1; // 1-second timeout for select
tv.tv_usec = 0;
printf("> ");
fflush(stdout);
int max_fd = (sock > STDIN_FILENO) ? sock : STDIN_FILENO;
int retval = select(max_fd + 1, &readfds, NULL, NULL, &tv);
if (retval == -1) {
perror("select");
break;
}
// Check if there is data from the server
if (FD_ISSET(sock, &readfds)) {
memset(buffer, 0, BUFFER_SIZE);
ssize_t bytes_received = recv(sock, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0';
printf("\nServer response: %s\n", buffer);
} else if (bytes_received == 0) {
printf("\nServer disconnected gracefully.\n");
break;
} else {
if (errno != EWOULDBLOCK && errno != EINTR) {
perror("\nrecv");
break;
}
}
}
// Check if there is user input
if (FD_ISSET(STDIN_FILENO, &readfds)) {
fgets(message, BUFFER_SIZE, stdin);
message[strcspn(message, "\n")] = 0;
if (strcmp(message, "exit") == 0) {
break;
}
send(sock, message, strlen(message), 0);
}
}
close(sock);
}
int main(int argc, char const *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s <server|client> <port> [ip_address]\n", argv[0]);
return 1;
}
int port = atoi(argv[2]);
if (port <= 0 || port > 65535) {
fprintf(stderr, "Invalid port number\n");
return 1;
}
if (strcmp(argv[1], "server") == 0) {
server(port);
} else if (strcmp(argv[1], "client") == 0) {
if (argc < 4) {
fprintf(stderr, "Usage: %s client <port> <ip_address>\n", argv[0]);
return 1;
}
client(argv[3], port);
} else {
fprintf(stderr, "Invalid mode: %s\n", argv[1]);
return 1;
}
return 0;
}