### Send Email Example with SMTP Client Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Demonstrates how to initialize the SMTP client, connect to a server, log in, and send a simple text email. Includes error handling and cleanup procedures. ```c #include "smtp/smtp_client.h" error_t sendEmailExample(void) { error_t error; SmtpClientContext smtpContext; IpAddr serverIpAddr; size_t written; // Define email addresses SmtpMailAddr from = { .name = "Embedded Device", .addr = "device@example.com", .type = SMTP_ADDR_TYPE_FROM }; SmtpMailAddr recipients[] = { { .name = "Admin", .addr = "admin@example.com", .type = SMTP_ADDR_TYPE_TO }, { .name = "Support", .addr = "support@example.com", .type = SMTP_ADDR_TYPE_CC } }; // Initialize SMTP client error = smtpClientInit(&smtpContext); if (error) return error; // Set timeout smtpClientSetTimeout(&smtpContext, 30000); // Resolve SMTP server error = getHostByName(NULL, "smtp.example.com", &serverIpAddr, HOST_TYPE_IPV4); if (error) { smtpClientDeinit(&smtpContext); return error; } // Connect to SMTP server (STARTTLS) error = smtpClientConnect(&smtpContext, &serverIpAddr, SMTP_SUBMISSION_PORT, SMTP_MODE_EXPLICIT_TLS); if (error) { printf("SMTP connection failed: %d\r\n", error); smtpClientDeinit(&smtpContext); return error; } // Login with credentials error = smtpClientLogin(&smtpContext, "device@example.com", "password123"); if (error) goto cleanup; printf("SMTP login successful\r\n"); // Simple text email error = smtpClientWriteMailHeader(&smtpContext, &from, recipients, 2, "Alert: Temperature Warning"); if (error) goto cleanup; const char *body = "The temperature sensor has detected an abnormal reading.\r\n" "Current temperature: 85.5 C\r\n" "Threshold: 80.0 C\r\n\r\n" "Please check the system immediately."; error = smtpClientWriteMailBody(&smtpContext, body, strlen(body), &written, 0); if (error) goto cleanup; error = smtpClientCloseMailBody(&smtpContext); if (error) goto cleanup; printf("Email sent successfully!\r\n"); // Email with attachment (multipart) smtpClientSetContentType(&smtpContext, "multipart/mixed"); smtpClientSetMultipartBoundary(&smtpContext, "----=_Part_001"); error = smtpClientWriteMailHeader(&smtpContext, &from, recipients, 1, "Report: Daily Log"); if (error) goto cleanup; // Text part error = smtpClientWriteMultipartHeader(&smtpContext, NULL, "text/plain", NULL, FALSE); if (error) goto cleanup; const char *textPart = "Please find the daily log attached."; smtpClientWriteMultipartBody(&smtpContext, textPart, strlen(textPart), &written, 0); // Attachment part error = smtpClientWriteMultipartHeader(&smtpContext, "log.txt", "text/plain", "base64", TRUE); // TRUE = last part if (error) goto cleanup; const char *attachment = "2024-01-15 10:00:00 - System started\r\n" "2024-01-15 10:05:23 - Sensor initialized\r\n" "2024-01-15 10:10:45 - First reading: 25.5 C\r\n"; // Note: In production, encode attachment as base64 smtpClientWriteMultipartBody(&smtpContext, attachment, strlen(attachment), &written, 0); error = smtpClientCloseMailBody(&smtpContext); if (error == NO_ERROR) { printf("Email with attachment sent!\r\n"); } cleanup: smtpClientDisconnect(&smtpContext); smtpClientClose(&smtpContext); smtpClientDeinit(&smtpContext); return error; } ``` -------------------------------- ### Perform HTTP GET and POST Requests Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Demonstrates the lifecycle of an HTTP request including initialization, connection, header configuration, and body transmission. ```c #include "http/http_client.h" error_t httpClientGetRequest(void) { error_t error; HttpClientContext httpContext; IpAddr serverIpAddr; uint_t statusCode; char buffer[1024]; size_t received; // Initialize HTTP client error = httpClientInit(&httpContext); if (error) return error; // Set timeout httpClientSetTimeout(&httpContext, 20000); // Resolve server address error = getHostByName(NULL, "api.example.com", &serverIpAddr, HOST_TYPE_IPV4); if (error) { httpClientDeinit(&httpContext); return error; } // Connect to HTTP server error = httpClientConnect(&httpContext, &serverIpAddr, 80); if (error) { httpClientDeinit(&httpContext); return error; } // Create HTTP request httpClientCreateRequest(&httpContext); httpClientSetMethod(&httpContext, "GET"); httpClientSetUri(&httpContext, "/api/data"); httpClientSetHost(&httpContext, "api.example.com", 80); httpClientAddHeaderField(&httpContext, "Accept", "application/json"); httpClientAddHeaderField(&httpContext, "User-Agent", "CycloneTCP/2.6.2"); // Send request header error = httpClientWriteHeader(&httpContext); if (error) goto cleanup; // Read response header error = httpClientReadHeader(&httpContext); if (error) goto cleanup; // Get status code statusCode = httpClientGetStatus(&httpContext); printf("HTTP Status: %u\r\n", statusCode); // Get Content-Type header const char *contentType = httpClientGetHeaderField(&httpContext, "Content-Type"); if (contentType) { printf("Content-Type: %s\r\n", contentType); } // Read response body while (1) { error = httpClientReadBody(&httpContext, buffer, sizeof(buffer) - 1, &received, 0); if (error == ERROR_END_OF_STREAM) break; if (error) goto cleanup; buffer[received] = '\0'; printf("%s", buffer); } // Close body httpClientCloseBody(&httpContext); cleanup: httpClientDisconnect(&httpContext); httpClientDeinit(&httpContext); return (error == ERROR_END_OF_STREAM) ? NO_ERROR : error; } error_t httpClientPostRequest(void) { error_t error; HttpClientContext httpContext; IpAddr serverIpAddr; size_t written; // Initialize and connect (similar to GET) httpClientInit(&httpContext); httpClientSetTimeout(&httpContext, 20000); ipStringToAddr("192.168.1.50", &serverIpAddr); httpClientConnect(&httpContext, &serverIpAddr, 80); // POST request with JSON body const char *jsonBody = "{\"sensor\":\"temperature\",\"value\":25.5}"; size_t bodyLen = strlen(jsonBody); httpClientCreateRequest(&httpContext); httpClientSetMethod(&httpContext, "POST"); httpClientSetUri(&httpContext, "/api/sensors"); httpClientSetHost(&httpContext, "192.168.1.50", 80); httpClientAddHeaderField(&httpContext, "Content-Type", "application/json"); httpClientSetContentLength(&httpContext, bodyLen); // Send header error = httpClientWriteHeader(&httpContext); if (error) goto cleanup; // Send body error = httpClientWriteBody(&httpContext, jsonBody, bodyLen, &written, 0); if (error) goto cleanup; // Read response error = httpClientReadHeader(&httpContext); printf("POST Response: %u\r\n", httpClientGetStatus(&httpContext)); cleanup: httpClientCloseBody(&httpContext); httpClientDisconnect(&httpContext); httpClientDeinit(&httpContext); return error; } ``` -------------------------------- ### Start DHCP Client Configuration Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Initializes and starts the DHCP client for a given network interface. It configures settings such as the interface, IP address index, rapid commit, manual DNS, and timeout, and registers state change and timeout event callbacks. Ensure the NetInterface is valid before calling. ```c error_t startDhcpClient(NetInterface *interface) { error_t error; DhcpClientSettings settings; // Get default settings dhcpClientGetDefaultSettings(&settings); // Configure DHCP client settings.interface = interface; settings.ipAddrIndex = 0; settings.rapidCommit = FALSE; settings.manualDnsConfig = FALSE; settings.timeout = 30000; // Register callbacks settings.stateChangeEvent = dhcpStateChangeCallback; settings.timeoutEvent = dhcpTimeoutCallback; // Initialize DHCP client error = dhcpClientInit(&dhcpClientContext, &settings); if (error) return error; // Start DHCP client error = dhcpClientStart(&dhcpClientContext); if (error) { dhcpClientDeinit(&dhcpClientContext); return error; } printf("DHCP client started\r\n"); return NO_ERROR; } ``` -------------------------------- ### FTP Client Example Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Demonstrates the usage of the CycloneTCP FTP client for various operations including connecting, logging in, changing directories, listing contents, downloading, uploading, creating directories, renaming, and deleting files. Ensure proper error handling and resource deinitialization. ```c #include "ftp/ftp_client.h" error_t ftpClientExample(void) { error_t error; FtpClientContext ftpContext; IpAddr serverIpAddr; FtpDirEntry dirEntry; char buffer[1024]; size_t length; // Initialize FTP client error = ftpClientInit(&ftpContext); if (error) return error; // Set timeout ftpClientSetTimeout(&ftpContext, 30000); // Resolve server address ipStringToAddr("192.168.1.200", &serverIpAddr); // Connect to FTP server (passive mode) error = ftpClientConnect(&ftpContext, &serverIpAddr, 21, FTP_MODE_PLAINTEXT | FTP_MODE_PASSIVE); if (error) { ftpClientDeinit(&ftpContext); return error; } // Login error = ftpClientLogin(&ftpContext, "username", "password"); if (error) goto cleanup; printf("FTP login successful\r\n"); // Get current working directory char currentDir[128]; error = ftpClientGetWorkingDir(&ftpContext, currentDir, sizeof(currentDir)); if (error == NO_ERROR) { printf("Current directory: %s\r\n", currentDir); } // Change directory error = ftpClientChangeWorkingDir(&ftpContext, "/data"); if (error) goto cleanup; // List directory contents error = ftpClientOpenDir(&ftpContext, "."); if (error == NO_ERROR) { printf("Directory listing:\r\n"); while (ftpClientReadDir(&ftpContext, &dirEntry) == NO_ERROR) { printf(" %c %8lu %s\r\n", (dirEntry.attributes & FTP_FILE_ATTR_DIRECTORY) ? 'd' : '-', dirEntry.size, dirEntry.name); } ftpClientCloseDir(&ftpContext); } // Download a file error = ftpClientOpenFile(&ftpContext, "config.txt", FTP_FILE_MODE_READ | FTP_FILE_MODE_TEXT); if (error == NO_ERROR) { printf("File contents:\r\n"); while (1) { error = ftpClientReadFile(&ftpContext, buffer, sizeof(buffer) - 1, &length, 0); if (error) break; buffer[length] = '\0'; printf("%s", buffer); } ftpClientCloseFile(&ftpContext); printf("\r\n"); } // Upload a file error = ftpClientOpenFile(&ftpContext, "upload.txt", FTP_FILE_MODE_WRITE | FTP_FILE_MODE_TEXT); if (error == NO_ERROR) { const char *content = "Hello from CycloneTCP!\r\nLine 2\r\nLine 3\r\n"; size_t written; error = ftpClientWriteFile(&ftpContext, content, strlen(content), &written, 0); ftpClientCloseFile(&ftpContext); if (error == NO_ERROR) { printf("File uploaded successfully (%u bytes)\r\n", written); } } // Create directory ftpClientCreateDir(&ftpContext, "backup"); // Rename file ftpClientRenameFile(&ftpContext, "upload.txt", "upload_backup.txt"); // Delete file ftpClientDeleteFile(&ftpContext, "temp.txt"); cleanup: ftpClientDisconnect(&ftpContext); ftpClientClose(&ftpContext); ftpClientDeinit(&ftpContext); return error; } ``` -------------------------------- ### C: Socket Polling Example Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Use this example to monitor multiple sockets for events like new connections, incoming data, or disconnections. It requires the 'core/socket.h' header. ```c #include "core/socket.h" error_t socketPollingExample(void) { error_t error; Socket *tcpServer, *udpSocket; Socket *clients[4] = {NULL}; SocketEventDesc eventDesc[6]; uint_t numEvents; int i; // Create TCP server socket tcpServer = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP); socketBind(tcpServer, &IP_ADDR_ANY, 8080); socketListen(tcpServer, 4); // Create UDP socket udpSocket = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_IP_PROTO_UDP); socketBind(udpSocket, &IP_ADDR_ANY, 5000); printf("Polling server started...\r\n"); while (1) { numEvents = 0; // Add TCP server to poll (wait for new connections) eventDesc[numEvents].socket = tcpServer; eventDesc[numEvents].eventMask = SOCKET_EVENT_ACCEPT; eventDesc[numEvents].eventFlags = 0; numEvents++; // Add UDP socket to poll eventDesc[numEvents].socket = udpSocket; eventDesc[numEvents].eventMask = SOCKET_EVENT_RX_READY; eventDesc[numEvents].eventFlags = 0; numEvents++; // Add connected clients to poll for (i = 0; i < 4; i++) { if (clients[i] != NULL) { eventDesc[numEvents].socket = clients[i]; eventDesc[numEvents].eventMask = SOCKET_EVENT_RX_READY | SOCKET_EVENT_CLOSED; eventDesc[numEvents].eventFlags = 0; numEvents++; } } // Wait for events (5 second timeout) error = socketPoll(eventDesc, numEvents, NULL, 5000); if (error == ERROR_TIMEOUT) { printf("Poll timeout, no events\r\n"); continue; } if (error) { printf("Poll error: %d\r\n", error); break; } // Process events for (i = 0; i < numEvents; i++) { if (eventDesc[i].eventFlags == 0) continue; // New TCP connection if (eventDesc[i].socket == tcpServer && (eventDesc[i].eventFlags & SOCKET_EVENT_ACCEPT)) { IpAddr clientAddr; uint16_t clientPort; Socket *newClient = socketAccept(tcpServer, &clientAddr, &clientPort); if (newClient != NULL) { // Find free slot for (int j = 0; j < 4; j++) { if (clients[j] == NULL) { clients[j] = newClient; char ipStr[40]; ipAddrToString(&clientAddr, ipStr); printf("Client connected from %s:%u\r\n", ipStr, clientPort); break; } } } } // UDP data received if (eventDesc[i].socket == udpSocket && (eventDesc[i].eventFlags & SOCKET_EVENT_RX_READY)) { char buffer[256]; IpAddr srcAddr; uint16_t srcPort; size_t received; error = socketReceiveFrom(udpSocket, &srcAddr, &srcPort, buffer, sizeof(buffer) - 1, &received, 0); if (error == NO_ERROR) { buffer[received] = '\0'; printf("UDP: %s\r\n", buffer); // Echo back socketSendTo(udpSocket, &srcAddr, srcPort, buffer, received, NULL, 0); } } // TCP client events for (int j = 0; j < 4; j++) { if (clients[j] != NULL && eventDesc[i].socket == clients[j]) { if (eventDesc[i].eventFlags & SOCKET_EVENT_CLOSED) { printf("Client disconnected\r\n"); socketClose(clients[j]); clients[j] = NULL; } else if (eventDesc[i].eventFlags & SOCKET_EVENT_RX_READY) { char buffer[256]; size_t received, written; error = socketReceive(clients[j], buffer, sizeof(buffer), &received, 0); if (error == NO_ERROR) { // Echo back socketSend(clients[j], buffer, received, &written, 0); } } } } } } // Cleanup socketClose(tcpServer); socketClose(udpSocket); for (i = 0; i < 4; i++) { if (clients[i]) socketClose(clients[i]); } return NO_ERROR; } ``` -------------------------------- ### Initialize TCP/IP Stack Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Configures network interfaces, MAC addresses, and drivers before starting the stack. Requires defining a NetContext and NetInterface structure. ```c #include "core/net.h" // Define network interfaces static NetInterface netInterface[1]; // TCP/IP stack context static NetContext netContext; void initTcpIpStack(void) { error_t error; NetSettings settings; MacAddr macAddr; Ipv4Addr ipv4Addr; // Get default settings netGetDefaultSettings(&settings); // Configure network interfaces settings.interfaces = netInterface; settings.numInterfaces = 1; // Initialize TCP/IP stack error = netInit(&netContext, &settings); if (error) { printf("Failed to initialize TCP/IP stack!\r\n"); return; } // Get default interface NetInterface *interface = netGetDefaultInterface(&netContext); // Set interface name netSetInterfaceName(interface, "eth0"); // Set host name netSetHostname(interface, "MyDevice"); // Set MAC address macStringToAddr("00-AB-CD-EF-01-23", &macAddr); netSetMacAddr(interface, &macAddr); // Set NIC driver netSetDriver(interface, &stm32f4xxEthDriver); netSetPhyDriver(interface, &lan8720PhyDriver); // Configure interface error = netConfigInterface(interface); // Set static IPv4 address ipv4StringToAddr("192.168.1.100", &ipv4Addr); ipv4SetHostAddr(interface, ipv4Addr); // Set subnet mask ipv4StringToAddr("255.255.255.0", &ipv4Addr); ipv4SetSubnetMask(interface, ipv4Addr); // Set default gateway ipv4StringToAddr("192.168.1.1", &ipv4Addr); ipv4SetDefaultGateway(interface, ipv4Addr); // Start TCP/IP stack error = netStart(&netContext); printf("TCP/IP stack started successfully!\r\n"); } ``` -------------------------------- ### DNS Resolution Example Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Demonstrates various DNS resolution scenarios, including IPv4, IPv6, and any address type resolution for hostnames. It also shows how to use mDNS for local network resolution and integrate DNS resolution with socket connections. Requires core/socket.h and dns/dns_client.h. ```c #include "core/socket.h" #include "dns/dns_client.h" error_t dnsResolutionExample(void) { error_t error; IpAddr ipAddr; char ipAddrStr[40]; // Simple hostname resolution (IPv4) error = getHostByName(NULL, "www.example.com", &ipAddr, HOST_TYPE_IPV4); if (error == NO_ERROR) { ipAddrToString(&ipAddr, ipAddrStr); printf("www.example.com resolved to: %s\r\n", ipAddrStr); } else { printf("DNS resolution failed: %d\r\n", error); } // IPv6 resolution error = getHostByName(NULL, "ipv6.google.com", &ipAddr, HOST_TYPE_IPV6); if (error == NO_ERROR) { ipAddrToString(&ipAddr, ipAddrStr); printf("ipv6.google.com resolved to: %s\r\n", ipAddrStr); } // Use specific interface NetInterface *interface = netGetDefaultInterface(&netContext); error = getHostByName(interface, "api.server.local", &ipAddr, HOST_TYPE_ANY); if (error == NO_ERROR) { ipAddrToString(&ipAddr, ipAddrStr); printf("api.server.local resolved to: %s\r\n", ipAddrStr); } // Resolve using mDNS (.local domains) error = getHostByName(interface, "printer.local", &ipAddr, HOST_TYPE_IPV4 | HOST_NAME_RESOLVER_MDNS); if (error == NO_ERROR) { ipAddrToString(&ipAddr, ipAddrStr); printf("printer.local (mDNS) resolved to: %s\r\n", ipAddrStr); } // Using DNS resolution in socket connect Socket *socket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP); if (socket != NULL) { error = getHostByName(NULL, "httpbin.org", &ipAddr, HOST_TYPE_IPV4); if (error == NO_ERROR) { error = socketConnect(socket, &ipAddr, 80); if (error == NO_ERROR) { printf("Connected to httpbin.org\r\n"); } } socketClose(socket); } return NO_ERROR; } ``` -------------------------------- ### Implement CoAP Client Communication Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Demonstrates initializing a CoAP client, configuring transport settings, and performing both GET and POST requests. Ensure the CoAP context is properly deinitialized after use to prevent resource leaks. ```c #include "coap/coap_client.h" #include "coap/coap_client_request.h" error_t coapClientExample(void) { error_t error; CoapClientContext coapContext; CoapClientRequest *request; IpAddr serverIpAddr; // Initialize CoAP client error = coapClientInit(&coapContext); if (error) return error; // Configure client coapClientSetTransportProtocol(&coapContext, COAP_TRANSPORT_PROTOCOL_UDP); coapClientSetTimeout(&coapContext, 10000); coapClientSetTokenLength(&coapContext, 4); // Resolve server address ipStringToAddr("192.168.1.100", &serverIpAddr); // Connect to CoAP server error = coapClientConnect(&coapContext, &serverIpAddr, 5683); if (error) { coapClientDeinit(&coapContext); return error; } // Create GET request request = coapClientCreateRequest(&coapContext); if (request == NULL) { coapClientDisconnect(&coapContext); coapClientDeinit(&coapContext); return ERROR_OUT_OF_RESOURCES; } // Initialize request coapClientInitRequest(request); // Set request parameters coapClientSetRequestType(request, COAP_TYPE_CON); coapClientSetRequestCode(request, COAP_CODE_GET); // Add URI path options coapClientSetUriPath(request, "/sensors/temperature"); // Add query parameters (optional) coapClientSetUriQuery(request, "unit=celsius"); // Send request and wait for response error = coapClientSendRequest(request, NULL, NULL); if (error) { coapClientDeleteRequest(request); goto cleanup; } // Get response CoapCode responseCode; error = coapClientGetResponseCode(request, &responseCode); printf("CoAP Response: %u.%02u\r\n", COAP_GET_CODE_CLASS(responseCode), COAP_GET_CODE_SUBCLASS(responseCode)); // Read response payload const uint8_t *payload; size_t payloadLen; error = coapClientGetPayload(request, &payload, &payloadLen); if (error == NO_ERROR && payloadLen > 0) { printf("Payload: %.*s\r\n", (int)payloadLen, payload); } // POST request example coapClientInitRequest(request); coapClientSetRequestType(request, COAP_TYPE_CON); coapClientSetRequestCode(request, COAP_CODE_POST); coapClientSetUriPath(request, "/actuators/led"); // Set content format coapClientSetContentFormat(request, COAP_CONTENT_FORMAT_TEXT_PLAIN); // Set payload const char *postPayload = "ON"; coapClientSetPayload(request, postPayload, strlen(postPayload)); // Send POST request error = coapClientSendRequest(request, NULL, NULL); coapClientDeleteRequest(request); cleanup: coapClientDisconnect(&coapContext); coapClientDeinit(&coapContext); return error; } ``` -------------------------------- ### Get DHCP Client State Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Retrieves the current state of the DHCP client. This function can be used for monitoring or decision-making based on the client's operational status. ```c DhcpState getDhcpState(void) { return dhcpClientGetState(&dhcpClientContext); } ``` -------------------------------- ### Implement MQTT Client Messaging Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Initializes the MQTT client, configures connection parameters, and handles message publishing and subscription in a loop. ```c #include "mqtt/mqtt_client.h" static MqttClientContext mqttContext; // Publish callback - called when message received void mqttPublishCallback(MqttClientContext *context, const char_t *topic, const uint8_t *message, size_t length, bool_t dup, MqttQosLevel qos, bool_t retain, uint16_t packetId) { char msgBuf[256]; size_t len = MIN(length, sizeof(msgBuf) - 1); memcpy(msgBuf, message, len); msgBuf[len] = '\0'; printf("MQTT Message on '%s': %s\r\n", topic, msgBuf); // Process sensor data if (!strcmp(topic, "sensors/temperature")) { float temp = atof(msgBuf); printf("Temperature: %.1f C\r\n", temp); } } error_t mqttClientExample(void) { error_t error; IpAddr brokerIpAddr; uint16_t packetId; // Initialize MQTT client error = mqttClientInit(&mqttContext); if (error) return error; // Register publish callback mqttClientRegisterPublishCallback(&mqttContext, mqttPublishCallback); // Configure client mqttClientSetVersion(&mqttContext, MQTT_VERSION_3_1_1); mqttClientSetTransportProtocol(&mqttContext, MQTT_TRANSPORT_PROTOCOL_TCP); mqttClientSetTimeout(&mqttContext, 20000); mqttClientSetKeepAlive(&mqttContext, 60); // Set client identifier mqttClientSetIdentifier(&mqttContext, "CycloneTCP_Device_001"); // Set credentials (optional) mqttClientSetAuthInfo(&mqttContext, "username", "password"); // Set will message (optional) mqttClientSetWillMessage(&mqttContext, "devices/status", "offline", 7, MQTT_QOS_LEVEL_1, TRUE); // Resolve broker address error = getHostByName(NULL, "broker.example.com", &brokerIpAddr, HOST_TYPE_IPV4); if (error) { mqttClientDeinit(&mqttContext); return error; } // Connect to broker (clean session) error = mqttClientConnect(&mqttContext, &brokerIpAddr, 1883, TRUE); if (error) { printf("MQTT connection failed!\r\n"); mqttClientDeinit(&mqttContext); return error; } printf("Connected to MQTT broker\r\n"); // Subscribe to topics error = mqttClientSubscribe(&mqttContext, "sensors/#", MQTT_QOS_LEVEL_1, &packetId); if (error) goto cleanup; printf("Subscribed to sensors/#\r\n"); // Publish a message const char *payload = "{\"status\":\"online\",\"version\":\"1.0\"}"; error = mqttClientPublish(&mqttContext, "devices/status", payload, strlen(payload), MQTT_QOS_LEVEL_1, TRUE, &packetId); if (error) goto cleanup; printf("Published device status\r\n"); // Process incoming messages (main loop) while (1) { error = mqttClientTask(&mqttContext, 1000); if (error && error != ERROR_TIMEOUT) break; // Publish sensor data periodically static uint32_t lastPublish = 0; if (osGetSystemTime() - lastPublish > 10000) { char sensorData[64]; sprintf(sensorData, "%.1f", readTemperature()); mqttClientPublish(&mqttContext, "sensors/temperature", sensorData, strlen(sensorData), MQTT_QOS_LEVEL_0, FALSE, NULL); lastPublish = osGetSystemTime(); } } cleanup: mqttClientDisconnect(&mqttContext); mqttClientClose(&mqttContext); mqttClientDeinit(&mqttContext); return error; } ``` -------------------------------- ### Implement a TCP Server with CycloneTCP Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Demonstrates creating a listening socket, binding to a port, and handling multiple client connections in an echo loop. ```c #include "core/socket.h" error_t tcpServerExample(void) { error_t error; Socket *serverSocket, *clientSocket; IpAddr clientIpAddr; uint16_t clientPort; size_t received, written; char buffer[512]; // Create listening socket serverSocket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP); if (serverSocket == NULL) { return ERROR_OUT_OF_RESOURCES; } // Bind to local port error = socketBind(serverSocket, &IP_ADDR_ANY, 8080); if (error) { socketClose(serverSocket); return error; } // Listen for connections (backlog of 5) error = socketListen(serverSocket, 5); if (error) { socketClose(serverSocket); return error; } printf("Server listening on port 8080...\r\n"); // Accept client connections while (1) { clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort); if (clientSocket != NULL) { char ipAddrStr[40]; ipAddrToString(&clientIpAddr, ipAddrStr); printf("Client connected from %s:%u\r\n", ipAddrStr, clientPort); // Set client timeout socketSetTimeout(clientSocket, 30000); // Echo server loop while (1) { error = socketReceive(clientSocket, buffer, sizeof(buffer), &received, 0); if (error) break; error = socketSend(clientSocket, buffer, received, &written, 0); if (error) break; } // Close client connection socketShutdown(clientSocket, SOCKET_SD_BOTH); socketClose(clientSocket); printf("Client disconnected\r\n"); } } socketClose(serverSocket); return NO_ERROR; } ``` -------------------------------- ### Implement HTTP Server Callbacks and Initialization Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Defines request and authentication callbacks for an HTTP server and demonstrates the initialization process using HttpServerSettings. ```c #include "http/http_server.h" // Request callback function error_t httpRequestCallback(HttpConnection *connection, const char_t *uri) { error_t error = ERROR_NOT_FOUND; // Handle API endpoints if (!strcmp(uri, "/api/status")) { // Build JSON response const char *json = "{\"status\":\"ok\",\"uptime\":12345}"; // Set response parameters connection->response.statusCode = 200; connection->response.contentType = "application/json"; connection->response.contentLength = strlen(json); // Send response header error = httpWriteHeader(connection); if (error) return error; // Send response body error = httpWriteStream(connection, json, strlen(json)); httpCloseStream(connection); return error; } else if (!strcmp(uri, "/api/led") && !strcmp(connection->request.method, "POST")) { // Read POST body char body[256]; size_t received; error = httpReadStream(connection, body, sizeof(body) - 1, &received, 0); if (error == NO_ERROR || error == ERROR_END_OF_STREAM) { body[received] = '\0'; // Process LED command... // Send success response connection->response.statusCode = 200; connection->response.contentLength = 0; httpWriteHeader(connection); httpCloseStream(connection); return NO_ERROR; } } return error; } // Authentication callback HttpAccessStatus httpAuthCallback(HttpConnection *connection, const char_t *user, const char_t *uri) { // Protect admin endpoints if (!strncmp(uri, "/admin", 6)) { if (!strcmp(user, "admin")) { return HTTP_ACCESS_ALLOWED; } return HTTP_ACCESS_BASIC_AUTH_REQUIRED; } return HTTP_ACCESS_ALLOWED; } error_t startHttpServer(void) { error_t error; static HttpServerContext httpServerContext; static HttpConnection httpConnections[4]; HttpServerSettings settings; // Get default settings httpServerGetDefaultSettings(&settings); // Configure server settings.interface = netGetDefaultInterface(&netContext); settings.port = 80; settings.maxConnections = 4; settings.connections = httpConnections; settings.rootDirectory = "/www"; settings.defaultDocument = "index.html"; // Register callbacks settings.requestCallback = httpRequestCallback; settings.authCallback = httpAuthCallback; // Initialize HTTP server error = httpServerInit(&httpServerContext, &settings); if (error) return error; // Start HTTP server error = httpServerStart(&httpServerContext); printf("HTTP server started on port 80\r\n"); return error; } ``` -------------------------------- ### Establish WebSocket connection and exchange data in C Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Demonstrates the full lifecycle of a WebSocket client, including initialization, connection, sending text/binary/fragmented messages, and receiving responses. ```c #include "web_socket/web_socket.h" error_t webSocketClientExample(void) { error_t error; WebSocket *webSocket; IpAddr serverIpAddr; WebSocketFrameType frameType; char buffer[512]; size_t received, written; // Initialize WebSocket module webSocketInit(); // Open WebSocket webSocket = webSocketOpen(); if (webSocket == NULL) { return ERROR_OUT_OF_RESOURCES; } // Set timeout webSocketSetTimeout(webSocket, 30000); // Set host and origin webSocketSetHost(webSocket, "echo.websocket.org"); webSocketSetOrigin(webSocket, "http://example.com"); // Set sub-protocol (optional) webSocketSetSubProtocol(webSocket, "mqtt"); // Resolve server address error = getHostByName(NULL, "echo.websocket.org", &serverIpAddr, HOST_TYPE_IPV4); if (error) { webSocketClose(webSocket); return error; } // Connect to WebSocket server error = webSocketConnect(webSocket, &serverIpAddr, 80, "/"); if (error) { printf("WebSocket connection failed: %d\r\n", error); webSocketClose(webSocket); return error; } printf("WebSocket connected!\r\n"); // Send text message const char *textMsg = "Hello, WebSocket!"; error = webSocketSend(webSocket, textMsg, strlen(textMsg), WS_FRAME_TYPE_TEXT, &written); if (error) goto cleanup; printf("Sent: %s\r\n", textMsg); // Receive response error = webSocketReceive(webSocket, buffer, sizeof(buffer) - 1, &frameType, &received); if (error == NO_ERROR) { buffer[received] = '\0'; printf("Received (%s): %s\r\n", (frameType == WS_FRAME_TYPE_TEXT) ? "text" : "binary", buffer); } // Send binary message uint8_t binaryData[] = {0x01, 0x02, 0x03, 0x04, 0x05}; error = webSocketSend(webSocket, binaryData, sizeof(binaryData), WS_FRAME_TYPE_BINARY, &written); if (error) goto cleanup; printf("Sent %u bytes of binary data\r\n", written); // Send fragmented message const char *part1 = "This is "; const char *part2 = "a fragmented "; const char *part3 = "message!"; webSocketSendEx(webSocket, part1, strlen(part1), WS_FRAME_TYPE_TEXT, &written, TRUE, FALSE); // First fragment webSocketSendEx(webSocket, part2, strlen(part2), WS_FRAME_TYPE_CONTINUATION, &written, FALSE, FALSE); // Middle fragment webSocketSendEx(webSocket, part3, strlen(part3), WS_FRAME_TYPE_CONTINUATION, &written, FALSE, TRUE); // Last fragment // Receive with fragment info bool_t firstFrag, lastFrag; while (1) { error = webSocketReceiveEx(webSocket, buffer, sizeof(buffer) - 1, &frameType, &received, &firstFrag, &lastFrag); if (error) break; buffer[received] = '\0'; printf("Fragment (first=%d, last=%d): %s\r\n", firstFrag, lastFrag, buffer); if (lastFrag) break; } cleanup: // Graceful shutdown webSocketShutdown(webSocket); webSocketClose(webSocket); return error; } ``` -------------------------------- ### Implement UDP Communication with CycloneTCP Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Shows how to open a UDP socket, enable broadcast, join a multicast group, and perform send/receive operations. ```c #include "core/socket.h" error_t udpExample(void) { error_t error; Socket *socket; IpAddr destIpAddr, srcIpAddr; uint16_t srcPort; size_t written, received; char buffer[256]; // Open UDP socket socket = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_IP_PROTO_UDP); if (socket == NULL) { return ERROR_OUT_OF_RESOURCES; } // Bind to local port error = socketBind(socket, &IP_ADDR_ANY, 5000); if (error) { socketClose(socket); return error; } // Enable broadcast socketEnableBroadcast(socket, TRUE); // Join multicast group (optional) IpAddr multicastAddr; ipStringToAddr("239.255.255.250", &multicastAddr); socketJoinMulticastGroup(socket, &multicastAddr); // Set multicast TTL socketSetMulticastTtl(socket, 4); // Send UDP datagram ipStringToAddr("192.168.1.255", &destIpAddr); const char *message = "UDP Broadcast Message"; error = socketSendTo(socket, &destIpAddr, 5000, message, strlen(message), &written, 0); // Set receive timeout socketSetTimeout(socket, 5000); // Receive UDP datagram error = socketReceiveFrom(socket, &srcIpAddr, &srcPort, buffer, sizeof(buffer) - 1, &received, 0); if (error == NO_ERROR) { buffer[received] = '\0'; char ipStr[40]; ipAddrToString(&srcIpAddr, ipStr); printf("Received from %s:%u: %s\r\n", ipStr, srcPort, buffer); } // Leave multicast group socketLeaveMulticastGroup(socket, &multicastAddr); socketClose(socket); return NO_ERROR; } ``` -------------------------------- ### Implement TCP Client Socket Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Demonstrates opening a stream socket, connecting to a server, and performing data exchange. Ensure the stack is initialized before calling socket functions. ```c #include "core/socket.h" error_t tcpClientExample(void) { error_t error; Socket *socket; IpAddr serverIpAddr; size_t written, received; char buffer[256]; // Open TCP socket socket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP); if (socket == NULL) { return ERROR_OUT_OF_RESOURCES; } // Set timeout error = socketSetTimeout(socket, 10000); // Set buffer sizes socketSetTxBufferSize(socket, 4096); socketSetRxBufferSize(socket, 4096); // Resolve server address ipStringToAddr("192.168.1.50", &serverIpAddr); // Connect to server error = socketConnect(socket, &serverIpAddr, 8080); if (error) { socketClose(socket); return error; } // Send data const char *request = "Hello, Server!"; error = socketSend(socket, request, strlen(request), &written, 0); if (error) { socketShutdown(socket, SOCKET_SD_BOTH); socketClose(socket); return error; } // Receive response error = socketReceive(socket, buffer, sizeof(buffer) - 1, &received, 0); if (error == NO_ERROR) { buffer[received] = '\0'; printf("Received: %s\r\n", buffer); } // Graceful shutdown socketShutdown(socket, SOCKET_SD_BOTH); socketClose(socket); return NO_ERROR; } ``` -------------------------------- ### DHCP Client State Change Callback Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Handles state transitions for the DHCP client, printing messages for each state and detailed network information when an address is bound. Requires the DhcpClientContext and NetInterface structures. ```c #include "dhcp/dhcp_client.h" static DhcpClientContext dhcpClientContext; // State change callback void dhcpStateChangeCallback(DhcpClientContext *context, NetInterface *interface, DhcpState state) { switch (state) { case DHCP_STATE_INIT: printf("DHCP: Initializing...\r\n"); break; case DHCP_STATE_SELECTING: printf("DHCP: Discovering servers...\r\n"); break; case DHCP_STATE_REQUESTING: printf("DHCP: Requesting address...\r\n"); break; case DHCP_STATE_BOUND: printf("DHCP: Address bound!\r\n"); // Print assigned configuration Ipv4Addr ipAddr, subnetMask, gateway; ipv4GetHostAddr(interface, &ipAddr); ipv4GetSubnetMask(interface, &subnetMask); ipv4GetDefaultGateway(interface, &gateway); char str[16]; ipv4AddrToString(ipAddr, str); printf(" IP Address: %s\r\n", str); ipv4AddrToString(subnetMask, str); printf(" Subnet Mask: %s\r\n", str); ipv4AddrToString(gateway, str); printf(" Gateway: %s\r\n", str); break; case DHCP_STATE_RENEWING: printf("DHCP: Renewing lease...\r\n"); break; case DHCP_STATE_REBINDING: printf("DHCP: Rebinding...\r\n"); break; default: break; } } ``` -------------------------------- ### DHCP Client Timeout Callback Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Handles the DHCP configuration timeout event, indicating that an IP address could not be obtained. This callback can be used to implement fallback mechanisms like static IP assignment or Auto-IP. ```c // Timeout callback void dhcpTimeoutCallback(DhcpClientContext *context, NetInterface *interface) { printf("DHCP: Configuration timeout!\r\n"); // Fall back to static IP or Auto-IP } ``` -------------------------------- ### Stop DHCP Client Source: https://context7.com/oryx-embedded/cyclonetcp/llms.txt Releases the IP address and stops the DHCP client, followed by deinitialization. This function should be called to clean up resources when the DHCP client is no longer needed. ```c void stopDhcpClient(void) { // Release IP address and stop client dhcpClientRelease(&dhcpClientContext); dhcpClientStop(&dhcpClientContext); dhcpClientDeinit(&dhcpClientContext); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.