I am using About+session Listener to control my lamp device. To receive the lampstatechange notification i have registered the signal handler for lampstatechange at announce (after introspect is success). But my application is not receiving the state change notification. Following are the code snippet i did to register lamp state signal. I am not able to understand what is happening why the callback is not receiving!
const InterfaceDescription* uniqueId = bus.GetInterface(LampServiceStateInterfaceName);
const InterfaceDescription::Member* sig = uniqueId->GetMember("LampStateChanged");
if (sig) {
QStatus sstatus = bus.RegisterSignalHandler(this, static_cast<MessageReceiver::SignalHandler>(&AJDeviceHandler::LampsStateChagedHandler), sig, "/org/allseen/LSF/Lamp");
printf("\n RegisterSignalHandler %s \n",QCC_StatusText(sstatus));
}
I have inherited the following classes of Alljoyn:
class AJDeviceHandler : public AboutListener, public SessionListener, public lsf::Thread, public PingListener, public MessageReceiver
[Note: The state change callback receives perfect when i run lighting_controller_service].
Related
I have a scenario where one of the clients is sending a request to Hub Class method AddMessage, which in turn should broadcast that message to all clients including the one who initiated it.
The problem is that I am able to call the Hub method AddMessage from the client as shown in the following code, but I couldn't find a way to handle the broadcast message on the client side which is initiated in the Hub class using the following line.
Clients.All.NotifyMessageToClients(name, message);
SignalR Hub Class
using System;
using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;
public class SignalRChatHub : Hub
{
public void AddMessage(string name, string message)
{
// Following call is supposed to notify all clients with passed parameters.
// They could have a method called NotifyMessageToClients to fetch the broadcasted message
Clients.All.NotifyMessageToClients(name, message);
}
}
SignalR Client
using System;
using Microsoft.AspNet.SignalR.Client;
public partial class Default : System.Web.UI.Page
{
HubConnection hubConnection;
IHubProxy stockTickerHubProxy;
public Default()
{
hubConnection = new HubConnection("http://localhost:6898/");
stockTickerHubProxy = hubConnection.CreateHubProxy("SignalRChatHub");
}
async public void SendAddNotification(string msgFrom, string msg)
{
// Following line calls Addmessage method in SignalRChatHub class
await stockTickerHubProxy.Invoke("Addmessage", "Ajendra", "Hello StackOverflow");
}
// I might need the method NotifyMessageToClients here... to receive broadcasted message
}
I have some idea about how to achieve the same in jQuery but not in C# by creating a client as I did above. How would I achieve this?
If the above approach doesn't make sense in any way, please suggest me the right one.
You need to listen to events from the server like this:
public partial class Default : System.Web.UI.Page
{
HubConnection hubConnection;
IHubProxy stockTickerHubProxy;
public Default()
{
hubConnection = new HubConnection("http://localhost:6898/");
stockTickerHubProxy = hubConnection.CreateHubProxy("SignalRChatHub");
// listen to server events...
// n is "name" and m is "message", but you can change to "a" and "b" or anything else...
stockTickerHubProxy.On<string, string>("NotifyMessageToClients", (n, m) =>
{
Console.WriteLine("Message received from server. Name: {0} | Message: {1}", n, m);
});
}
// "async" methods should return Task instead of void....
// unless they are event handlers for UI applications...
public async Task SendAddNotification(string msgFrom, string msg)
{
// first, start the connection...
await stockTickerHubProxy.Start();
// Following line calls Addmessage method in SignalRChatHub class
await stockTickerHubProxy.Invoke("Addmessage", "Ajendra", "Hello StackOverflow");
// you don't stop the connection, otherwise you won't be able to receive calls from the server
}
}
...if you need to update UI in WPF, for example, you should implement your event like this:
stockTickerHubProxy.On<string, string>("NotifyMessageToClients", (a,b) =>
Dispatcher.InvokeAsync(() =>
{
// update UI...
textBox.Text += string.Format("Name: {0} | Message: {1}", a, b);
})
);
I suggest reading this guide for deeper details.
I am trying to use the Caller method outside my Hub Context. I have a helper class which works fine when broadcasting a message to all users like so:
hub.Clients.All.newLessonAlert(notif);
It won't allow me to use the Caller method within this class but this works fine in the hub context class. Why is this? I have also tried to move all of my functions inside the context class but I now get this unhanded exception:
Using a Hub instance not created by the HubPipeline is unsupported
Is there a straightforward way to continue to use my helper class and identify connections to the hub?
I solved this in the following way:
I created a OnConnected method in my Hub class. This assigned the currently connected user to a group.
[HubName("NotificationsHub")]
public class NotificationHub : Hub
{
private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
public override Task OnConnected()
{
string userid = Context.Request.User.Identity.GetUserId();
Groups.Add(Context.ConnectionId, userid);
return base.OnConnected();
}
}
Modified my HubHelper class to now broadcast this alert to the currently connected user (specified by the user's ID)
public void HighScoreAlert(int gameid, int score, string userID)
{
string message = "High Score achieved on " + gameid;
hub.Clients.Group(userID).score(message);
}
For the controller action I pass in the user's ID and then call the HubHelper method featured above.
Hope this helps someone
I want to create a new system to send real time trade execution messages to users using SignalR. In the old system, each client connects to the trading server using Java Applet TCP connection.
I use the following tutorial as reference
http://www.asp.net/signalr/overview/getting-started/tutorial-server-broadcast-with-signalr
There is a line of code in the StockTicker constructor to update the stock prices:
_timer = new Timer(UpdateStockPrices, null, _updateInterval, _updateInterval);
However, I need to update trade execution in real time instead of updating stock prices per 250ms.
Is it okay to create TCP connection to my trading server per client in the constructor? It seems that in the sample code, the constructor of StockTicker (i.e. my TradingManager) will be called one time only. But in my design, I want to create a TCP connection per client. How should I change the code to do this?
Here is my code:
TradingHub.cs
public class TradingHub : Hub
{
private readonly TradingManager _tradingManager;
public TradingHub() : this(TradingManager.Instance) { }
public TradingHub(TradingManager tradingManager)
{
_tradingManager = tradingManager;
}
...
}
TradingManager.cs
public class TradingManager
{
// Singleton instance
private readonly static Lazy<TradingManager> _instance = new Lazy<TradingManager>(
() => new TradingManager());
...
public static TradingManager Instance{ get{ return _instance.Value; } }
public TradingManager()
{
...
this.apiConnector.MessageReceived += new CustomEventHandler(this.api_MessageReceived);
init();
}
private IHubConnectionContext<dynamic> Clients { get; set; }
private void init()
{
TradingSession tradingSession = getLoginSession(user);
// connect to trading server using TCP connection
this.apiConnector.ensureConnected(host, port, tradingSession);
// send keep alive message to trading server periodically
_timer = new Timer(sendKeepAlive, null, _updateInterval, _updateInterval);
}
private void api_MessageReceived(object sender, CustomEventArgs e)
{
// when web server receives trade execution from server, send out the message immediately
Clients.Caller.SendTradeExecutionMessage(......);
}
public static TradingSession getLoginSession(string user)
{
...
}
private void sendKeepAlive(object state)
{
...
}
}
If you were to make a new TradingManager in your Hub constructor instead of referencing a singleton, you would be creating more than one TradingManager per SignalR connection. Hubs are reinstantiated per method call. Every time you invoke a hub method or a hub event is called (e.g. OnConnected, OnReconnected, OnDisconnected), your constructor will be called.
However, OnConnected is only called once per SignalR connection. By the way, SignalR connections are completely orthogonal to TCP connections. With the long polling transport, for example, a new HTTP request is sent each time a message is received.
I think you want to create a new TradingManager instance each time OnConnected is called and potentially associate it with the client's Context.ConnectionId and store it (perhaps in a ConcurrentDictionary) so you can retrieve it using the connection id when your Hub methods are called. You can then dereference the stored TradingManager instance for a given connection id in OnDisconnected.
You can learn more about SignalR connections at:
http://www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events
You can learn more about the Hub API and the On* methods at:
http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-server#connectionlifetime
I'm trying to find an alternative to using REST to read Azure Service Bus Topic Subscriptions from the browser. Seems like SignalR would be a natural for this but I can't seem to find anyone that has done it. I'm not talking about scale-out, just a SignalR Hub that would relay a set of Service Bus functions back and forth to the browser. I'm thinking of functions like, addReceiver(string topic, string subscriptionID);defineSubscription(string name, string subscriptionRule);deleteSubscription(string name);postMessageToTopic(string topic, string message);addReceiver would initiate an async receive on the subscription. Each time a message came available from Service Bus, a function would be called on the JS client.
Here's some code to point people in the right direction.
namespace SBTester
{
public class SBHub : Hub
{
public void AddReceiver(string topic, string subscriptionName, string subscriptionFilter)
{
string messageData;
TopicConnector.Initialize( topic,
Context.ConnectionId + "." + subscriptionName,
subscriptionFilter);
// Initiate receive loop on Service Bus
TopicConnector.SBClient.OnMessage((receivedMessage) =>
{
try
{
// Process the message
messageData = receivedMessage.GetBody<string>();
Clients.Caller.onMessage(topic, messageData);
}
catch
{
// Handle any message processing specific exceptions here
}
});
}
public void DefineSubscription(string topic, string subscriptionRule)
{
// Call Service Bus to create Subscription on the Specified topic
}
public void PostMessageToTopic(string topic, string message)
{
// Call Service Bus to send a message
Clients.All.addNewMessageToPage(topic, message);
}
}
}
From your Hub code you could directly call the Service Bus APIs to send messages or directly use Service Bus APIs from JavaScript/Browsers: http://developers.de/blogs/damir_dobric/archive/2014/03/27/microsoft-azure-service-bus-receiving-of-messages-from-queue-and-topic-with-javascript.aspx
I want to broadcast message using SignalR from server to all clients at particular server time. This broadcast message should be automatic where all clients keep listening to server method and once we reach the scheduled time on server, server should broadcast the message.
But I don't find a way to this. I was successful by invoking from a client and broadcasting it to all clients but not automatically.
How this can be achieved.
First you need some sort of hub:
public class MyHub : Hub {}
You then can connect to this hub with clients or whatever you want to do. Then you need some type of looping class that sends to your hub (you could also do this within the hub as a static timer but we'll do this as a separate class).
public class Looper
{
public Timer Interval
public Looper(TimeSpan interval)
{
Interval = new Timer(Loop, null, TimeSpan.Zero, interval);
}
private static void Loop(object state)
{
GlobalHost.ConnectionManager.GetHubContext<ChatHub>().Clients.All.executeYourMethod();
}
}
Now we need to instantiate this class somewhere, we'll do that inside our hub as a static:
public class MyHub : Hub
{
public static Looper MyInterval = new Looper(TimeSpan.FromSeconds(1)); // Send every 1 second
}
Hope this helps!
You can just add a timer to your hub class and broadcast to each client at the required intervals.