Other Parts Discussed in Thread: CC3235SF, SYSBIOS
Tool/software:
I am working on a CC3235SF application using TI SimpleLink SDK 7.10.00.13 and TI-RTOS7.
The device performs AP provisioning via an HTTP server, then switches to STA mode and should connect to a local MQTT broker at 192.168.0.50:1883.
Workflow:
-
On first boot, device starts in AP mode (
SmartPi-ConfigSSID), accepts Wi-Fi + MQTT broker details over HTTP POST, saves them to flash. -
Device switches to STA mode, connects to given Wi-Fi SSID.
-
After STA IP is acquired, device calls
MqttClient_ConnectToLocalBroker()using the stored broker IP and port. -
Local broker sends AWS endpoint + certs back to device.
-
Device then connects to AWS MQTT broker over TLS.
Problem:
-
When device connects to broker immediately after AP → STA switch,
MQTTClient_connect()fails with error -2023 (“Unknown MQTT error”). -
Raspberry Pi Mosquitto logs show:
-
If I flash TI’s default
mqtt_client_app.cexample in STA mode (with static config), connection works fine to the same broker. -
My ESP32 implementation with the same broker works perfectly.
-
So broker side is confirmed working.
Code details:
-
I am using TI’s native
MQTTClient_*API (notMQTT_IF). -
Before
MQTTClient_connect(), I do a TCP connectivity test to ensure broker IP/port is reachable — that passes. -
Client ID is generated from MAC address, e.g.
CC3235SF_7C5701010000. -
No TLS for local broker (plain TCP).
-
SDK: SimpleLink CC32xx 7.10.00.13, Toolchain: GCC 9.2.1, Board: CC3235SF-LAUNCHXL.
Observation:
-
If I reboot the device and start directly in STA mode (bypassing AP mode), MQTT connects successfully.
-
The problem appears only on first run after AP → STA switch without reboot.
Questions:
-
Is there a required cleanup/reset step after AP → STA mode before starting
MQTTClient_connect()? -
Could NWP sockets from AP mode be interfering with the MQTT connection?
-
Any recommended sequence to reliably start MQTT immediately after switching modes?
Logs (failing case):
Application Started
Device MAC Address: 645801010000
[NETAPP EVENT] IP Acquired No configuration found. Starting in AP mode.
[NETAPP EVENT] IP Acquired
Device in AP mode. SSID: SmartPi-Config, IP: 192.168.4.1, Port: 5000
[HTTP POST] Received data: {"wifi_password":"Macb00k@20","wifi_ssid":"IOT_WiFi"}
[HTTP POST] Received data: {"host_addr":"192.168.0.50","keepalive":60,"port":188 3,"qos":2}
[HTTP POST] Received data: {"node_data":"gateway:1\nnode:s\npoint:s"} Provisioning complete. Saving configuration...
Configuration file saved. Device is configured. Switching to STA mode...
Switching device to STA mode...
Wi-Fi profile added for SSID: IOT_WiFi
Device restarted in STA mode.
Waiting for IP from router...
[WLAN EVENT] STA Connected to AP
[NETAPP EVENT] IP Acquired Got IP: 192.168.0.77
Got STA IP: 192.168.0.77
[MQTT] MQTT client init (native API)
[MQTT] MAC-based Client ID: clientId3403de5bb8d
Connecting to local MQTT broker...
[MQTT] Testing network connectivity to 192.168.0.50:1883...
[MQTT] Using static IP: 192.168.0.50 -> 192.168.0.50
[MQTT] Attempting TCP connection...
[MQTT] TCP connection successful
[MQTT] MAC-based Client ID: clientId3403de5bb8d
[MQTT] Using Client ID: clientId3403de5bb8d
[MQTT] Security: Plain TCP (no TLS)
[MQTT] Creating MQTT client...
[MQTT] Connecting to broker...
[MQTT] Connection failed: Unknown MQTT error (-2023)
[MQTT] Disconnected and deleted client
Failed to connect to local broker.
[MQTT] No active MQTT connection
this is my code:
/*
* mqtt_client_app.c – Enhanced TI MQTT Client Implementation
* Fixed static IP parsing for CC3235SF (no byte swap bug)
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <ti/net/mqtt/mqttclient.h>
#include <ti/drivers/net/wifi/simplelink.h>
#include "uart_term.h"
#include "app_config.h"
// AWS cert filenames stored in CC3235SF flash
#define AWS_ROOT_CA_FILENAME "/certs/aws_ca.pem"
#define AWS_CLIENT_CERT_FILENAME "/certs/aws_client.pem"
#define AWS_PRIVATE_KEY_FILENAME "/certs/aws_key.pem"
// MQTT Client configuration
#define MQTT_CLIENT_USERNAME NULL
#define MQTT_CLIENT_PASSWORD NULL
#define MQTT_KEEP_ALIVE_SEC 60
#define MQTT_CLEAN_SESSION true
// Global MQTT Client handle
MQTTClient_Handle g_mqttClient = NULL;
int g_switchToAws = 0;
char g_awsCaCertBuf[2048];
char g_awsClientCertBuf[2048];
char g_awsClientKeyBuf[2048];
char ClientId[32] = {0};
// Optional topics
char record_topic_buf[128];
char transmit_topic_buf[128];
char factory_reset_topic_buf[128];
/* ================= Error Strings ================= */
const char* getMqttErrorString(int32_t errorCode)
{
switch(errorCode) {
case MQTTCLIENT_ERR_FNPARAM: return "Invalid function parameter";
case MQTTCLIENT_ERR_NETWORK: return "Network error";
case MQTTCLIENT_ERR_PKT_AVL: return "Packet availability error";
case MQTTCLIENT_ERR_TIMEOUT: return "Operation timeout";
case MQTTCLIENT_ERR_BADCALL: return "Invalid function call";
case MQTTCLIENT_ERR_CONTENT: return "Content error";
case MQTTCLIENT_ERR_NOTCONN: return "Not connected";
default:
return (errorCode < 0) ? "Unknown MQTT error" : "Operation successful";
}
}
/* ================= FIXED: Network Connectivity Test ================= */
int32_t testNetworkConnectivity(const char* serverAddr, uint16_t port)
{
SlSockAddrIn_t addr;
int16_t sockId;
int32_t status;
UART_PRINT("[MQTT] Testing network connectivity to %s:%d...\n\r", serverAddr, port);
sockId = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, 0);
if (sockId < 0) {
UART_PRINT("[MQTT] Failed to create socket (error: %d)\n\r", sockId);
return -1;
}
addr.sin_family = SL_AF_INET;
addr.sin_port = sl_Htons(port);
unsigned long resolvedIP;
/* FIX: If serverAddr is already an IPv4 address, parse it manually */
if (isdigit((unsigned char)serverAddr[0])) {
unsigned int b1, b2, b3, b4;
sscanf(serverAddr, "%u.%u.%u.%u", &b1, &b2, &b3, &b4);
resolvedIP = sl_Htonl(SL_IPV4_VAL(b1, b2, b3, b4));
UART_PRINT("[MQTT] Using static IP: %s -> %u.%u.%u.%u\n\r",
serverAddr, b1, b2, b3, b4);
} else {
// Resolve hostname via DNS
status = sl_NetAppDnsGetHostByName((signed char*)serverAddr,
strlen(serverAddr),
&resolvedIP, SL_AF_INET);
if (status < 0) {
UART_PRINT("[MQTT] DNS resolution failed for %s (err: %d)\n\r",
serverAddr, status);
sl_Close(sockId);
return -1;
}
}
addr.sin_addr.s_addr = resolvedIP;
// Timeout options
struct SlTimeval_t timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
sl_SetSockOpt(sockId, SL_SOL_SOCKET, SL_SO_RCVTIMEO, &timeout, sizeof(timeout));
sl_SetSockOpt(sockId, SL_SOL_SOCKET, SL_SO_SNDTIMEO, &timeout, sizeof(timeout));
UART_PRINT("[MQTT] Attempting TCP connection...\n\r");
status = sl_Connect(sockId, (SlSockAddr_t*)&addr, sizeof(SlSockAddrIn_t));
if (status < 0) {
UART_PRINT("[MQTT] TCP connection failed (error: %d)\n\r", status);
if (status == -111) UART_PRINT("[MQTT] ECONNREFUSED: Broker refused connection\n\r");
sl_Close(sockId);
return -1;
}
UART_PRINT("[MQTT] TCP connection successful\n\r");
sl_Close(sockId);
return 0;
}
/* ================= MQTT Callback ================= */
void mqttClientCb(int32_t event, void *metaData, uint32_t metaDataLen,
void *data, uint32_t dataLen)
{
switch(event) {
case MQTTClient_OPERATION_CB_EVENT:
UART_PRINT("[MQTT] Operation callback received\n\r");
break;
case MQTTClient_RECV_CB_EVENT:
UART_PRINT("[MQTT] Message received: %.*s\n\r", dataLen, (char*)data);
break;
case MQTTClient_DISCONNECT_CB_EVENT:
UART_PRINT("[MQTT] Disconnected from broker\n\r");
break;
default:
UART_PRINT("[MQTT] Unknown event: %d\n\r", event);
break;
}
}
/* ================= Disconnect Helper ================= */
void MqttClient_Disconnect(void)
{
if (g_mqttClient) {
MQTTClient_disconnect(g_mqttClient);
MQTTClient_delete(g_mqttClient);
g_mqttClient = NULL;
UART_PRINT("[MQTT] Disconnected and deleted client\n\r");
}
}
/* ================= Init ================= */
void MqttClient_Init(void)
{
UART_PRINT("[MQTT] MQTT client init (native API)\n\r");
}
/* ================= Test MQTT Publish ================= */
int32_t MqttClient_Publish(const char* topic, const char* payload, int qos)
{
if (!g_mqttClient) {
UART_PRINT("[MQTT] No active MQTT connection\n\r");
return -1;
}
UART_PRINT("[MQTT] Publishing to '%s': %s\n\r", topic, payload);
int32_t rc = MQTTClient_publish(g_mqttClient,
(char*)topic, strlen(topic),
(char*)payload, strlen(payload),
0); // QoS0 only
if (rc < 0) {
UART_PRINT("[MQTT] Publish failed (code %d)\n\r", rc);
return rc;
}
UART_PRINT("[MQTT] Publish OK\n\r");
return 0;
}
int32_t SetClientIdNamefromMacAddress(void)
{
_u16 macAddressLen = SL_MAC_ADDR_LEN; // correct type for sl_NetCfgGet
_u8 macAddress[SL_MAC_ADDR_LEN];
int32_t ret = sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET, NULL, &macAddressLen, macAddress);
if (ret < 0) {
UART_PRINT("[MQTT] Failed to get MAC address (error %d)\n\r", ret);
return -1;
}
snprintf(g_macAddressStr, 20, "clientId%02x%02x%02x%02x%02x%02x",
macAddress[0], macAddress[1], macAddress[2],
macAddress[3], macAddress[4], macAddress[5]);
UART_PRINT("[MQTT] MAC-based Client ID: %s\n\r", g_macAddressStr);
return 0;
}
/* ================= Connect to Local MQTT Broker - MINIMAL FIX ================= */
int32_t MqttClient_ConnectToLocalBroker(void)
{
MqttClient_Disconnect(); // safety
if (testNetworkConnectivity(g_appConfig.local_mqtt_host, g_appConfig.local_mqtt_port) < 0) {
UART_PRINT("[MQTT] Network connectivity test failed\n\r");
return -1;
}
MQTTClient_Params clientParams;
MQTTClient_ConnParams connParams;
memset(&clientParams, 0, sizeof(clientParams));
memset(&connParams, 0, sizeof(connParams));
static char forcedClientId[32];
if (SetClientIdNamefromMacAddress() == 0) {
snprintf(forcedClientId, sizeof(forcedClientId), "%s", g_macAddressStr);
} else {
strcpy(forcedClientId, "clientIdDefault");
}
UART_PRINT("[MQTT] Using Client ID: %s\n\r", forcedClientId);
clientParams.clientId = forcedClientId;
clientParams.blockingSend = true;
clientParams.connParams = &connParams;
// Force MQTT protocol to 3.1.1 (Mosquitto default)
// clientParams.mqttVersion = MQTT_3_1_1;
// Connection parameters
connParams.serverAddr = g_appConfig.local_mqtt_host;
connParams.port = g_appConfig.local_mqtt_port;
connParams.netconnFlags = MQTTCLIENT_NETCONN_IP4; // IPv4 only
connParams.nFiles = 0;
connParams.secureFiles = NULL;
UART_PRINT("[MQTT] Security: Plain TCP (no TLS)\n\r");
UART_PRINT("[MQTT] Creating MQTT client...\n\r");
g_mqttClient = MQTTClient_create(mqttClientCb, &clientParams);
if (!g_mqttClient) {
UART_PRINT("[MQTT] MQTTClient_create failed\n\r");
return -1;
}
UART_PRINT("[MQTT] Connecting to broker...\n\r");
int32_t rc = MQTTClient_connect(g_mqttClient);
if (rc < 0) {
UART_PRINT("[MQTT] Connection failed: %s (%d)\n\r",
getMqttErrorString(rc), rc);
MqttClient_Disconnect();
return rc;
}
UART_PRINT("[MQTT] Connected to local broker\n\r");
return 0;
}
/* ================= Test MQTT Publish ================= */
/*int32_t MqttClient_TestPublish(void)
{
if (!g_mqttClient) {
UART_PRINT("[MQTT] No active MQTT connection\n\r");
return -1;
}
const char* topic = "test/connection";
const char* message = "Hello from CC3235SF!";
UART_PRINT("[MQTT] Publishing to '%s'\n\r", topic);
int32_t rc = MQTTClient_publish(g_mqttClient, (char*)topic, strlen(topic),
(char*)message, strlen(message), 0);
if (rc < 0) {
UART_PRINT("[MQTT] Publish failed: %s (%d)\n\r", getMqttErrorString(rc), rc);
return rc;
}
UART_PRINT("[MQTT] Test message published successfully\n\r");
return 0;
} */
/* ================= Subscribe to Topic ================= */
int32_t MqttClient_Subscribe(const char* topic)
{
if (!g_mqttClient) {
UART_PRINT("[MQTT] No active MQTT connection\n\r");
return -1;
}
UART_PRINT("[MQTT] Subscribing to topic: %s\n\r", topic);
MQTTClient_SubscribeParams subParams;
memset(&subParams, 0, sizeof(subParams));
subParams.topic = (char*)topic;
subParams.qos = MQTT_QOS_0;
int32_t rc = MQTTClient_subscribe(g_mqttClient, &subParams, 1);
if (rc < 0) {
UART_PRINT("[MQTT] Subscribe failed: %s (code %d)\n\r", getMqttErrorString(rc), rc);
return rc;
}
UART_PRINT("[MQTT] Successfully subscribed to %s\n\r", topic);
return 0;
}
/* ================= Connect to AWS MQTT Broker ================= */
int32_t MqttClient_ConnectToAws(void)
{
MqttClient_Disconnect();
// Save certs received via local broker
sl_FsDel((unsigned char *)AWS_ROOT_CA_FILENAME, 0);
sl_FsDel((unsigned char *)AWS_CLIENT_CERT_FILENAME, 0);
sl_FsDel((unsigned char *)AWS_PRIVATE_KEY_FILENAME, 0);
UART_PRINT("[MQTT] AWS certs prepared.\n\r");
MQTTClient_Params clientParams;
MQTTClient_ConnParams connParams;
memset(&clientParams, 0, sizeof(clientParams));
memset(&connParams, 0, sizeof(connParams));
clientParams.clientId = g_macAddressStr;
clientParams.blockingSend = true;
clientParams.connParams = &connParams;
connParams.serverAddr = "a2y0oc86fl7cm.iot.us-east-2.amazonaws.com"; // Change to your AWS endpoint
connParams.port = 8883;
connParams.netconnFlags = MQTTCLIENT_NETCONN_URL | MQTTCLIENT_NETCONN_SEC;
// Secure files
static char *secureFiles[] = {
(char*)AWS_PRIVATE_KEY_FILENAME,
(char*)AWS_CLIENT_CERT_FILENAME,
(char*)AWS_ROOT_CA_FILENAME,
NULL
};
connParams.nFiles = 3;
connParams.secureFiles = secureFiles;
UART_PRINT("[MQTT] Connecting to AWS MQTT Broker...\n\r");
g_mqttClient = MQTTClient_create(mqttClientCb, &clientParams);
if (!g_mqttClient) {
UART_PRINT("[MQTT] MQTTClient_create failed for AWS\n\r");
return -1;
}
int32_t rc = MQTTClient_connect(g_mqttClient);
if (rc < 0) {
UART_PRINT("[MQTT] AWS connect failed: %s (code %d)\n\r", getMqttErrorString(rc), rc);
MqttClient_Disconnect();
return rc;
}
UART_PRINT("[MQTT] Connected to AWS MQTT broker\n\r");
return 0;
}
provisioning:
// provisioning.c
/* Standard Includes */
#include <mqtt_client_app.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
/* TI-DRIVERS Header files */
#include <ti/drivers/net/wifi/simplelink.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/GPIO.h>
#include <uart_term.h>
#include <ti/net/slnetif.h>
#include <ti/net/slnetsock.h>
#include <ti/net/slnetutils.h>
/* Custom Application Includes */
#include "app_config.h"
#include "ir_app.h"
#include "cJSON.h"
/* TI-RTOS Headers */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/hal/Seconds.h>
//#include "ifmod/mqtt_if.h"
//#include "ifmod/debug_if.h"
//#include "ifmod/uart_if.h"
//#include "ifmod/wifi_if.h"
//#include "ifmod/mqtt_if.h"
//#include "ifmod/debug_if.h"
//#include "ifmod/ota_if.h"
//#include "ifmod/utils_if.h"
//#include "ifmod/ota_vendors.h"
#define SPAWN_TASK_PRIORITY (9)
// *** CRITICAL FIX #1: Increased stack size for tasks that use networking libraries ***
#define TASK_STACK_SIZE (8192)
#define SL_STOP_TIMEOUT (200)
#define LOG_MESSAGE UART_PRINT
/* Global Variables */
AppConfig_t g_appConfig;
/* ============================================================================
* GLOBAL VARIABLES
* ============================================================================ */
char g_macAddressStr[13] = {0}; // Global MAC address (12 hex chars + null)
// Flag to signal completion from the event handler to the main thread
volatile uint8_t g_isProvisioningComplete = 0;
/* Forward Declarations */
void *mainApplicationThread(void *arg);
int32_t startApMode(void);
int32_t connectAsSta(void);
int32_t saveConfiguration(void);
int32_t loadConfiguration(void);
//=============================================================================
// SimpleLink Event Handlers
//=============================================================================
void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) {
if(!pWlanEvent) return;
if(pWlanEvent->Id == SL_WLAN_EVENT_CONNECT) {
LOG_MESSAGE("[WLAN EVENT] STA Connected to AP\n\r");
} else if (pWlanEvent->Id == SL_WLAN_EVENT_DISCONNECT) {
LOG_MESSAGE("[WLAN EVENT] STA Disconnected from AP\n\r");
}
}
void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent) {
if(pNetAppEvent && pNetAppEvent->Id == SL_NETAPP_EVENT_IPV4_ACQUIRED) {
LOG_MESSAGE("[NETAPP EVENT] IP Acquired\n\r");
}
}
void SimpleLinkHttpServerEventHandler(SlNetAppHttpServerEvent_t *p, SlNetAppHttpServerResponse_t *r) {}
void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) {}
void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent) {}
void SimpleLinkFatalErrorEventHandler(SlDeviceFatal_t *slFatalErrorEvent) {}
void SimpleLinkNetAppRequestMemFreeEventHandler(uint8_t *buffer) {}
void SimpleLinkNetAppRequestEventHandler(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse)
{
if (pNetAppRequest->Type == SL_NETAPP_REQUEST_HTTP_POST && pNetAppRequest->requestData.PayloadLen > 0)
{
char* bodyCopy = (char*)malloc(pNetAppRequest->requestData.PayloadLen + 1);
if (bodyCopy)
{
memcpy(bodyCopy, pNetAppRequest->requestData.pPayload, pNetAppRequest->requestData.PayloadLen);
bodyCopy[pNetAppRequest->requestData.PayloadLen] = '\0';
cJSON *root = cJSON_Parse(bodyCopy);
if (root) {
LOG_MESSAGE("[HTTP POST] Received data: %s\n\r", bodyCopy);
if (cJSON_GetObjectItem(root, "wifi_ssid")) {
strncpy(g_appConfig.wifi_ssid, cJSON_GetObjectItem(root, "wifi_ssid")->valuestring, sizeof(g_appConfig.wifi_ssid) - 1);
strncpy(g_appConfig.wifi_password, cJSON_GetObjectItem(root, "wifi_password")->valuestring, sizeof(g_appConfig.wifi_password) - 1);
} else if (cJSON_GetObjectItem(root, "host_addr")) {
strncpy(g_appConfig.local_mqtt_host, cJSON_GetObjectItem(root, "host_addr")->valuestring, sizeof(g_appConfig.local_mqtt_host) - 1);
g_appConfig.local_mqtt_port = cJSON_GetObjectItem(root, "port")->valueint;
} else if (cJSON_GetObjectItem(root, "node_data")) {
g_isProvisioningComplete = 1;
}
cJSON_Delete(root);
}
free(bodyCopy);
}
}
sl_NetAppSend(pNetAppRequest->Handle, 0, NULL, SL_NETAPP_HTTP_RESPONSE_200_OK);
}
//=============================================================================
// Helper Functions
//=============================================================================
int32_t startApMode(void) {
sl_WlanSetMode(ROLE_AP);
uint8_t sec_type = SL_WLAN_SEC_TYPE_WPA_WPA2;
sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_SSID, strlen(AP_SSID_PREFIX), (unsigned char*)AP_SSID_PREFIX);
sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_SECURITY_TYPE, 1, &sec_type);
sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_PASSWORD, strlen(AP_PASSWORD), (unsigned char*)AP_PASSWORD);
SlNetCfgIpV4Args_t ipV4;
ipV4.Ip = SL_IPV4_VAL(192, 168, 4, 1);
ipV4.IpMask = SL_IPV4_VAL(255, 255, 255, 0);
ipV4.IpGateway = SL_IPV4_VAL(192, 168, 4, 1);
ipV4.IpDnsServer = SL_IPV4_VAL(0,0,0,0);
sl_NetCfgSet(SL_NETCFG_IPV4_AP_ADDR_MODE, SL_NETCFG_ADDR_STATIC, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4);
sl_Stop(SL_STOP_TIMEOUT);
sl_Start(NULL, NULL, NULL);
SlNetAppDhcpServerBasicOpt_t dhcp_server_info;
dhcp_server_info.lease_time = 3600;
dhcp_server_info.ipv4_addr_start = SL_IPV4_VAL(192, 168, 4, 100);
dhcp_server_info.ipv4_addr_last = SL_IPV4_VAL(192, 168, 4, 110);
sl_NetAppSet(SL_NETAPP_DHCP_SERVER_ID, SL_NETAPP_DHCP_SRV_BASIC_OPT, sizeof(dhcp_server_info), (_u8*)&dhcp_server_info);
sl_NetAppStart(SL_NETAPP_HTTP_SERVER_ID | SL_NETAPP_DHCP_SERVER_ID);
uint16_t port = 5000;
sl_NetAppSet(SL_NETAPP_HTTP_SERVER_ID, SL_NETAPP_HTTP_PRIMARY_PORT_NUMBER, sizeof(port), (uint8_t *)&port);
LOG_MESSAGE("Device in AP mode. SSID: %s, IP: 192.168.4.1, Port: 5000\n\r", AP_SSID_PREFIX);
return 0;
}
int32_t connectAsSta(void)
{
int32_t ret;
_i32 role;
_u16 len;
_u16 configOpt;
SlNetCfgIpV4Args_t ipV4 = {0};
LOG_MESSAGE(" Switching device to STA mode...\n\r");
// 1️⃣ Stop HTTP & DHCP servers (cleanup AP)
sl_NetAppStop(SL_NETAPP_HTTP_SERVER_ID | SL_NETAPP_DHCP_SERVER_ID);
// 2️⃣ Set the mode to STA BEFORE stopping the network processor
ret = sl_WlanSetMode(ROLE_STA);
if (ret < 0) {
LOG_MESSAGE(" Error setting STA mode: %ld\n\r", ret);
return ret;
}
// 3️⃣ Add Wi-Fi credentials to profiles
SlWlanSecParams_t secParams = {0};
secParams.Key = (_i8*)g_appConfig.wifi_password;
secParams.KeyLen = strlen(g_appConfig.wifi_password);
secParams.Type = SL_WLAN_SEC_TYPE_WPA_WPA2;
// Remove all old profiles (optional but avoids wrong AP reconnects)
sl_WlanProfileDel(0xFF);
ret = sl_WlanProfileAdd((_i8*)g_appConfig.wifi_ssid,
strlen(g_appConfig.wifi_ssid),
0, // no BSSID
&secParams,
NULL,
1, // priority
0);
if (ret < 0) {
LOG_MESSAGE(" Failed to add Wi-Fi profile: %ld\n\r", ret);
return ret;
}
LOG_MESSAGE(" Wi-Fi profile added for SSID: %s\n\r", g_appConfig.wifi_ssid);
// 4️⃣ Restart the network processor so STA mode takes effect
sl_Stop(SL_STOP_TIMEOUT);
sleep(1); // allow hardware settle time
// sl_Start() return value = current role
role = sl_Start(NULL, NULL, NULL);
if (role != ROLE_STA) {
LOG_MESSAGE(" Device did NOT switch to STA mode (role=%ld)\n\r", role);
return -1;
}
LOG_MESSAGE(" Device restarted in STA mode.\n\r");
// 5️⃣ Wait for IP address (DHCP)
LOG_MESSAGE(" Waiting for IP from router...\n\r");
len = sizeof(SlNetCfgIpV4Args_t);
configOpt = 0;
int retries = 0;
while (ipV4.Ip == 0 && retries < 30) {
sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE,
&configOpt,
&len,
(_u8*)&ipV4);
sleep(1);
retries++;
}
if (ipV4.Ip == 0) {
LOG_MESSAGE(" Failed to get IP address after 30 seconds.\n\r");
return -1;
}
LOG_MESSAGE(" Got IP: %d.%d.%d.%d\n\r",
SL_IPV4_BYTE(ipV4.Ip, 3),
SL_IPV4_BYTE(ipV4.Ip, 2),
SL_IPV4_BYTE(ipV4.Ip, 1),
SL_IPV4_BYTE(ipV4.Ip, 0));
return 0;
}
int32_t saveConfiguration() {
long fileHandle = sl_FsOpen((unsigned char *)CONFIG_FILENAME, SL_FS_CREATE | SL_FS_OVERWRITE | SL_FS_CREATE_MAX_SIZE(sizeof(AppConfig_t)), 0);
sl_FsWrite(fileHandle, 0, (unsigned char *)&g_appConfig, sizeof(AppConfig_t));
sl_FsClose(fileHandle, 0, 0, 0);
LOG_MESSAGE("Configuration file saved.\n\r");
return 0;
}
int32_t loadConfiguration() {
long fileHandle = sl_FsOpen((unsigned char *)CONFIG_FILENAME, SL_FS_READ, 0);
if (fileHandle < 0) return -1;
sl_FsRead(fileHandle, 0, (unsigned char *)&g_appConfig, sizeof(AppConfig_t));
sl_FsClose(fileHandle, 0, 0, 0);
LOG_MESSAGE("Configuration file loaded.\n\r");
return 0;
}
/* ============================================================================
* GET MAC ADDRESS
* ============================================================================ */
void getMacAddress(void)
{
uint16_t macAddressLen = SL_MAC_ADDR_LEN;
uint8_t macAddress[SL_MAC_ADDR_LEN];
// Get the device Mac address (requires sl_Task to be running)
sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET, 0, &macAddressLen, &macAddress[0]);
// Format the MAC into global string
snprintf(g_macAddressStr, sizeof(g_macAddressStr),
"%02X%02X%02X%02X%02X%02X",
macAddress[0], macAddress[1], macAddress[2],
macAddress[3], macAddress[4], macAddress[5]);
UART_PRINT("Device MAC Address: %s\n\r", g_macAddressStr);
}
/* ============================================================================
* MAIN APPLICATION THREAD
* ============================================================================ */
void *mainApplicationThread(void *arg)
{
/* 1️⃣ Start Wi-Fi */
sl_Start(NULL, NULL, NULL);
UART_PRINT(" SimpleLink Wi-Fi driver started\n\r");
/* 2️⃣ Init SlNet for MQTT & BSD Sockets */
SlNetIf_init(0);
SlNetSock_init(0);
SlNetUtil_init(0);
UART_PRINT(" SlNet layer initialized\n\r");
/* 3️⃣ Load Wi-Fi/MQTT config or start AP mode */
if (loadConfiguration() < 0) {
UART_PRINT(" No configuration found. Starting in AP mode.\n\r");
startApMode();
while (!g_isProvisioningComplete) {
sleep(1);
}
UART_PRINT(" Provisioning complete. Saving configuration...\n\r");
saveConfiguration();
sleep(1);
}
/* 4️⃣ Switch to STA mode */
UART_PRINT(" Device is configured. Switching to STA mode...\n\r");
connectAsSta();
/* 5️⃣ Wait for STA IP */
_u16 len = sizeof(SlNetCfgIpV4Args_t);
_u16 configOpt = 0;
SlNetCfgIpV4Args_t ipV4 = {0};
int retries = 0;
while (ipV4.Ip == 0 && retries < 30) {
sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE, &configOpt, &len, (_u8 *)&ipV4);
sleep(1);
retries++;
}
if (ipV4.Ip == 0) {
UART_PRINT(" Failed to acquire an IP address.\n\r");
while (1); // Stop for debugging
}
UART_PRINT(" Got STA IP: %d.%d.%d.%d\n\r",
SL_IPV4_BYTE(ipV4.Ip, 3),
SL_IPV4_BYTE(ipV4.Ip, 2),
SL_IPV4_BYTE(ipV4.Ip, 1),
SL_IPV4_BYTE(ipV4.Ip, 0));
/* 6️⃣ Init MQTT */
MqttClient_Init();
/* 7️⃣ Build and set Client ID */
if (SetClientIdNamefromMacAddress() != 0) {
UART_PRINT("️ Using default Client ID due to MAC fetch error\n\r");
strcpy(ClientId, "clientIdDefault");
}
/* 8️⃣ Connect to Local MQTT broker */
UART_PRINT(" Connecting to local MQTT broker...\n\r");
if (MqttClient_ConnectToLocalBroker() < 0) {
UART_PRINT(" Failed to connect to local broker.\n\r");
} else {
UART_PRINT(" Local MQTT active.\n\r");
}
/* 9️⃣ Main loop */
while (1)
{
static uint32_t lastPublish = 0;
uint32_t currentTime = Seconds_get();
if (currentTime - lastPublish > 30) {
lastPublish = currentTime;
MqttClient_Publish("device/heartbeat", "{\"status\":\"online\"}", MQTT_QOS_0);
}
if (g_switchToAws) {
UART_PRINT(" Switching to AWS MQTT...\n\r");
if (MqttClient_ConnectToAws() == 0) {
UART_PRINT(" AWS MQTT active.\n\r");
g_switchToAws = 0;
} else {
UART_PRINT(" AWS MQTT connection failed. Retrying...\n\r");
sleep(10);
}
}
sleep(1);
}
}
/* ============================================================================
* MAIN ENTRY POINT
* ============================================================================ */
int main(void) {
pthread_t spawnThread = (pthread_t)NULL;
pthread_t appThread = (pthread_t)NULL;
pthread_attr_t pAttrs;
struct sched_param priParam;
GPIO_init();
SPI_init();
InitTerm();
UART_PRINT("Application Started\n\r");
/* Start sl_Task thread */
pthread_attr_init(&pAttrs);
priParam.sched_priority = SPAWN_TASK_PRIORITY;
pthread_attr_setschedparam(&pAttrs, &priParam);
pthread_attr_setstacksize(&pAttrs, TASK_STACK_SIZE);
pthread_create(&spawnThread, &pAttrs, sl_Task, NULL);
/* Read MAC Address now that SimpleLink driver is active */
getMacAddress();
/* Launch main application thread */
priParam.sched_priority = 1;
pthread_attr_setschedparam(&pAttrs, &priParam);
pthread_attr_setstacksize(&pAttrs, TASK_STACK_SIZE);
pthread_create(&appThread, &pAttrs, mainApplicationThread, NULL);
BIOS_start();
return 0;
}
app_config:-
#ifndef APP_CONFIG_H_
#define APP_CONFIG_H_
#include <ti/drivers/net/wifi/simplelink.h>
#include <ti/net/mqtt/mqttclient.h>
#include <pthread.h>
/* =================================================================
1. APPLICATION STATE AND EVENT TYPE DEFINITIONS
================================================================= */
typedef enum {
APP_STATE_INIT,
APP_STATE_AP_CONFIG_MODE,
APP_STATE_STA_CONNECTING,
APP_STATE_OPERATIONAL,
APP_STATE_ERROR
} AppState_e;
typedef enum {
AppEvent_STARTED,
AppEvent_CONNECTED,
AppEvent_IP_ACQUIRED,
AppEvent_DISCONNECT,
AppEvent_CONFIG_FOUND,
AppEvent_CONFIG_NOT_FOUND,
AppEvent_PROVISIONING_STOPPED,
AppEvent_ERROR
} AppEvent;
/* =================================================================
2. CONFIGURATION STRUCT DEFINITION
================================================================= */
typedef struct {
char wifi_ssid[33]; // Wi-Fi SSID (up to 32 chars + null)
char wifi_password[65]; // Wi-Fi Password (up to 64 chars + null)
char local_mqtt_host[64]; // Local MQTT broker IP/hostname
uint16_t local_mqtt_port; // Local MQTT broker port
char node_gateway[33]; // Node gateway identifier
int node_id; // Node ID for device identification
} AppConfig_t;
/* =================================================================
3. SHARED GLOBAL VARIABLES (extern)
================================================================= */
extern volatile AppState_e g_CurrentState; // Current application state
extern AppConfig_t g_appConfig; // Global application configuration
extern MQTTClient_Handle g_mqttClient; // MQTT client handle
extern char g_macAddressStr[]; // Device MAC address (string)
extern uint8_t g_macAddress[6];
extern int g_switchToAws; // Flag to trigger AWS MQTT switch
/* =================================================================
4. SHARED FUNCTION DECLARATIONS (extern)
================================================================= */
extern int16_t SignalEvent(AppEvent event); // Event signaling
extern int32_t MqttClient_ConnectToAws(void); // Connect to AWS MQTT
extern void MqttClient_Init(void); // Initialize MQTT client
extern char ClientId[32];
extern int32_t SetClientIdNamefromMacAddress(void);
/* =================================================================
5. FILESYSTEM AND CONSTANT DEFINES
================================================================= */
#define CONFIG_FILENAME "/config.cfg"
#define AWS_ROOT_CA_FILENAME "/certs/aws_ca.pem"
#define AWS_CLIENT_CERT_FILENAME "/certs/aws_client.pem"
#define AWS_PRIVATE_KEY_FILENAME "/certs/aws_key.pem"
#define AP_SSID_PREFIX "SmartPi-Config" // AP mode SSID prefix
#define AP_PASSWORD "12345678" // AP mode password
#define MQTT_TOPIC_MAX_LEN 64
#define AWS_MQTT_URL "your-aws-endpoint.amazonaws.com"
#endif /* APP_CONFIG_H_ */