MangOH Red
Description produit
mangOH™ Red est une plateforme Internet des objets (IoT) basse consommation, dotée d'une autonomie batterie atteignant 10 ans. Selon mangoh.io, voici ses caractéristiques :
- Format de la taille d'une carte de crédit idéal pour concevoir rapidement des démonstrations de faisabilité
- Connecteur enfichable pour ajouter des modules compatibles CF3®, y compris des modules sans fil (2G à 4G et LTE-M/NB-IoT), pour atteindre jusqu'à 10 ans de durée de vie des batteries (le module CF3 utilisé dans cet article est le modèle WP8548_1103113, référence DigiKey 1645-1022-1-ND)
- Logement de carte d'extension IoT pour connecter toute technologie basée sur la norme ouverte IoT Expansion Card
- Carte Smart SIM intégrée de Sierra Wireless avec jusqu'à 100 Mo gratuits, selon la région, et compatible avec toutes les cartes SIM en vente sur le marché
- Intégration à la plateforme IoT AirVantage pour créer, déployer et gérer des solutions dans le cloud
- Technologies Wi-Fi b/g/n et Bluetooth 4.2 BLE intégrées avec Cortex-M4 pour fournir un accès en temps réel aux E/S
- Capteurs de lumière et de pression, accéléromètre/gyroscope intégrés, et connecteur compatible Raspberry Pi à 26 broches (référence du câble du connecteur DigiKey Electronics 1597-1065-ND)
(Source de l'image : Talon Communications Inc.)
Contenu de la boîte
La boîte que nous avons ouverte inclut les éléments suivants :
- mangOH Red
- Module CF3 (WP8548_1103113 dans le cas présent)
- Câble micro-USB
- 2 antennes (1 antenne principale et 1 GNSS)
- Carte micro-SIM de Sierra Wireless avec allocation de données initiale
Configuration matérielle
Suivez les instructions de configuration figurant dans le guide de configuration et d'utilisation de mangOH Red.
Le mangOH Red comprend deux ports micro-USB.
La configuration matérielle est simple : branchez le câble micro-USB au mangOH et à un ordinateur, connectez l'antenne et insérez la carte SIM dans le logement à l'arrière du mangOH. La figure suivante montre l'illustration de l'architecture matérielle tirée du guide pour les développeurs mangOH Red :
(Source de l'image : Talon Communications Inc.)
Connecteur Raspberry Pi
La référence DigiKey du connecteur à câble plat est 1597-1065-ND. Les images suivantes illustrent le schéma de brochage du Raspberry Pi (les broches non utilisées par le mangOH Red sont grisées) et du mangOH Red : les connexions relient la broche 1 à la broche 1, la broche 2 à la broche 2, etc.
(Source de l'image : pinout.xyz)
(Source de l'image : Talon Communications Inc.)
Configuration logicielle
La configuration logicielle est un peu plus compliquée. Lorsque vous commencez à travailler avec ce dispositif, il est important de noter que trois entités sont impliquées dans le produit final du mangOH. Le mangOH Red est la carte proprement dite ; Sierra Wireless est le fabricant du module CF3 et le propriétaire d'AirVantage, qui est une plateforme cloud IoT stockant les données du mangOH ; et Legato est l'interface de ligne de commande (CLI) utilisée pour se connecter au mangOH. J'aborderai chacun de ces éléments et la façon de se connecter à leurs forums.
Le premier site Web à consulter est celui consacré aux premiers pas avec mangOH. Vous pouvez choisir un système d'exploitation Windows ou Linux (Mac OS est également compatible, mais j'en parlerai plus tard). Qu'importe le système d'exploitation choisi, vous devrez toujours intégrer l'interface Legato via une machine virtuelle (Oracle VirtualBox) sur Windows ou un module complémentaire pour le développement Legato sur Linux. Le manuel de configuration Windows et le manuel de configuration Linux constituent d'excellentes ressources à utiliser lors de la configuration de votre machine. Je ne m'attarderai donc pas sur ce sujet ici.
Si vous utilisez une machine Linux 64 bits, faites attention au point n°6 de la page 16 du manuel de configuration Linux.
Vous devez également télécharger Developer Studio, qui est disponible pour les systèmes d'exploitation Windows, Linux et Mac. D'après le site Web de Sierra Wireless, « Developer Studio est l'environnement de développement intégré (IDE) de Sierra Wireless pour l'infrastructure d'application Legato ». Cela signifie que vous avez deux options pour la création de vos applications : vous pouvez utiliser un programme textuel de base ou opter pour Developer Studio, qui est un programme graphique permettant d'automatiser certaines instances de création de fichier/dossier. J'ai téléchargé Developer Studio sur chaque système d'exploitation et le seul problème que j'ai constaté concerne Java 8 pour Mac OS. Pour une raison que j'ignore, la version standard de Java 8 n'est pas adaptée à l'exécution de Developer Studio, et j'ai donc dû télécharger et installer le kit de développement Java SE 8u151 d'Oracle.
Applications d'exemple et structure de fichier
Le point de départ idéal, après la configuration de mangOH, est Legato sur Github. Téléchargez ou clonez le dossier Legato. Vous pouvez également consulter les explications des applications d'exemple Legato pour certains des exemples téléchargés sur Github. Le site Web des applications d'exemple Legato est également une excellente ressource pour les « guides pratiques ».
La structure de fichier est également un élément important. Chaque application présente la structure de répertoire/fichier suivante :
La structure de fichier peut également inclure des types de fichier .API et .h, en fonction de l'application. Le cœur de la programmation se trouve dans le fichier .c, tandis que les autres fichiers offrent des instructions dédiées au compilateur pour la création de l'application.
Exemple : application de message pour la localisation GNSS
L'application d'exemple qui illustre la majorité des fonctionnalités du mangOH Red est une application pouvant envoyer par message les coordonnées du mangOH Red à l'utilisateur. La structure de fichier est présentée ci-dessus.
Le code du fichier textLoc.c est inclus ci-dessous. Cliquez ici pour consulter la vidéo New Product Discovery de Randall Restle dans laquelle il présente le mangOH Red.
Copier
textLoc.c //-------------------------------------------------------------------------------------------------- /** @file textLoc.c * * This app illustrates a sample usage of ultra low power mode API. This app reads the current gps * location and then sends it as a text message to a destination cell phone number. Once the text * message has been sent, the device enters ultra low power mode. The device will wake up from * ultra low power mode after a configurable delay. * * @note This app expects destination cell number to be specified in environment variable section * of adef file. If nothing specified in environment variable, it will send message to a default * non-existent phone number. * * Copyright (C) Sierra Wireless Inc. */ //-------------------------------------------------------------------------------------------------- #include "legato.h" /* IPC APIs */ #include "interfaces.h" //-------------------------------------------------------------------------------------------------- /** * GPS timeout interval in minutes * * @note Please change this timeout value as needed. */ //-------------------------------------------------------------------------------------------------- #define GPSTIMEOUT 15 //-------------------------------------------------------------------------------------------------- /** * Default phone number to send location information. * * @note This is a non-existent phone number (ref: * https://en.wikipedia.org/wiki/Fictitious_telephone_number). */ //-------------------------------------------------------------------------------------------------- #define DEFAULT_PHONE_NO "8005550101" //-------------------------------------------------------------------------------------------------- /** * Timer interval(in seconds) to exit from shutdown/ultralow-power state. * * @note Please change this interval as needed. */ //-------------------------------------------------------------------------------------------------- #define ULPM_EXIT_INTERVAL 30 //-------------------------------------------------------------------------------------------------- /** * Gpio used to exit from shutdown/ultralow-power state. * * @note Please change gpio number as needed. */ //-------------------------------------------------------------------------------------------------- #define WAKEUP_GPIO_NUM 38 //-------------------------------------------------------------------------------------------------- /** * Pointer to the null terminated string containing the destination phone number. */ //-------------------------------------------------------------------------------------------------- static const char *DestPhoneNumberPtr; //-------------------------------------------------------------------------------------------------- /** * Attempts to use the GPS to find the current latitude, longitude and horizontal accuracy within * the given timeout constraints. * * @return * - LE_OK on success * - LE_UNAVAILABLE if positioning services are unavailable * - LE_TIMEOUT if the timeout expires before successfully acquiring the location * * @note * Blocks until the location has been identified or the timeout has occurred. */ //-------------------------------------------------------------------------------------------------- static le_result_t GetCurrentLocation( int32_t *latitudePtr, ///< [OUT] latitude of device - set to NULL if not needed int32_t *longitudePtr, ///< [OUT] longitude of device - set to NULL if not needed int32_t *horizontalAccuracyPtr, ///< [OUT] horizontal accuracy of device - set to NULL if not ///< needed uint32_t timeoutInSeconds ///< [IN] duration to attempt to acquire location data before ///< giving up. A value of 0 means there is no timeout. ) { le_posCtrl_ActivationRef_t posCtrlRef = le_posCtrl_Request(); if (!posCtrlRef) { LE_ERROR("Can't activate the Positioning service"); return LE_UNAVAILABLE; } le_result_t result; const time_t startTime = time(NULL); LE_INFO("Checking GPS position"); while (true) { result = le_pos_Get2DLocation(latitudePtr, longitudePtr, horizontalAccuracyPtr); if (result == LE_OK) { break; } else if ( (timeoutInSeconds != 0) && (difftime(time(NULL), startTime) > (double)timeoutInSeconds)) { result = LE_TIMEOUT; break; } else { // Sleep for one second before requesting the location again. sleep(1); } } le_posCtrl_Release(posCtrlRef); return result; } //-------------------------------------------------------------------------------------------------- /** * Sends an SMS text message to the given destination with the given message content. * * @return * - LE_OK on success * - LE_FAULT on failure */ //-------------------------------------------------------------------------------------------------- static le_result_t SendTextMessage( const char *destinationNumberPtr, ///< [IN] Phone number to send the text message to as ASCII ///< values const char *messageBodyPtr ///< [IN] Text message body content ) { le_result_t result = LE_OK; LE_INFO("Sending SMS"); le_sms_MsgRef_t sms = le_sms_Create(); if (le_sms_SetDestination(sms, destinationNumberPtr) != LE_OK) { result = LE_FAULT; LE_ERROR("Could not set destination phone number"); goto sms_done; } if (le_sms_SetText(sms, messageBodyPtr) != LE_OK) { result = LE_FAULT; LE_ERROR("Could not set text message body"); goto sms_done; } if (le_sms_Send(sms) != LE_OK) { result = LE_FAULT; LE_ERROR("Could not send SMS message"); goto sms_done; } LE_INFO("SMS Message sent"); sms_done: le_sms_Delete(sms); return result; } //-------------------------------------------------------------------------------------------------- /** * Send the device location as a text message * * Attempts to send an SMS text message containing the current device location to the destination * phone number. * * @note * No failure notification is provided if location services or SMS send are unsuccessful. */ //-------------------------------------------------------------------------------------------------- static void SendSmsCurrentLocation( void ) { char smsBody[LE_SMS_TEXT_MAX_LEN]; int32_t latitude; int32_t longitude; int32_t horizontalAccuracy; const le_result_t result = GetCurrentLocation(&latitude, &longitude, &horizontalAccuracy, GPSTIMEOUT * 60); if (result == LE_OK) { snprintf(smsBody, sizeof(smsBody), "Loc:%d,%d", latitude, longitude); } else { strncpy(smsBody, "Loc:unknown", sizeof(smsBody)); } SendTextMessage(DestPhoneNumberPtr, smsBody); } //-------------------------------------------------------------------------------------------------- /** * Configure the boot source and shutdown MDM. */ //-------------------------------------------------------------------------------------------------- static void CfgShutDown ( void ) { // Boot after specified interval. if (le_ulpm_BootOnTimer(ULPM_EXIT_INTERVAL) != LE_OK) { LE_ERROR("Can't set timer as boot source"); return; } // Boot on gpio. Please note this is platform dependent, change it when needed. if (le_ulpm_BootOnGpio(WAKEUP_GPIO_NUM, LE_ULPM_GPIO_LOW) != LE_OK) { LE_ERROR("Can't set gpio: %d as boot source", WAKEUP_GPIO_NUM); return; } // Initiate shutdown. if (le_ulpm_ShutDown() != LE_OK) { LE_ERROR("Can't initiate shutdown."); } } //-------------------------------------------------------------------------------------------------- /** * Callback function to handle change of network registration state. */ //-------------------------------------------------------------------------------------------------- static void RegistrationStateHandler ( le_mrc_NetRegState_t state, ///< [IN] Network registration state. void *contextPtr ///< [IN] Context pointer. ) { switch(state) { case LE_MRC_REG_HOME: case LE_MRC_REG_ROAMING: LE_INFO("Registered"); SendSmsCurrentLocation(); LE_INFO("Now configure boot source and shutdown MDM"); CfgShutDown(); break; case LE_MRC_REG_SEARCHING: LE_INFO("Searching..."); break; case LE_MRC_REG_NONE: LE_INFO("Not registered"); break; case LE_MRC_REG_DENIED: LE_ERROR("Registration denied"); break; case LE_MRC_REG_UNKNOWN: LE_ERROR("Unknown registration state"); break; } } //-------------------------------------------------------------------------------------------------- /** * Simulate entry into the current NetReg state by calling RegistrationStateHandler * * RegistrationStateHandler will only be notified of state change events. This function exists to * simulate the change into the current state. */ //-------------------------------------------------------------------------------------------------- static void SimulateNetRegStateChangeToCurrentState( void *ignoredParam1, ///< Only exists to allow this function to conform to the ///< le_event_DeferredFunc_t declaration void *ignoredParam2 ///< Only exists to allow this function to conform to the ///< le_event_DeferredFunc_t declaration ) { le_mrc_NetRegState_t currentNetRegState; LE_FATAL_IF(le_mrc_GetNetRegState(¤tNetRegState) != LE_OK, "Couldn't get NetRegState"); RegistrationStateHandler(currentNetRegState, NULL); } //-------------------------------------------------------------------------------------------------- /** * Get the destination phone number. **/ //-------------------------------------------------------------------------------------------------- static void GetDestinationCellNo ( void ) { DestPhoneNumberPtr = getenv("DEST_CELL_NO"); if (!DestPhoneNumberPtr) { LE_WARN( "No destination cell number is specified. Using a default non-existent number"); DestPhoneNumberPtr = DEFAULT_PHONE_NO; } LE_INFO("Destination phone number = %s", DestPhoneNumberPtr); } COMPONENT_INIT { char version[LE_ULPM_MAX_VERS_LEN + 1]; LE_INFO("TextLoc started"); // Get ultra low power manager firmware version LE_FATAL_IF( le_ulpm_GetFirmwareVersion(version, sizeof(version)) != LE_OK, "Failed to get ultra low power firmware version"); LE_INFO("Ultra Low Power Manager Firmware version: %s", version); // Now check whether boot was due to timer expiry. if (le_bootReason_WasTimer()) { LE_INFO("Booted from timer, not sending another text message."); } else if (le_bootReason_WasGpio(WAKEUP_GPIO_NUM)) { LE_INFO("Booted from GPIO, not sending another text message."); } else { // Get the destination phone number GetDestinationCellNo(); // Register a callback handler for network registration state. le_mrc_AddNetRegStateEventHandler( (le_mrc_NetRegStateHandlerFunc_t)RegistrationStateHandler, NULL); le_event_QueueFunction(&SimulateNetRegStateChangeToCurrentState, NULL, NULL); } } The textLoc.adef file is: textLoc.adef sandboxed: false version: 1.0.0 maxFileSystemBytes: 512K executables: { textloc = ( textLocComponent ) } processes: { envVars: { LE_LOG_LEVEL = DEBUG // This is a non-existent fictitious phone number. Change it to a valid phone number. DEST_CELL_NO = 8005550101 } run: { ( textloc ) } maxCoreDumpFileBytes: 512K maxFileBytes: 512K } bindings: { textloc.textLocComponent.le_mrc -> modemService.le_mrc textloc.textLocComponent.le_posCtrl -> positioningService.le_posCtrl textloc.textLocComponent.le_pos -> positioningService.le_pos textloc.textLocComponent.le_sms -> modemService.le_sms textloc.textLocComponent.le_ulpm -> powerMgr.le_ulpm textloc.textLocComponent.le_bootReason -> powerMgr.le_bootReason } The Component.cdef: Component.cdef requires: { api: { modemServices/le_mrc.api modemServices/le_sms.api positioning/le_posCtrl.api positioning/le_pos.api le_ulpm.api le_bootReason.api } } sources: { textLoc.c } Makefile: Makefile TARGETS := $(MAKECMDGOALS) .PHONY: all $(TARGETS) all: $(TARGETS) $(TARGETS): mkapp -v -t $@ \ textLoc.adef clean: rm -rf _build_* *.update

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum