带SIM卡和天线的MKR GSM 1400通过HTTP POST向Kaa云发送数据的Arduino代码问题排查
Let's break down why your Arduino code isn't working, even though the serial monitor says you're connected. I'll walk through the key issues and share a corrected version that matches your working cURL command.
Key Issues in Your Code
1. Missing SSL/TLS Support for HTTPS
Your code uses GSMClient, which is a plain TCP client. Kaa's endpoint uses HTTPS (port 443), so you need to use GSMSSLClient to establish a secure encrypted connection. Without this, your "connection" is just a raw TCP handshake—but the critical HTTPS handshake will fail silently, so no data actually gets transmitted to the cloud.
2. Malformed HTTP Request Format
Your POST request has several formatting errors:
- You included the full
https://connect.cloud.kaaiot.com:443in the request line, but HTTP standards require only the path here. The server is specified via theHostheader instead. - You're missing mandatory headers:
Content-Type: application/json: Tells Kaa you're sending valid JSON dataHost: connect.cloud.kaaiot.com: Required for all HTTP/1.1 requests
- Your JSON payload doesn't match the working cURL command (yours is a single object, cURL uses an array of objects). While Kaa might accept single objects, aligning with your proven cURL request eliminates unnecessary variables.
3. Unnecessary Reconnection Spam
Your loop calls client.connect(server, port) every iteration, which causes unnecessary connection churn. Instead, check if the client is already connected before attempting to reconnect.
4. No Server Response Debugging
You never read the server's response after sending the request. This means you can't see error codes (like 401 Unauthorized for a bad token, or 400 Bad Request for invalid JSON) that would help you debug exactly what's going wrong.
5. Syntax Error in Unused Code
The line String queryString = String(" \"temperature\": ) + String(temp) "); has unclosed quotes. Even though it's commented out, it's a bug waiting to happen if you uncomment it later.
Corrected Arduino Code
Here's the fixed version that addresses all these issues:
#include <ArduinoHttpClient.h> #include <MKRGSM.h> #include <ArduinoJson.h> const char PINNUMBER[] = ""; const char GPRS_APN[] = ""; const char GPRS_LOGIN[] = ""; const char GPRS_PASSWORD[] = ""; const String TOKEN = ""; // Fill in your endpoint token const String APP_VERSION = ""; // Fill in your app version name const unsigned long publishInterval = 5000UL; // 5 seconds unsigned long lastPublish = 0; // Use GSMSSLClient for HTTPS connections (critical for port 443) GSMSSLClient client; GPRS gprs; GSM gsmAccess; const char server[] = "connect.cloud.kaaiot.com"; const int port = 443; HttpClient httpClient = HttpClient(client, server, port); void setup() { Serial.begin(9600); while (!Serial); // Wait for serial monitor to connect (native USB only) Serial.println("Initializing GSM connection..."); boolean connected = false; // Connect to GSM and GPRS network while (!connected) { if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { connected = true; Serial.println("GSM/GPRS connected successfully!"); } else { Serial.println("Failed to connect. Retrying..."); delay(1000); } } } void loop() { // Reconnect to server if disconnected if (!client.connected()) { Serial.println("Connecting to Kaa server..."); if (client.connect(server, port)) { Serial.println("Connected to Kaa cloud!"); } else { Serial.println("Server connection failed. Retrying in 3 seconds..."); delay(3000); return; // Skip rest of loop if connection fails } } // Publish data at specified interval unsigned long now = millis(); if (now - lastPublish >= publishInterval) { lastPublish = now; // Generate sample sensor data int temp = random(18, 24); // Range: 18-23 inclusive int humidity = random(40, 60); Serial.printf("Publishing data: temperature=%d, humidity=%d\n", temp, humidity); // Build the exact path from your working cURL command String path = "/kp1/" + APP_VERSION + "/dcx/" + TOKEN + "/json"; // Send properly formatted POST request httpClient.beginRequest(); httpClient.post(path); // Add required HTTP headers httpClient.sendHeader("Host", server); httpClient.sendHeader("Content-Type", "application/json"); // Send Content-Length header (good practice for JSON payloads) String payload = "[{\"temperature\": " + String(temp) + ", \"humidity\": " + String(humidity) + "}]"; httpClient.sendHeader("Content-Length", payload.length()); // Finalize headers and send payload httpClient.endRequest(); httpClient.print(payload); // Read and print server response for debugging Serial.println("\nServer response:"); int statusCode = httpClient.responseStatusCode(); Serial.printf("Status code: %d\n", statusCode); String responseBody = httpClient.responseBody(); Serial.println(responseBody); } // Small delay to prevent loop spam delay(100); }
Additional Tips
- Fill in your credentials: Make sure you populate
PINNUMBER,GPRS_APN,GPRS_LOGIN,GPRS_PASSWORD,TOKEN, andAPP_VERSIONwith your actual values. - Use serial output for debugging: The corrected code prints the server's status code and response body. This will immediately tell you if there's an authentication issue, invalid path, or malformed JSON.
- Power supply: MKR GSM 1400 uses significant power during GPRS/SSL connections. Use a robust power supply (not just USB) if running the device for extended periods.
内容的提问来源于stack exchange,提问作者Timor Bader

