Receive messages from Azure IotHub in xamarin .netstandard - azure

I am developing the xamarin app in .netStandard 2.0 using visual studio 2019.I have a problem to received data from iothub.I able to send data from xamarin app to iot hub but unable to received data from azure iothub.
Liberies
Microsoft.Azure.Device (1.20.0)
Microsoft.Azure.Device.Client (1.24.0)
private const string DeviceConnectionString = "HostName=[your hostname];DeviceId=[your DeviceId];SharedAccessKey=[your shared key]";
public async Task Start()
{
try
{
DeviceClient deviceClient =
DeviceClient.CreateFromConnectionString(DeviceConnectionString, TransportType.http1);
await SendEvent(deviceClient);
await ReceiveCommands(deviceClient);
}
catch (Exception ex)
{
Debug.WriteLine("Error in sample: {0}", ex.Message);
}
}
async Task SendEvent(DeviceClient deviceClient)
{
string dataBuffer;
dataBuffer = "Hello Iot";
Message eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer));
await deviceClient.SendEventAsync(eventMessage);
}
async Task ReceiveCommands(DeviceClient deviceClient)
{
Message receivedMessage;
string messageData;
while (true)
{
receivedMessage = await deviceClient.ReceiveAsync();
if (receivedMessage != null)
{
messageData = Encoding.ASCII.GetString(receivedMessage.GetBytes());
txtblkMessages.Text = messageData + "\n" + txtblkMessages.Text;
await deviceClient.CompleteAsync(receivedMessage);
}
await Task.Delay(TimeSpan.FromSeconds(1));
}
}

Related

Request body goes missing when application is deployed to Azure

I have a net6.0 Razor pages app that is running fine locally, but doesn't work when deployed to Azure. It seems that POST bodies are going missing.
Here's some middleware...
public async Task Invoke(HttpContext context)
{
_logger.LogInformation("BodyLogger");
if (!context.Request.Body.CanSeek)
{
context.Request.EnableBuffering();
}
if (context.Request.Method == "POST")
{
_logger.LogInformation("POST cl=" + context.Request.ContentLength.ToString());
try
{
_logger.LogInformation("BodyLogger try");
string body = "";
context.Request.Body.Position = 0;
using (var reader = new StreamReader(context.Request.Body, leaveOpen: true))
{
_logger.LogInformation("BodyLogger using");
body = await reader.ReadToEndAsync();
}
context.Request.Body.Position = 0;
_logger.LogInformation($"BODY ok (length {body?.Length ?? 0})" + (body ?? "(null)"));
}
catch (Exception e)
{
_logger.LogError("BODY error " + e.Message);
throw;
}
}
await _next.Invoke(context);
}
...and what appears in ApplicationInsights.
What's going on?!
Updage
Even more strangely: it still doesn't work if it's deployed to a different Azure Web App resource, and this middleware
app.Use(async (HttpContext context, RequestDelegate next) =>
{
if (context.Request.Path == "/post")
{
if (!context.Request.Body.CanSeek)
{
context.Request.EnableBuffering();
}
//context.Request.Body.Position = 0;
context.Request.Body.Seek(0, SeekOrigin.Begin);
string body = "";
using (var reader = new StreamReader(context.Request.Body, leaveOpen: true))
{
body = await reader.ReadToEndAsync();
}
//context.Request.Body.Position = 0;
context.Request.Body.Seek(0, SeekOrigin.Begin);
await context.Response.WriteAsJsonAsync("The body was: " + body);
return;
}
await next.Invoke(context);
});
works both as the first and the last middleware.
I've noticed that absent from the ApplicationInsights logs are the Kestrel messages
Connection id "0HMOAORGGN3ES", Request id "0HMOAORGGN3ES:00000003": started reading request body.
Connection id "0HMOAORGGN3ES", Request id "0HMOAORGGN3ES:00000003": done reading request body.
It turns out that in some cases my custom ITelemetryInitializer for ApplicationInsights (turned off in development) was reading the request body.

How can I capture audio in Blazor Server?

My app:
https://vcat.azurewebsites.net/voice
uses azure voice to text service on a blazor server side. It works fine locally, but when published at azure it does not work.
What is wrong?
As I have understood it is not only me who has this problem. This is another one:
CognitiveServices.Speech Blazor Server not working when Published to Azure
here is the code:
private async Task record()
{
try
{
_isRecording = true;
_question = string.Empty;
_answer = string.Empty;
using var audioConfig = AudioConfig.FromDefaultMicrophoneInput();
using var speechRecognizer = new SpeechRecognizer(_speechConfig, audioConfig);
var speechRecognitionResult = await speechRecognizer.RecognizeOnceAsync();
_question = speechRecognitionResult.Text;
_isRecording = false;
if (string.IsNullOrEmpty(_question))
{
_question = "Please try again!";
}
else
{
//_isThinking = true;
await answer();
//_isThinking = false;
await speak();
}
}
catch (Exception ex)
{
Error?.ProcessError(ex);
}
}

Receiving BrokeredMessage from ServiceBus from a nodejs server

I am reading messages from an existing Azure ServiceBus from a new nodejs Server.
This is the way the messages are being sent to the ServiceBus from a .NET server:
var topicClient = TopicClient.CreateFromConnectionString(serviceBusConnectionString, routingKey);
var brokeredMessage = new BrokeredMessage(message.ToJson());
topicClient.Send(brokeredMessage);
Where topicClient is Microsoft.ServiceBus.Messaging.TopicClient
I am using the following method to read the messages on a nodejs server using azure-sb package:
sbClient = ServiceBusClient.createFromConnectionString(connectionString)
subscriptionClient = this.sbClient.createSubscriptionClient(topicName, subscriptionName);
receiver = this.subscriptionClient.createReceiver(ReceiveMode.receiveAndDelete);
messages = await this.receiver.receiveMessages(10,10);
console.log(messages.map(message => { message.body }));
message.body is a buffer and when I do message.body.toString('utf-8') I get something like:
#string3http://schemas.microsoft.com/2003/10/Serialization/��{VALID JSON}
I am interested of course in the valid JSON in between.
In the .net servers we simply do brokeredMessage.GetBody() and we get the object, so is there an easy way on nodejs to do the same?
According to my test, if we use the standard library Microsoft.Azure.ServiceBus to send messages in .Net application, it will directly JSON parse the message in node application
For example
This is my C# code to send a message:
class Program
{
static void Main(string[] args)
{
string connectionString = "Endpoint=sb://...";
var client = new TopicClient(connectionString, "");
var payload = JsonConvert.SerializeObject(new DemoMessage() { Title = $"hello!!! {DateTime.Now}" });
var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload));
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
client.SendAsync(serviceBusMessage).Wait();
}
private class DemoMessage
{
public DemoMessage()
{
}
public string Title { get; set; }
}
This is my Node.js code to receive a message:
const { ServiceBusClient, ReceiveMode } = require("#azure/service-bus");
// Define connection string and related Service Bus entity names here
const connectionString =
"Endpoint=sb://";
const topicName = "***";
const subscriptionName = "***";
async function main() {
const sbClient = ServiceBusClient.createFromConnectionString(
connectionString,
);
const subscriptionClient = sbClient.createSubscriptionClient(
topicName,
subscriptionName,
);
const receiver = subscriptionClient.createReceiver(ReceiveMode.receiveAndDelete);
try {
const messages = await receiver.receiveMessages(1);
console.log("Received messages:");
console.log(messages.map((message) => message.body));
await subscriptionClient.close();
} finally {
await sbClient.close();
}
}
main().catch((err) => {
console.log("Error occurred: ", err);
});
Besides, if you still use the library WindowsAzure.ServiceBus, we need to use BrokeredMessage(Stream messageBodyStream, bool ownsStream) to initialize an object.
Because we use BrokeredMessage(platload) to initialize, it will use DataContractSerializer with a binary XmlDictionaryWriter to initialize an object. So, the payload is being serialized using DataContractSerializer with a binary XmlDictionaryWriter and this is the cause that explains why the body of the message has in its start the type indication #string3http://schemas.microsoft.com/2003/10/Serialization/.
For example
This is my C# code to send a message:
var client =TopicClient.CreateFromConnectionString(connectionString, "test");
var payload = JsonConvert.SerializeObject(new DemoMessage() { Title = $"hello BrokeredMessage!!! {DateTime.Now}" });
using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(payload))) {
var serviceBusMessage = new BrokeredMessage(stream,true);
await client.SendAsync(serviceBusMessage);
}
I use the same code to receive
For more details, please refer to here.

Flutter push notification is working only when app is in background

My problem is regarding the push notification using Flutter and firebase_messaging plugin
Problem:
I have integrated firebase_messaging plugin to my flutter app for push notification.
I can guarantee that the setup is correct to the best of my knowledge as i am receiving push notification. The problem occurs when pushes are received only when my app is running in the background(like minimizing but available in the system memory). Pushes are not received when app is in foreground or is killed.
To provide a solution on what I have tried, I could not figure out actually needs to be done.
I have followed tutorials on this and applied every single step to overcome the problem but to no avail.
I am using nodeJS to handle the firebase-admin and serviceaccountkey file as I need device_tokens from my DB.
NodeJS
const firebase = require('firebase-admin');
const serviceAccount = require('../controller/firebase/serviceAccountKey.json');
firebase.initializeApp({
credential: firebase.credential.cert(serviceAccount)
});
//Function to actually implement the push
const pushNotificationInitiatorSubscription = (resultValue) => {
let devicesTokenString = resultValue[0]['device_token'];
const firebaseToken = devicesTokenString;
const payLoad = {
notification: {
title: 'New Subscription',
body: 'You have a new subscription to your material ' + resultValue[0]['course_name']
}
};
const option = {
priority: 'high'
};
firebase.messaging().sendToDevice(firebaseToken, payLoad, option).then(success => {
// console.log(success.results[0]['error']);
// console.log(success.results[1]['error']);
// console.log(success);
}).catch(err => {
console.log(err);
})
Flutter
import 'package:firebase_messaging/firebase_messaging.dart';
class FirebaseCloudMessage {
static FirebaseCloudMessage _instance = new FirebaseCloudMessage.internal();
FirebaseCloudMessage.internal();
factory FirebaseCloudMessage() => _instance;
final FirebaseMessaging _firebaseMessaging = new FirebaseMessaging();
configureFirebaseListeners() {
print('Here');
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("Message $message");
// return message;
}, onLaunch: (Map<String, dynamic> message) async {
print("Message $message");
// return message;
}, onResume: (Map<String, dynamic> message) async {
print("Message $message");
// return message;
});
}
}
Help would be appreciated. Thanks
This is the default behavior of notifications received from the firebase notification service currently. You have to manually write code if you wanna show the notification when your app is in the foreground.
Here's a demo of showing notification in flutter using flutter_local_notifications package.
NOTE: This is a really basic example of showing notifications in flutter using flutter_local_notification package. There's a lot you can configure. For a detailed explanation, visit homepage of this package or read this really good medium article
Step 1: install flutter_local_notifications package in your pubspec.yaml
Step 2: initiate FlutterLocalNotifications in initState():
#override
void initState() {
super.initState();
var initializationSettingsAndroid =
new AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = new IOSInitializationSettings();
var initializationSettings = new InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
Step 3: Create a function to handle click events on the notification. This function will be called when a user will tap on the notification.
Future<dynamic> onSelectNotification(String payload) async {
/*Do whatever you want to do on notification click. In this case, I'll show an alert dialog*/
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text(payload),
content: Text("Payload: $payload"),
),
);
}
Step 4: Write a function to show notification:
Future<void> _showNotification(
int notificationId,
String notificationTitle,
String notificationContent,
String payload, {
String channelId = '1234',
String channelTitle = 'Android Channel',
String channelDescription = 'Default Android Channel for notifications',
Priority notificationPriority = Priority.High,
Importance notificationImportance = Importance.Max,
}) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
channelId,
channelTitle,
channelDescription,
playSound: false,
importance: notificationImportance,
priority: notificationPriority,
);
var iOSPlatformChannelSpecifics =
new IOSNotificationDetails(presentSound: false);
var platformChannelSpecifics = new NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
notificationId,
notificationTitle,
notificationContent,
platformChannelSpecifics,
payload: payload,
);
}
Step 5: Call the _showNotification() function:
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
//print("Message $message");
_showNotification(1234, "GET title FROM message OBJECT", "GET description FROM message OBJECT", "GET PAYLOAD FROM message OBJECT");
return;
}
}
After this, you will be able to show notification even when your app is in the foreground. Hopefully, this will be useful.

Subscribing to Azure Push Notification service in Xamarin Forms

I tried to integrate with Push Notifications to my forms application. Azure messaging component is used for achieving this.
Below is the code i am using. I am getting the trigger to RegisteredForRemoteNotifications method. But RegisterNativeAsync method doesn't seem to be doing the job.
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
{
var push = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
new NSSet());
UIApplication.SharedApplication.RegisterUserNotificationSettings(push);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
else
{
const UIRemoteNotificationType not = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(not);
}
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
Hub = new SBNotificationHub(conStirng, NotifHubPath);
Hub.UnregisterAllAsync(deviceToken, (error) =>
{
//Get device token
var id = deviceToken.ToString();
var tag = "username";
var tags = new List<string> { tag };
Hub.RegisterNativeAsync(id, new NSSet(tags.ToArray()), (errorCallback) =>
{
if (errorCallback != null)
{
//Log to output
}
});
});
}
What am i doing wrong here? How can i confirm if the Register function is success or failure.?
You need to check if the error from the response of the register method is null or not. if it is null means the it is a success.
var hub = new SBNotificationHub (cs, "your-hub-name");
hub.RegisterNativeAsync (deviceToken, null, err => {
if (err != null)
Console.WriteLine("Error: " + err.Description);
else
Console.WriteLine("Success");
});
In the case of windows universal apps we can check the registrationId property of the response.
private async void InitNotificationsAsync()
{
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var hub = new NotificationHub("<hub name>", "<connection string with listen access>");
var result = await hub.RegisterNativeAsync(channel.Uri);
// Displays the registration ID so you know it was successful
if (result.RegistrationId != null)
{
var dialog = new MessageDialog("Registration successful: " + result.RegistrationId);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}

Resources