How to send Azure IoT commands back to NodeMcu

Microsoft is has made their IoT platform very open. There are lots of ways to connect to it, using various protocols like HTTP, MQTT and AMQP. And Microsoft provides multiple SDKs to connect to their IoT platform using languages like Python, .Net, Java, Node JS and C. So it’s not that hard to connect to the platform whatever your development platform is.

If you follow my blog, you will notice that I normally connect to the platform using UWP. It’s great for testing purposes and it even runs on a Raspberry Pi using Windows 10 Core. I also connect a lot using ‘special’ Arduino’s. Although these are not connected to the Internet by default, I have a couple of The Things UNO boards which have wireless connectivity using Lora. The Arduino’s connect to the Azure IoT platform using the The Things Network Lora platform.

I also connected using a Photon, using the Particle cloud. This works almost out of the box but for now, it’s only one way; I can only send telemetry to the Particle cloud. I hope to see the ability for receive commands,  arriving at the Photon, in the near future.

Currently I have some NodeMCU laying around and a friend showed me how to connect to the Azure IoT Platform using the Azure IoT for C SDK.

nodemcu-lua-cp2102-1

It’s not that hard to get it to send some telemetry, once you know what to do (thanks, Jan Willem 🙂 ) but retrieving commands is less straight forward. In this blog, we take a closer look.

Once you have deployed the AzureIoTHub sketch on your NodeMCU 1.0 (running an ESP-12), together with WIFI SSID, WIFI Password and  the connection string of a device registered in your IoT Hub, you will see in the Serial Monitor the successful transmission of a message:

nmcc01

And in the Device Explorer, the message is received:

nmcc02

This is done in the sketch using:

myWeather->DeviceId = "sonaresp";
myWeather->WindSpeed = avgWindSpeed + (rand() % 4 + 2);

This ‘device’ is just defined as a class, actually:

DECLARE_MODEL(ContosoAnemometer,
WITH_DATA(ascii_char_ptr, DeviceId),
WITH_DATA(int, WindSpeed),
WITH_ACTION(TurnFanOn),
WITH_ACTION(TurnFanOff),
WITH_ACTION(SetAirResistance, int, Position),
);

I’m not a hardcore C developer but this class structure is well designed. And directly I was trying to figure out how to execute the three actions.

I tried various ways to send commands using the Device Explorer. It was soon clear I had to send JSON to the NodeMCU but the format of the JSON message was unclear. Then I came across a blog post explaining the format in more detail.

This way, I figured out that the three actions can be called using these commands (in the Device Explorer):

{"Name" : "TurnFanOn", "Parameters" : {}}
{"Name" : "TurnFanOff", "Parameters" : {}}
{"Name" : "SetAirResistance", "Parameters" : { "Position" : 5 }}

You can send them:
nmcc03
And the result is:
nmcc04

Adding your own actions

Then I was thinking, how about more interesting methods, eg. an action with two parameters? So I wrote this pretty lame action named SetAirBreak:

DECLARE_MODEL(ContosoAnemometer,
...
WITH_ACTION(SetAirBreak, int, Min, int, Max)
);

EXECUTE_COMMAND_RESULT SetAirBreak(ContosoAnemometer* device, int Min, int Max)
{
 (void)device;
 (void)printf("Setting Air Break between %d and %d.\r\n", Min, Max);
 return EXECUTE_COMMAND_SUCCESS;
}

So I send:

{"Name" : "SetAirBreak", "Parameters" : { "Min" : 42, "Max" : 142 }}

The command is executed seconds later:

nmcc05

Sending NodeMCU action commands using C# code

The proof of the pudding is in the eating. Until now we have seen that on the NodeMCU, we can receive and execute commands. But can we execute them in regular code also? Yes, we can!

Here is an example of C# code:

var connectionString = "HostName=[your IoT Hub].azure-devices.net;SharedAccessKeyName=[security policy];SharedAccessKey=[access key]";

var serviceClient = ServiceClient.CreateFromConnectionString(connectionString);

dynamic setAirBreak = new
{
    Name = "SetAirBreak",
    Parameters = new
    {
        Min = 155,
        Max = 255
    }
};

var dynJson = JsonConvert.SerializeObject(setAirBreak);
var dynArray = Encoding.UTF8.GetBytes(dynJson);
var commandMessage = new Message(dynArray);
serviceClient.SendAsync("sonaresp", commandMessage);

After creating a serviceClient for the Azure IoTHub, we design a message. Here I use a dynamic, I design a class structure on the fly. The dynamic is serialized to a JSON string and this JSON string is encoded and sent to the device of my choice:

nmcc06

Conclusion

This proofs the NodeMCU is a first class citizen device for the Azure IoT platform. A NodeMCU costs around three dollars and supports Wifi out of the box. This is great value for a device like this. Yes, Wifi consumes a lot of energy and JSON is not the most efficient way for communication but the device support deep sleep so there is a good trade-off.

I still am very pleased with a communication platform like Lora but when it comes to Wifi, please consider NodeMCU running C.

Advertenties