Now I have the following solution. Can someone maybe check my code if this is a common way or will I get some trouble with it?
First I created a hub class "MyHub.cs"
Do I have to use lazy initialization?
Is the OnReconnected section ok?
[HubName("data")]
public class DataHub : Hub
{
List<LineUser> userList = new List<LineUser>();
public static ConcurrentDictionary<string, LineUser> MyUsers = new ConcurrentDictionary<string, LineUser>();
public override Task OnConnected()
{
var context = GlobalHost.ConnectionManager.GetHubContext<DataHub>();
string userConnectionID = Context.ConnectionId;
MyUsers.TryAdd(Context.ConnectionId, new LineUser() { ConnectionID = Context.ConnectionId });
return base.OnConnected();
}
public override Task OnReconnected()
{
var context = GlobalHost.ConnectionManager.GetHubContext<DataHub>();
string userConnectionID = Context.ConnectionId;
if (MyUsers.TryAdd(Context.ConnectionId, new LineUser() { ConnectionID = Context.ConnectionId }))
_userCount++;
var resconnectedUser = new LineUser();
MyUsers.TryGetValue(userConnectionID, out resconnectedUser);
Groups.Add(userConnectionID, resconnectedUser.LineNr.ToString());
return base.OnReconnected();
}
public override Task OnDisconnected(bool stopCalled)
{
var context = GlobalHost.ConnectionManager.GetHubContext<DataHub>();
string userConnectionID = Context.ConnectionId;
LineUser garbage;
var disconnectedUser = new LineUser();
MyUsers.TryGetValue(userConnectionID, out disconnectedUser);
Groups.Remove(userConnectionID, disconnectedUser.LineNr.ToString());
MyUsers.TryRemove(userConnectionID, out garbage);
return base.OnDisconnected(stopCalled);
}
[HubMethodName("registerName")]
public void RegisterConId(int LineNr, string userConnectionID)
{
var oldUser = new LineUser();
var newUser = new LineUser();
newUser.LineNr = LineNr;
newUser.ConnectionID = userConnectionID;
newUser.Connected = true;
MyUsers.TryGetValue(userConnectionID, out oldUser);
MyUsers.TryUpdate(userConnectionID, newUser, oldUser);
Groups.Add(userConnectionID, LineNr.ToString());
}
}
Then I have created an backgoundjob with Quartz.net "BackGroundJob.cs"
(This one will be triggered every second from class JobScheduler after application start).
If new sensor data are available, I send the sensor data to a specific group(the group name will be created after the client calls the HubMethodName "registerName".
Because sensor nr. 6 data should only send to client nr. 6 (all clients with nr. 6 are in group "6")
public class BackGroundJob : IJob
{
//Global variable to save the result between to background job executions
SensorData oldsensorData = new SensorData();
public Task Execute(IJobExecutionContext context)
{
var newSensorData = ReadSensorData();
if (!newSensorData.Equals(oldsensorData))
{
IHubContext hub = GlobalHost.ConnectionManager.GetHubContext<DataHub>();
result = hub.Clients.Group(newSensorData.LineNr.ToString()).announceToLine("Sensor data for Line: " + newSensorData.LineNr.ToString() + " Temp: " + newSensorData.Temp.ToString());
//Save new data to global object
oldsensorData = newSensorData;
}
throw new NotImplementedException();
}
private SensorData ReadSensorData()
{
SensorData newSensorData = new SensorData();
//Code block to read sensor data from external device and save it to "newSensorData" object
return newSensorData;
}
}
And my client view looks like this:
1. LineData.cshtml
@{
ViewBag.Title = "Line Data";
}
<h1>Linie: @ViewBag.LineNr</h1>
<h2>Temperature</h2>
<div id="sensorData"></div>
@section scripts{
<script>
var LineNr = parseInt(@ViewBag.LineNr);
</script>
<script src="~/signalr/js"></script>
<script src="~/Scripts/my/SignalR.js"></script>
}
and 2. my SignalR.js
(function () {
var myHub = $.connection.data;
// start hub connection
$.connection.hub.start()
.done(function () {
//Register line number for group name
myHub.server.registerName(LineNr, $.connection.hub.id);
})
.fail(function () {
alert("SignalR Error for Line " + LineNr + " !");
});
// try reconnect after 5s
$.connection.hub.disconnected(function () {
setTimeout(function () {
$.connection.hub.start();
}, 5000); // Restart connection after 5 seconds.
});
// Clients functions
myHub.client.announceToLine = function (data) {
$("#sensorData").html(data);
}
})()