Récemment, j'ai travaillé sur un projet IoT utilisant un microcontrôleur MSP430F5529 et un processeur réseau CC3100 tous deux de Texas Instrument. Pour l'évaluation, j'utilise la rampe de lancement MSP430F5529 et le boosterpack CC3100 . J'essaie de faire en sorte que l'appareil se connecte au cloud. J'ai réussi à implémenter l' application d'exemple de météo CC3100 qui se connecte à www.openweathermap.org . Cet exemple provient des exemples d'application du SDK CC3100 . Le programme reçoit et répond avec succès du site Web www.openweathermap.org . L'application utilise la méthode GET pour faire une demande à partir du site Web.
J'ai également testé avec succès le code contre www.mocky.io . L'appareil reçoit une réponse de code d'état 200 OK. Mais lorsque je teste contre le site de test requestb.in , je n'obtiens ni un code de réponse d'erreur 408 Timeout ni un code de réponse de redirection d'URL de 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"*
Ci-dessous est le principal qui comprend certaines des conditions de configuration. Une partie du code de gestion des erreurs a été supprimée par souci de concision.
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;
}
Ci-dessous se trouve le code getCredentials () qui appelle get data.
<!-- 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;
}
Ci-dessous est une fonction getdata () où j'obtiens l'erreur.
/*!
\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;
}
La sécurité du point d'accès est configurée comme
#define SEC_TYPE SL_SEC_TYPE_WPA_WPA2 /* Security type of the Access point */
Enfin, il existe peu de capteurs POC fabriqués avec CC3100 qui doivent transférer des données vers le cloud. Pour plus de simplicité, nous utilisons le boosterpack, nous devons finalement faire en sorte que les capteurs POC communiquent avec le cloud via le Wifi.
la source
Réponses:
La différence est que le site requestb.in nécessite HTTP sur TLS avec SNI
Il s'agit d'un protocole HTTP / HTTPS assez complexe et d'une question de sécurité probablement mieux abordée ailleurs dans le système SE, et concernant principalement les détails du
requestb.in
service contre lequel vous testez plutôt que le projet IoT que vous pourriez éventuellement faire. Mais tant qu'il reste ici ...Débogage du code de réponse requestb.in lors d'une tentative de HTTP sur le port 80
Tu as dit:
Voyons ce qui se passe:
Le statut HTTP 301 est "Déplacé en permanence", tandis que le 302 que vous attendiez est parfois utilisé pour une redirection temporaire . Puisqu'ils ne prévoient probablement pas de vous laisser utiliser HTTP sur un socket TCP ordinaire sur le port 80, la redirection permanente qu'ils envoient est la réponse la plus correcte.
Cela aurait été beaucoup plus utile si vous aviez capturé le code d'état que _a été_ envoyé plutôt que d'en répertorier simplement deux qui_n'ont pas été_ envoyés
Quoi qu'il en soit, ce que le serveur dit, c'est que nous devons utiliser HTTPS.
Alors, que devez-vous faire pour vous connecter au serveur via HTTPS?
À un niveau de base, HTTPS signifie simplement parler HTTP sur une connexion sécurisée avec TLS (ou auparavant, SSL), plutôt que de le faire sur un socket TCP ordinaire.
Votre CC3100 prend en charge TLS et SSL , et il existe quelques informations minimales sur la modification de l'un des exemples de client HTTP du SDK pour effectuer une connexion HTTPS en créant à la place un canal sécurisé, disponible sur http://processors.wiki.ti.com/index.php / CC3100_HTTP_Client
Cependant, dans ce cas,
requestb.in
cela pourrait ne pas être suffisant.Si vous
s_client
deviez envoyer une requête GET très simple dans la commande openssl (ou faire la même chose sur le CC3100)(le
sleep
fait de faire ouvrir à openssl une réponse plutôt que de raccrocher à la fin de l'entrée)Vous obtiendriez une erreur étrange:
Vous pourriez penser que cela a quelque chose à voir avec les versions SSL vs TLS, mais en fait c'est parce que cela
requestb.in
nécessite quelque chose appelé Server Name Indication (Wikipedia) . Cela signifie que vous devez indiquer à la pile SSL d'indiquer au serveur sous quel nom de serveur il doit s'authentifier.En poursuivant avec les démonstrations en ligne de commande, nous ajoutons simplement un
-servername
argument:Si cela est fait avec le hachage URL d'une instance requestb.in valide, cela produit un résultat et est visible dans le panneau de journalisation du navigateur qui l'a créé.
Implémentation de l'indication de nom de serveur (SNI) sur le CC3xxx
Il y a des messages sur le forum suggérant que l'implémentation TLS sur le CC3xxx n'a pas supporté SNI, et qu'il n'y a pas de plans concrets pour l'ajouter; cependant, vous pouvez vérifier si c'est toujours le cas.
Mais il est important de se rappeler qu'il y a un arbre de couches réseau impliqué:
Étant donné que le CC3100 vous permet de parler TCP (et en fait, vous le faisiez dans votre code existant), vous êtes libre d'apporter "votre propre" implémentation TLS qui prend en charge SNI. Par exemple, ce billet de blog traite du portage de la bibliothèque mbed TLS (anciennement PolarSSL) vers le CC3xxx et mentionne SNI comme capacité.
TL; DR
requestb.in
est une cible difficile car elle nécessite que vous parliez HTTP sur une session sécurisée avec TLS et implémentant l' indication de nom de serveur . Si parler à cet hôte ne fait pas partie de votre projet ultime, il pourrait être préférable de simplement passer aux hôtes qui sont - ceux destinés à être utilisés avec un minimum de clients intégrés sur les appareils IoT pourraient bien être configurés pour rendre les choses un peu plus faciles en n'utilise pas SNI.Il sera également beaucoup plus efficace si vous prenez l'habitude de capturer les détails des problèmes que vous rencontrez - le développement intégré est toujours difficile à déboguer, et moins il y a d'informations sur les échecs que vous capturez via la journalisation ou un débogueur, plus vous passez de temps à deviner .
la source
Il est très probable que openweathermap.org et www.mocky.io prennent en charge http ou le port 80. Ci-dessous, quelques indices.
openweathermap.org
www.mocky.io
On dirait que requestb.in prend en charge HTTPS ou le port 443 uniquement.
requestb.in
Cela pourrait expliquer le problème. Voici quelques références qui pourraient vous aider.
Dans la fiche technique du CC3100, il n'y a aucune référence au CC3100 fonctionnant avec HTTPS. Toutes les références concernent uniquement HTTP. Cela explique probablement mieux le problème. Attachez ci-dessous un sauf de la fiche technique.
Ressemble à la fiche technique CC3120 prend en charge HTTPS. Attacher ci-dessous est sauf de la fiche technique. Il y a peu de références à HTTPS.
La voie à suivre la plus probable est de remplacer le CC3100 par le CC3120.
Références:
la source