I have already working and simple code to get the number of users using SIGNALR. I'm new with using it.
All I need now is to get a list of online users and offline users.
here is my code
OnlineCountHub.cs
public class OnlineCountHub : Hub
{
private static int Count = 0;
public override async Task OnConnectedAsync()
{
var u = Context.User.Identity;
var result = u.IsAuthenticated ? u.Name : "";
var claims = Context.User.Claims.ToList();
foreach (var user in claims)
{
//await Groups.AddToGroupAsync(Context.ConnectionId, user.Value);
// await Groups.AddToGroupAsync("ConectedUsers-ConnectionId", "ConnectedUsers-GroupName");
// await Groups.AddToGroupAsync("UNConectedUsers-ConnectionId", "UNConnectedUsers-GroupName");
}
Count++;
await base.OnConnectedAsync();
await Clients.User("9b9ff00d-6de4-4487-9f00-99bd7f3aa345").SendAsync("updateCount", Count);
//return Task.CompletedTask;
}
public override async Task OnDisconnectedAsync(Exception exception)
{
//var claims = Context.User.Claims.ToList();
//foreach (var user in claims)
//{
// await Groups.RemoveFromGroupAsync(Context.ConnectionId, user.Value);
//}
Count--;
await base.OnDisconnectedAsync(exception);
await Clients.User("9b9ff00d-6de4-4487-9f00-99bd7f3aa345").SendAsync("updateCount", Count);
//return Task.CompletedTask;
}
}
onlinecount.js
let onlineCount = document.querySelector('span.online-count');
let updateCountCallback = function (message) {
if (!message) return;
console.log('updateCount = ' + message);
if (onlineCount) onlineCount.innerText = message;
};
function onConnectionError(error) {
if (error && error.message) console.error(error.message);
}
let countConnection = new signalR.HubConnectionBuilder().withUrl('/onlinecount').build();
countConnection.on('updateCount', updateCountCallback);
countConnection.onclose(onConnectionError);
countConnection.start()
.then(function () {
console.log('OnlineCount Connected');
})
.catch(function (error) {
console.error(error.message);
});
Don't forget
Startup.cs [ConfigureServices]
if (EnableSignalR)
services.AddSignalR();
Startup.cs [Configure]
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
if (EnableSignalR)
endpoints.MapHub<OnlineCountHub>("/onlinecount");
});
layout or index
#if (Startup.EnableSignalR)
{
<strong class="text-warning ps-3 mt-3 text-white">Online(<span class="online-count"></span>)</strong>
}
#if (Startup.EnableSignalR)
{
<script src="~/SignalR/signalRlibs/signalr.js"></script>
<script src="~/SignalR/onlinecount.js"></script>
}
Now .. how to pass to the view list of online users and list of offline users ?
I'm confused with SignalR connection, the solution working well on my computer but when hosted on the Linux server it returns some errors, SLL installed on the server.
Please anyone can guide me what is missing :(
I'm using .Net core 3.1
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddHttpClient();
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequiredLength = 2;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 0;
options.Password.RequireNonAlphanumeric = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddAuthentication();
services.AddAuthorization();
services.AddMvc();
services.AddScoped<ILoginService, LoginService>();
services.AddScoped<IAdminService, AdminService>();
services.AddScoped<ITradingService, TradingService>();
services.AddScoped<UserManager<ApplicationUser>, UserManager<ApplicationUser>>();
services.AddScoped<SignInManager<ApplicationUser>, SignInManager<ApplicationUser>>();
services.AddSignalR();
services.AddSingleton(s =>
{
using var scope = s.CreateScope();
var user = scope.ServiceProvider.GetRequiredService<IUserService>();
var config = scope.ServiceProvider.GetRequiredService<IConfiguration>();
var hub = scope.ServiceProvider.GetRequiredService<IHubContext<MessagesHub>>();
return new RedisClient(hub, config, user);
});
services.AddTransient<IUserService, UserService>();
}
..
..
[System.Obsolete]
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApplicationLifetime applicationLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
applicationLifetime.ApplicationStarted.Register(OnAppStarted);
applicationLifetime.ApplicationStopping.Register(OnAppStopping);
applicationLifetime.ApplicationStopped.Register(OnAppStopped);
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseLoggedUserMiddleware();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapHub<MessagesHub>("/messagesHub");
});
}
..
..
public class MessagesHub : Hub
{
private readonly Logger _logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
public MessagesHub(RedisClient redisClient)
{
}
public override Task OnConnectedAsync()
{
var username = Context.GetHttpContext().User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name);
if (username != null) {
_logger.Info($"{username?.Value} connected to SignalR");
}
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
var username = Context.GetHttpContext().User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name);
if (username != null)
{
_logger.Info($"{username?.Value} disconnected from SignalR");
}
if(exception != null)
{
_logger.Error(exception);
}
return base.OnDisconnectedAsync(exception);
}
}
and this is the code that connects on messageHub from js
var connection = new signalR.HubConnectionBuilder().withUrl("/messagesHub").build();
connection.on("ReceiveReflectionMessage", function (message) {
newReflection = JSON.parse(message);
handleReflection(newReflection);
});
And this for Layout view:
<script src="~/js/signalr/dist/browser/signalr.js" defer></script>
<script src="~/js/messages.js" defer></script>
At the end, no messages received on the frontend due to failed connection, so what is the missing or must add some configurations ??
using Discord.Commands;
using Discord;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using NadekoBot.Services;
using System.Threading;
using System.Collections.Generic;
using NadekoBot.Services.Database.Models;
using System.Net.Http;
using NadekoBot.Attributes;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using NLog;
using NadekoBot.Extensions;
using System.Diagnostics;
namespace NadekoBot.Modules.Searches
{
public partial class Searches
{
public class StreamStatus
{
public bool IsLive { get; set; }
public string ApiLink { get; set; }
public string Views { get; set; }
public string Game { get; set; }
public string Status { get; set;}
}
public class HitboxResponse {
public bool Success { get; set; } = true;
[JsonProperty("media_is_live")]
public string MediaIsLive { get; set; }
public bool IsLive => MediaIsLive == "1";
[JsonProperty("media_views")]
public string Views { get; set; }
}
public class TwitchResponse
{
public string Error { get; set; } = null;
public bool IsLive => Stream != null;
public StreamInfo Stream { get; set; }
public class StreamInfo
{
public int Viewers { get; set; }
public string Game { get; set; }
public ChannelInfo Channel { get; set;}
public class ChannelInfo {
public string Status { get; set; )
}
}
}
public class BeamResponse
{
public string Error { get; set; } = null;
[JsonProperty("online")]
public bool IsLive { get; set; }
public int ViewersCurrent { get; set; }
}
public class StreamNotFoundException : Exception
{
public StreamNotFoundException(string message) : base("Stream '" + message + "' not found.")
{
}
}
[Group]
public class StreamNotificationCommands : ModuleBase
{
private static Timer checkTimer { get; }
private static ConcurrentDictionary<string, StreamStatus> oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
private static ConcurrentDictionary<string, StreamStatus> cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
private static Logger _log { get; }
private static bool FirstPass { get; set; } = true;
static StreamNotificationCommands()
{
_log = LogManager.GetCurrentClassLogger();
checkTimer = new Timer(async (state) =>
{
oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>(cachedStatuses);
cachedStatuses.Clear();
IEnumerable<FollowedStream> streams;
using (var uow = DbHandler.UnitOfWork())
{
streams = uow.GuildConfigs.GetAllFollowedStreams();
}
await Task.WhenAll(streams.Select(async fs =>
{
try
{
var newStatus = await GetStreamStatus(fs).ConfigureAwait(false);
if (FirstPass)
{
return;
}
StreamStatus oldStatus;
if (oldCachedStatuses.TryGetValue(newStatus.ApiLink, out oldStatus) &&
(oldStatus.IsLive != newStatus.IsLive)
{
var server = NadekoBot.Client.GetGuild(fs.GuildId);
if (server == null)
return;
var channel = server.GetTextChannel(fs.ChannelId);
if (channel == null)
return;
try
{
var msg = await channel.EmbedAsync(fs.GetEmbed(newStatus)).ConfigureAwait(false);
}
catch { }
}
}
catch { }
}));
FirstPass = false;
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
}
private static async Task<StreamStatus> GetStreamStatus(FollowedStream stream, bool checkCache = true)
{
string response;
StreamStatus result;
switch (stream.Type)
{
case FollowedStream.FollowedStreamType.Hitbox:
var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username.ToLowerInvariant()}";
if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result))
return result;
using (var http = new HttpClient())
{
response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false);
}
var hbData = JsonConvert.DeserializeObject<HitboxResponse>(response);
if (!hbData.Success)
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
result = new StreamStatus()
{
IsLive = hbData.IsLive,
ApiLink = hitboxUrl,
Views = hbData.Views
};
cachedStatuses.AddOrUpdate(hitboxUrl, result, (key, old) => result);
return result;
case FollowedStream.FollowedStreamType.Twitch:
var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username.ToLowerInvariant())}?client_id=67w6z9i09xv2uoojdm9l0wsyph4hxo6";
if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result))
return result;
using (var http = new HttpClient())
{
response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false);
}
var twData = JsonConvert.DeserializeObject<TwitchResponse>(response);
if (twData.Error != null)
{
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
}
result = new StreamStatus()
{
IsLive = twData.IsLive,
ApiLink = twitchUrl,
Views = twData.Stream?.Viewers.ToString() ?? "0"
Game = twData.Stream?.Game,
Status = twData.Stream?.Channel?.Status
};
cachedStatuses.AddOrUpdate(twitchUrl, result, (key, old) => result);
return result;
case FollowedStream.FollowedStreamType.Beam:
var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username.ToLowerInvariant()}";
if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result))
return result;
using (var http = new HttpClient())
{
response = await http.GetStringAsync(beamUrl).ConfigureAwait(false);
}
var bmData = JsonConvert.DeserializeObject<BeamResponse>(response);
if (bmData.Error != null)
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
result = new StreamStatus()
{
IsLive = bmData.IsLive,
ApiLink = beamUrl,
Views = bmData.ViewersCurrent.ToString()
};
cachedStatuses.AddOrUpdate(beamUrl, result, (key, old) => result);
return result;
default:
break;
}
return null;
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Hitbox([Remainder] string username) =>
await TrackStream((ITextChannel)Context.Channel, username, FollowedStream.FollowedStreamType.Hitbox)
.ConfigureAwait(false);
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Twitch([Remainder] string username) =>
await TrackStream((ITextChannel)Context.Channel, username, FollowedStream.FollowedStreamType.Twitch)
.ConfigureAwait(false);
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Beam([Remainder] string username) =>
await TrackStream((ITextChannel)Context.Channel, username, FollowedStream.FollowedStreamType.Beam)
.ConfigureAwait(false);
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task ListStreams()
{
IEnumerable<FollowedStream> streams;
using (var uow = DbHandler.UnitOfWork())
{
streams = uow.GuildConfigs
.For(Context.Guild.Id,
set => set.Include(gc => gc.FollowedStreams))
.FollowedStreams;
}
if (!streams.Any())
{
await Context.Channel.SendConfirmAsync("You are not following any streams on this server.").ConfigureAwait(false);
return;
}
var text = string.Join("\n", await Task.WhenAll(streams.Select(async snc =>
{
var ch = await Context.Guild.GetTextChannelAsync(snc.ChannelId);
return $"`{snc.Username}`'s stream on **{(ch)?.Name}** channel. 【`{snc.Type.ToString()}`】";
})));
await Context.Channel.SendConfirmAsync($"You are following **{streams.Count()}** streams on this server.\n\n" + text).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task RemoveStream(FollowedStream.FollowedStreamType type, [Remainder] string username)
{
username = username.ToLowerInvariant().Trim();
var fs = new FollowedStream()
{
ChannelId = Context.Channel.Id,
Username = username,
Type = type
};
bool removed;
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(gc => gc.FollowedStreams));
removed = config.FollowedStreams.Remove(fs);
if (removed)
await uow.CompleteAsync().ConfigureAwait(false);
}
if (!removed)
{
await Context.Channel.SendErrorAsync("No such stream.").ConfigureAwait(false);
return;
}
await Context.Channel.SendConfirmAsync($"Removed `{username}`'s stream ({type}) from notifications.").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task CheckStream(FollowedStream.FollowedStreamType platform, [Remainder] string username)
{
var stream = username?.Trim();
if (string.IsNullOrWhiteSpace(stream))
return;
try
{
var streamStatus = (await GetStreamStatus(new FollowedStream
{
Username = stream,
Type = platform,
}));
if (streamStatus.IsLive)
{
await Context.Channel.SendConfirmAsync($"Streamer {username} is online with {streamStatus.Views} viewers.");
}
else
{
await Context.Channel.SendConfirmAsync($"Streamer {username} is offline.");
}
}
catch
{
await Context.Channel.SendErrorAsync("No channel found.");
}
}
private static async Task TrackStream(ITextChannel channel, string username, FollowedStream.FollowedStreamType type)
{
username = username.ToLowerInvariant().Trim();
var fs = new FollowedStream
{
GuildId = channel.Guild.Id,
ChannelId = channel.Id,
Username = username,
Type = type,
};
StreamStatus status;
try
{
status = await GetStreamStatus(fs).ConfigureAwait(false);
}
catch
{
await channel.SendErrorAsync("Stream probably doesn't exist.").ConfigureAwait(false);
return;
}
using (var uow = DbHandler.UnitOfWork())
{
uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FollowedStreams))
.FollowedStreams
.Add(fs);
await uow.CompleteAsync().ConfigureAwait(false);
}
await channel.EmbedAsync(fs.GetEmbed(status), $"🆗 I will notify this channel when status changes.").ConfigureAwait(false);
}
}
}
public static class FollowedStreamExtensions
{
public static EmbedBuilder GetEmbed(this FollowedStream fs, Searches.StreamStatus status)
{
var embed = new EmbedBuilder().WithTitle(fs.Username)
.WithUrl(fs.GetLink())
.WithThumbnailUrl(fs.GetLink())
.WithDescription(status.Status)
.AddField(efb => efb.WithName("Status")
.WithValue(status.IsLive ? "Online" : "Offline")
.WithIsInline(true))
.AddField(efb => efb.WithName("Viewers")
.WithValue(status.IsLive ? status.Views : "-")
.WithIsInline(true))
.AddField(efb => efb.WithName("Game">
.WithValue(status.Game)
.WithIsInlin(true))
.AddField(efb => efb.WithName("Platform")
.WithValue(fs.Type.ToString())
.WithIsInline(true))
.WithColor(status.IsLive ? "NadekoBot.OkColor" : "NadekoBot.ErrorColor");
return embed;
}
public static string GetLink(this FollowedStream fs) {
if (fs.Type == FollowedStream.FollowedStreamType.Hitbox)
return $"http://www.hitbox.tv/{fs.Username}/";
else if (fs.Type == FollowedStream.FollowedStreamType.Twitch)
return $"http://www.twitch.tv/{fs.Username}/";
else if (fs.Type == FollowedStream.FollowedStreamType.Beam)
return $"https://beam.pro/{fs.Username}/";
else
return "??";
}
}
}
I'm attempting to get this discord bot to announce when someone streaming on Twitch goes Live by amending its code to give me more information (ie Game and Status) but I keep getting an error that I can't for the life of me find and fix! I was told the issue is between coding on a PC and coding on a Mac? Not sure that's 100% accurate. Can someone please run this code and help me get this to work properly? Thanks!
I have problem in my site
I need push notification and I use server sent event javascript and Handler.ashx.
My NotificationHandler.ashx:
public class NotificationHandler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{
public void EndProcessRequest(IAsyncResult result)
{
}
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/event-stream";
context.Response.CacheControl = "no-cache";
var _json = new JsonStringSerializer();
var _chat = new ChatManager();
while (true)
{
var GetStorage = _chat.GetStorage();
var GetJson = _json.SerializeToString<ChatUserStorage>(GetStorage);
context.Response.Write(string.Format("data: {0}\n\n", GetJson));
context.Response.Flush();
if (context.Response.IsClientConnected == false)
{
break;
}
System.Threading.Thread.Sleep(3000);
}
}
public bool IsReusable
{
get
{
return false;
}
}
JavaScript :
function ServerSentNotification() {
sourceEventSource = new EventSource('/services/NotificationHandler.ashx', { retry: 1000 });
sourceEventSource.addEventListener("open", function (event) {
}, false);
sourceEventSource.addEventListener("error", function (event) {
if (event.eventPhase == EventSource.CLOSED) {
}
}, false);
sourceEventSource.addEventListener("message", function (event) {
UpdateProgress(event.data);
}, false);
}
All request stuck my page and another ajax poll not working request waiting.
I use web application framework 4.0
I'm trying to learn websocket. I started sending simple string between peers and everything was fine. Now I'm trying to send Object to my javascript client but the onmessage function never fires. Here is the code:
Java serverside:
#ServerEndpoint(value = "/event/{id}",
encoders={PositionJSONEncoder.class},
decoders={PositionJSONDecoder.class}
)
public class SocketManager {
private static ConcurrentHashMap<String, Session> users = new ConcurrentHashMap<String, Session>();
#OnMessage
public void onMessage(Position position, #PathParam("id") String id, Session session) {
log.info("user "+id+", "+position.toString());
try {
for(Entry<String, Session> entry : users.entrySet()) {
if(!entry.getKey().equals(position.getUserID()) && entry.getValue().isOpen()) {
entry.getValue().getBasicRemote().sendObject(position);
}
}
} catch (EncodeException ee) {
log.error(ee);
} catch (IOException ioe) {
log.error(ioe);
}
}
}
The serverendpoint encoder (I'll omit the decoder, server handle data correctly):
public class PositionJSONEncoder implements Encoder.Text<Position>{
private Gson gson = new Gson();
public void destroy() {}
public void init(EndpointConfig arg0) {}
public String encode(Position arg0) throws EncodeException {
return gson.toJson(arg0);
}
}
The relevant client side (AngularJS):
app.factory('socket', function() {
var service = {};
service.ws = {};
service.connect = function(userID) {
this.ws = new WebSocket("ws://localhost:8080/event/"+userID);
};
service.disconnect = function() {
if(this.ws != undefined && this.ws != null) {
this.ws.onclose();
}
};
service.ws.onopen = function() {
// TODO
};
service.ws.onmessage = function(msg) {
try {
alert('roba: '+JSON.parse(msg.data));
} catch(err) {
alert(err.message);
}
};
service.ws.onclose = function() {
// TODO
};
service.ws.onerror = function(evt) {
alert(evt.data);
};
return service;
});
The model the server send:
public class Position {
private String userID;
private Float lat;
private Float lng;
public Position() {}
public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public Float getLat() {
return lat;
}
public void setLat(Float lat) {
this.lat = lat;
}
public Float getLng() {
return lng;
}
public void setLng(Float lng) {
this.lng = lng;
}
#Override
public String toString() {
return userID+"["+"lat: "+lat+", "+"lng: "+lng+"]";
}
}
My pom's dependencies:
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<!-- GSON JSON serializer -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
The server gets the JSON object from the client correctly, but when it sends some Position object back the client, the onmessage function won't fire. I can see the Encoder is working as it returns strings like this:
{"userID":"bob","lat":2.0,"lng":2.0}
I see the websocket carry the messages:
but my javascript onmessage function always stay silent. I also implemented an onerror function but I can't get any feedback from it too. I'm using wildfly-8.0.0.Final.
Update: I implement a java websocket client. This client receive websocket frame sent by the server. Is my AngularJS client wrong?
I found what was wrong. In my javascript client I assigned a function to an undefined object. Here:
service.ws.onmessage = function(msg) {
try {
alert('roba: '+JSON.parse(msg.data));
} catch(err) {
alert(err.message);
}
};
service.ws.onmessage was undefined, that's why onmessage function never fire. I change my angular factory in this way:
app.factory('socket', function() {
var service = {};
service.ws = {};
service.connect = function(userID) {
this.ws = new WebSocket("ws://localhost:8080/event/"+userID);
this.ws.onmessage = function(msg) {
try {
alert('roba: '+JSON.parse(msg.data).lat+' :: '+JSON.parse(msg.data).lng);
} catch(err) {
alert(err.message);
}
};
this.ws.onerror = function(evt) {
alert('error: '+evt.data);
};
};
service.disconnect = function() {
if(this.ws != undefined && this.ws != null) {
this.ws.onclose();
}
};
return service;
});