quinta-feira, 3 de novembro de 2022

LOM204A - Programando com Zephyr RTOS - NEWER

 

O objetivo deste BLOG é demonstrar como é possível utilizar o Zephyr para programação do WISOL LOM204. Foi utilizado o Starter Kit LOM204 para o teste. O exemplo permitirá via linha de comandos o acesso à rede LoRaWAN e então será enviado um texto "HELLO" via OTA, AU915 (FSB1), ao servidor LoRaWAN CHIRPSTACK.

BETA - EM TESTES - APENAS PARA PROGRAMADORES COM ZEPHYR

Baseado no B-L072Z-LRWAN1


Módulo


O que é TTN
A Rede de Coisas (TTN) é uma iniciativa iniciada pela sociedade civil holandesa. O objetivo é ter redes LoRaWAN instaladas em todas as cidades do mundo. Ao interconectar essas redes locais, a TTN quer construir uma infra-estrutura mundial para facilitar uma Internet das Coisas (IoT) pública.

A The Things Network (TTN) é o servidor IoT na nuvem utilizado nesse projeto. É um dos servidores gratuitos para LoRaWAN mais utilizados, com mais de 90 mil desenvolvedores, mais de 9 mil gateways de usuários conectados à rede ao redor do mundo e mais de 50 mil aplicações em funcionamento.

A TTN comercializa "nós" e gateways LoRa e provê treinamento individual e coletivo para empresas e desenvolvedores que desejam utilizar o LoRa. Possui uma comunidade bem ativa nos fóruns, sempre colaborando e ajudando a resolver problemas, além de prover diversos meios de integrar a TTN com a aplicação que se deseja usar. Possui integração nativa com diversas aplicações como: Cayenne (utilizado nesse trabalho), Hypertext Transfer Protocol (HTTP), permitindo ao usuário realizar uplink para um gateway e receber downlink por HTTP, OpenSensors e EVRYTHNG . Caso o usuário queira criar sua própria aplicação, a TTN disponibiliza Application Programming Interface (API) para uso com Message Queuing Telemetry Transport (MQTT) e diversos Software Developer Kits (SDK) para uso com as linguagens Python, Java , Node.Js , NODE-RED e Go

A rede TTN utiliza o protocolo LoRaWAN objetivando uma cobertura em longo alcance para os dispositivos da rede, caracterizando-a assim com uma Wide Area Network (WAN). Devido ao baixo consumo de energia e ao uso da tecnologia LoRa, é chamada de LPWAN (Low Power Wide Area Network). O grande diferencial da TTN é seu estabelecimento como uma rede aberta (open-source) e colaborativa (crowd-sourced), onde qualquer usuário pode contribuir instalando um gateway em sua residência.

Os elementos da TTN são classificados como: 

• Endpoints (nós): Os dispositivos responsáveis pela camada de sensoriamento da rede, o endpoint LoRaWAN. Podem coletar informações através de sensores e também acionar dispositivos/máquinas via atuadores. São configurados através de uma das três classes distintas do protocolo LaRaWAN; 

• Gateways: Elementos responsáveis por concentrar e processar as informações enviadas pelos endpoints. Os gateways em geral estão conectados a internet, seja por WiFi/Ethernet ou 3G/4G em locais remotos. Mesmo que uma mesma rede LoRaWAN tenha diferentes objetivos, baseados em aplicações distintas, os gateways possuem o objetivo comum de fornecer a maior área de cobertura possível; 

• Aplicações: Conectar e interligar os diferentes dispositivos da rede TTN para o fornecimento de informações gerais sobre a coleta de dados dos dispositivos.
ZEPHYR
O que é Zephyr

O sistema operacional Zephyr é baseado em um kernel de pequena dimensão projetado para uso em sistemas com recursos restritos e embarcados: de sensores ambientais incorporados simples e wearables de LED a sofisticados controladores embarcados, relógios inteligentes e aplicativos sem fio IoT.

O Projeto Zephyr RTOS é um esforço recente da Fundação Linux para fornecer ao mundo embarcado um Sistema Operacional em Tempo Real gratuito, seguro e completo. Ele foi projetado desde o início para ser um RTOS moderno, escalável, seguro e responsivo com um foco claro em protocolos e fundações de IoT. Este RTOS de código aberto é licenciado pelo Apache 2.0 e possui um modelo de desenvolvimento totalmente aberto

LOM204A e o Zephyr

Como o módulo LOM204A é baseado no chip STM32L0 (CPU), será possível rodar o Zephyr sem problemas. O usuário deve dar atenção ao mapeamento de GPIOS de acesso ao SX1276 (Semtech LoRa).

C:\msys64\home\Usuario\loramac-node\src\boards

O link abaixo, é roteiro Básico para que você possa preparar o ambiente para programar o LOM204, sobre o WSL2




$source ~/zephyrproject/.venv/bin/activate










Cmake muito antigo 
cd ~
wget https://github.com/Kitware/CMake/releases/download/v3.21.1/cmake-3.21.1-Linux-x86_64.sh
chmod +x cmake-3.21.1-Linux-x86_64.sh
sudo ./cmake-3.21.1-Linux-x86_64.sh --skip-license --prefix=/usr/local
hash -r
Compile Blynk para verificar instalação OK
west build -p always -b b_l072z_lrwan1 samples/basic/blinky
 
Compilacao
cd  /home/osboxes/zephyrproject/zephyr 
west build -p always -b b_l072z_lrwan1 samples/subsys/lorawan/class_a -p 
.
.
-- The C compiler identification is GNU 12.1.0 -- The CXX compiler identification is GNU 12.1.0 -- The ASM compiler identification is GNU -- Found assembler: /home/osboxes/zephyr-sdk-0.15.1/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc -- Configuring done -- Generating done -- Build files have been written to: /home/osboxes/zephyrproject/zephyr/build -- west build: building application [1/171] Preparing syscall dependency handling [2/171] Generating include/generated/version.h -- Zephyr version: 3.2.99 (/home/osboxes/zephyrproject/zephyr), build: zephyr-v3.2.0-1267-g278120acb600 [161/171] Linking C executable zephyr/zephyr_pre0.elf [165/171] Linking C executable zephyr/zephyr_pre1.elf [171/171] Linking C executable zephyr/zephyr.elf Memory region Used Size Region Size %age Used FLASH: 74484 B 192 KB 37.88% RAM: 13944 B 20 KB 68.09% IDT_LIST: 0 GB 2 KB 0.00% (.venv) osboxes@osboxes:~/zephyrproject/zephyr$  
Configuração do aplicativo do LOM204A
Antes de criar o aplicativo e ingressar em uma rede LoRaWAN, você precisa de uma conta em um provedor de back-end LoRaWAN. Em seguida, crie um aplicativo LoRaWAN e registre seu dispositivo. Como este aplicativo foi fortemente testado com o backend fornecido pelo CHIRPSTACK. Assim que seu aplicativo e dispositivo forem criados e registrados, você terá várias informações (fornecidas pelo provedor LoRaWAN).
Assim que seu aplicativo e dispositivo forem criados e registrados, você terá várias informações fornecidas pelo provedor LoRaWAN:
  • O tipo de procedimento de JOIN: ABP (Ativação por personalização) ou OTAA (Ativação Over The Air) 
  • O dispositivo EUI: uma matriz de 8 bytes 
  • A aplicação EUI: uma matriz de 8 bytes 
  • A chave do aplicativo: uma matriz de 16 bytes 
  • O endereço do dispositivo: uma matriz de 4 bytes, necessária apenas com o procedimento de junção ABP 
  • A chave de sessão do aplicativo: uma matriz de 16 bytes, necessária apenas com o procedimento de junção ABP 
  • A chave de sessão de rede: uma matriz de 16 bytes, necessária apenas com o procedimento de junção ABP 
  • Depois de obter essas informações, edite o Makefile adequadamente ou use os comandos set/get no shell do aplicativo de teste.
Editando arquivos para gerar o APP
 
Em 
/home/osboxes/zephyrproject/zephyr/samples/subsys/lorawan/class_a/src
Altere main.c para as credenciais OTAA
* Customize based on network configuration */
#define LORAWAN_DEV_EUI                 { 0xDD, 0xEE, 0xAA, 0xDD, 0xBB, 0xEE,\
                                          0xEE, 0xFF }
#define LORAWAN_JOIN_EUI                { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
                                          0x00, 0x00 }
#define LORAWAN_APP_KEY                 { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE,\
                                          0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88,\
                                          0x09, 0xCF, 0x4F, 0x3C }
Menuconfig (opcional)
/home/osboxes/zephyrproject/zephyr
west build -t menuconfig 
(Top)
                                                                      Zephyr Kernel Configuration
    Devicetree Info  ----
    Modules  --->
    Board Selection (STMicroelectronics B-L072Z-LRWAN1 Discovery kit)  --->
    Board Options  ----
    SoC/CPU/Configuration Selection (STM32L0x Series MCU)  --->
    Hardware Configuration  --->
    ARM Options  --->
    General Architecture Options  --->
-*- MPU features  --->
-*- Assign appropriate permissions to kernel areas in SRAM
[ ] Support code/data section relocation
    Floating Point Options  ----
    Cache Options  ----
    General Kernel Options  --->
    Device Options  ----
    Virtual Memory Support  ----
    Device Drivers  --->
    C Library  --->
    Additional libraries  --->
    Sub Systems and OS Services  --->
    Build and Link Features  --->
    Boot Options  --->
    Compatibility  --->
[ ] Allow for the legacy include paths (without the zephyr/ prefix) (DEPRECATED)
[Space/Enter] Toggle/enter  [ESC] Leave menu           [S] Save
[O] Load                    [?] Symbol info            [/] Jump to symbol
[F] Toggle show-help mode   [C] Toggle show-name mode  [A] Toggle show-all mode
[Q] Quit (prompts for save) [D] Save minimal config (advanced)
Em RegionAU915.c
/home/osboxes/zephyrproject/modules/lib/loramac-node/src/mac/region
void RegionAU915InitDefaults( InitDefaultsParams_t* params ) { Band_t bands[AU915_MAX_NB_BANDS] = { AU915_BAND0 }; switch( params->Type ) { case INIT_TYPE_DEFAULTS: { if( ( params->NvmGroup1 == NULL ) || ( params->NvmGroup2 == NULL ) ) { return; } RegionNvmGroup1 = (RegionNvmDataGroup1_t*) params->NvmGroup1; RegionNvmGroup2 = (RegionNvmDataGroup2_t*) params->NvmGroup2; RegionBands = (Band_t*) params->Bands; // Initialize 8 bit channel groups index RegionNvmGroup1->JoinChannelGroupsCurrentIndex = 0; // Initialize the join trials counter RegionNvmGroup1->JoinTrialsCounter = 0; // Default bands memcpy1( ( uint8_t* )RegionBands, ( uint8_t* )bands, sizeof( Band_t ) * AU915_MAX_NB_BANDS ); // Channels for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ ) { // 125 kHz channels RegionNvmGroup2->Channels[i].Frequency = 915200000 + i * 200000; RegionNvmGroup2->Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0; RegionNvmGroup2->Channels[i].Band = 0; } for( uint8_t i = AU915_MAX_NB_CHANNELS - 8; i < AU915_MAX_NB_CHANNELS; i++ ) { // 500 kHz channels RegionNvmGroup2->Channels[i].Frequency = 915900000 + ( i - ( AU915_MAX_NB_CHANNELS - 8 ) ) * 1600000; RegionNvmGroup2->Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6; RegionNvmGroup2->Channels[i].Band = 0; } // Initialize channels default mask (FSB2) RegionNvmGroup2->ChannelsDefaultMask[0] = 0xFF00; RegionNvmGroup2->ChannelsDefaultMask[1] = 0x0000; RegionNvmGroup2->ChannelsDefaultMask[2] = 0x0000; RegionNvmGroup2->ChannelsDefaultMask[3] = 0x0000; RegionNvmGroup2->ChannelsDefaultMask[4] = 0x0000; RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000; // Copy channels default mask RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE ); // Copy into channels mask remaining RegionCommonChanMaskCopy( RegionNvmGroup1->ChannelsMaskRemaining, RegionNvmGroup2->ChannelsMask, CHANNELS_MASK_SIZE ); break; } case INIT_TYPE_RESET_TO_DEFAULT_CHANNELS: { // Intentional fallthrough } case INIT_TYPE_ACTIVATE_DEFAULT_CHANNELS: { // Copy channels default mask RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE ); for( uint8_t i = 0; i < CHANNELS_MASK_SIZE; i++ ) { // Copy-And the channels mask RegionNvmGroup1->ChannelsMaskRemaining[i] &= RegionNvmGroup2->ChannelsMask[i]; } break; } default: { break; } } 
}

Em 
/home/osboxes/zephyrproject/zephyr/samples/subsys/lorawan/class_a
Altere prj.conf
CONFIG_LOG=y
CONFIG_SPI=y
CONFIG_PRINTK=y
CONFIG_SERIAL=y

CONFIG_LORA=y
CONFIG_LORA_SX12XX=y
CONFIG_LORA_LOG_LEVEL_DBG=y
CONFIG_LORA_SX127X=y

CONFIG_HAS_SEMTECH_RADIO_DRIVERS=y
CONFIG_HAS_SEMTECH_LORAMAC=y

CONFIG_LORAWAN=y
CONFIG_LORAMAC_REGION_AU915=y
CONFIG_LORAWAN_LOG_LEVEL_DBG=y
CONFIG_LORAWAN_NVM_NONE=y
#CONFIG_LORAWAN_NVM_SETTINGS=y
CONFIG_LORAWAN_SYSTEM_MAX_RX_ERROR=90

CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048


CONFIG_TEST_RANDOM_GENERATOR=y
Configurando GPIOS para ser compatível com LOM204A
 
Em 
/home/osboxes/zephyrproject/zephyr/boards/arm/b_l072z_lrwan1
edit 
b_l072z_lrwan1.dts
&spi1 {
        pinctrl-0 = <&spi1_nss_pa4 &spi1_sck_pa5
                     &spi1_miso_pa6 &spi1_mosi_pa7>;
        pinctrl-names = "default";
        status = "okay";
        cs-gpios = <&gpioa 4 GPIO_ACTIVE_LOW>;

        lora: lora@0 {
                compatible = "semtech,sx1276";
                reg = <0>;
                reset-gpios = <&gpioa 8 GPIO_ACTIVE_LOW>;
                dio-gpios = <&gpioa 12 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>,
                            <&gpiob 2 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>,
                            <&gpiob 5 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>,
                            <&gpiob 0 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>,
                            <&gpioa 11 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
                            /*<&gpioa 4 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;*/
                rfi-enable-gpios = <&gpioa 15 GPIO_ACTIVE_HIGH>;
                rfo-enable-gpios = <&gpioc 2 GPIO_ACTIVE_HIGH>;
                pa-boost-enable-gpios = <&gpioc 1 GPIO_ACTIVE_HIGH>;
                tcxo-power-gpios = <&gpiob 1 GPIO_ACTIVE_HIGH>;
                tcxo-power-startup-delay-ms = <5>;
                spi-max-frequency = <1000000>;
        };
};
UART
&usart1 {
        pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>;
        pinctrl-names = "default";
        current-speed = <115200>;
        status = "okay";
};

&usart2 {
        pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3>;
        pinctrl-names = "default";
        current-speed = <115200>;
        status = "okay";
};

SUBBAND
AU915 FSB2
1.0.2
Na pasta
/home/osboxes/zephyrproject/zephyr/build/zephyr
você encontrará o zephyr.hex 
Utilize STM32 PROGRAMMER para gravar


Enviando um TEXTO

Abra o Emulador de Terminal

PA2 e PA3 do LOM204A

*** Booting Zephyr OS build zephyr-v3.2.0-1267-g278120acb600 ***
Starting up Lora node...

Starting Lorawan stack...
Joining TTN network over OTTA


[00:00:00.200,000] <inf> sx127x: SX127x version 0x12 found
[00:00:00.302,000] <dbg> lorawan: lorawan_init: LoRaMAC Initialized
[00:00:00.322,000] <dbg> lorawan: lorawan_join: Network join request sent!
Sending data...

[00:00:05.813,000] <dbg> lorawan: mlme_confirm_handler: Received MlmeConfirm (for MlmeRequest 1)
[00:00:05.813,000] <inf> lorawan: Joined network! DevAddr: 01c8ef34
[00:00:05.824,000] <inf> lorawan_node: New Datarate: DR_2, Max Payload 11
[00:00:05.824,000] <inf> lorawan: Datarate changed: DR_2

Downlink data received:

Data size: 0
Data Port: 0
RSSI:      -42
SNR:       8
Data pend: 0

Data sent!



CÓDIGO FONTE
#define   OTAA
//#define ABP

#include <zephyr/lorawan/lorawan.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/random/rand32.h>

#define DEFAULT_RADIO_NODE DT_ALIAS(lora0)
BUILD_ASSERT(DT_NODE_HAS_STATUS(DEFAULT_RADIO_NODE, okay), "No default LoRa radio specified in DT");
#define DEFAULT_RADIO DT_LABEL(DEFAULT_RADIO_NODE)

#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(lorawan_node);

/* Customize based on network configuration */
// OTAA
#ifdef OTAA
#define LORAWAN_DEV_EUI         { 0xXX, 0xXX, 0xXX, 0xFF, 0xXX, 0xEE, 0x8C, 0xXX }    // MSB Format!
#define LORAWAN_JOIN_EUI        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }    // MSB Format!
#define LORAWAN_APP_KEY         { 0xF1, 0xD1, 0x1D, 0x78, 0xDA, 0x2A, 0xEF, 0xB2, 0x7C, 0x70, 0x35, 0x08, 0x25, 0xB8, 0xB6, 0x3B }
#endif

// ABP
#ifdef ABP
#define LORAWAN_DEV_ADDR        { 0x00, 0x00, 0x00, 0x00 }
#define LORAWAN_NWK_SKEY        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define LORAWAN_APP_SKEY        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define LORAWAN_APP_EUI         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#endif

#define DELAY K_MSEC(10000)

char data[] = {'H', 'E', 'L', 'L', 'O'};

/* size of stack area used by each thread */
#define STACKSIZE 1024

/* scheduling priority used by each thread */
#define PRIORITY 7

// Call back functions:
// Downlink callback
static void dl_callback(uint8_t port, bool data_pending, int16_t rssi, int8_t snr,  uint8_t len, const uint8_t *data)
{   
    printk("\nDownlink data received: \n");
    for(int i=0; i < len; i++ )
        printk("%02X ", data[i]);
    
    printk("\n");
    printk("Data size: %d\n" , len );
    printk("Data Port: %d\n" , port );
    printk("RSSI:      %d\n" , (int16_t)rssi );
    printk("SNR:       %d\n" , (int16_t)snr );
    printk("Data pend: %d\n" , data_pending );

    printk("\n\n");

}

// ADR change callback
static void lorwan_datarate_changed(enum lorawan_datarate dr)
{   
    uint8_t unused, max_size;
    
    lorawan_get_payload_sizes(&unused, &max_size); 
    LOG_INF("New Datarate: DR_%d, Max Payload %d", dr, max_size);
}

/* Main program.
*/

void main(void)
{
	const struct device *lora_dev;
	struct lorawan_join_config join_cfg;
#ifdef OTAA
	uint8_t dev_eui[] = LORAWAN_DEV_EUI;
	uint8_t join_eui[] = LORAWAN_JOIN_EUI;
	uint8_t app_key[] = LORAWAN_APP_KEY;
#endif

#ifdef ABP
    uint8_t dev_addr[] = LORAWAN_DEV_ADDR;
    uint8_t nwk_skey[] = LORAWAN_NWK_SKEY;
    uint8_t app_skey[] = LORAWAN_APP_SKEY;
    uint8_t app_eui[]  = LORAWAN_APP_EUI;
#endif
	int ret;


    printk("Starting up Lora node...\n\n");

	lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0));
	if (!lora_dev) {
        printk("Lora default radio not found.\nExiting program.\n");
		return;
	}

    printk("Starting Lorawan stack...\n");
	ret = lorawan_start();
	if (ret < 0) {
		printk("lorawan_start failed: %d\n\n", ret);
		return;
	}

    // Enable ADR
    lorawan_enable_adr( true );
    
    // Enable callbacks
    struct lorawan_downlink_cb downlink_cb = {
        .port = LW_RECV_PORT_ANY,
        .cb = dl_callback
    };

    lorawan_register_downlink_callback( &downlink_cb );
    lorawan_register_dr_changed_callback( lorwan_datarate_changed );

    uint32_t random = sys_rand32_get();

    uint16_t dev_nonce = random & 0x0000FFFF;

#ifdef OTAA
	join_cfg.mode = LORAWAN_CLASS_A;
	join_cfg.dev_eui = dev_eui;
	join_cfg.otaa.join_eui = join_eui;
	join_cfg.otaa.app_key = app_key;
	join_cfg.otaa.nwk_key = app_key;
        join_cfg.otaa.dev_nonce = dev_nonce;
#endif

#ifdef ABP
    join_cfg.mode = LORAWAN_ACT_ABP;
    join_cfg.dev_eui = dev_addr;
    join_cfg.abp.dev_addr = dev_addr;
    join_cfg.abp.app_skey = app_skey;
    join_cfg.abp.nwk_skey = nwk_skey;
    join_cfg.abp.app_eui  = app_eui;
#endif


	printk("Joining TTN network over");
#ifdef OTAA
    printk(" OTTA\n\n\n");
#else
    printk(" ABP\n\n\n");
#endif

    // Loop until we connect
    do {
    	ret = lorawan_join(&join_cfg);
    	if (ret < 0) {
	    	printk("lorawan_join_network failed: %d\n\n", ret);
            printk("Sleeping for 10s to try again to join network.\n\n");
            k_sleep(K_MSEC(10000));
	    }
    } while ( ret < 0 );

	printk("Sending data...\n\n");

	while (1) {
		ret = lorawan_send(2, data, sizeof(data), LORAWAN_MSG_CONFIRMED);

		if (ret == -EAGAIN) {
			k_sleep(DELAY);
			continue;
		}

		if (ret < 0) {
			k_sleep(DELAY);
			continue;
		}

		printk("Data sent!\n\n");
		k_sleep(DELAY);
	}
}

DOWNLINK 


DÚVIDAS

Sobre a SMARTCORE

A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.
Nosso portifólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.

Mais detalhes em www.smartcore.com.br 

Nenhum comentário:

Postar um comentário