Unità MangOH Red
Descrizione del prodotto
L'unità mangOH™ Red è una piattaforma a basso consumo per Internet delle cose (IoT) in grado di funzionare a batteria fino a 10 anni. Secondo mangoh.io essa offre:
- Fattore di forma pari a una carta di credito ideale per realizzare rapidamente dimostrazioni della validità dei progetti in fase di sviluppo;
- Uno zoccolo a innesto per l'aggiunta di qualunque modulo compatibile con CF3™, compresi i moduli wireless (da 2G a 4G e LTE-M/NB-IoT), per ottenere una durata della batteria fino a 10 anni (per questo articolo è stato utilizzato un modulo CF3 WP8548_1103113 (codice componente DigiKey 1645-1022-1-ND));
- Uno slot per schede di espansione IoT in cui inserire qualunque tecnologia basata sullo standard aperto di tali schede;
- Una Smart SIM di Sierra Wireless integrata con dati gratuiti fino a un massimo di 100 MB, a seconda dell'area geografica, con la possibilità di utilizzare anche qualunque SIM disponibile in commercio;
- L'integrazione con la piattaforma IoT AirVantage per creare, distribuire e gestire le soluzioni nel cloud;
- Wi-Fi b/g/n e Bluetooth 4.2 BLE incorporati con un core Cortex-M4 per l'accesso in tempo reale agli I/O; e
- Un accelerometro/giroscopio e sensori di pressione e di luce incorporati, oltre a un connettore a 26 pin compatibile con Raspberry Pi (il codice componente DigiKey del cavo per il connettore è 1597-1065-ND).
(Immagine per gentile concessione di Talon Communications Inc.)Contenuto della confezione
La confezione aperta per questo articolo conteneva:
- Unità mangOH Red
- Modulo CF3 (WP8548_1103113 nel nostro caso)
- Cavo Micro-USB
- 2 antenne (1 principale e 1 per il sistema satellitare di navigazione globale (GNSS)
- Scheda micro SIM Sierra Wireless con allocazione iniziale dei dati
Installazione hardware
Seguire le istruzioni di installazione contenute nella Guida per l'installazione e l'uso dell'unità mangOH Red.
Sull'unità mangOH Red sono presenti due porte Micro-USB.
L'installazione hardware è risultata particolarmente semplice: è stato sufficiente collegare il cavo Micro-USB all'unità mangOH e a un computer, collegare le antenne e inserire la scheda SIM nello slot presente sul lato posteriore dell'unità mangOH. La figura riportata di seguito mostra un'illustrazione dell'architettura hardware tratta dalla Guida mangOH Red per gli sviluppatori:
(Immagine per gentile concessione di Talon Communications Inc.)Connettore per Raspberry Pi.
Il codice componente DigiKey del connettore per cavi a nastro è 1597-1065-ND. Le immagini riportate di seguito mostrano lo schema della piedinatura sia per il Raspberry Pi (nel quale i pin non utilizzati dall'unità MangOH Red sono ombreggiati), sia per l'unità MangOH Red: i collegamenti sono dal pin 1 al pin 1, dal pin 2 al pin 2 e così via.
(Immagine per gentile concessione di pinout.xyz)
(Immagine per gentile concessione di Talon Communications Inc.)Installazione software
L'installazione software è risultata leggermente più complicata. Quando si inizia il percorso per lavorare con questo dispositivo, vale la pena osservare che nel prodotto finale dell'unità mangOH sono coinvolti tre elementi. L'unità MangOH Red è la scheda vera e propria, Sierra Wireless è il produttore del modulo CF3, nonché il proprietario di AirVantage, vale a dire il cloud IoT in cui vengono memorizzati i dati provenienti dall'unità mangOH, e infine l'interfaccia a riga di comando (CLI) Legato, basata su Linux, utilizzata per il collegamento con l'unità mangOH. Nell'articolo, esaminerò a mano a mano ciascuno di tali elementi e le modalità di collegamento ai rispettivi forum.
Visitare per primo il sito della Guida introduttiva a mangOH. È possibile selezionare i sistemi operativi Windows o Linux (anche Mac OS è compatibile, ma ne parlerò più avanti). A prescindere dal sistema operativo scelto, occorre comunque incorporare l'interfaccia CLI Legato tramite una macchina virtuale (Oracle VirtualBox) su Windows, o un add-on per lo sviluppo di Legato su Linux. Il Manuale di installazione per Windows e il Manuale di installazione per Linux sono risorse eccellenti durante l'installazione della macchina, quindi non riprodurrò qui le relative informazioni.
Se si utilizza una macchina Linux a 64 bit, prestare attenzione al punto 6 a pagina 16 del Manuale di installazione per Linux.
Occorre inoltre scaricare Developer Studio, disponibile per i sistemi operativi Windows, Linux e Mac. Secondo il sito Web di Sierra Wireless, "Developer Studio è l'ambiente di sviluppo integrato (IDE) di Sierra Wireless per il framework applicativo Legato". Ciò significa che per la creazione delle proprie app si hanno a disposizione due opzioni, vale a dire utilizzare un programma di testo base oppure servirsi di Developer Studio, uno strumento a base grafica che automatizza alcune delle operazioni di creazione dei file / delle cartelle. Ho scaricato Developer Studio per ciascun sistema operativo e ho incontrato un unico intoppo, vale a dire il requisito di Java 8 per Mac OS; per qualche motivo, l'installazione regolare di Java 8 non è stata sufficiente per l'esecuzione di Developer Studio, quindi in ultimo ho scaricato e installato il kit di sviluppo Java SE 8u151 Oracle.
App campione e struttura dei file
Una volta installata l'unità mangOH, il punto migliore per iniziare è Legato su Github. Scaricare o clonare la cartella Legato. Visitare su Github anche le spiegazioni relative alle App campione Legato per alcuni dei campioni scaricati. Il sito web delle app campione Legato è inoltre una risorsa eccellente per le spiegazioni "How To".
Occorre prestare attenzione anche alla struttura dei file. Ogni applicazione ha la seguente struttura di directory/file:

A seconda dell'applicazione, la struttura dei file può inoltre includere file dei tipi .API e .h. La parte sostanziosa della programmazione si trova nel file .c, mentre gli altri file contengono istruzioni destinate al compilatore per la creazione delle applicazioni.
Esempio: app di testo di localizzazione GNSS
L'applicazione tipo che illustra molto di ciò che l'unità mangOH Red è in grado di fare è quella che invia all'utente un testo con le coordinate dell'unità mangOH Red stessa. La struttura dei file è riportata sopra.
Il codice per il file textLoc.c è riportato di seguito. Fare clic qui per visualizzare l'articolo Alla scoperta di nuovi prodotti in cui Randall Restle ha presentato per la prima volta l'unità mangOH Red.
Copy
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


