Vor kurzem habe ich an einem IoT-Projekt mit einem MSP430F5529-Mikrocontroller und einem CC3100-Netzwerkprozessor von Texas Instrument gearbeitet. Zur Auswertung verwende ich die Startrampe MSP430F5529 und das Boosterpack CC3100 . Ich versuche, das Gerät dazu zu bringen, eine Verbindung zur Cloud herzustellen. Ich habe die CC3100 Get Weather- Beispielanwendung erfolgreich implementiert, die eine Verbindung zu www.openweathermap.org herstellt . Dieses Beispiel stammt aus CC3100 SDK-Beispielanwendungen . Das Programm erhält und antwortet erfolgreich von der Website www.openweathermap.org . Die Anwendung verwendet die GET-Methode, um eine Anfrage von der Website zu stellen.
Ich habe den Code auch erfolgreich gegen www.mocky.io getestet . Das Gerät erhält eine Statuscode 200 OK-Antwort. Wenn ich jedoch gegen requestb.in test site teste, erhalte ich weder einen 408 Timeout-Fehlerantwortcode noch einen URL-Umleitungsantwortcode von 302.
#define WEATHER_SERVER "api.openweathermap.org"
#define TEST_SERVER "requestb.in"
//#define TEST_SERVER "www.mocky.io"
#define PREFIX_BUFFER "GET /data/2.5/weather?q="
#define POST_BUFFER "&APPID=xxxxxxxxxxxxxxxxxx&mode=xml&units=imperial HTTP/1.1\r\nHost:api.openweathermap.org\r\nAccept: */"
#define POST_BUFFER2 "*\r\n\r\n"
#define PREFIX_BUFFER_TEST "GET /1m75pgt1"
#define POST_BUFFER_TEST_1 " HTTP/1.1\r\nHost:requestb.in\r\nAccept: */"
#define POST_BUFFER_TEST_2 "\r\n\r\n"*
//#define PREFIX_BUFFER_TEST "GET /v2/5967a65d1100007d16b6c2b4"
//#define POST_BUFFER_TEST_1 " HTTP/1.1\r\nHost:www.mocky.io\r\nAccept: */"
//#define POST_BUFFER_TEST_2 "\r\n\r\n"*
Nachfolgend finden Sie die wichtigsten Informationen zu einigen Einrichtungsbedingungen. Ein Teil des Fehlerbehandlungscodes wurde der Kürze halber entfernt.
int main(int argc, char** argv)
{
_i32 retVal = -1;
retVal = initializeAppVariables();
ASSERT_ON_ERROR(retVal);
/* Stop WDT and initialize the system-clock of the MCU */
stopWDT();
initClk();
/*
* Following function configures the device to default state by cleaning
* the persistent settings stored in NVMEM (viz. connection profiles &
* policies, power policy etc)
*
* Applications may choose to skip this step if the developer is sure
* that the device is in its default state at start of application
*
* Note that all profiles and persistent settings that were done on the
* device will be lost
*/
retVal = configureSimpleLinkToDefaultState();
/*
* Assumption is that the device is configured in station mode already
* and it is in its default state
*/
retVal = sl_Start(0, 0, 0);
/* Connecting to WLAN AP */
retVal = establishConnectionWithAP();
retVal = getCredentials();
retVal = disconnectFromAP();
return 0;
}
Unten finden Sie den Code getCredentials (), mit dem Aufrufdaten abgerufen werden.
<!-- language: lang-c -->
static _i32 getCredentials()
{
_i32 retVal = -1;
pal_Strcpy((char *)g_DeviceData.HostName, TEST_SERVER);
retVal = getHostIP_Device();
g_DeviceData.SockID = createConnection();
ASSERT_ON_ERROR(g_DeviceData.SockID);
retVal = getData();
ASSERT_ON_ERROR(retVal);
retVal = sl_Close(g_DeviceData.SockID);
ASSERT_ON_ERROR(retVal);
return 0;
}
Unten ist eine Funktion getdata () , bei der der Fehler angezeigt wird.
/*!
\brief This function Obtains the required data from the server
\param[in] none
\return 0 on success, -ve otherwise
\note
\warning
*/
static _i32 getData()
{
_u8 *p_startPtr = NULL;
_u8 *p_endPtr = NULL;
_u8* p_bufLocation = NULL;
_i32 retVal = -1;
pal_Memset(g_DeviceData.Recvbuff, 0, sizeof(g_DeviceData.Recvbuff));
/* Puts together the HTTP GET string. */
p_bufLocation = g_DeviceData.SendBuff;
pal_Strcpy(p_bufLocation, PREFIX_BUFFER_TEST);
p_bufLocation += pal_Strlen(PREFIX_BUFFER_TEST);
pal_Strcpy(p_bufLocation, POST_BUFFER_TEST_1);
p_bufLocation += pal_Strlen(POST_BUFFER_TEST_1);
pal_Strcpy(p_bufLocation, POST_BUFFER_TEST_2);
/* Send the HTTP GET string to the open TCP/IP socket. */
retVal = sl_Send(g_DeviceData.SockID, g_DeviceData.SendBuff, pal_Strlen(g_DeviceData.SendBuff), 0);
if(retVal != pal_Strlen(g_DeviceData.SendBuff))
ASSERT_ON_ERROR(HTTP_SEND_ERROR);
/* Receive response */
retVal = sl_Recv(g_DeviceData.SockID, &g_DeviceData.Recvbuff[0], MAX_SEND_RCV_SIZE, 0);
if(retVal <= 0)
ASSERT_ON_ERROR(HTTP_RECV_ERROR);
g_DeviceData.Recvbuff[pal_Strlen(g_DeviceData.Recvbuff)] = '\0';
return SUCCESS;
}
Die Sicherheit für den Access Point ist eingerichtet als
#define SEC_TYPE SL_SEC_TYPE_WPA_WPA2 /* Security type of the Access point */
Schließlich gibt es nur wenige mit CC3100 hergestellte POC-Sensorgeräte, die Daten in die Cloud übertragen müssen. Der Einfachheit halber verwenden wir das Boosterpack. Schließlich müssen die POC-Sensorgeräte über WLAN mit der Cloud kommunizieren.
quelle
Antworten:
Der Unterschied besteht darin, dass für die Site requestb.in HTTP über TLS mit SNI erforderlich ist
Dies ist eine ziemlich komplexe HTTP / HTTPS- Protokoll- und Sicherheitsfrage , die wahrscheinlich an anderer Stelle im SE-System besser behandelt wird und sich hauptsächlich auf Details des
requestb.in
Dienstes bezieht, gegen den Sie testen, und nicht auf das IoT-Projekt, das Sie möglicherweise gerade ausführen. Aber solange es hier bleibt ...Debuggen des Antwortcodes requestb.in beim Versuch von HTTP auf Port 80
Du sagtest:
Mal sehen was passiert:
Der HTTP-Status 301 lautet "Permanent verschoben", während der erwartete 302 manchmal für eine temporäre Umleitung verwendet wird. Da sie wahrscheinlich nicht vorhaben, HTTP jemals an einem einfachen TCP-Socket an Port 80 verwenden zu lassen, ist die permanente Weiterleitung, die sie senden, die korrektere Antwort.
Es wäre viel hilfreicher gewesen, wenn Sie den Statuscode erfasst hätten, der gesendet wurde, anstatt nur zwei aufzulisten, die nicht gesendet wurden
Auf jeden Fall sagt der Server, dass wir HTTPS verwenden müssen.
Was müssten Sie also tun, um über HTTPS eine Verbindung zum Server herzustellen?
Grundsätzlich bedeutet HTTPS einfach, HTTP über eine mit TLS (oder früher SSL) gesicherte Verbindung zu sprechen, anstatt dies über einen einfachen TCP-Socket zu tun.
Ihr CC3100 unterstützt TLS und SSL . Es gibt nur wenige Informationen zum Ändern eines der HTTP-Client-Beispiele des SDK, um eine HTTPS-Verbindung herzustellen, indem stattdessen ein sicherer Kanal unter http://processors.wiki.ti.com/index.php bereitgestellt wird / CC3100_HTTP_Client
In diesem Fall ist
requestb.in
dies jedoch möglicherweise nicht ausreichend.Wenn Sie eine sehr einfache GET-Anforderung in den
s_client
Befehl von openssl leiten (oder dasselbe auf dem CC3100 tun)(Damit
sleep
soll openssl auf eine Antwort warten, anstatt am Ende der Eingabe aufzulegen.)Sie würden einen seltsamen Fehler erhalten:
Möglicherweise hat dies etwas mit SSL- oder TLS-Versionen zu tun, aber tatsächlich ist dies darauf zurückzuführen,
requestb.in
dass etwas namens Server Name Indication (Wikipedia) erforderlich ist . Dies bedeutet effektiv, dass Sie dem SSL-Stack mitteilen müssen, unter welchem Servernamen er sich authentifizieren soll.Wenn Sie mit den Befehlszeilendemonstrationen fortfahren, fügen Sie einfach ein
-servername
Argument hinzu:Wenn dies mit dem URL-Hash einer gültigen requestb.in-Instanz erfolgt, wird ein Ergebnis erstellt, das im Protokollbereich des Browsers angezeigt wird, der das erstellt hat.
Implementieren der Servernamenanzeige (SNI) auf dem CC3xxx
Es gibt einige Forum - Beiträge darauf hindeutet , dass die TLS - Implementierung auf der CC3xxx hat SNI nicht unterstützt wird , und dass es keine konkreten Pläne , dies zu addieren; Sie können jedoch überprüfen, ob dies immer noch der Fall ist.
Es ist jedoch wichtig, sich daran zu erinnern, dass es sich um einen Baum von Netzwerkebenen handelt:
Da Sie mit dem CC3100 TCP sprechen können (und dies tatsächlich in Ihrem vorhandenen Code getan haben), können Sie Ihre eigene TLS-Implementierung mit SNI-Unterstützung "mitbringen". In diesem Blogbeitrag wird beispielsweise die Portierung der Bibliothek mbed TLS (ehemals PolarSSL) auf das CC3xxx erläutert und SNI als Funktion erwähnt.
TL; DR
requestb.in
ist ein herausforderndes Ziel, da Sie HTTP über eine mit TLS gesicherte Sitzung sprechen und die Servernamenanzeige implementieren müssen . Wenn die Kommunikation mit diesem Host nicht Teil Ihres endgültigen Projekts ist, ist es möglicherweise besser, einfach zu den Hosts zu wechseln, die für die Verwendung mit minimalen eingebetteten Clients auf IoT-Geräten vorgesehen sind, um die Arbeit zu vereinfachen SNI nicht verwenden.Es wird auch weitaus effizienter, wenn Sie sich angewöhnen, die Details von Problemen zu erfassen, auf die Sie stoßen. Die eingebettete Entwicklung ist immer schwierig zu debuggen. Je weniger Informationen über Fehler Sie über die Protokollierung oder einen Debugger erfassen, desto mehr Zeit wird für das Erraten aufgewendet .
quelle
Es ist sehr wahrscheinlich, dass sowohl openweathermap.org als auch www.mocky.io http oder Port 80 unterstützen. Nachfolgend einige Hinweise.
openweathermap.org
www.mocky.io
Sieht so aus, als würde requestb.in nur HTTPS oder Port 443 unterstützen.
requestb.in
Dies könnte das Problem erklären. Im Folgenden finden Sie einige Referenzen, die hilfreich sein könnten.
Im CC3100-Datenblatt gibt es keine Verweise auf CC3100, die mit HTTPS arbeiten. Alle Verweise beziehen sich nur auf HTTP. Dies erklärt das Problem wahrscheinlich besser. Fügen Sie unten eine Ausnahme aus dem Datenblatt hinzu.
Laut Datenblatt unterstützt CC3120 HTTPS. Anhang unten ist außer aus dem Datenblatt. Es gibt nur wenige Verweise auf HTTPS.
Der wahrscheinlichste Weg nach vorne ist das Ersetzen des CC3100 durch CC3120.
Verweise:
quelle