Environmental Sensor
Answer
11/3/17 4:01 PM

Good afternoon Franjo,

I've discoverd a XDK tutorial on my laptop called "Sensor Guide XDK 110". To make sure that we're looking at the same document I've sended you the pdf Version via Mail.

In this tutorial it is described how to initalize and later read the sensor data of different single sensor or for the environmental sensors.

I'm running a bit into trouble when I try to determine the correct place for implementing the code snippets in my current project.

E.g. chapter 6: 'Envrionmental Sensor'

In which Project folders i exactly need to copy the given codesnippets ( Code 19-24 in the pdf) ?

Furthermore, when I add a code snippet e.g. to my ApplicationTemplate.c i receive a error like:

'Invalid declaration of 'returnOverSamplingValue'.

However, the variable returnOverSamplingValue is given in that way within the training (see code e.g. snippet 21 within the pdf) ?

 

Thank you very much in advance & have a nice weekend

Best regards

Nils

 

 

 

0 (0 Votes)
RE: Environmental Sensor
Answer
11/6/17 6:12 PM as a reply to Nils Hilser.

Hello Nils,

I have split your request in your old thread in a new one since the old initial issue is already solved. This will give other users with similar questions the benefit to find the thread more easily and to benefit from the proposed solutions as well.

I took a look a the guide as well and I will give you a short introduction about how to use the code.

The code should be used with a XdkApplicationTemplate for starters. All code needs to be pasted into XdkApplicationTemplate.c, here you can declare functions for initializing the sensor and reading it. As an example for initializing, declare:

void initializeSensor(void) {
  // paste code from guide here
}

Afterwards, you can use initializeSensor() in appInitSystem() after BCDS_UNUSED(param2)

Furthermore, Code 19 is used to display the sensor handle you which is neccessary to initialize the used sensor with the API of the environmental sensor. The code snippets 20 to 22 provde a simple implementation using the environmental sensor API Code 23 and 24 provide an overview on how the data can be read from the environmental sensor.

Additionally please note that Code 21 already makes an initialization of the environmental sensor with pre-settings. Code 22 also initializes the sensor (without changing the settings).

If you use Code 21, remove the call of Environmental_init(), and the following if-statement from Code 22.

Regarding your error, I have tried the tutorial to confirm that it works correctly, and it does. I assume that this error will be solved if you follow my instructions.

Please let me know if that was helpful and do not hesitate to ask if you have further questions.

Kind regards,
Franjo

0 (0 Votes)
RE: Environmental Sensor
Answer
11/20/17 12:36 PM as a reply to Franjo Stjepandic.

Hello Franjo,

i apated my Application template from the previous post (https://xdk.bosch-connectivity.com/community/-/message_boards/message/306413). But still I'm running in some uncertainities.

As you advised I opened a new function called 

void initializeSensor(void) {}

Later in my Application Template within the void appInitSystem(void * CmdProcessorHandle, uint32_t param2) function I 'recalled' the function below the command BCDS_UNUSED(param2).

The only code snippet from the guide I was able to use without receiving an error was code 22.

So I copied the code snippet of code 22 to my application Template. I assume that this script is capable to read my environmental sensor data. 

Within the function static void clientTask(void*pvParameters) I removed/uncommented the msg.payload = "Hello" and replaced it with msg.payloadlen= sizeof(str(returnValue)). In my thinking returnValue is the variable which carries the desired sensor data ?! So the str() function will give me the string of it and sizeof() the required length. Am I correct with this assumption?

However, I do not really understand the difference between code snippet 22 and 23 and 24. Is it correct that code 21 (I'm not able to add this snippet without an error to my application template)and 22 (this one I can copy without a problem to my application template) are basically doing exactly the same thing?

In regard to snippet 23 and 24.. what is the difference to code 21 and 22. I'm asking this because from my understanding all 4 codes have a common denominator --> they read sensor data. Could please explain me more detailed the difference and between the four snippets, as well in regard to their field of application?

In the following you can find my most recent application template. The rest of the files within the project were not changed. They remained the same as in the previous post (see link above).

/* system header files */
#include <stdio.h>
#include "BCDS_Basics.h"
#include "BCDS_WlanConnect.h"
#include "BCDS_NetworkConfig.h"
#include "MQTTClient.h"
#include "MQTTConnect.h"
/* additional interface header files */
#include "FreeRTOS.h"
#include "timers.h"

/* own header files */
#include "MQTT_3.1_new.h"
#include "BCDS_CmdProcessor.h"
#include "BCDS_Assert.h"

/* Interface for the Gyroscope */
//#include "BCDS_Environmental.h" SETTING FROM GUIDE
#include "EnvironmentalSensor.h"
/* Interface for all sensors on the XDK */
#include "XdkSensorHandle.h"

/* constant definitions ***************************************************** */
#define CLIENT_BUFF_SIZE 1000
/* local variables ********************************************************** */
#define CLIENT_TASK_STACK_SIZE 1024
#define CLIENT_TASK_PRIORITY 1
#define CLIENT_YIELD_TIMEOUT 10
#define SECONDS(x) ((portTickType) (x * 1000) / portTICK_RATE_MS)

Network n;
Client c;


returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);


static unsigned char buf[CLIENT_BUFF_SIZE];
static unsigned char readbuf[CLIENT_BUFF_SIZE];

// PUBLISH TASK IMPLEMENTATION

static uint32_t clientMessageId = 0;

void initializeSensor(void){
    /* Sensor Handler for the BME280 Sensor */

    extern Environmental_HandlePtr_T xdkEnvironmental_BME280_Handle;

    /* initialize environmental sensor */
    if (RETCODE_OK != returnValue) {
    // do something
    }
    /* read and print BME280 environmental sensor data */
    Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };
    returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);
    if ( RETCODE_OK == returnValue) {
    printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int)
    bme280.temperature, (long int) bme280.humidity);

    }
}


static void clientTask(void*pvParameters)
{MQTTMessage msg;
for(;;)
{
vTaskDelay(SECONDS(1));
msg.id = clientMessageId++;
msg.qos = 2;
msg.payload = str(returnValue);
msg.payloadlen= sizeof(str(returnValue));
//msg.payload = "Hello";
//msg.payloadlen = sizeof("Hello")-1;
MQTTPublish(&c, "xdk, &msg); //--> I changed the topic to only "xdk" only
MQTTYield(&c, CLIENT_YIELD_TIMEOUT);
}
}
//VOID APPINITSYSTEM (xTimerHandle xTimer) ! PUBLISH TASK CREATION

void appInitSystem(void * CmdProcessorHandle, uint32_t param2)
{
    if (CmdProcessorHandle == NULL)
    {
        printf("Command processor handle is null \n\r");
        assert(false);
    }
    BCDS_UNUSED(param2);
    initializeSensor();
    WlanConnect_SSID_T connectSSID = (WlanConnect_SSID_T) "xxxx";
    WlanConnect_PassPhrase_T connectPassPhrase = (WlanConnect_PassPhrase_T)
    "1234";
    WlanConnect_Init();
    NetworkConfig_SetIpDhcp(0);
    Retcode_T rc_wlan=WlanConnect_WPA(connectSSID, connectPassPhrase, NULL);
    printf("rc_wlan: %d\n\r", (int) Retcode_getCode(rc_wlan));
    NewNetwork(&n);
    int rc_connect=ConnectNetwork(&n,"10.4.1.151", 1883); //1883
    printf("rc_connect: %d\n\r", rc_connect);
    MQTTClient(&c, &n, 1000, buf, CLIENT_BUFF_SIZE, readbuf,
    CLIENT_BUFF_SIZE);

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = "xdk123";
    data.keepAliveInterval = 100;
    data.cleansession = 1;
    MQTTConnect(&c, &data);

       xTaskCreate(clientTask, (const char * const) "Mqtt Client App",
       CLIENT_TASK_STACK_SIZE, NULL, CLIENT_TASK_PRIORITY, null);
}


/**@} */
/** ************************************************************************* */
 

I would be very glad for any further help. My aim is to receive sensor data via mqtt on my broker. 

Currently i do not receive any string or as desired sensor data on my broker.

 

 I will send you the entire project as well via mail.

Kind regards

Nils

 

 

 

 

 

 

0 (0 Votes)
RE: Environmental Sensor
Answer
11/20/17 12:41 PM as a reply to Nils Hilser.

Hello Franjo,

small adaption:

//#include "BCDS_Environmental.h" SETTING FROM GUIDE
#include "EnvironmentalSensor.h"

should be the other way around:

include "BCDS_Environmental.h" SETTING FROM GUIDE
//#include "EnvironmentalSensor.h"

However, this seems not to be the issue.  Btw. what is the differenve between both statements ?

 

Thank you very much in advance

Looking forward to hear from you

 

Kind regards

 

Nils

 

0 (0 Votes)
RE: Environmental Sensor
Answer
11/20/17 3:45 PM as a reply to Nils Hilser.

Good evening Franjo,

 

while I was working on my piece of code I stumbeld upon the MQTT paho guide. For some reason I forgot the existence of this training... I think this one is exactly doing what i would like to do (sending sensor data via Mqtt). However I was following the instructions of a relatively new version of this Mqtt training. So far the newest I was able to find:
(XDK110: Getting Started Guide with MQTT (Paho Demo)
Document revision 1.5
Document release date July 17, 2017

However, it seems that the paho files are not adapted to the need of applying it under the latest workbench version (3.0) ? 

I adapted the paho Mqtt files with files from a folder eclispse paho folder I still had on my harddrive. Name of this file is org.eclipse.paho.mqtt.embedded-c-1.0.0. The adaption of the MQTT paho files with files of the eclipse paho folder is as well described within the guide. But I was not able to the paho eclispe file which was stored on my harddrive within the internet.

My questions would be the following:

- Is there a complete MQTT paho training for the latest version of the workbench available?
Cause there are many functions delievering an error while creating the project. I was only able to find the new name for a few functions (from workbench 2 to workbench 3) within the XDK forum..

- What makes more sense ? to continue with the reconstruction of my Hello string approach or to 
   spend the time into the MQTT paho training ?

 

Would be glad for any help

 

Thank you in advance

 

Best regards and have a nice evening

 

Nils

 

 

0 (0 Votes)
RE: Environmental Sensor
Answer
11/20/17 7:48 PM as a reply to Nils Hilser.

Hello Nils,

I will gladly answer your questions and give you the necessary hints to get your code working.

Regarding your errors, it is good to implement a function called initializeSensor() to paste the guide code into it. Unfortunately you missed to paste the line returnValue = Environmental_init(xdkEnvironmental_BME280_Handle); in it as well. Without that line, the environmental sensor will not be initialized properly and shows an unintended behaviour.

Furthermore, the line extern Environmental_HandlePtr_T xdkEnvironmental_BME280_Handle; can be deleted, since the handle is provided by the interface XdkSensorHandle.h.

Regarding your issue about the guide codes. Code 21 and 22 are not exactly the same. Code 21 shows how to initialize the environmental sensor with pre-settings.

Code 22 shows how to simply implement the environmental sensor and read data from it with less configuration. I would recommend to use this code for your application as a starting point.

The codes 23 and 24 display the differences when reading data from the environmental sensor. Code 23 shows how to get the sensor data in its physical representation. This means that the digitized sensor values are converted into their physical values.

On the opposite, code 24 shows how to get the sensor data in its digital representation.

For more information about these values, you can take a look at the related section in the sensor guide.

Regarding the include EnvironmentalSensor.h, you only need to include the interface XdkSensorHandle.h which provides all interfaces and sensor variables for every sensor the XDK integrates.

The interface Environmental.h is the interface which provides the functionality for the environmental sensor and where you can find all necessary functions. Furthermore, it is included in XdkSensorHandle.h and does not need to be included in your implementation file.

The interface EnvironmentalSensor.h in that case is an application header file from an example of the XDK-Workbench and offers no direct functionality to use the environmental sensor.

Regarding your use case, I would recommend splitting the code for the environmental sensor into two parts as follows.

Retcode_T initializeSensor(void){ returnValue = Environmental_init(xdkEnvironmental_BME280_Handle); return returnValue; } Environmental_Data_T ReadSensor(void){ Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) }; returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280); if ( RETCODE_OK == returnValue) { printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int) bme280.temperature, (long int) bme280.humidity); } return bme280; }

With this you will have a function for initializing the environmental sensor properly and one to read data from it. The function initializeSensor() can stay in appInitSystem() and readSensor() should be passed into the function clientTask(). Please note that currently, the function readSensor() returns a struct, which holds the data of the environmental sensor. To send it as a string via MQTT, I recommend to convert the data into a string, by using the function snprintf(). The function gives you the benefit, that you additionally receive the length of the string as return value. The approach you described should fit too, but nevertheless I recommend the use of snprintf().

Regarding the MQTT paho demo, there is no updated documentation for the XDK-Workbench 3.1.0, since the demo is no longer available for download due to incompatibilities with the latest version of the MQTT paho demo. For more information about that, please refer to this thread here. Regarding your question, what would make sense to continue? I would recommend to continue implementing your own application to send sensor data to your MQTT broker, since you gain a lot of experience regarding implementing applications for the XDK.

Besides that a short recommendation, since you asked some questions which are mostly in detail described in the Environmental section of the sensor guide, I would recommend read through the section to get familiar with the functionality of the environmental sensor.

Furthermore, I would also recommend to going through an C-Tutorial since C programming is absolutely necessary when developing with the XDK. If needed I can recommend a guide that covers most of the needed basics.

Please let me know if that was helpful and do not hesitate to ask if you have further questions.

Kind regards,
Franjo

0 (0 Votes)
RE: Environmental Sensor
Answer
11/24/17 12:44 PM as a reply to Franjo Stjepandic.

Good afternoon Franjo,

Thank you a lot for your detailed answer. It helped me a lot to achieve a better understanding. 

I would be glad if you could forward me a guide for C programming. Usually Iam used to program in C++ or python. However, pure C is really new for me and I need to get more familar with.


Apart from that I was implementing your suggestions.

I adapted my old initializeSensor() function as you suggested. it looks now like this:

void initializeSensor(void){
    //Sensor Handler for the BME280 Sensor

    returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);

    //initialize environmental sensor
    if (RETCODE_OK != returnValue) {
    // do something
    }
    // read and print BME280 environmental sensor data
    Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };
    returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);
    if ( RETCODE_OK == returnValue) {
    printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int)
    bme280.temperature, (long int) bme280.humidity);

    }
}


However, regarding your advice I replaced this way of initialization with the following code:


Retcode_T initializeSensor(void){returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);

return returnValue;

}
Environmental_Data_T ReadSensor(void){ Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };

returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);

if (RETCODE_OK == returnValue) { printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int) bme280.temperature, (long int) bme280.humidity);
}
return bme280;
}


While doing this the workbench showed me an error regarding the variable returnValue.
Unused or not decleaard or something... as far as i remember was the message. That is reasonable because the variable returnValue was not declared.
So i did this at the top of the application template in the following way:

char returnValue; //empty varibale to write a string into


Now the entire application template looks like this:

/* system header files */
#include <stdio.h>
#include "BCDS_Basics.h"
#include "BCDS_WlanConnect.h"
#include "BCDS_NetworkConfig.h"
#include "MQTTClient.h"
#include "MQTTConnect.h"
/* additional interface header files */
#include "FreeRTOS.h"
#include "timers.h"

/* own header files */
#include "MQTT_3.1_new.h"
#include "BCDS_CmdProcessor.h"
#include "BCDS_Assert.h"

/* Interface for the Gyroscope */
//#include "BCDS_Environmental.h" SETTING FROM GUIDE
//#include "EnvironmentalSensor.h"
/* Interface for all sensors on the XDK */
#include "XdkSensorHandle.h" //NOTE XDKSensorHandle interface for all sensors

/* constant definitions ***************************************************** */
#define CLIENT_BUFF_SIZE 1000
/* local variables ********************************************************** */
#define CLIENT_TASK_STACK_SIZE 1024
#define CLIENT_TASK_PRIORITY 1
#define CLIENT_YIELD_TIMEOUT 10
#define SECONDS(x) ((portTickType) (x * 1000) / portTICK_RATE_MS)

Network n;
Client c;

char returnValue;

static unsigned char buf[CLIENT_BUFF_SIZE];
static unsigned char readbuf[CLIENT_BUFF_SIZE];

// PUBLISH TASK IMPLEMENTATION

static uint32_t clientMessageId = 0;


//Function for INITIALIZE sensor and READ data from it

Retcode_T initializeSensor(void){returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);

return returnValue;

}
Environmental_Data_T ReadSensor(void){ Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };

returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);

if (RETCODE_OK == returnValue) { printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int) bme280.temperature, (long int) bme280.humidity);
}
return bme280;
}

// Second alternative for INITIAlIZE and READ data from sensor
/*
void initializeSensor(void){
    //Sensor Handler for the BME280 Sensor

    returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);

    //initialize environmental sensor
    if (RETCODE_OK != returnValue) {
    // do something
    }
    // read and print BME280 environmental sensor data
    Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };
    returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);
    if ( RETCODE_OK == returnValue) {
    printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int)
    bme280.temperature, (long int) bme280.humidity);

    }
}

*/

static void clientTask(void*pvParameters)
{MQTTMessage msg;
for(;;)
{
vTaskDelay(SECONDS(1));
ReadSensor();// needs to be passed in the client Task function
msg.id = clientMessageId++;
msg.qos = 2;

//msg.payload = str("data");

//msg.payloadlen= sizeof(str("data"));

msg.payload = snprintf(ReadSensor); //advantage: snprintf: returns additionally the length of the string

MQTTPublish(&c,"xdk",&msg);
MQTTYield(&c, CLIENT_YIELD_TIMEOUT);
}
}
//VOID APPINITSYSTEM (xTimerHandle xTimer) ! PUBLISH TASK CREATION

void appInitSystem(void * CmdProcessorHandle, uint32_t param2)
{
    if (CmdProcessorHandle == NULL)
    {
        printf("Command processor handle is null \n\r");
        assert(false);
    }
    BCDS_UNUSED(param2);
    initializeSensor();
    WlanConnect_SSID_T connectSSID = (WlanConnect_SSID_T) "Internet";
    WlanConnect_PassPhrase_T connectPassPhrase = (WlanConnect_PassPhrase_T)
    "XXXX";
    WlanConnect_Init();
    NetworkConfig_SetIpDhcp(0);
    Retcode_T rc_wlan=WlanConnect_WPA(connectSSID, connectPassPhrase, NULL);
    printf("rc_wlan: %d\n\r", (int) Retcode_getCode(rc_wlan));
    NewNetwork(&n);
    int rc_connect=ConnectNetwork(&n,"10.4.1.8", 1883); //1883
    printf("rc_connect: %d\n\r", rc_connect);
    MQTTClient(&c, &n, 1000, buf, CLIENT_BUFF_SIZE, readbuf,
    CLIENT_BUFF_SIZE);

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = "xdk123";
    data.keepAliveInterval = 100;
    data.cleansession = 1;
    MQTTConnect(&c, &data);

       xTaskCreate(clientTask, (const char * const) "Mqtt Client App",
       CLIENT_TASK_STACK_SIZE, NULL, CLIENT_TASK_PRIORITY, null);
}

/**@} */
/** ************************************************************************* */

I do not receive any error messages when flashing the project to my XDK.

Unfortunately, is still do not receive any message at my broker (compare: picture 1).
The picture shows my approach to access the data on my broker via node.red.

The purple node shows the mqtt subscriber and the green node (msg.payload) has the debug function in order to see the incoming messages within the debug tab.

As you can see no data gets published.

I added in addition a picture of my folder structure of the project(see: picture 2).

Furhtermore, I became aware that for some header files like BCDS_Basics.h no header file in form of a standalone file in my project is existing.
What that some header files have a own file/skript in the project and others not?


You have any idea what could still be the issue why no data gets published?

Thank you very much in advance 

Kind regards

Nils

0 (0 Votes)
RE: Environmental Sensor
Answer
11/24/17 2:41 PM as a reply to Nils Hilser.

Hello Nils,

First of all, regarding a tutorial on C-Programming, there are three I can strongly recommend:

  • Learn C, this offers some entry tutorials and has an online-compiler, so you don't have to bother setting up an appropriate C environment on your computer.
  • Tutorialspoint C Tutorial, this is a comprehensive guide on all things C related.
  • Learn C in Y minutes, this is a quick reference for experienced programmers, offering a comprehensive overview of C syntax. This is not recommended if you do not feel comfortable with programming in general
In general, C++ is basically C, but extended with object orientation. C is also a bit less forgiving, but the semantics are mostly the same.

As for your current issue, I see a few improvements you could make.

For example, the variable returnValue should be of type Retcode_T . Retcodes can have up to 32 bit, while a char only has 8 bit length. Additionally, I would allocate this variable locally in every function that uses it, instead of globally.

Secondly, I wonder why the application would build successfully, since you have an error in the function clientTask() :

 

msg.payload = snprintf(ReadSensor);

ReadSensor() is a function, and should be called as such. Additionally, you actually use it earlier within clientTask, but do not take its return value.

Additionally, you do not use snprintf() correctly, please see the documentation of this function for an example and explanation here.

Please tell me if this was helpful, and do not hesitate to ask further questions.

Kind regards,
Franjo

0 (0 Votes)
RE: Environmental Sensor
Answer
11/27/17 2:41 PM as a reply to Franjo Stjepandic.

Good afternoon Franjo,

Thanks for your reply ! I will start digging in the literature you provided. 

I applied your suggestions and my application template looks now like the following.

Of course, you were right that the function initializeSensor will not return any data.. that was a mistake from my side.

To retrieve the sensor data I was following the link you posted.

 

The assignment of the sensor data to a variable takes place in the function

static void clientTask(void*pvParameters)

Within the following section of the function, I assigned a variable called Sensor_data to the snprintf function. To be honest Ive never heard about the datatyoe Retcode_T before. But in my opinion, since the variable returnValue is from that datatype the buffer should provide the same storage capacity ?

Furthermore the variable which gets assigned to the buffer and will be printed later should be defined in the same way ?

So my variable declaration at the top of the application template regarding these three variables looks like the following:

 

Retcode_T returnValue; //char stores only 8, Retcode_T stores 32 bit
Retcode_T buffer;
Retcode_T Sensor_data;

 

The assignment of the variable to the content of the buffer within the static void clientTask(void*pvParameters) function looks like the following:


Sensor_data = snprintf(buffer,100,"Sensordata:",returnValue);
msg.payload = Sensor_data;

if (Sensor_data>=0 && Sensor_data<100)      // check returned value

   snprintf (buffer+Sensor_data, 100-Sensor_data,"", returnValue);

 puts (buffer);

From my understanding the puts(buffer) would be only necessary for debug purposes to see the current content within the buffer. I assigned the sensor data within the buffer ,by using the snprintf function to the variable Sensor_data.

Afterwards the msg.payload so content that will be sended via MQTT gets assigned to the variable Sensor_data.

Is this way correct ?

 

Furthermore, when I flash the project I receive a really unexpected error message. It markes the variable #include "MQTTClient.h" as a not exsisting folder. But the folder structure and its content hasnt changed at all. You have maybe any idea where is this behaviour deriving from ?

 

I expected an error within my variable assignments I showed above but not that a file cannot be found. 

Before I foget there is another error occuring within the template MQTTClient.c. Its an issue with the naming of SUCCESS and FAILURE. I read already within the community that this error should not prevent the programm from working correctly..So the both variables remained in my script...

In the following you can see my new approach within the Application template. Is there anything else I do still not consider ?

 

Thanks a lot for your help !

 

Kind regards

 

Nils

 

APPLICATION TEMPLATE:

/* system header files */
#include <stdio.h>
#include "BCDS_Basics.h"
#include "BCDS_WlanConnect.h"
#include "BCDS_NetworkConfig.h"
#include "MQTTClient.h"
#include "MQTTConnect.h"
/* additional interface header files */
#include "FreeRTOS.h"
#include "timers.h"


/* own header files */
#include "Sensor_MQTT.h"
#include "BCDS_CmdProcessor.h"
#include "BCDS_Assert.h"

/* Interface for the Gyroscope */
//#include "BCDS_Environmental.h" SETTING FROM GUIDE
//#include "EnvironmentalSensor.h"
/* Interface for all sensors on the XDK */
#include "XdkSensorHandle.h" //NOTE XDKSensorHandle interface for all sensors

/* constant definitions ***************************************************** */
#define CLIENT_BUFF_SIZE 1000
/* local variables ********************************************************** */
#define CLIENT_TASK_STACK_SIZE 1024
#define CLIENT_TASK_PRIORITY 1
#define CLIENT_YIELD_TIMEOUT 10
#define SECONDS(x) ((portTickType) (x * 1000) / portTICK_RATE_MS)


Network n;
Client c;

Retcode_T returnValue; //char stores only 8, Retcode_T stores 32 bit

//char buffer [100];

Retcode_T buffer;

int Sensor_data;

static unsigned char buf[CLIENT_BUFF_SIZE];
static unsigned char readbuf[CLIENT_BUFF_SIZE];

// PUBLISH TASK IMPLEMENTATION

static uint32_t clientMessageId = 0;


//Function for INITIALIZE sensor and READ data from it

Retcode_T initializeSensor(void){returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);

return returnValue;

}
Environmental_Data_T ReadSensor(void){ Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };

returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);

if (RETCODE_OK == returnValue) { printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int) bme280.temperature, (long int) bme280.humidity);
}
return bme280;
}

// Second alternative for INITIAlIZE and READ data from sensor
/*
void initializeSensor(void){
    //Sensor Handler for the BME280 Sensor

    returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);

    //initialize environmental sensor
    if (RETCODE_OK != returnValue) {
    // do something
    }
    // read and print BME280 environmental sensor data
    Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };
    returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);
    if ( RETCODE_OK == returnValue) {
    printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int)
    bme280.temperature, (long int) bme280.humidity);

    }
}

*/

static void clientTask(void*pvParameters)
{MQTTMessage msg;
for(;;)
{
vTaskDelay(SECONDS(1));
ReadSensor();// needs to be passed in the client Task function
msg.id = clientMessageId++;
msg.qos = 2;

//msg.payload=str(returnValue);

//msg.payloadlen= sizeof(str(returnValue));

//msg.payload = snprintf(returnValue); //advantage: snprintf: returns additionally the length of the string
Sensor_data = snprintf(buffer,100,"Sensordata:",returnValue);
msg.payload = Sensor_data;

if (Sensor_data>=0 && Sensor_data<100)      // check returned value

   snprintf (buffer+Sensor_data, 100-Sensor_data,"", returnValue);

 puts (buffer);


MQTTPublish(&c,"xdk",&msg);
MQTTYield(&c, CLIENT_YIELD_TIMEOUT);
}
}
//VOID APPINITSYSTEM (xTimerHandle xTimer) ! PUBLISH TASK CREATION

void appInitSystem(void * CmdProcessorHandle, uint32_t param2)
{
    if (CmdProcessorHandle == NULL)
    {
        printf("Command processor handle is null \n\r");
        assert(false);

    }
    BCDS_UNUSED(param2);
    initializeSensor();
    WlanConnect_SSID_T connectSSID = (WlanConnect_SSID_T) "RF-401";
    WlanConnect_PassPhrase_T connectPassPhrase = (WlanConnect_PassPhrase_T)
    "Support4You!";
    WlanConnect_Init();
    NetworkConfig_SetIpDhcp(0);
    Retcode_T rc_wlan=WlanConnect_WPA(connectSSID, connectPassPhrase, NULL);
    printf("rc_wlan: %d\n\r", (int) Retcode_getCode(rc_wlan));
    NewNetwork(&n);
    int rc_connect=ConnectNetwork(&n,"10.4.1.8", 1883); //1883
    printf("rc_connect: %d\n\r", rc_connect);
    MQTTClient(&c, &n, 1000, buf, CLIENT_BUFF_SIZE, readbuf,
    CLIENT_BUFF_SIZE);

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = "xdk123";
    data.keepAliveInterval = 100;
    data.cleansession = 1;
    MQTTConnect(&c, &data);

       xTaskCreate(clientTask, (const char * const) "Mqtt Client App",
       CLIENT_TASK_STACK_SIZE, NULL, CLIENT_TASK_PRIORITY, null);
}


/**@} */
/** ************************************************************************* */
 

0 (0 Votes)
RE: Environmental Sensor
Answer
11/27/17 5:17 PM as a reply to Nils Hilser.

Hello Nils,

first, Retcode_T is the type you should use for return codes of functions. Return codes basically indicate how an operation finished. This helps in verifying whether the function was successful or not, and if it wasn't, it usually indicates the reason. Of course, not every function has a return-code, you should take a look at the declaration of the functions respectively.

All in all, I would initialize your global variables as follows:

Retcode_T returnValue; // You do not need Sensor_Data and buffer

To finally read the data properly, and put it as the message's payload appropriately, you can use the following code-snippet, that utilizes the function ReadSensor() from your implementation:

Environmental_Data_T bme280 = ReadSensor();
sprintf(msg.payload, "Humidity: %d, Pressure: %d, Temperature: %d",
            (int) bme280.humidity,
            (int) bme280.pressure,
            (int) bme280.temperature);
msg.payloadlen = strlen(msg.payload) - 1;
printf("Payload: %s", msg.payload) // for verification

Note that this assumes that msg.payload has enough size, which should be the case, as CLIENT_BUFF_SIZE is declared as 1000 in your code, which is more than enough for both the message information and the payload.

Additionally, the msg.payloadlen is set to strlen(msg.payload) - 1, and the 1 is subtracted to account for the null-character that is added to the string by the function sprintf().

With these changes, your code should be able to compile and produce appropriate output to verify whether the payload is correctly applied.

As for why #include "MQTTClient.h" is marked as a not existing folder, could you please tell me the exact error in the console log? Additionally, did you make any changes in the Makefile of the project?

Please tell me if this was helpful, and do not hesitate to ask further questions.

Kind regards,
Franjo

0 (0 Votes)
RE: Environmental Sensor
Answer
11/29/17 10:41 AM as a reply to Franjo Stjepandic.

Good afternoon Franjo,

Thanks for you answer.

The error with the MQTTClient.h file occurs within the Application template while including the header file
with the statement:

#include "MQTTClient.h"

Error msg.: fatalError. MQTTClient.h: no such file or dicrectory.


Within the makefile all relevant files are mentioned (see snippet of makefile below):


#List all the application source file under variable BCDS_XDK_APP_SOURCE_FILES in a similar pattern as below
export BCDS_XDK_APP_SOURCE_FILES = \
    $(BCDS_APP_SOURCE_DIR)/Main.c \
    $(BCDS_APP_SOURCE_DIR)/sens_Mqtt_1711.c \
    $(BCDS_APP_SOURCE_DIR)/paho/XDK/mqttXDK.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTConnectClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTConnectServer.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTDeserializePublish.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTFormat.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTPacket.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSerializePublish.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSubscribeClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSubscribeServer.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTUnsubscribeClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTUnsubscribeServer.c    


Error occurs later within the line:
        debug: 
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk debug


Attached as well a snippet of the folder structure.

Thank you in advance 


Best regards

Nils

 

 

0 (0 Votes)
RE: Environmental Sensor
Answer
11/29/17 11:47 AM as a reply to Nils Hilser.

Hello Franjo, 

 

for this error the folder structure seemed to be responsible (Which i do not understand since the folder structure was working in this way before...). When both files are in the same folder, the project is flashing without a problem..

 

Regards

 

Nils

 

0 (0 Votes)
RE: Environmental Sensor
Answer
11/29/17 2:38 PM as a reply to Nils Hilser.

Good afternoon Franjo,

Finally with the following Application template:

/* system header files */
#include <stdio.h>
#include "BCDS_Basics.h"
#include "BCDS_WlanConnect.h"
#include "BCDS_NetworkConfig.h"
#include "MQTTClient.h"
#include "MQTTConnect.h"

//#include "MQTTConnect.h"

/* additional interface header files */
#include "FreeRTOS.h"
#include "timers.h"

/* own header files */
#include "try_nls.h"
#include "BCDS_CmdProcessor.h"
#include "BCDS_Assert.h"

/* Interface for the Gyroscope */
//#include "BCDS_Environmental.h" SETTING FROM GUIDE
//#include "EnvironmentalSensor.h"
/* Interface for all sensors on the XDK */
#include "XdkSensorHandle.h" //NOTE XDKSensorHandle interface for all sensors

/* constant definitions ***************************************************** */
#define CLIENT_BUFF_SIZE 1000
/* local variables ********************************************************** */
#define CLIENT_TASK_STACK_SIZE 1024
#define CLIENT_TASK_PRIORITY 1
#define CLIENT_YIELD_TIMEOUT 10
#define SECONDS(x) ((portTickType) (x * 1000) / portTICK_RATE_MS)


Network n;
Client c;

Retcode_T returnValue; //char stores only 8, Retcode_T stores 32 bit

char buffer [100];

//Retcode_T buffer; No Retcode for buffer or Sensor_data

//int Sensor_data;

static unsigned char buf[CLIENT_BUFF_SIZE];
static unsigned char readbuf[CLIENT_BUFF_SIZE];

// PUBLISH TASK IMPLEMENTATION

static uint32_t clientMessageId = 0;


//Function for INITIALIZE sensor and READ data from it

Retcode_T initializeSensor(void){returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);

return returnValue;

}
Environmental_Data_T ReadSensor(void){ Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };

returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);

if (RETCODE_OK == returnValue) { printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int) bme280.temperature, (long int) bme280.humidity);
}
return bme280;
}


static void clientTask(void*pvParameters)
{MQTTMessage msg;
for(;;)
{
vTaskDelay(SECONDS(1));
ReadSensor();// needs to be passed in the client Task function
msg.id = clientMessageId++;
msg.qos = 2;

Environmental_Data_T bme280 = ReadSensor();

sprintf(msg.payload, "Humidity: %d, Pressure: %d, Temperature: %d",
            (int) bme280.humidity,
            (int) bme280.pressure,
            (int) bme280.temperature);
msg.payloadlen = strlen(msg.payload) - 1;
printf("Payload: %s", msg.payload); // for verification

//******* Read Sensor data **********
/*
Sensor_data = snprintf(buffer,100,"Sensordata:",returnValue);
msg.payload = Sensor_data;

if (Sensor_data>=0 && Sensor_data<100)      // check returned value

   snprintf (buffer+Sensor_data, 100-Sensor_data,"", returnValue);

 puts (buffer);

 //******* Read Sensor data **********
*/
MQTTPublish(&c,"xdk",&msg);

MQTTYield(&c, CLIENT_YIELD_TIMEOUT);

}
}
//VOID APPINITSYSTEM (xTimerHandle xTimer) ! PUBLISH TASK CREATION

void appInitSystem(void * CmdProcessorHandle, uint32_t param2)
{
    if (CmdProcessorHandle == NULL)
    {
        printf("Command processor handle is null \n\r");
        assert(false);

    }
    BCDS_UNUSED(param2);
    initializeSensor();
    WlanConnect_SSID_T connectSSID = (WlanConnect_SSID_T) "XXXX";
    WlanConnect_PassPhrase_T connectPassPhrase = (WlanConnect_PassPhrase_T)
    "1234";
    WlanConnect_Init();
    NetworkConfig_SetIpDhcp(0);
    Retcode_T rc_wlan=WlanConnect_WPA(connectSSID, connectPassPhrase, NULL);
    printf("rc_wlan: %d\n\r", (int) Retcode_getCode(rc_wlan));
    NewNetwork(&n);
    int rc_connect=ConnectNetwork(&n,"10.4.1.8", 1883); //1883
    printf("rc_connect: %d\n\r", rc_connect);
    MQTTClient(&c, &n, 1000, buf, CLIENT_BUFF_SIZE, readbuf,
    CLIENT_BUFF_SIZE);

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = "xdk123";
    data.keepAliveInterval = 100;
    data.cleansession = 1;
    MQTTConnect(&c, &data);

       xTaskCreate(clientTask, (const char * const) "Mqtt Client App",
       CLIENT_TASK_STACK_SIZE, NULL, CLIENT_TASK_PRIORITY, null);
}


And the folder strucutre, which you can see within the attached image I do not receive an error, while flashing the project in regard to the  MQTTClient.h file.


However, I doubt the folder strucutre is correct because the structure I used before was never an issue.

In addition, you can see the current makefile of the project below:

# This makefile triggers the targets in the application.mk

# The default value "../../.." assumes that this makefile is placed in the 
# folder xdk110/Apps/<App Folder> where the BCDS_BASE_DIR is the parent of 
# the xdk110 folder.
BCDS_BASE_DIR ?= ../../..

# Macro to define Start-up method. change this macro to "CUSTOM_STARTUP" to have custom start-up.
export BCDS_SYSTEM_STARTUP_METHOD = DEFAULT_STARTUP
export BCDS_APP_NAME = try_nls
export BCDS_APP_DIR = $(CURDIR)
export BCDS_APP_SOURCE_DIR = $(BCDS_APP_DIR)/source

#Please refer BCDS_CFLAGS_COMMON variable in application.mk file
#and if any addition flags required then add that flags only in the below macro 
#export BCDS_CFLAGS_COMMON = 

#List all the application header file under variable BCDS_XDK_INCLUDES 
export BCDS_XDK_INCLUDES = \
    
#List all the application source file under variable BCDS_XDK_APP_SOURCE_FILES in a similar pattern as below
export BCDS_XDK_APP_SOURCE_FILES = \
    $(BCDS_APP_SOURCE_DIR)/Main.c \
    $(BCDS_APP_SOURCE_DIR)/try_nls.c \
    $(BCDS_APP_SOURCE_DIR)/paho/XDK/mqttXDK.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTConnectClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTConnectServer.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTDeserializePublish.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTFormat.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTPacket.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSerializePublish.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSubscribeClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSubscribeServer.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTUnsubscribeClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTUnsubscribeServer.c    

.PHONY: clean    debug release flash_debug_bin flash_release_bin

clean: 
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk clean

debug: 
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk debug

release: 
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk release

flash_debug_bin: 
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk flash_debug_bin
    
flash_release_bin: 
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk flash_release_bin

cleanlint: 
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk cleanlint
    
lint: 
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk lint
    
cdt:
    $(MAKE) -C $(BCDS_BASE_DIR)/xdk110/Common -f application.mk cdt


Still there is not data arriving at the broker...

I understand most of the parts that are part of the application template. Why there is no data arriving I have no clue...


Thank you a lot in advance


Regards

0 (0 Votes)
RE: Environmental Sensor
Answer
11/29/17 5:12 PM as a reply to Nils Hilser.

Hello Nils,

Your makefile is not optimal in a sense that it doesn't tell the compiler where to look for header-files. As you said, if the file including the header-file and the header-file itself are in the same folder, it works.

This is because with an include with quotation marks, the compiler will first look for the file in the path that you have written down, relative to the directory the inclluding file is in. Examples:

// this is file source/application.c

#include "my_dir/my-header.h" // will look for my-header.h in source/my_dir
#include "my-header.h" // will look for my-header.h in source (and no sub-directories!)

If they are not found within the specified directories, the compiler will look in the system's header list. You can add directories to the list, by adding them in the Makefile.

The corresponding variable in the Makefile is BCDS_XDK_INCLUDES, which you can find on line 21. You can add the paho-directory by inserting the following below line 19:

-I$(BCDS_APP_SOURCE_DIR)/paho \

I hope this helps explain why it didn't work before.

I forgot to answer regarding the SUCCESS and FAILURE variables - you can safely ignore these errors, as they are produced by the linker, and not the compiler. The compiler will know where to find them during the build process.

Regarding your implementation, I have made a slight mistake. You do actually have to use a buffer to store the string first. The variable msg.payload cannot be used as the target of sprintf().

Changing this as follows should make it work:

snprintf(buffer, 100, "Humidity: %d, Pressure: %d, Temperature: %d",
            (int) bme280.humidity, (int) bme280.pressure,
            (int) bme280.temperature);
msg.payload = buffer;
msg.payloadlen = strlen(buffer) - 1;
printf("Payload: %s\n\r", (char *) msg.payload); // for verification

In your code, you already have buffer declared, so there shouldn't be any other changes neccessary. I have tested this with a mosquitto server, producing the following output while breathing onto the XDK:

Humidity: 30, Pressure: 97533, Temperature: 2805
Humidity: 30, Pressure: 97532, Temperature: 2804
Humidity: 30, Pressure: 97527, Temperature: 2803
Humidity: 32, Pressure: 97525, Temperature: 2803
Humidity: 33, Pressure: 97531, Temperature: 2804
Humidity: 34, Pressure: 97530, Temperature: 2804
Humidity: 34, Pressure: 97537, Temperature: 2804
Humidity: 52, Pressure: 97548, Temperature: 2807
Humidity: 67, Pressure: 97544, Temperature: 2811
Humidity: 73, Pressure: 97539, Temperature: 2812
Humidity: 76, Pressure: 97540, Temperature: 2817
Humidity: 76, Pressure: 97518, Temperature: 2818
Humidity: 54, Pressure: 97542, Temperature: 2814
Humidity: 69, Pressure: 97538, Temperature: 2820
Humidity: 75, Pressure: 97535, Temperature: 2822
Humidity: 76, Pressure: 97536, Temperature: 2823

Please tell me if this was helpful, and do not hesitate to ask further questions.

Kind regards,
Franjo

0 (0 Votes)
RE: Environmental Sensor
Answer
12/1/17 7:50 AM as a reply to Franjo Stjepandic.

Good morning Franjo,

thanks a lot !

I was leaving the application template and the MQTTClient.h file in the same folder (paho) and adapted the sensor reading function snprintf as you suggested.
As far As i understood the way of keeping the files in the same folder is ok (or you using the hint you gave by adpating the makefile).


Flashing works fine, and the green LED is lighting afterwards at the XDK.

Unfortunately,still no message at the broker.


Application template now looks like the following (I changed the quality of service from 2 to 0):


/* system header files */
#include <stdio.h>
#include "BCDS_Basics.h"
#include "BCDS_WlanConnect.h"
#include "BCDS_NetworkConfig.h"
#include "MQTTClient.h"
#include "MQTTConnect.h"

//#include "MQTTConnect.h"

/* additional interface header files */
#include "FreeRTOS.h"
#include "timers.h"

/* own header files */
#include "try_nls.h"
#include "BCDS_CmdProcessor.h"
#include "BCDS_Assert.h"

/* Interface for the Gyroscope */
//#include "BCDS_Environmental.h" SETTING FROM GUIDE
//#include "EnvironmentalSensor.h"
/* Interface for all sensors on the XDK */
#include "XdkSensorHandle.h" //NOTE XDKSensorHandle interface for all sensors

/* constant definitions ***************************************************** */
#define CLIENT_BUFF_SIZE 1000
/* local variables ********************************************************** */
#define CLIENT_TASK_STACK_SIZE 1024
#define CLIENT_TASK_PRIORITY 1
#define CLIENT_YIELD_TIMEOUT 10
#define SECONDS(x) ((portTickType) (x * 1000) / portTICK_RATE_MS)


Network n;
Client c;

Retcode_T returnValue; //char stores only 8, Retcode_T stores 32 bit

char buffer [100];

//Retcode_T buffer; No Retcode for buffer or Sensor_data

//int Sensor_data;

static unsigned char buf[CLIENT_BUFF_SIZE];
static unsigned char readbuf[CLIENT_BUFF_SIZE];

// PUBLISH TASK IMPLEMENTATION

static uint32_t clientMessageId = 0;


//Function for INITIALIZE sensor and READ data from it

Retcode_T initializeSensor(void){returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);

return returnValue;

}
Environmental_Data_T ReadSensor(void){ Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };

returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);

if (RETCODE_OK == returnValue) { printf("BME280 Environmental Conversion Data :\n\rp =%ld Pa\n\rt =%ld mDeg\n\rh =%ld %%rh\n\r", (long int) bme280.pressure, (long int) bme280.temperature, (long int) bme280.humidity);
}
return bme280;
}


static void clientTask(void*pvParameters)
{MQTTMessage msg;
for(;;)
{
vTaskDelay(SECONDS(1));

ReadSensor();// needs to be passed in the client Task function

msg.id = clientMessageId++;
msg.qos = 2;

Environmental_Data_T bme280 = ReadSensor();

snprintf(buffer, 100, "Humidity: %d, Pressure: %d, Temperature: %d",
            (int) bme280.humidity, (int) bme280.pressure,
            (int) bme280.temperature);
msg.payload = buffer;
msg.payloadlen = strlen(buffer) - 1;
printf("Payload: %s\n\r", (char *) msg.payload); // for verification


MQTTPublish(&c,"xdk",&msg);

MQTTYield(&c, CLIENT_YIELD_TIMEOUT);

}
}

void appInitSystem(void * CmdProcessorHandle, uint32_t param2)
{
    if (CmdProcessorHandle == NULL)
    {
        printf("Command processor handle is null \n\r");
        assert(false);

    }
    BCDS_UNUSED(param2);
    initializeSensor();
    WlanConnect_SSID_T connectSSID = (WlanConnect_SSID_T) "XXXX";
    WlanConnect_PassPhrase_T connectPassPhrase = (WlanConnect_PassPhrase_T)
    "1234";
    WlanConnect_Init();
    NetworkConfig_SetIpDhcp(0);
    Retcode_T rc_wlan=WlanConnect_WPA(connectSSID, connectPassPhrase, NULL);
    printf("rc_wlan: %d\n\r", (int) Retcode_getCode(rc_wlan));
    NewNetwork(&n);
    int rc_connect=ConnectNetwork(&n,"10.4.1.8", 1883);
    printf("rc_connect: %d\n\r", rc_connect);
    MQTTClient(&c, &n, 1000, buf, CLIENT_BUFF_SIZE, readbuf,
    CLIENT_BUFF_SIZE);

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = "xdk123";
    data.keepAliveInterval = 100;
    data.cleansession = 1;
    MQTTConnect(&c, &data);

       xTaskCreate(clientTask, (const char * const) "Mqtt Client App",
       CLIENT_TASK_STACK_SIZE, NULL, CLIENT_TASK_PRIORITY, null);
}

the debug function 'printf("Payload: %s\n\r", (char *) msg.payload);' is as well no printing any results..#
So I assume still something in the ClientTask function or within the ReadSensor(void) function is not to 100% correct.

Just another question for a better understanding:


Why is it necessary to call again the function ReadSensor() within ClientTask()
and to state Environmental_Data_T bme280 = ReadSensor() within ClientTask;

I thought it is directly possible to call the variable bme280 as it is the return of function abovw ReadSensor(void).


Could it be that there are any possible mistakes left..?

Thanks a lot in advance

Kind regards

Nils
 

0 (0 Votes)
RE: Environmental Sensor
Answer
12/1/17 3:48 PM as a reply to Nils Hilser.

Hello Nils,

indeed, the first call of ReadSensor() can be removed (i.e. the one that doesn't save the data in the variable bme280). Using this without retrieving the data is not neccessary, as you pointed out correctly.

But, this should not hinder the application to work properly. I have copied your code and only modified the WiFi SSID / PW and the MQTT broker address. Additionally, I removed the include for the header-file try_nls.h, since that file is not required at all.

If the code does not work, could you tell me what is printed to the console? Additionally, have you tried it out with any other network? For example, using a Smartphone as a hotspot.

The only other issue I can imagine would be that you did not adapt the code properly from Workbench version 2.0.1 to 3.0.0 and higher. Could you show me the implementations of the functions expired(), countdown_ms(), countdown() and left_ms() from the implementation file at source > paho > XDK > mqttXDK.c?

Kind regards,
Franjo

0 (0 Votes)
RE: Environmental Sensor
Answer
12/4/17 12:21 PM as a reply to Franjo Stjepandic.

Good afternoon Franjo,

I was setting all lines of code within the try_nls.h file as a command. So there is no active programmcode left within this sheet.

Additionally, I was looking again at the mqttXDK.c file, located within the paho>XDK folder.


Within this file I included the following header files:


#include <stdint.h>
#include "freeRTOS.h"
#include "task.h"


Furthermore, I replaced the original function of workbench version 2.0:

 PowerMgt_GetSystemTimeMs();


of the functions expired(), countdown_ms(), countdown() and left_ms() with the function:


xTaskGetTickCount()/portTICK_PERIOD_MS;


So the mqqtXDK.c file is now looking like the following:


/* system header files */
#include <stdint.h>
#include "freeRTOS.h"
#include "task.h"

/* interface header files */
//#include "BCDS_PowerMgt.h"

/* own header files */
#include "mqttXDK.h"

char expired(Timer* timer) {
    long left = timer->end_time - xTaskGetTickCount()/portTICK_PERIOD_MS;
    return (left < 0);
}


void countdown_ms(Timer* timer, unsigned int timeout) {
    timer->end_time = xTaskGetTickCount()/portTICK_PERIOD_MS + timeout;
}


void countdown(Timer* timer, unsigned int timeout) {
    timer->end_time = xTaskGetTickCount()/portTICK_PERIOD_MS + (timeout * 1000);
}


int left_ms(Timer* timer) {
    long left = timer->end_time - xTaskGetTickCount()/portTICK_PERIOD_MS;
    return (left < 0) ? 0 : left;
}


void InitTimer(Timer* timer) {
    timer->end_time = 0;
}


int xdk_read(Network* n, uint8_t* buffer, int len, int timeout_ms) {
    SlTimeval_t timeVal;
    SlFdSet_t fdset;
    int rc = 0;
    int recvLen = 0;

    SL_FD_ZERO(&fdset);
    SL_FD_SET(n->my_socket, &fdset);

    timeVal.tv_sec = 0;
    timeVal.tv_usec = timeout_ms * 1000;
    if (sl_Select(n->my_socket + 1, &fdset, NULL, NULL, &timeVal) == 1) {
        do {
            rc = sl_Recv(n->my_socket, buffer + recvLen, len - recvLen, 0);
            recvLen += rc;
        } while(recvLen < len);
    }
    return recvLen;
}

int xdk_write(Network* n, uint8_t* buffer, int len, int timeout_ms) {
    SlTimeval_t timeVal;
    SlFdSet_t fdset;
    int rc = 0;
    int readySock;

    SL_FD_ZERO(&fdset);
    SL_FD_SET(n->my_socket, &fdset);

    timeVal.tv_sec = 0;
    timeVal.tv_usec = timeout_ms * 1000;
    do {
        readySock = sl_Select(n->my_socket + 1, NULL, &fdset, NULL, &timeVal);
    } while(readySock != 1);
    rc = sl_Send(n->my_socket, buffer, len, 0);
    return rc;
}
void xdk_disconnect(Network* n) {
    sl_Close(n->my_socket);
}

void NewNetwork(Network* n) {
    n->my_socket = 0;
    n->mqttread = xdk_read;
    n->mqttwrite = xdk_write;
    n->disconnect = xdk_disconnect;
}

int TLSConnectNetwork(Network *n, char* addr, int port, SlSockSecureFiles_t* certificates, unsigned char sec_method, unsigned int cipher, char server_verify) {
    SlSockAddrIn_t sAddr;
    int addrSize;
    int retVal;
    unsigned long ipAddress;

    retVal = sl_NetAppDnsGetHostByName((_i8*) addr, strlen(addr), &ipAddress, AF_INET);
    if (retVal < 0) {
        return -1;
    }

    sAddr.sin_family = AF_INET;
    sAddr.sin_port = sl_Htons((unsigned short)port);
    sAddr.sin_addr.s_addr = sl_Htonl(ipAddress);

    addrSize = sizeof(SlSockAddrIn_t);

    n->my_socket = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET);
    if (n->my_socket < 0) {
        return -1;
    }

    SlSockSecureMethod method;
    method.secureMethod = sec_method;
    retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method));
    if (retVal < 0) {
        return retVal;
    }

    SlSockSecureMask mask;
    mask.secureMask = cipher;
    retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_MASK, &mask, sizeof(mask));
    if (retVal < 0) {
        return retVal;
    }

    if (certificates != NULL) {
        retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_FILES, certificates->secureFiles, sizeof(SlSockSecureFiles_t));
        if(retVal < 0)
        {
            return retVal;
        }
    }

    retVal = sl_Connect(n->my_socket, ( SlSockAddr_t *)&sAddr, addrSize);
    if( retVal < 0 ) {
        if (server_verify || retVal != -453) {
            sl_Close(n->my_socket);
            return retVal;
        }
    }

    return retVal;
}

int ConnectNetwork(Network* n, char* addr, int port)
{
    SlSockAddrIn_t sAddr;
    int addrSize;
    int retVal = -1;
    unsigned long ipAddress;

    sl_NetAppDnsGetHostByName((_i8*) addr, strlen((char*)addr), &ipAddress, AF_INET);

    sAddr.sin_family = AF_INET;
    sAddr.sin_port = sl_Htons((unsigned short)port);
    sAddr.sin_addr.s_addr = sl_Htonl(ipAddress);

    addrSize = sizeof(SlSockAddrIn_t);

    n->my_socket = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);
    if( n->my_socket < 0 ) {
        // error
        return -1;
    }

    retVal = sl_Connect(n->my_socket, ( SlSockAddr_t *)&sAddr, addrSize);
    if( retVal < 0 ) {
        // error
        sl_Close(n->my_socket);
        return retVal;
    }

    return retVal;
}

The only thing i could consider is the //#include "BCDS_PowerMgt.h" header file. Could tell me if this header file is necessarry for retrieving sensor data ?


From my understanding i need to include a header file like this within this template but instead of 

"BCDS_PowerMgt.h"

maybe including

#include "XdkSensorHandle.h" (as I know now this is acting as an interface for receiving all sensor data).

Thank you in advance 


Best regards

Nils

0 (0 Votes)
RE: Environmental Sensor
Answer
12/4/17 12:30 PM as a reply to Nils Hilser.

Hello Franjo, 

 

I tried the inclunding of the "XdkSensorHandle.h" within the mqttXDK.c file. But its not changing the situation. Still after the flashing the project the green LED is shining.

 

Let me make sure that the issue is not related to the way HOW i flash projects to the XDK. I think i read in a manual that the safest way to flash a project to the XDK is the following:

 

1. turn the on/off switch on the off position.

2.press the lower button (indicated with one dot) and switch at the same time the on/off switch in the on position.

3. while releasing the the button with one dot the LEDs change from red to red, orange and green

4. After flashing my project to the XDK only the green LED is remaining.

 

Is this correct? Iam a bit afraid that maybe the way i flash projects to the XDK is maybe the source of error.

 

Thanks in advance !

 

Kind regards

 

Nils

 

0 (0 Votes)
RE: Environmental Sensor
Answer
12/4/17 12:35 PM as a reply to Nils Hilser.

Oh i forgot to answer your question, regarding the messages appearing at the console of my workbench.

 

Well, there is nothing appearing at all. At least no sensor data. But this should be the case while the 

 the line printf("Payload: %s\n\r", (char *) msg.payload); should print any data to the console..

What i see at the console after flashing the project is the following:


 INFO | Connecting to XDK device 'XDK Device 2' in port 'COM4'...
 INFO | Connection to port 'COM4' established
 INFO | Flashing file 'C:/XDK-Workbench/workspace/try_nls/debug/try_nls.bin'...
 INFO | Application checksum '6003' successfully verified.
 INFO | Transmission successfully completed!
 INFO | Booting application...
 INFO | XDK DEVICE 2:  Jumping to application
 INFO | Disconnecting XDK device 'XDK Device 2' from port 'COM4'...
 INFO | Port 'COM4' has been disconnected
 INFO | Connecting to XDK device 'XDK Device 2' in port 'COM4'...
 INFO | Connection to port 'COM4' established
 

Best regards

 

Nils

0 (0 Votes)
RE: Environmental Sensor
Answer
12/4/17 5:51 PM as a reply to Nils Hilser.

Hello Nils,

the fact that the application does not print anything at all, and the fact that your try_nls.h is empty (at least that's what I understood from one of your previous posts), lead me to believe that the application is simply not starting at all.

Make sure that your source-file Main.c, which had been automatically generated when the project was created, has the following content:

// system header files
#include <stdio.h>
#include "BCDS_Basics.h"

/* additional interface header files */
#include "XdkSystemStartup.h"
#include "BCDS_Assert.h"
#include "BCDS_CmdProcessor.h"
#include "FreeRTOS.h"
#include "task.h"
#include "try_nls.h" // This is your header-file!

/* own header files */

/* global variables ********************************************************* */
static CmdProcessor_T MainCmdProcessor;

/* functions */

int main(void)
{
    /* Mapping Default Error Handling function */
    Retcode_T returnValue = Retcode_Initialize(DefaultErrorHandlingFunc);
    if (RETCODE_OK == returnValue)
    {
        returnValue = systemStartup();
    }
    if (RETCODE_OK == returnValue)
    {
        returnValue = CmdProcessor_initialize(&MainCmdProcessor, (char *) "MainCmdProcessor", TASK_PRIO_MAIN_CMD_PROCESSOR, TASK_STACK_SIZE_MAIN_CMD_PROCESSOR, TASK_Q_LEN_MAIN_CMD_PROCESSOR);
    }
    if (RETCODE_OK == returnValue)
    {
        /* Here we enqueue the application initialization into the command
         * processor, such that the initialization function will be invoked
         * once the RTOS scheduler is started below.
         */
        returnValue = CmdProcessor_enqueue(&MainCmdProcessor, appInitSystem, &MainCmdProcessor, UINT32_C(0));
    }
    if (RETCODE_OK != returnValue)
    {
        printf("System Startup failed");
        assert(false);
    }
    /* start scheduler */
    vTaskStartScheduler();
}

This implements the startup of the application. It also requires some information, that should be available in try_nls.h. For this, the header-file try_nls.h should have the following content:

#ifndef XDK110_XDKAPPLICATIONTEMPLATE_H_
#define XDK110_XDKAPPLICATIONTEMPLATE_H_

/* Priorities */
#define TASK_PRIO_MAIN_CMD_PROCESSOR                (UINT32_C(1))
#define TASK_STACK_SIZE_MAIN_CMD_PROCESSOR          (UINT16_C(700))
#define TASK_Q_LEN_MAIN_CMD_PROCESSOR                (UINT32_C(10))

/**
 * @brief This is a template function where the user can write his custom application.
 *
 * @param[in] CmdProcessorHandle Handle of the main commandprocessor
 *
 * @param[in] param2  Currently not used will be used in future
 */
void appInitSystem(void * CmdProcessorHandle, uint32_t param2);

#endif /* XDK110_XDKAPPLICATIONTEMPLATE_H_ */

/** ************************************************************************* */

If this does not solve this issue, please tell me which Workbench you use, and please send your current project to me directly. Your implementation code is correct now - There is just some issue with the application not starting at all.

Kind regards,
Franjo

0 (0 Votes)
RE: Environmental Sensor
Answer
12/5/17 9:49 PM as a reply to Franjo Stjepandic.

Good evening Franjo,

Thanks,

all changes you recommended were already correct within the project.

So i uncommented the try_nls.h header file --> then it looks again like the one you have sent.

Furhtermore the Main.c file is looking like you said in your previous post.

I tried now to use the hivemq broker (see snapshot attached) instead of a raspberry pi.

Furthermore, I tried it now within a different wifi network.


For that I changed the required data within the try_nls.c (application template).

I hope i did the changes regarding the snapshot within the application template correct.

Even so, there should be data at the console.But there isnt.

The workbench version I'm using is:

XDK Workbench

Version            : 3.1.0
Build date        : 2017-10-25T00:27:56Z
Git Commit    : before_generator_refactoring-181-g8789764

 


The only issue i could still imagine is within the makefile and the allocation of the h and c files.
Now all c files expected the one within the XDK folder are located within the paho folder.

Additionally there is a header file within the paho/XDK folder and is named: mqttXDK.h.

 

So I changed this section of the makefile like the following:


for the header files:

export BCDS_XDK_INCLUDES = \
-I$(BCDS_APP_SOURCE_DIR)/paho \
$(BCDS_APP_SOURCE_DIR)/paho/XDK/mqttXDK.h


for the c files:

#List all the application source file under variable BCDS_XDK_APP_SOURCE_FILES in a similar pattern as below

export BCDS_XDK_APP_SOURCE_FILES = \
    $(BCDS_APP_SOURCE_DIR)/Main.c \
    $(BCDS_APP_SOURCE_DIR)/paho/try_nls.c \
    $(BCDS_APP_SOURCE_DIR)/paho/XDK/mqttXDK.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTConnectClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTConnectServer.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTDeserializePublish.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTFormat.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTPacket.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSerializePublish.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSubscribeClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTSubscribeServer.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTUnsubscribeClient.c \
    $(BCDS_APP_SOURCE_DIR)/paho/MQTTUnsubscribeServer.c    


But still nothing appearing at the console --> so the makefile seemed to be correct.


Ive sent you the project via Mail (incuding my last adpation of the make file).


Thanks a lot !

Iam curious what the issue in fact will be.

Hope i was not forgetting something obvious....

Kind regards

Nils

 

 

0 (0 Votes)
RE: Environmental Sensor
Answer
12/6/17 4:51 PM as a reply to Nils Hilser.

Hello Nils,

I have replied to the e-mail you have sent me.

Kind regards,
Franjo

0 (0 Votes)
RE: Environmental Sensor
Answer
12/8/17 3:31 PM as a reply to Franjo Stjepandic.

Good evening Franjo,

thanks a lot for your commitment !

 

The code is working like a charm now !

 

I have a more general question. 

I think it should be possible to use other communication protocols than MQTT
e.g.: AMQP or OPC-UA ? 

What do I would need to consider e.g. to convert the MQTT project to a AMQP project ?

 

Thanks a lot have a nice weekend !

 

Kind regards

 

Nils

 

 

0 (0 Votes)
RE: Environmental Sensor
Answer
12/11/17 5:07 PM as a reply to Nils Hilser.

Hello Nils,

it is quite difficult to turn your MQTT project into an AMQP project, since there is no AMQP library on the XDK, and no AMQP demo for the XDK either.

The MQTT Paho demo, which you currently use, basically works because the files inside the Paho folder can easily be adapted to any embedded device with a WiFi chip. The MQTT implementation comes from Paho, a third party company, which only needs two files that tell the MQTT implementation how to count time on the device, and how to send and receive messages via TCP. The adaption is done via mqttXDK.c and mqttXDK.h, if you want to check it out. This basically defines functions, which are used inside Paho's MQTT implementation.

Additionally, the XDK offers another library in Workbench version 3.1, that also allows implementing an MQTT client.

I do not know if there are easily adaptable AMQP implementations available by a third party, such as is the case for MQTT.

If you wanted to use AMQP, you'd either have to find such an implementation which you would have to adapt to the XDK, or implement the specification yourself, i.e. sending / receiving packets via TCP for subscribing, publishing, connecting, etc. This would take a lot of time.

The same goes for OPC-UA.

Overall, I recommend to use libraries that are natively available on the XDK via the SDK.

Please tell me if this was helpful, and do not hesitate to ask further questions.

Kind regards,
Franjo

0 (0 Votes)