How pinch AZURE_IOT_NX_CONTEXT to send new state of device properties to IoT Hub
sergiosolorzano opened this issue ยท 5 comments
Hi, I am trying to change the reported ledState in device twin when I change it in the actual device (mxchip AZ3166).
If I send this message to IoT Hub from nx_client.c when a device button is pressed, I think nx_context is not ready and the packet fails on tls packet error checks.
It works by changing a bool in nx_client.c when the button state changes and setting up a callback in azure_iot_nx_client.c that is executed by client_run() in azure_iot_nx_client.c. However this creates unnecessary overhead checking the button status constantly. Unfortunatly including nx_client.c to azure_iot_nx_client.c doesn't work to pick-up device led state variables.
Storing AZURE_IOT_NX_CONTEXT at nx_client.c from a prior use when a callback occurred threw the same packet error checks.
Is there an easier way to pinch AZURE_IOT_NX_CONTEXT at nx_client when a device button is pressed?
Thank you for your help
Hi,
Are you accessing the static AZURE_IOT_NX_CONTEXT azure_iot_nx_client
from the nx_client.c?
Which function are you accessing this variable from?
The global azure_iot_nx_client and the nx_client variable in the callbacks are pointing at the same structure so there wouldnt be a difference between the two.
Its possible that you are running into threading issues, because if you are using executing this in an interrupt from the button press, then this could be causing conflicts with the client_run() thread.
Are you able to post the code?
Hi @ryanwinter thank you for your response and apologies for the delay, I was travelling.
This is the repo that works and that I think creates overhead at client_run() to change the reported ledState. I fire azure_iot_nx_client.c->process_set_device_bool_event() at azure_iot_nx_client.c->client_run() as a callback on the ledState.
This is the repo that doesn't work and I don't use a callback to change the reported ledState but call a function to send the packet with the ledState to IoT hub. It fails at nxe_secure_tls_packet_allocate.c->_nxe_secure_tls_packet_allocate() where it checks for the appropriate caller NX_THREADS_ONLY_CALLER_CHECKING. These are the debug lines I added to track, I think the problem is that aure_iot_nx_client is not ready:
At nx_client - Set level LED State ON
nx_azure_iot_hub_client.c-> At nx_azure_iot_hub_client_reported_properties_create waitoption:4294967295
***nx_azure_iot.c-> nx_azure_iot_publish_packet_GET with waitoption:4294967295
At Top checks for errors in TLS packet: _nxe_secure_tls_packet_allocate.c-> _nxe_secure_tls_packet_allocate with waitoption:4294967295
At checks for errors packet_allocate to call allocate a packet.
nx_azure_iot.c-> FAIL nx_secure_tls_packet_allocate: Create publish packet failed
Error: Failed create reported properties (0x00000011)
ERROR: azure_iot_nx_client_publish_bool_property (0x00000011)At azure_iot_nx_client.c Appended value 1nx_packet_allocate.c -> waitoption:0 ````
Please let me know if I can provide further information.
Thank you for your help ! Sergio
Debugging this right now, I'll let you know what I find.
The azure_iot_nx_client structure is correct (assuming the board is connected, if it's not connected then it crashes at this point).
So you found the correct spot, the nxe_secure_tls_packate_allocate is making sure that the allocation is happening on a TX_THREAD, which obviously is not the case as this being called from a system interrupt.
You have a couple of options:
-
Do the other method you are doing, set a bool somewhere and check on the main thread and send a property when needed. I understand that this has some level of unnecessary checking though the overheads are relatively minimum and the benefits are simpler code and also more control over when messages are sent from the device and coordination of these with other messages.
-
Pass a message from the ISR to the main TX_THREAD. You could use TX_EVENT_FLAGS similar to how they are used in the client_run() function in azure_iot_nx_client.c.
Basically you set a bit in the TX_EVENT_FLAG_GROUP, and then ThreadX can wait on that flag to be set and will start processing at that time.
Both approaches are similar, the idea is to do as little as possible in the ISR, and pass the main processing off to a TX_THREAD.
Thanks a bunch for your guidance and looking into this @ryanwinter !