MicrochipTech / gcp-iot-core-examples

Google Cloud Platform IOT Core Examples
Other
111 stars 21 forks source link

Read the full topic and payload buffer received from the cloud #8

Closed danielepsv closed 4 years ago

danielepsv commented 4 years ago

Hi,

I've been using SAMD21 + WINC1510 + ATECC608A. I'm making a project that is controlled mainly by an android/ios app that talks to the cloud and/or database. Does anyone knows how can I read the full topic and payload buffer received from the cloud? I found the function client_process_message() in client_task.c and I've tried this prints:

*printf("\n\rReceive from cloud:\n\r"); printf("topic: %s\n\r", (char)data->topicName->cstring); printf("payload: %s\n\r", (char)data->message->payload); printf("buffer: %s\n\r", (char)data);**

Result: Receive from cloud: topic: (R payload: buffer: hQ

Does anyone knows how can I make these prints work?

Best regards, Daniele

danielepsv commented 4 years ago

Update. I can't receive commands because I'm on the wrong topic (config), but when I try to subscribe to "/devices/%s/commands/#" it fails...

MQTT Subscription to commands failed (-1) MQTT Client Failed to Connect (-1) MQTT Client Failed to Connect (-1) MQTT Client Failed to Connect (-1) MQTT Client Failed to Connect (-1) MQTT Client Failed to Connect (-1) MQTT Client Failed to Connect (-1)

I can't subscribe to more then 1 topic???

On client_state_connect() in client_task.c I added the following code:

status = client_commands_subscribe(pCtx); if(status) { CLIENT_PRINTF("MQTT Subscription to commands failed (%d)\r\n", status); return; }

The client_commands_subscribe() is a copy of the client_subscribe() function. And commands_sub_topic() is a copy of config_get_client_sub_topic() in config.c that I replaced with a different topic (int rv = snprintf(buf, buflen, "/devices/d%s/commands/#", device_id);)

Any thoughts? What am I doing wrong ? Thanks. Best regards, Daniele

danielepsv commented 4 years ago

Connected to config I get:

/****/ Subscribed to topic: /devices/d012330EA689B0074EE/config[0]... (0 is the status) topic[35]: /devices/d012330EA689B0074EE/events

Failed to publish the MQTT message: -1

topic[35]: /devices/d012330EA689B0074EE/events Success publishing the MQTT message!

Receive from cloud: topic: /devices/d012330EA689B0074EE/config payload: gfgfg /****/

Connected to commands:

/****/ Subscribed to topic: /devices/d012330EA689B0074EE/commands/#[0]... (0 is the status)

topic[35]: /devices/d012330EA689B0074EE/events Failed to publish the MQTT message: -1

topic[35]: /devices/d012330EA689B0074EE/events Success publishing the MQTT message! /****/

Nothing else... Why?

Thanks in advance, Daniele

bryan-hunt commented 4 years ago

These a questions for Paho and GCP. The GCP mqtt server is not a full mqtt implementation so there are feature it does not support. I assume in order to subscribe to a different topic you would have to manually create the topic in the console (or through the management APIs).

danielepsv commented 4 years ago

I'll check it out thank you Bryan!

danielepsv commented 4 years ago

Hi,

There are 4 MQTT topics for devices to work with (this is all on device side, not Cloud side):

/devices/{device-id}/commands /devices/{device-id}/config /devices/{device-id}/state /devices/{device-id}/events

So I've tested with the same project/registry/region in AVR-IoT and SAMD21 in both I subscribed to /devices/{device-id}/commands/# topic. In AVR-IoT I receive the data in the callback function, on SAMD21 the callback function is not even activated... But on the cloud, it says the command was sent successfully to the device but nothing shows up.

Best regards, Daniele

15Sax commented 4 years ago

Hi Daniel ( @L4z3rb34m )

About your last comment.

I would like to send telemetry to a topic in the cloud which I have created called "projects/myproject/topics/mytopic" (NOT A SUBFOLDER).

You say that I have to write "devices/mydevice/events" on the device to publish to the cloud but how can I differentiate between one topic and another? Should it be something like "devices/mydevice/mytopic"?

Thank you and best regards. Santi

15Sax commented 4 years ago

Hi Daniel ( @L4z3rb34m )

Have you solved the problem receiving commands to the device?

danielepsv commented 4 years ago

Hi there,

Nop I did not...

The topic "projects/myproject/locations/mylocation/registries/myregistry/devices/mydevice" is the client id. The subscribe topic by default is "devices/mydevice/config". To publish/send telemetry events to the cloud you have to use the topic "devices/mydevice/events" (on publish topic). To receive data from the cloud on your device, you need the "devices/mydevice/commands/#" (on subscribe topic) your device listens to the subscribed topic.

Differences in subscribed topic: If I use the config topic every time your device restarts a config is sent to the device.(Not what I want) If I use the commands topic I received data from cloud when I want. (What I need)

Do you know why samd21 receives from config but not from commands?

Bryan you said : "I assume in order to subscribe to a different topic you would have to manually create the topic in the console (or through the management APIs)." I don't agree because GCP creates this four topics on your project (you don't need to create manually I just need to subscribe to the one I want): /devices/{device-id}/commands/# <- this doesn't work /devices/{device-id}/config <- this works /devices/{device-id}/state <- not tested (so far I didn't need it) /devices/{device-id}/events <- this works

I believe this might be a problem with the library, because I've tested this with AVR-IOT board and commands topic worked also I used the same project, same topics...

But I'm still not sure or close to solve this...

Best regards, Daniele

danielepsv commented 4 years ago

Hello again,

I can not detect anything unusual besides the structure of the topics: ... / config ... / commands /# <- does the library know what to do with / #?

I'm asking this because the topic "config" works just fine. Thanks in advance.

Best regards, Daniele

15Sax commented 4 years ago

Hi,

Thank you for your response.

I have the same problem with the subscription to /commands/# I don't receive anything from cloud.

In addition I would like to ask you if you can receive a big amount of bytes from the config (because commands doesn't work) on the device. GCP documentation says that it is possible to receive up to 64KB with configuration messages (up to 256KB with commands). But when I send a message with 1464 bytes or more the device stops! I tried to change the size of the mqtt_rx_buf of g_client_context but it does not work.

Best regards, Santi.

danielepsv commented 4 years ago

Hi Santi,

I had this issue when sending to the cloud. In the function to send to the cloud (where you build your json structure) I increasing the json array size ex: char json[200];

This worked for me. As for receiving in "config" topic i didn't detect anything wrong as for "commands" they don't work. uint8_t mqtt_rx_buf[CLIENT_MQTT_RX_BUF_SIZE]; <- uin16_t

define CLIENT_MQTT_RX_BUF_SIZE (1024) <- (2048)

I don't know if this works.

Best regards, Daniele

15Sax commented 4 years ago

Hi,

Could you try to receive a configuration message from the cloud with more than 1500 characters and tell me if it works for you, please? I think it is a library problem and I don't know what to do to solve it. About your solutions:

Best regards, Santi.

danielepsv commented 4 years ago

Hi,

When you subscribe to a topic with the termination "/#" you receive data (payload) from route folder and the sublevels of this path.

I tested send commands with a subfolder and without a subfolder. With subfolder this example works but without it it does not.

With AVR-IOT it works with and without a subfolder. With this project it only receives from the sublevels.

Hope this helps someone.

Santi I didn't had time try your example but maybe if you use commands maybe it works. To send a command from cloud functions use this:

////////////////////////////////////////////////////////////////////

json = { variable_name : value }; <- example

var msg = Buffer.from(JSON.stringify(json)).toString('base64');

const jwtAccess = new google.auth.JWT(); jwtAccess.fromJSON(serviceAccount); jwtAccess.scopes = 'https://www.googleapis.com/auth/cloud-platform'; google.options({ auth: jwtAccess }); var devicePath = 'projects/' + project_id + '/locations/' + cloud_region + '/registries/' + registry_id + '/devices/' + deviceId; var client = google.cloudiot('v1');

const commandRequest = { name: devicePath, binaryData: msg, subfolder: "events" <- you can use any name you prefer };

return client.projects.locations.registries.devices.sendCommandToDevice(commandRequest);

////////////////////////////////////////////////////////////////////

Best regards, Daniele