Arduino MKR1000 How to send Message to Azure IoT Hub - azure

I am trying to setup a basic example of sending a message from the Arduino MKR1000 to the Azure IOT Event Hub but can't seem to get any of the online examples to work and I am new to Arduino.
Any pointers for a simple working example?
I tried this example and changing slightly to POST a message rather than receive but no luck. I can connect to the Wifi with no issues, its just when posting the HTTP request it errors with "HTTP Error 411. The request must be chunked or have a content length". It also doesn't seem like the most clean approach but I just wan't to get something basic up and running for now to play with :)
Code Example:
#include <SPI.h>
#include <WiFi101.h>
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
const int MKR1000_LED = 6 ;
///*** Azure IoT Hub Config ***///
//see: http://mohanp.com/ for details on getting this right if you are not sure.
char hostname[] = "*****.azure-devices.net"; // host name address for your Azure IoT Hub
char feeduri[] = "/devices/MKR1000/messages/events?api-version=2018-06-30"; //feed URI
char authSAS[] = "SharedAccessSignature sr=******.azure-devices.net%2Fdevices%2FMKR1000&sig=*****&se=******";
///*** Azure IoT Hub Config ***///
unsigned long lastConnectionTime = 0;
const unsigned long pollingInterval = 5L * 1000L; // 5 sec polling delay, in milliseconds
int status = WL_IDLE_STATUS;
WiFiSSLClient client;
void setup() {
Serial.println("setup...");
pinMode(MKR1000_LED, OUTPUT);
//check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Wifi connected...");
}
void loop()
{
String response = "";
char c;
///read response if WiFi Client is available
while (client.available()) {
c = client.read();
response.concat(c);
}
if (!response.equals(""))
{
Serial.println(response);
//if there are no messages in the IoT Hub Device queue, Azure will return 204 status code.
if (response.startsWith("HTTP/1.1 204"))
{
//turn off onboard LED
digitalWrite(MKR1000_LED, LOW);
}
else
{
//turn on onboard LED
digitalWrite(MKR1000_LED, HIGH);
}
}
// polling..if pollingInterval has passed
if (millis() - lastConnectionTime > pollingInterval) {
digitalWrite(MKR1000_LED, LOW);
azureHttpRequest("{TEST MESSAGE!}");
}
}
// this method makes an HTTPS connection to the Azure IOT Hub Server:
void azureHttpRequest(String data) {
// close any connection before send a new request.
// This will free the socket on the WiFi shield
client.stop();
// if there's a successful connection:
if (client.connect(hostname, 443)) {
//make the GET request to the Azure IOT device feed uri
client.print("POST "); //Do a GET
client.print(feeduri); // On the feedURI
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(hostname); //with hostname header
client.print("Authorization: ");
client.println(authSAS); //Authorization SAS token obtained from Azure IoT device explorer
//client.println("Connection: close");
client.println("Content-Type: application/json");
client.println("Content-Length: " + data.length());
client.println("\r\n\r\n" + data);
// note the time that the connection was made:
lastConnectionTime = millis();
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
}
}
Edit: I have seen that there is a full Azure IOT library with a simple HTTP example, but this also doesn't run (it gets passed the wifi connection and failing with call to azure) but this example project is fairly large and I was hoping for a simple example to build upon!
https://github.com/Azure/azure-iot-arduino

Related

Is there any solutions available to send data from BluetoothGattServer to connected devices simultaneously?

Here is my server code:
private BluetoothGattServer mGattServer;
mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
GattServerCallback gattServerCallback = new GattServerCallback(this, context.getApplicationContext());
mGattServer = mBluetoothManager.openGattServer(context, gattServerCallback);
BluetoothGattService service = new BluetoothGattService(SERVICE_UUID,
BluetoothGattService.SERVICE_TYPE_PRIMARY);
// Write characteristic
BluetoothGattCharacteristic writeCharacteristic = new BluetoothGattCharacteristic(
CHARACTERISTIC_ECHO_UUID,
BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE,
// Somehow this is not necessary, the client can still enable notifications//
BluetoothGattCharacteristic.PERMISSION_WRITE | BluetoothGattDescriptor.PERMISSION_READ);
BluetoothGattDescriptor clientConfigurationDescriptor = new BluetoothGattDescriptor(
CHARACTERISTIC_AUDIO_UUID,
BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE);
clientConfigurationDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
service.addCharacteristic(writeCharacteristic);
mGattServer.addService(service);
Once a client is connected, I am adding the connected device to my device list:
#Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
mServerActionListener.log("onConnectionStateChange " + device.getAddress()
+ "\nstatus " + status
+ "\nnewState " + newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
mServerActionListener.addDevice(device);
//mServerActionListener.notifyCharacteristicEcho("start".getBytes());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mServerActionListener.removeDevice(device);
}
}
Here I am sending data:
BluetoothGattService service = mGattServer.getService(SERVICE_UUID);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(uuid);
characteristic.setValue(value);
// Indications require confirmation, notifications do not
boolean confirm = BluetoothUtils.requiresConfirmation(characteristic);
for (BluetoothDevice device : mDevices) {
mGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
}
Right now I am sending data to multiple connected devices by iterating through the devices list. But we cannot notify lengthy data like streaming through this way. Because when multiple notifications are to be sent, an application must wait for onNotificationSent callback to be received before sending additional notifications.
Is there any other solutions available to send data to the connected devices? I want to send notification to all connected devices at the same time.
In ios it is possible to send data to the list of devices. 'chunk' is the list of devices in the below code.
peripheralManager.updateValue(chunk, for: transCharacteristic, onSubscribedCentrals: arrCentral)

C# as sender and python as receiver in Azure event hub

I have an IoT device that is connected to Azure event hub. I'm trying to make this device communicate with azure databricks and azure event hub is placed in between as a middleware. The problem is that after we are able to send messages via ".NET framework", it is never shown in messages received in "python" command line (we should do that as we work separately for each part)
I followed the guidelines .NET framework as sender and python as receiver, and this doesn't work.
I am seeing that there are spikes in the request and message graphs under event hub stream instances, but it just never shows in the receiver
==================================UPDATE==================================
Just deleted the eventhub and recreated and it seems work.
However, messages are received in the form of long strings something like this below:
Received: 662a2a44-4414-4cb5-a9e9-a08d12a417e0
Received: b68ef8f8-305f-4726-84e4-f35b76de30c5
Received: e94dfb73-972c-47b4-baef-1ab41b06be28
Received: 8eda384d-f79d-4cdf-9db3-fe5c2156553b
Received: d154283f-a8c2-4a4c-a7d5-e8d8129b568d
Received: 3e3e190e-f883-416c-a5be-b8cd8547d152
Received: e218c63b-85b3-4f4f-8f04-cb5ffc6d8921
Received: 0adec5ad-e351-4151-ba56-01093e0f383d
Received 8 messages in 0.05406975746154785 seconds
This happens when I read the messages in format below:
print("Received: {}".format(event_data.body_as_str(encoding='UTF-8')))
I just give it a try, and I can repro your issue. And here are something you need to check.
1.In you sender(in c#), you should make sure your message to send is correct. Like below:
static void SendingRandomMessages()
{
var eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, eventHubName);
int i = 0;
while (true)
{
try
{
// make sure the message is correct.
var message = i+":"+Guid.NewGuid().ToString()+":"+DateTime.Now;
Console.WriteLine("{0} > Sending message: {1}", DateTime.Now, message);
var myeventdata = new EventData(Encoding.UTF8.GetBytes(message));
eventHubClient.Send(myeventdata);
i++;
//eventHubClient.Send(new EventData(Encoding.UTF8.GetBytes(message)));
}
catch (Exception exception)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("{0} > Exception: {1}", DateTime.Now, exception.Message);
Console.ResetColor();
}
Thread.Sleep(2000);
}
}
2.There seems some delay for the receiver(in python), so I execute the python receiver about 3 times, and I can see the expected output. The screenshot as below:
Update 1022: as we discussed in the comment, there is a solution for fixing just receiving even / odd number event data.
In you sender(in c#), use the code below, which sends event data to partition 0:
static void SendingRandomMessages()
{
var eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, eventHubName);
var myclient = eventHubClient.CreatePartitionedSender("0");
int i = 30;
while (true)
{
var message = i + ":" + Guid.NewGuid().ToString() + ":" + DateTime.Now;
Console.WriteLine("{0} > Sending message: {1}", DateTime.Now, message);
var myeventdata = new EventData(Encoding.UTF8.GetBytes(message));
myclient.Send(myeventdata);
i++;
Thread.Sleep(2000);
}
}
then in your receiver(in python), specify the partition to 0(use this PARTITION = "0"), then you can get all the event data.

IOT hub not recieving or sending messages

Iam trying to make a simple app for my raspberry pi that will send a message to the IOThub and then try to receive a response however nothing is happening.
I copied the connectionstring from the device controller. Ofcource I hidden it for this question.
I see it printing out that the message was succesfully sended to the iothub but when I check the iothub I see 0 received messages.
Iam using the free tier of the iothub is this a limitation?
public sealed partial class MainPage : Page
{
private const string DeviceConnectionString = "Hidden";
private readonly DeviceClient _deviceClient;
public MainPage()
{
this.InitializeComponent();
_deviceClient = DeviceClient.CreateFromConnectionString(DeviceConnectionString, TransportType.Amqp); //Already tried using different transport types but no succes.
}
public async Task SendEvent()
{
Debug.WriteLine("\t{0}> Sending message", DateTime.Now.ToLocalTime());
var commandMessage = new Message(Encoding.ASCII.GetBytes("Cloud to device message."));
await _deviceClient.SendEventAsync(commandMessage);
Debug.WriteLine("Succesfully sended message to IotHub");
}
public async Task ReceiveCommands()
{
Debug.WriteLine("\nDevice waiting for commands from IoTHub...\n");
while (true)
{
var receivedMessage = await _deviceClient.ReceiveAsync();
if (receivedMessage != null)
{
var messageData = Encoding.ASCII.GetString(receivedMessage.GetBytes());
Debug.WriteLine("\t{0}> Received message: {1}", DateTime.Now.ToLocalTime(), messageData);
var propCount = 0;
foreach (var prop in receivedMessage.Properties)
{
Debug.WriteLine("\t\tProperty[{0}> Key={1} : Value={2}", propCount++, prop.Key, prop.Value);
}
await _deviceClient.CompleteAsync(receivedMessage);
Debug.WriteLine("Finishing recieving message");
}
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
private async void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
Debug.WriteLine("Sending event");
await SendEvent();
await ReceiveCommands();
Debug.WriteLine("Received commands");
}
}
It is nothing to do with free tier of the iothub. There is no such limitation.
You can't receive Device-To-Cloud(D2C) messages using DeviceClient that you used in ReceiveCommands(). It is by designed. You look like having some misunderstanding of Azure IoT Hub message types and SDKs.
There are two kinds of message types: Device-To-Cloud(D2C) message and Cloud-To-Device(C2D) message.
And two kinds of SDKs: device SDK and service SDK.
Device SDK is used to connect to and send D2C messages to Azure IoT Hub.
While service SDK is used to manage and send C2D messages to devices.
So, if you send C2D messages to device in Device Explorer you will receive these messages in your ReceiveCommands method.
If you want to receive D2C message you can utilize Event Hub-compatible endpoint(messages/events). Here is a console sample you can reference. But this is can't be done in UWP due to service bus not supported in UWP.

How to Connect IoT device to the remote monitoring preconfigured solution (Windows)? How to implement and specify the behaviour of IoT hub device?

https://learn.microsoft.com/en-us/azure/iot-suite/iot-suite-connecting-devices#create-a-c-sample-solution-on-windows
Add the following functions that execute when the device receives the SetTemperature and SetHumidity commands from IoT Hub:
EXECUTE_COMMAND_RESULT SetTemperature(Thermostat* thermostat, int temperature)
{
(void)printf("Received temperature %d\r\n", temperature);
thermostat->Temperature = temperature;
return EXECUTE_COMMAND_SUCCESS;
}
EXECUTE_COMMAND_RESULT SetHumidity(Thermostat* thermostat, int humidity)
{
(void)printf("Received humidity %d\r\n", humidity);
thermostat->Humidity = humidity;
return EXECUTE_COMMAND_SUCCESS;
}
Add the following function that sends a message to IoT Hub:
static void sendMessage(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const unsigned char* buffer, size_t size)
{
IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(buffer, size);
if (messageHandle == NULL)
{
printf("unable to create a new IoTHubMessage\r\n");
}
else
{
if (IoTHubClient_SendEventAsync(iotHubClientHandle, messageHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
{
printf("failed to hand over the message to IoTHubClient");
}
else
{
printf("IoTHubClient accepted the message for delivery\r\n");
}
IoTHubMessage_Destroy(messageHandle);
}
free((void*)buffer);
}
More in given link
The article you're referring to here shows you how to build and run this sample code on a Windows desktop machine using Visual Studio. There are two other equivalent articles that show you how to run the same code on a Linux machine or an mbed device.
If you want to follow an in-depth tutorial on how to use another hardware device such as a Raspberry Pi or Intel Edison with Azure IoT Hub, then take a look at the collection of IoT Hub tutorials in the Get started folder here.

unable to get tile push notification in windows phone 8 from azure notification hub

I am written code to send push notification to windows phone 8 by azure notification hub.
i am able to send to the toast notification to windows phone 8 and windows phone 8 also able to get notification . but when i am sending tile notification, it is sending tile notification successfully, but windows phone 8 is not getting this tile notification.
i already used BindToShellTile and BindToShellToast at the time of getting the channel Uri and after that i am doing the registration by this channel uri and checked IDCAPPUSH_NOTIFICATION the capabilities in windowsphone porject manifest to allow the push notification.
Below my Code for Bind the Device to Tile And Toast.
public void GetNotificationChannel()
{
/// Holds the push channel that is created or found.
HttpNotificationChannel pushChannel;
// The name of our push channel.
string channelName = "ToastChannel";
// Try to find the push channel.
pushChannel = HttpNotificationChannel.Find(channelName);
// If the channel was not found, then create a new connection to the push service.
if (pushChannel == null)
{
pushChannel = new HttpNotificationChannel(channelName);
// Register for all the events before attempting to open the channel.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
// Register for this notification only if you need to receive the notifications while your application is running.
pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);
pushChannel.Open();
// Bind this new channel for toast and tile notifications.
pushChannel.BindToShellToast();
pushChannel.BindToShellTile();
}
else
{
// The channel was already open, so just register for all the events.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
// Register for this notification only if you need to receive the notifications while your application is running.
pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);
// Display the URI for testing purposes. Normally, the URI would be passed back to your web service at this point.
System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());
//MessageBox.Show(String.Format("Channel Uri is {0}",
// pushChannel.ChannelUri.ToString()));
}
}
Below Code is sued to registered this device in notification hub.
// notification tois nothing but channel uri
private static async void WindowsPhoneRegistrations(string notificationToken)
{
try
{
var notificationHub = GetNotificationHubClient();
// this wil retunr the notification hub client by using the notificationconnectionstring // and hub path
var windowsPhoneRegistrationDescription = await notificationHub.CreateMpnsNativeRegistrationAsync();
}
catch (Exception ex)
{
throw;
}
}
Below code is for sending the tile notification
private static async void SendWindowsPhone8ToastNotification()
{
try
{
string windowsPhone8ToastFinalTemplate = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\" Version=\"2.0\">" +
"<wp:Tile Id=\"txt1\" Template=\"IconicTile\">" +
"<wp:SmallIconImage>http://flyosity.com/images/_blogentries/networkicon/step2.png</wp:SmallIconImage>" +
"<wp:IconImage>http://flyosity.com/images/_blogentries/networkicon/step2.png</wp:IconImage>" +
"<wp:WideContent1 >This is sample</wp:WideContent1>" +
"<wp:Count >1</wp:Count>" +
"<wp:Title >Good</wp:Title>" +
"</wp:Tile>" +
"</wp:Notification>";
var notificationHub = GetNotificationHubClient();
NotificationOutcome n = await notificationHub.SendMpnsNativeNotificationAsync(HttpUtility.HtmlEncode(windowsPhone8ToastFinalTemplate));
}
catch (Exception ex)
{
throw;
}
}
I am able to send the tile notification to notification hubs with out any exceptions and getting the status from notification hub after sending . but device is not getting the tile notification.
what i missed out or did mistake somewhere in this code to get the tile notification in windows phone 8. please help.

Resources