Friday, January 8, 2021

MQTT tutorial for Azure sphere MT3620

 INTRODUCTION



Azure Sphere MT3620 is very powerfull ARM based dev kit with wifi connectivity.As I explained all the basic installation steps and flashing first blink an led highlevelapp in my previous project I am directly jumping to MQTT implementation.
Or if you are still struggling with setup SDK and build first app then follow Microsoft documentation
If you are new to mqtt and dont have mqtt broker in your pc/server/rpi then please follow my project to setup mqtt broker
for starting this tutorial you should
  • installed azure sphere sdk in your pc
  • CMake and ninja tools for building and flashing
  • MQTT broker installed in pc or access to any mqtt broker to publish and subscribe data
  • already flashed succefully a code in AZURE sphere mt3620
As I said above make sure you already succesfully done blink an led code before going for mqtt kind of tasks

HOW I MADE MQTT PUBLISH using AZURE Sphere MT3620

I made this possible by simply editing codes done by a member developer community.I referred this project
STEP 1
dowload zip from this git
STEP 2
extract that to your project directory
STEP 3
you will find Sphere_HighLevelApp folder make sure you are able to compile and build that app
STEP 4:files editing
open CMakeSettings.json file and replace that with below data.in this I edited AZURE_SPHERE_TARGET_API_SET value due to some error popup. if 7 is working for you then no need to edit it 5. here I am using 5.
{ "environments": [ { "environment": "AzureSphere" } ], "configurations": [ { "name": "ARM-Debug", "generator": "Ninja", "configurationType": "Debug", "inheritEnvironments": [ "AzureSphere" ], "buildRoot": "${projectDir}\\out\\${name}", "installRoot": "${projectDir}\\install\\${name}", "cmakeToolchain": "${env.AzureSphereDefaultSDKDir}CMakeFiles\\AzureSphereToolchain.cmake", "buildCommandArgs": "-v", "ctestCommandArgs": "", "variables": [ { "name": "AZURE_SPHERE_TARGET_API_SET", "value": "latest-lts" } ] }, { "name": "ARM-Release", "generator": "Ninja", "configurationType": "Release", "inheritEnvironments": [ "AzureSphere" ], "buildRoot": "${projectDir}\\out\\${name}", "installRoot": "${projectDir}\\install\\${name}", "cmakeToolchain": "${env.AzureSphereDefaultSDKDir}CMakeFiles\\AzureSphereToolchain.cmake", "buildCommandArgs": "-v", "ctestCommandArgs": "", "variables": [ { "name": "AZURE_SPHERE_TARGET_API_SET", "value": "5" } ] } ] }
Then open CMakeLists.txt file and replace as below. here also I edited target api value
# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. cmake_minimum_required(VERSION 3.10) project(OBD2_MQTT C) azsphere_configure_tools(TOOLS_REVISION "20.04") azsphere_configure_api(TARGET_API_SET "5") add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c ./thirdparty/MQTT-C/src/mqtt.c ./thirdparty/MQTT-C/src/mqtt_pal.c "mqtt_utilities.c" # "parson.c" "common.c" ) # "uart_utilities.c") TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} PUBLIC ./thirdparty/MQTT-C/include ./) target_link_libraries(${PROJECT_NAME} applibs pthread gcc_s c) azsphere_target_hardware_definition(${PROJECT_NAME} TARGET_DIRECTORY "Hardware/mt3620_rdb" TARGET_DEFINITION "sample_hardware.json") azsphere_target_add_image_package(${PROJECT_NAME})
Then open app_manifest.json.here we have to set capabilities of app. here we are going to use one led and mqtt in this code.So in "AllowedConnections" variable set your MQTT broker IP.
{ "SchemaVersion": 1, "Name" : "UART_HighLevelApp", "ComponentId" : "4f2d9823-dbbd-4740-a7dd-198c32ba34fe", "EntryPoint": "/bin/app", "CmdArgs": [], "Capabilities": { "AllowedConnections": [ "192.168.43.59"], "Gpio": [ "$SAMPLE_LED" ], }, "ApplicationType": "Default" }
Now we can open main.c file to edit. here also we have to set ip address of broker and mqtt topic name.iam using topic name "AZURE".please don't bother about commented section in code(i have commented out lines which are not required for this basic app.Initial code was developed for reading UART data and send it to mqtt).j
ust set static char* mqttConf_topic = "AZURE";//topic name
static char* mqttConf_brokerIp = "192.168.43.59";//fill your mqtt broker ip here
/* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. */ // This sample C application for Azure Sphere demonstrates how to use a UART (serial port). // The sample opens a UART with a baud rate of 115200. Pressing a button causes characters // to be sent from the device over the UART; data received by the device from the UART is echoed to // the Visual Studio Output Window. // // It uses the API for the following Azure Sphere application libraries: // - UART (serial port) // - GPIO (digital input for button) // - log (messages shown in Visual Studio's Device Output window during debugging) // - eventloop (system invokes handlers for timer events) #include <errno.h> #include <stdbool.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <time.h> #include <unistd.h> // applibs_versions.h defines the API struct versions to use for applibs APIs. #include "applibs_versions.h" //#include <applibs/uart.h> #include <applibs/gpio.h> #include <applibs/log.h> //#include <applibs/eventloop.h> #include "mqtt_utilities.h" #include "common.h" // By default, this sample targets hardware that follows the MT3620 Reference // Development Board (RDB) specification, such as the MT3620 Dev Kit from // Seeed Studio. // // To target different hardware, you'll need to update CMakeLists.txt. See // https://github.com/Azure/azure-sphere-samples/tree/master/Hardware for more details. // // This #include imports the sample_hardware abstraction from that hardware definition. #include <hw/sample_hardware.h> //#include "eventloop_timer_utilities.h" //MQTT Variable #define MQTT_PUBLISH_PERIOD 500000000 //static EventLoopTimer* publishMQTTMsgTimer = NULL; static char* mqttConf_topic = "AZURE"; static char* mqttConf_brokerIp = "192.168.43.59"; //MQTT Variable //#define UART_SEND_PERIOD 5 //static EventLoopTimer* sendUartTimer = NULL; //const size_t receiveBufferSize = 20; // File descriptors - initialized to invalid value //static int gpioButtonFd = -1; //static int uartFd = -1; //EventLoop *eventLoop = NULL; //EventRegistration* uartEventReg = NULL; //EventLoopTimer *buttonPollTimer = NULL; // State variables //static GPIO_Value_Type buttonState = GPIO_Value_High; //const char* engineRPMCmd = "010C\r"; //const char* engineTempCmd = "0105\r"; //const char* engineFuelCmd = "012F\r"; //static int engineRPM; //static int engineTemp; //static int engineFuel; //static char rxData[33]; //static char rxIndex = 0; //static char Data[20]; //static void TerminationHandler(int signalNumber); //static void SendUartMessage(int uartFd, const char *dataToSend); //static void ButtonTimerEventHandler(EventLoopTimer *timer); //static ExitCode InitPeripheralsAndHandlers(void); //static void CloseFdAndPrintError(int fd, const char *fdName); //static void ClosePeripheralsAndHandlers(void); //mqtt test code int test_mqtt() { Log_Debug("Im in\n"); int res = MQTTInit(mqttConf_brokerIp, "1883", mqttConf_topic); Log_Debug(res); Log_Debug("done init\n"); //MQTTPublish(mqttConf_topic, "{\"engineTemp\":\"67.0\",\"engineRpm\":\"32.0\",\"fuel\":\"51.0\"}"); MQTTPublish(mqttConf_topic, "Wiring It my way"); // while (1) // { // } //Log_Debug("done publish\n"); } /// <summary> /// Main entry point for this application. /// </summary> int main(void) //int main(int argc, char *argv[]) {//test_mqtt(); /* Log_Debug("UART application starting.\n"); // test_mqtt(); exitCode = InitPeripheralsAndHandlers(); // Use event loop to wait for events and trigger handlers, until an error or SIGTERM happens while (exitCode == ExitCode_Success) { EventLoop_Run_Result result = EventLoop_Run(eventLoop, -1, true); // Continue if interrupted by signal, e.g. due to breakpoint being set. if (result == EventLoop_Run_Failed && errno != EINTR) { exitCode = ExitCode_Main_EventLoopFail; } } ClosePeripheralsAndHandlers(); Log_Debug("Application exiting.\n"); // return exitCode;*/ int fd = GPIO_OpenAsOutput(SAMPLE_LED, GPIO_OutputMode_PushPull, GPIO_Value_High); if (fd < 0) { Log_Debug( "Error opening GPIO: %s (%d). Check that app_manifest.json includes the GPIO used.\n", strerror(errno), errno); // return ExitCode_Main_Led; } const struct timespec sleepTime = {.tv_sec = 1, .tv_nsec = 0}; while (true) { test_mqtt(); GPIO_SetValue(fd, GPIO_Value_Low); nanosleep(&sleepTime, NULL); GPIO_SetValue(fd, GPIO_Value_High); nanosleep(&sleepTime, NULL); } }
STEP 5 make and build
Now we can make app by running
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="/opt/azurespheresdk/CMakeFiles/AzureSphereToolchain.cmake" -DAZURE_SPHERE_TARGET_API_SET="5" -DCMAKE_BUILD_TYPE="Debug" ./Sphere_HighLevelApp
run the above command in correct directory.It will respond in terminal below
-- The C compiler identification is GNU 8.2.0 -- Check for working C compiler: /opt/azurespheresdk/Sysroots/5/tools/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-musleabi/arm-poky-linux-musleabi-gcc -- Check for working C compiler: /opt/azurespheresdk/Sysroots/5/tools/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-musleabi/arm-poky-linux-musleabi-gcc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Configuring done -- Generating done -- Build files have been written to: /home/bagmo/AZURE
if make is ok we cab build using command
ninja
that will show responds similar to
[1/1] Generating OBD2_MQTT.imagepackage Azure Sphere Utility version 20.11.0.58388 Copyright (C) Microsoft Corporation. All rights reserved. Start time (UTC): Wednesday, 06 January 2021 14:42:42 verbose: Creating image package. verbose: Azure Sphere application image package written. verbose: Appending metadata. verbose: Wrote metadata: Section: Identity Image Type: Application Component ID: 4f2d9823-dbbd-4740-a7dd-198c32ba34fe Image ID: 348406ca-a96d-46b7-af5e-24c4d3c548ac Section: Signature Signing Type: ECDsa256 Cert: a8d5cc6958f48710140d7a26160fc1cfc31f5df0 Section: Debug Image Name: UART_HighLevelApp Built On (UTC): 06/01/21 2:42:43 pm Built On (Local): 06/01/21 8:12:43 pm Section: Temporary Image Remove image at boot: False Under development: True Section: ABI Depends Depends on: ApplicationRuntime, version 5 verbose: Packaging completed successfully. verbose: Output file is at: /home/bagmo/AZURE/OBD2_MQTT.imagepackage Command completed in 00:00:04.5303249.
now image file will be generated in that folder which need to flash to device for that device should be enable development
azsphere device enable-development
if it is already enabled and some image is running then run
azsphere device sideload delete
which will return delete any image running
now we can deploy our image to device
azsphere device sideload deploy --image-package OBD2_MQTT.imagepackage
the above command will deploy image to device and device will start blinking and publishing data to mqtt
Deploying '/home/bagmo/AZURE/OBD2_MQTT.imagepackage' to the attached device. Image package '/home/bagmo/AZURE/OBD2_MQTT.imagepackage' has been deployed to the attached device.
Now we can subscribe to mqtt topic to see data
mosquitto_sub -h 192.168.43.59 -t AZURE
replace ip with your broker ip
it will continuously print data received(here I am sending text "wiring it my way" from device
Wiring It my way Wiring It my way Wiring It my way Wiring It my way Wiring It my way
so we successfully published data using azure sphere mt3260 to mqtt.
Guys please try it out and comment your opinions and doubts.i will try to figure out and answer. Lets Hack it

Hello world with Azure Sphere MT3620 starter kit

 

[There are couple of changes and updates for this Azure spheres sdk CLI etc . SO PLEASE CHECK MICROSOFT DOCUMENTATION INCASE OF ANY DIFFICULTY QUCKSTART LINK ]


installation of SDK

Before starting installation you need to update your linux packages. I Am using Ubuntu 19.10.
use commands in your terminal
sudo apt-get update sudo apt-get install -y net-tools curl
then follow the steps

Download the install script from here

https://aka.ms/AzureSphereSDKInstall/Linux
  • enable execution of installation script using
chmod +x install_azure_sphere_sdk.sh
  • in that directory now run the installation script using
sudo ./install_azure_sphere_sdk.sh
  • after this you will get some primary key fingerprint.make sure that the key is same as key shown here
  • then reboot your pc

installation of CMake and Ninja

In this tutorial iam using CLI to build apps for azure sphere, you can use visual studio code also. For building apps we need to install CMake and Ninja
use the command for the installation
sudo apt install cmake ninja-build


claiming device

  • Connect your device to pc using usb
  • open CLI
  • add new user using command
azsphere login --newuser <email-address>
  • then login
azsphere login
  • Now we have to create a new tenant
azsphere tenant create --name <my-tenant>
tenant name can not rename after, so make sure you need that name
  • now we can enable app development on the device
azsphere device enable-development
  • then claim your device
azsphere device claim
  • if you want to connect your device to a wifi network then add ssid and password using
azsphere device wifi add --ssid <yourSSID> --psk <yourNetworkKey>
then to check the connection status, use command
azsphere device wifi show-status
it will show as
SSID : xxxx Configuration state : enabled Connection state : connected Security state : psk Frequency : 2442 Mode : station Key management : WPA2-PSK WPA State : COMPLETED IP Address : 192.168.1.xxx MAC Address : 00:02:c5:03:72:cc


build hello world app

azsphere device enable-development
To create the build and.imagepackage files for the HelloWorld_HighLevelApp sample application:
  • create a new directory and enter into it using
mkdir build cd build
now we have created a new directory named build
  • now in /azure-sphere-samples-master/Samples/HelloWorld/HelloWorld_HighLevelApp open main.c file include
/* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. */ // This minimal Azure Sphere app repeatedly toggles GPIO 8, which is the red channel of RGB // LED 1 on the MT3620 RDB. Use this app to test that device and SDK installation succeeded // that you can build, deploy, and debug a CMake app with Visual Studio. // // It uses the API for the following Azure Sphere application libraries: // - gpio (digital input for button) // - log (messages shown in Visual Studio's Device Output window during debugging) #include <stdbool.h> #include <errno.h> #include <string.h> #include <time.h> #include <applibs/log.h> #include <applibs/gpio.h> // By default, this sample's CMake build targets hardware that follows the MT3620 // Reference Development Board (RDB) specification, such as the MT3620 Dev Kit from // Seeed Studios. // // To target different hardware, you'll need to update the CMake build. The necessary // steps to do this vary depending on if you are building in Visual Studio, in Visual // Studio Code or via the command line. // // See https://github.com/Azure/azure-sphere-samples/tree/master/Hardware for more details. // // This #include imports the sample_hardware abstraction from that hardware definition. //#include <hw/sample_hardware.h>//anas #include <hw/mt3620_rdb.h>//anas /// <summary> /// Exit codes for this application. These are used for the /// application exit code. They they must all be between zero and 255, /// where zero is reserved for successful termination. /// </summary> typedef enum { ExitCode_Success = 0, ExitCode_Main_Led = 1 } ExitCode; int main(void) { Log_Debug("Starting CMake Hello World application...\n"); int fd = GPIO_OpenAsOutput(MT3620_RDB_HEADER1_PIN6_GPIO, GPIO_OutputMode_PushPull, GPIO_Value_High); int fd1= GPIO_OpenAsOutput(MT3620_RDB_HEADER1_PIN4_GPIO, GPIO_OutputMode_PushPull, GPIO_Value_High); if (fd < 0) { Log_Debug( "Error opening GPIO: %s (%d). Check that app_manifest.json includes the GPIO used.\n", strerror(errno), errno); return ExitCode_Main_Led; } const struct timespec sleepTime = {.tv_sec = 0, .tv_nsec = 500000000}; while (true) { GPIO_SetValue(fd, GPIO_Value_Low); nanosleep(&sleepTime, NULL); GPIO_SetValue(fd1, GPIO_Value_High); nanosleep(&sleepTime, NULL); GPIO_SetValue(fd, GPIO_Value_High); nanosleep(&sleepTime, NULL); GPIO_SetValue(fd1, GPIO_Value_Low); nanosleep(&sleepTime, NULL); } }
just copy above code and save and replace main.c(i have included #include <hw/mt3620_rdb.h> and changed pinsetup I am using external LEDs in PWM pins in socket 1 and 2 you can use build in led also)
  • now open app_manifest.json file in azure-sphere-samples-master/Samples/HelloWorld/HelloWorld_HighLevelApp
  • replace the data in app_manifest.json as below and save it.
{ "SchemaVersion": 1, "Name": "HelloWorld_HighLevelApp", "ComponentId": "1689d8b2-c835-2e27-27ad-e894d6d15fa9", "EntryPoint": "/bin/app", "CmdArgs": [], "Capabilities": { "Gpio": [ "$MT3620_RDB_HEADER1_PIN6_GPIO","$MT3620_RDB_HEADER1_PIN4_GPIO"] }, "ApplicationType": "Default" }
you need to use correct pin numbers which can be found in mt3620_rdb.json
I refer this for pinouts
  • now run cmake in command line
cmake \ -G "Ninja" \ -DCMAKE_TOOLCHAIN_FILE="/opt/azurespheresdk/CMakeFiles/AzureSphereToolchain.cmake" \ -DAZURE_SPHERE_TARGET_API_SET="4" \ -DAZURE_SPHERE_TARGET_HARDWARE_DEFINITION_DIRECTORY="/home/bagmo/Desktop/azure-sphere-samples-master/Hardware/mt3620_rdb" \ -DAZURE_SPHERE_TARGET_HARDWARE_DEFINITION="mt3620_rdb.json" \ --no-warn-unused-cli \ -DCMAKE_BUILD_TYPE="Debug" \ -DCMAKE_MAKE_PROGRAM="ninja" \ "/home/bagmo/Desktop/azure-sphere-samples-master/Samples/HelloWorld"
make sure that path are correct for DAZURE_SPHERE_TARGET_HARDWARE_DEFINITION_DIRECTORY=
and the last parameter should be path for HelloWorld_HighLevelApp sample.
  • run below command to build the application and create the imagepackage file.
ninja
it will return like
[5/5] Generating HelloWorld_HighLevelApp.imagepackage Azure Sphere Utility version 20.1.6.56107 Copyright (C) Microsoft Corporation. All rights reserved. Start time (UTC): Monday, 30 March 2020 06:46:43 verbose: Creating image package. verbose: Azure Sphere application image package written. verbose: Appending metadata. verbose: Wrote metadata: Section: Identity Image Type: Application Component ID: 1689d8b2-c835-2e27-27ad-e894d6d15fa9 Image ID: dfccede2-fde7-489d-8056-5013e314556e Section: Signature Signing Type: ECDsa256 Cert: a8d5cc6958f48710140d7a26160fc1cfc31f5df0 Section: Debug Image Name: HelloWorld_HighLevelApp Built On (UTC): 30/03/20 6:46:44 am Built On (Local): 30/03/20 12:16:44 pm Section: Temporary Image Remove image at boot: False Under development: True Section: ABI Depends Depends on: ApplicationRuntime, version 4 verbose: Packaging completed successfully. verbose: Output file is at: /home/bagmo/Desktop/build/HelloWorld_HighLevelApp.imagepackage Command completed in 00:00:01.5862753.
now we can flash builded app to azure sphere using
azsphere device sideload deploy --imagepackage HelloWorld_HighLevelApp.imagepackage
now the device will be flashing and rebooting.

Troubleshooting

  • if there is already an app is running in your device which is using same gpio then you will not able to flash the app.
error: Could not deploy application to device: Application manifest requests a GPIO that is already in use by another application.
in this case delete other apps running in device using
azsphere device sideload delete
  • if the below error is showing
ERROR: Could not establish SLIP connection.
disconnect your device usb and reconnect then enter the below command
sudo /opt/azurespheresdk/Tools/azsphere_connect.sh
  • to check running status of applications use command
azsphere device app show-status

New changes after updates in azure

After couple of months in jan 2021 i checked the azure sphere and platform again,some of updates were there.New SDK version and new CLI was introduces.so i thought to update this tutorial with those data.
If any of you have trouble to build a highlevelapp follow this tutorial in microsoft document.