Not getting BLE client connection notifications using Tmds.Dbus library - bluetooth-lowenergy

Environment: Ubuntu 20.04
I am running a BlueZ BLE gatt server and need to know when a client connects.
I have a simple program to monitor BlueZ device connections that is based on Tmds.Dbus (https://github.com/tmds/Tmds.DBus). Here is the relevant code:
using(var connection = new Connection(Address.System)) {
connection.StateChanged += (s, e) => OnStateChanged(e);
await connection.ConnectAsync();
var dev = connection.CreateProxy<bluez.DBus.IDevice1>("org.bluez", "/org/bluez/hci0");
await dev.WatchPropertiesAsync(p => {
Console.WriteLine("Property");
});
var objManager = connection.CreateProxy<bluez.DBus.IObjectManager>("org.bluez", "/org/bluez/hci0");
await objManager.WatchInterfacesAddedAsync(obj => {
Console.WriteLine("Added");
});
...
[DBusInterface("org.bluez.Device1")]
interface IDevice1 : IDBusObject
{
...
Task<IDisposable> WatchPropertiesAsync(Action<PropertyChanges> handler);
}
[DBusInterface("org.freedesktop.DBus.ObjectManager")]
interface IObjectManager : IDBusObject
{
Task<IDisposable> WatchInterfacesAddedAsync(Action<(ObjectPath #object, IDictionary<string, IDictionary<string, object>> interfaces)> handler, Action<Exception> onError = null);
...
}
The problem I am running into is that I never get any event at all when a client connects or disconnects. However, if I run dbus-monitor, I can see InterfacesAdded on ObjectManager and Property changes on Device1.
Wondering if I am just missing something. Tmds.Dbus is just a .NET core wrapper over DBus APIs. Regards

Related

.NET Framework SignalR Clients.Caller Not working as expected

I am currently using SignalR in my .NET framework project to send updates to the client for a long running process. There can be many processes running simultaneously and the client will subscribe to any one of the process using an unique ID. I am using Groups to identify the clients who are subscribed to a particular process. If a client subscribes to a process in middle, I must send all the previous messages to that client. The code goes something like this
public class ProgressHub : Hub
{
public async Task SubscribeToProgress(string id)
{
foreach (var message in GetPreviousMessages(id)) // Getting all the previous messages
{
await Clients.Caller.SendMessage(message); // Sending Messages to the current caller alone
}
await Groups.Add(Context.ConnectionId, id); // Added the current client to a group to be used further
}
}
The client listens to Send Message
The above code snippet is not working (No messages in the network tab).
I tried many things
await Clients.Client(Context.ConnectionId).SendMessage(message);
await Clients.All.SendMessage(message); // Just to check if it works
all the above without await, but nothing seems to work.
After fiddling around a bit, I was able to come up with this
public class ProgressHub : Hub
{
public async Task SubscribeToProgress(string id)
{
await Groups.Add(Context.ConnectionId, id); // Adding client to the group first
foreach (var message in GetPreviousMessages(id))
{
await Clients.Group(id).SendMessage(message); // Sending messages to the group all together
}
}
}
But this has an undesirable side effect of sending the older messages to client who are already connected. Sure, I can exclude the other connectionIDs and send out the message, but this seems like an hack. Logically speaking, the first snippet should have worked just fine.
are you add configuration in Program.cs ?
using SignalRChat.Hubs;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.MapHub<ChatHub>("/chatHub");
app.Run();
and you can read this reference :
Microsoft

Signalr core client - call server methode from Razor component

How can I send a message to my server from, let's say a Razor component?
The situation:
I have a working SignalR (Core) connection with my server.
My client code:
public class StartMySignalR
{
HubConnection connection;
public async void StartSignalRHub()
{
connection = new HubConnectionBuilder()
.WithUrl(new Uri("https://myurl.my/LogOnHub"))
.WithAutomaticReconnect()
.Build();
connection.On<string>("ReceiveMessage", (message) =>
{
//Do some stuff
ii.InsertIntoLog("INFO", "SignalR ID = " + message);
});
//Start SignalR client
await connection.StartAsync();
//Send message to server (test connection).
await connection.InvokeAsync("WelcomeMessage", connection.ConnectionId);
I send a test message to my server, that works fine. I can also send a message back from my server,.. so far so good. But now I want to do that from a Razor component in my OnInitializedAsync() Task. So when my page loads, the test message is sent to my server. There I am stuck. When I try to send the message from my Razor component I receive an error (System.NullReferenceExeption - Object reference not set to an instance of an object) -> connection was null error.
Can somebody put me in the right direction?
When I set the Hubconnection to static it works.
public static HubConnection connection;

.NET CORE GRPC stream exception

I'm working on a .NET Core chat room using gRPC (BI Directional streaming).
client, for now, is a console app (.net core 3.1, server is 5.0).
client-server communication was working alright and suddenly, I started having RpcExceptions thrown.
the problem is, the exceptions thrown have StatusCode=OK and no details.
here is a code sample (simplified)
SERVER Stream RPC
if (!await requestStream.MoveNext())
return;
//Open Connection - set user stream to server's output
client.Stream = responseStream;
while(await requestStream.MoveNext())
{
var chatMessage = requestStream.Current;
chatMessage.Msg = $"{requestStream.Current.ClientName}: {requestStream.Current.Msg}";
foreach (var user in loggedClients)
{
user.Stream.WriteAsync(chatMessage);
}
}
Client Code
using (var streaming = client.RPC_BroadcastChatMessage(metaData))
{
//Read stream and display on console
var readTask = Task.Run(async () =>
{
while (await streaming.ResponseStream.MoveNext())
{
Console.WriteLine($"{streaming.ResponseStream.Current.Msg}");
}
});
//Send first message (empty string) - for a welcome message
Console.WriteLine("Sending empty msg");
await streaming.RequestStream.WriteAsync(emptyMsg);
//Wait for messages from user and send to server
Console.WriteLine("Type message and press Enter to send...");
string line = Console.ReadLine();
while (!string.Equals(line, "exit", StringComparison.OrdinalIgnoreCase))
{
var stream = streaming.RequestStream;
var msg = new ChatMessage()
{
ClientId = clientId,
ClientName = $"User{userNumber}",
Msg = line,
RoomId = roomId
};
await stream.WriteAsync(msg);
line = Console.ReadLine();
}
}
Exception
Grpc.Core.RpcException: Status(StatusCode="OK", Detail="")
both client and server run locally.
I've tried googling the exception but haven't found anything yet (not statusCode=OK related, anyways).
does anyone has any leads? I would very much appreciate it.

SignalR client does not receive message through Masstransit

I had a problem sending messages to clients via MassTransit and SignalR
Startup:
//SignalR
services.AddSignalR().AddMassTransitBackplane();
#region MassTransit RabbitMq
services.AddScoped<SendCosistListToScaleConsumer>();
services.AddScoped<CreateConsistListConsumer>();
services.AddMassTransit(x =>
{
x.AddSignalRHubConsumers<NotifyHub>();
x.AddBus(provider => Bus.Factory.CreateUsingRabbitMq(conf =>
{
conf.Host(Configuration["Rabbit:Host"], host => {
host.Username(Configuration["Rabbit:Username"]);
host.Password(Configuration["Rabbit:Password"]);
});
conf.ReceiveEndpoint(Configuration["Rabbit:ReceiveEndpoint"], e => {
e.PrefetchCount = 16;
e.UseMessageRetry(n => n.Interval(3, 100));
#region Consumers
e.Consumer<SendCosistListToScaleConsumer>();
e.Consumer<CreateConsistListConsumer>();
#endregion
});
conf.AddSignalRHubEndpoints<NotifyHub>(provider);
}));
});
services.AddMassTransitHostedService();
#endregion
....
app.UseSignalR(endpoints =>
{
endpoints.MapHub<NotifyHub>("/notify");
});
Consumer:
public class CreateConsistListConsumer : IConsumer<ICreateConsistList>
{
IReadOnlyList<IHubProtocol> protocols = new IHubProtocol[] { new JsonHubProtocol() };
public Task Consume(ConsumeContext<ICreateConsistList> context)
{
context.Publish<All<NotifyHub>>(
new
{
Message = protocols.ToProtocolDictionary("SendMessageToAllUsers", new object[] { "CompanyId", context.Message.CompanyId })
});
return Task.CompletedTask;
}
}
Console App (SignalR Client):
hubConnection.On<Object>("SendMessageToAllUsers", param => {
Console.WriteLine(param);
});
If I understand correctly how MassTransii and SignalR work, then this code is enough to send messages to clients.
With the help of debugging, I looked that CreateConsistListConsumer is working, but clients do not receive reporting.
  At the same time, the client connects to the hub and correctly receives messages from other sources, but not from MassTransit.
What am I doing wrong?
I have been facing the same issue last week.
It seem SignalR is doing some special work with handling hubs, and couldn't make Masstransit SignalR service to work.
I ended up using a static hub reference as described here.
Basically, I am just calling Core DI to get my hub context, then store it into a static property (as in the sample in the Github issue listed above).
When needed, I call the reference from within my MassTransit Consumer, and I am done.

Can you run a asp.net core 3.0 gRPC CLIENT in IIS? (possibly on Azure?)

I've read a lot of conflicting information about this and it seems people are not 100% clear on what is possible and what is not. I am certain that you cannot host a gRPC server app in IIS due to the HTTP/2 limitations. The documentation is pretty clear. However, I want to use IIS as a reverse proxy, with the internal side communicating using gRPC. So the client would be in IIS, not the server. I assumed that since the communication at this point (i.e. the back end) was not funneled through IIS, there would be no issue with this. However, I keep seeing mixed answers.
I have created a dumb webapp that is hosted in IIS Express and can successfully post to my service running on Kestrel with gRPC.
Client code sample below. The SubmitButton is just a form post on the razor page.
public async void OnPostSubmitButton()
{
// The port number(5001) must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
Server code is the boilerplate template for gRPC but looks like this:
namespace grpcGreeter
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
// Additional configuration is required to successfully run gRPC on macOS.
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
namespace grpcGreeter
{
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
}
This works. But, because I keep seeing mixed information saying it that it won't, I am not certain that once I go to deploy the client code (i.e. the reverse proxy), if I will run into problems. I would like to use a host like Azure...but don't know if it's possible or not.
Any clarity on the subject would be greatly appreciated.
As far as I know, we could use asp.net core mvc or razor page application as the client to call the grpc server.
But gRPC client requires the service to have a trusted certificate when you hosted the application on remote server IIS.
If you don't have the permission to install the certificate, you should uses HttpClientHandler.ServerCertificateCustomValidationCallback to allow calls without a trusted certificate.
Notice: this will make the call not security.
Additional configuration is required to call insecure gRPC services with the .NET Core client. The gRPC client must set the System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport switch to true and use http in the server address.
Code as below:
AppContext.SetSwitch(
"System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var httpClientHandler = new HttpClientHandler();
// Return `true` to allow certificates that are untrusted/invalid
httpClientHandler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(httpClientHandler);
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "World" });

Resources