Atmosphere #Disconnect does not get called when we close browser window - atmosphere

Using the chat example, when I close the browser window, I do not ever see the #Disconnect method called.
Here is my service:-
package org.atmosphere.samples.chat;
import java.io.IOException;
import org.atmosphere.config.service.Disconnect;
import org.atmosphere.config.service.ManagedService;
import org.atmosphere.config.service.Ready;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#ManagedService(path = "{room: [a-zA-Z][a-zA-Z_0-9]*}")
public class Chat
{
private static final Logger LOGGER = LoggerFactory.getLogger(Chat.class);
#Ready
public void onReady(final AtmosphereResource inAtmosphereResource)
{
LOGGER.info("Browser {} connected.", inAtmosphereResource.uuid());
}
#Disconnect
public void onDisconnect(AtmosphereResourceEvent event)
{
if (event.isCancelled())
{
LOGGER.info("Browser {} unexpectedly disconnected", event.getResource().uuid());
}
else if (event.isClosedByClient())
{
LOGGER.info("Browser {} closed the connection", event.getResource().uuid());
}
else
{
LOGGER.info("close event was called, but I know not why");
}
}
#org.atmosphere.config.service.Message(encoders = { JacksonEncoder.class }, decoders = { JacksonDecoder.class })
public Message onMessage(Message message) throws IOException
{
LOGGER.info("{} just send {}", message.getAuthor(), message.getMessage());
return message;
}
}
Here is my JS:-
$(function () {
"use strict";
var header = $('#header');
var content = $('#content');
var input = $('#input');
var status = $('#status');
console.log(document.location.hash);
var bookingNumber = document.location.hash.substring(1, document.location.hash.length);
console.log(bookingNumber);
var myName = false;
var author = null;
var logged = false;
var socket = $.atmosphere;
var subSocket;
var transport = 'websocket';
// We are now ready to cut the request
var request = { url: document.location.toString().replace(/#.*/, "") + 'chat/' + bookingNumber,
contentType : "application/json",
trackMessageLength : true,
shared : true,
logLevel : "debug",
transport : transport ,
fallbackTransport: 'long-polling'};
request.onOpen = function(response) {
content.html($('>p<', { text: 'Atmosphere connected using ' + response.transport }));
input.removeAttr('disabled').focus();
status.text('Choose name:');
transport = response.transport;
if (response.transport == "local") {
subSocket.pushLocal("Name?");
}
};
request.onTransportFailure = function(errorMsg, request) {
jQuery.atmosphere.info(errorMsg);
if (window.EventSource) {
request.fallbackTransport = "sse";
transport = "see";
}
header.html($('<h3>', { text: 'Atmosphere Chat. Default transport is WebSocket, fallback is ' + request.fallbackTransport }));
};
request.onMessage = function (response) {
// We need to be logged first.
if (!myName) return;
var message = response.responseBody;
try {
var json = jQuery.parseJSON(message);
} catch (e) {
console.log('This doesn\'t look like a valid JSON: ', message.data);
return;
}
if (!logged) {
logged = true;
status.text(myName + ': ').css('color', 'blue');
input.removeAttr('disabled').focus();
subSocket.pushLocal(myName);
} else {
input.removeAttr('disabled');
var me = json.author == author;
var date = typeof(json.time) == 'string' ? parseInt(json.time) : json.time;
addMessage(json.author, json.message, me ? 'blue' : 'black', new Date(date));
}
};
request.onClose = function(response) {
logged = false;
}
subSocket = socket.subscribe(request);
input.keydown(function(e) {
if (e.keyCode === 13) {
var msg = $(this).val();
if (author == null) {
author = msg;
}
subSocket.push(jQuery.stringifyJSON({ author: author, message: msg }));
$(this).val('');
input.attr('disabled', 'disabled');
if (myName === false) {
myName = msg;
}
}
});
function addMessage(author, message, color, datetime) {
content.append('<p><span style="color:' + color + '">' + author + '</span> # ' +
+ (datetime.getHours() < 10 ? '0' + datetime.getHours() : datetime.getHours()) + ':'
+ (datetime.getMinutes() < 10 ? '0' + datetime.getMinutes() : datetime.getMinutes())
+ ': ' + message + '</p>');
}
});
I am running on glassfish 3, with web sockets and comet enabled.
UPDATE I forgot to mention that I am using v 2.1.0RC1

tested with GF 3.1.2.2:
Blockquote
[#|2013-12-02T10:43:24.743-0500|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=25;_ThreadName=http-thread-pool-8080(4);|10:43:24.743 [http-thread-pool-8080(4)] INFO org.atmosphere.samples.chat.Chat - Browser 0f7f5596-bd25-4dda-a488-1357da8487f5 closed the connection
Let's havce the discussion on the Atmosphere ML in case you are still experiencing issue. I've tested with the sample BTW.
-- Jeanfrancois

Related

Not being able to send message into chatroom using npm ws package

I'm using npm ws package for websocket. I'm not being able send message into chatroom. any idea how to do it. Below is my code with sendMessage() and broadcast()
const sendMessage = (room_name, message, socket) => {
// rooms[room_name].message = JSON.stringify(message);
const obj = rooms[room_name];
for(i=0;i<obj.length;i++){
var temp = obj[i];
for(var innerObject in temp){
var wsClientID = temp[innerObject];
if(socket!==wsClientID){
wsClientID.send(JSON.stringify({
'message':message,
}));
}
}
}
// rooms[room_name].message = message;
socket.send(JSON.stringify(message));
// rooms[room_name].message = message;
}
socket.on("message", async (data) => {
broadcast(data)}
function broadcast(data) {
var count = 0;
for (const client of server.clients) {
if (client.readyState === socket.OPEN) {
count++;
client.send(data.toString())
}
}
}

upload image using file transfer ionic 3 not work on iOS

upload image using file transfer in ionic 3 works fine on android,
but give me error on iOS when try it in simulator ..
* this is the error:
My Ionic Code:
chooseImageFromGallery()
{
this.type="0"
const options: CameraOptions = {
quality: 60,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
saveToPhotoAlbum:true,
sourceType:0
}
this.camera.getPicture(options)
.then((imageData) => {
if (this.platform.is('ios'))
{
this.base64Image = imageData;
}
else
{
this.base64Image = imageData;
}
this.uploadimage(); // this function to upload img to server
},
(err) => {
}).then((path)=>{
})
}
uploadimage(){
this.photoSrc="";
this.translate.get("uploading Image...").subscribe(
value => {
this.sucesss=false
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: "file",
fileName:'test',
chunkedMode:false,
mimeType:"image/jpeg",
headers:{
Connection:"close"
},
httpMethod: "POST",
}
//------------ android ------------//
this.base64Image =this.base64Image
//------------ ios ------------//
//this.base64Image =this.base64Image.substring(28)
fileTransfer.upload(this.base64Image,encodeURI('mydomain/api/Product/upload'), options)
.then((data:any) => {
alert("upload success ")
}, (err) => {
this.translate.get( "error in upload Data").subscribe(
value => {
this.service.presentToast(value,2000)
}
)
})
})
}
using asp.net api2 .. My server Code :
[HttpPost]
[Route("upload")]
[AllowAnonymous]
public HttpResponseMessage uploadImage()
{
var request = HttpContext.Current.Request;
if (Request.Content.IsMimeMultipartContent())
{
foreach (string file in request.Files)
{
var postedFile = request.Files[file];
if (postedFile != null && postedFile.ContentLength > 0)
{
string root = HttpContext.Current.Server.MapPath("~/ServerImg");
root = root + "/" + postedFile.FileName;
postedFile.SaveAs(root);
//Save post to DB
return Request.CreateResponse(HttpStatusCode.Found, new
{
error = false,
status = "created",
path = root
});
}
else
{
return Request.CreateResponse(HttpStatusCode.NotFound, new
{
error = true
});
}
// var title = request.Params["title"];
}
// }
return null;
}
else
{
return Request.CreateResponse(HttpStatusCode.Forbidden, new
{
error = true
});
}
}
I spend more than 4 days.. but nothing is work for me ..
And this code works fine on Android but not iOS I don't know what's the wrong, I tried real iPhone and Xcode simulator and not worked
always upload error {"code":3... "http_status":500,..
Can anyone Help me please...

SignalR causing bad request 400 seen on the server

We are having an issue with signalR. We have an auction site that runs on signalr for real time bidding. We fixed some issues with the browser and everything seemed to be working well. Then we installed new relic on our server and noticed that every minute we are getting http error code 400 on signalr connect, reconnect and abort. Here's a screenshot:
SignalR connect and reconnect are the most time consuming operations of the site according to new relic.
Here is SignalR backend code (We use sql server as signalr backplane):
public class SignalRHub : Hub
{
public void BroadCastMessage(String msg)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<SignalRHub>();
hubContext.Clients.All.receiveMessage(msg);
}
}
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
string appString=string.Empty;
//Gets the connection string.
if (System.Configuration.ConfigurationSettings.AppSettings["SignaRScaleoutConn"] != null)
{
appString = System.Configuration.ConfigurationSettings.AppSettings["SignaRScaleoutConn"].ToString();
}
GlobalHost.DependencyResolver.UseSqlServer(appString);
GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromMinutes(15); //I added this timeout, but it is not required.
app.MapSignalR();
}
}
The javascript client looks like this, it's lengthy, but most of it is jQuery to affect the DOM, I include it all in case something may be wrong inside it.
$(function () {
var chatProxy = $.connection.signalRHub;
$.connection.hub.start();
chatProxy.client.receiveMessage = function (msg) {
var all = $(".soon").map(function () {
var hiddenModelId = $("#hiddenListingId");
if (msg == hiddenModelId.val()) {
$.ajax({
async: "true",
url: "/Listing/AuctionRemainingTime",
type: "POST",
dataType: 'json',
data: '{ "listingID": "' + msg + '"}',
contentType: "application/json; charset=utf-8",
success: function (data) {
if (data != null) {
SoonSettings.HasReloadedThisTick = false;
var element = document.getElementById(msg);
var obj = JSON.parse(data)
// For Clock Counter End Date Time Interval
// Adds 2 minutes to the soon clock when bid is close to finishing.
var hdID = "hdn" + obj.ListingId;
var hdValue = $("#" + hdID);
if (obj.EndDate != hdValue.val()) {
SoonSettings.HasUpdated = false; //Allows clock to change color once it gets under two minutes.
$('#' + hdID).val(obj.EndDate);
Soon.destroy(element);
Soon.create(element, { //Recreates clock with the before 2 minute tick event.
'due': 'in ' + obj.Seconds + ' seconds',
'layout':'group label-uppercase',
'visual':'ring cap-round progressgradient-00fff6_075fff ring-width-custom gap-0',
'face':'text',
'eventTick': 'tick'
});
}
var highbid = obj.HighBidderURL;
// For Date Ends Info.
var ListingEndDate = $("#tdAuctionListingEndDate");
if (obj.EndDate != ListingEndDate.val()) {
$('#' + hdID).val(obj.EndDate);
ListingEndDate.text(obj.EndDate + " Eastern");
ListingEndDate.effect("pulsate", { times: 5 }, 5000);
}
else
{
$(".Bidding_Current_Price").stop(true, true); ///Removes the pulsating effect.
$(".Bidding_Current_Price").removeAttr("style"); //Removes unnecessary attribute from HTML.
}
//Bid div notification.
if (obj.AcceptedActionCount.replace(/[^:]+:*/, "") > 0) {
if (obj.Disposition != '' && obj.Disposition != null) {
if (obj.Disposition == "Neutral") {
$("#spanNeutralBid").show();
$("#divOutbidNotification").hide();
$("#spanPositiveBid").hide();
$("#divProxyBidNotification").hide();
}
else if (obj.Disposition == "Positive") {
$("#spanPositiveBid").show();
$("#divOutbidNotification").hide();
$("#spanNeutralBid").hide();
$("#divProxyBidNotification").hide();
}
else if (obj.Disposition == "Negative") {
$("#divOutbidNotification").show();
$("#spanNeutralBid").hide();
$("#spanPositiveBid").hide();
$("#divProxyBidNotification").hide();
}
else {
$("#divOutbidNotification").hide();
$("#spanNeutralBid").hide();
$("#divProxyBidNotification").hide();
$("#spanPositiveBid").hide();
}
}
}
// For Highlight Current Price when it is Updated
var hdCurrentPrice = $("#hdnCurrentPrice");
if (obj.CurrentPrice != hdCurrentPrice.val()) {
$(".Bidding_Current_Price").text(obj.CurrentPrice);
$(".Bidding_Current_Price").effect("pulsate", { times: 5 }, 5000);
$("#hdnCurrentPrice").val(obj.CurrentPrice);
}
else {
$(".Bidding_Current_Price").stop(true, true);
$(".Bidding_Current_Price").removeAttr("style");
}
// For ReservePrice Status
$("#spanReservePriceStatus").html(obj.ReservePriceStatus);
$("#smallReservePriceStatus").html(obj.ReservePriceStatus);
// For Bid Count
var spanBidCounter = $("#spanBidCount");
$(spanBidCounter).text(obj.AcceptedActionCount);
var stringAppend = "<tr id='trhHighBidder'><td><strong>HighBidder</strong></td>";
stringAppend += "<td>";
if (obj.isAdmin == true) {
stringAppend += "<a id='anchorHighBid' href=" + obj.HighBidderURL + ">";
stringAppend += "<span id='spanHighBidder'>" + obj.CurrentListingActionUserName + "</span>"
stringAppend += "</a>";
}
else {
stringAppend += "<span id='spanHighBidderAnonymous'>" + obj.CurrentListingActionUserName + "</span>";
}
stringAppend += "</td></tr>";
if (obj.AcceptedActionCount.replace(/[^:]+:*/, "") > 0) {
if ($("#tblAuctionDetail").find("#rowHighBidder").length > 0) {
if ($("#tblAuctionDetail").find("#trhHighBidder").length > 0) {
$("#trhHighBidder").remove();
}
}
else {
//add tr to table
if (!$("#tblAuctionDetail").find("#trhHighBidder").length > 0) {
$('#tblAuctionDetail > tbody > tr:eq(6)').after(stringAppend);
}
}
}
// For High Bidder
if (obj.isAdmin) {
var anchorElement = $("#anchorHighBid");
$(anchorElement).attr("href", obj.HighBidderURL);
var spanHighBidder = $("#spanHighBidder");
$(spanHighBidder).text(obj.CurrentListingActionUserName);
}
else {
var spanAdminHighBid = $("#spanHighBidderAnonymous");
$(spanAdminHighBid).text(obj.CurrentListingActionUserName)
}
}
},
error: function (xhr, textStatus, errorThrown) {
}
});
}
});
};
});
Is there anything wrong with the client or the server signalr code that may need to be changed to avoid these errors happening so often? The 400 code has the tendency of showing up almost every minute. I am very new to signalR and know very little of how to make effective code with it.
The real time bidding in the site does work, it's just to find a way to avoid these constant errors. Any help explaining anything of how signalR works is appreciated.
Thanks,
I'd give a try changing the transportation method of SignalR: http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#transport
and check if problem persists.
If possible to get UserAgent from Bad Request log, try to narrow down which browsers get 400 error. I think, maybe, some browsers are not connecting with correct transport method.

Dealing with EventEmitter events in Meteor?

I am trying to use an Asterisk Manager NPM module in Meteor, but am having difficulties with processing emitted events.
This NPM module establishes a permanent connection to Asterisk Manager and emits whatever Events it receives from Asterisk. I've managed to patch the code so that it runs in Meteor. It connects to Asterisk, emits events and I can log them to console, but once I try to do something with the data, like insert it into a collection, I receive the following error:
Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
How do I overcome that? Thank you.
server side code:
var ami = new AsteriskManager( { username: 'meteor', password: '123456' } );
ami.on('ami_data', function(data){
console.log(data); // <- this works fine
// the following causes the error
EventsLog.insert({ timestamp: (new Date()).getTime(),
data: data});
});
ami.connect(function(){});//creates a socket connection and sends the login action
the patched npm module code:
var util = Npm.require('util');
var events = Npm.require('events').EventEmitter;
var net = Npm.require('net');
var AsteriskConstructor = function AsteriskManager(params){
params = params || {};
this.net = net;
this.CRLF = "\r\n";
this.END = "\r\n\r\n";
this.buffer = "";
this.port = params.port || 5038;
this.host = params.host || 'localhost';
this.username = params.username || 'username';
this.password = params.password || 'password';
this.enable_debug = params.debug || false;
this.reconnect = params.reconnect || false;
this.reconnect_after = params.reconnect_after || 3000;
this.events = (params.events != undefined ? params.events : true);
this.identifier = params.identifier || false;
this.ami_encoding = params.ami_encoding || 'ascii';
};
AsteriskManager = AsteriskConstructor;
util.inherits(AsteriskManager, events);
AsteriskManager.prototype.connect = function(connect_cb, data_cb){
var self = this;
self.debug('running ami connect');
self.socket = null;
self.socket = this.net.createConnection(this.port, this.host);//reopen it
self.socket.setEncoding(this.ami_encoding);
self.socket.setKeepAlive(true, 500);
self.socket.on('connect', function(){
self.debug('connected to Asterisk AMI');
//login to the manager interface
self.send({Action: 'login', Username : self.username, Secret : self.password, Events: (self.events ? 'on' : 'off')});
if(connect_cb && typeof connect_cb == 'function'){
connect_cb();
}
}).on('data', function(data){
if(data_cb && typeof data_cb == 'function'){
data_cb(data);
}
var all_events = self.processData(data);
for(var i in all_events){
var result = all_events[i];
if(result.response && result.message && /Authentication/gi.exec(result.message) == 'Authentication'){
self.emit('ami_login', ((result.response == 'Success') ? true : false) ,result);
}
self.emit('ami_data', result);
}
}).on('drain', function(){
self.debug('Asterisk Socket connection drained');
self.emit('ami_socket_drain');
}).on('error', function(error){
if(error){
self.debug('Asterisk Socket connection error, error was: ' + error);//prob lost connection to ami due to asterisk restarting so restart the connection
}
self.emit('ami_socket_error', error);
}).on('timeout',function(){
self.debug('Asterisk Socket connection has timed out');
self.emit('ami_socket_timeout');
}).on('end', function() {
self.debug('Asterisk Socket connection ran end event');
self.emit('ami_socket_end');
}).on('close', function(had_error){
self.debug('Asterisk Socket connection closed, error status - ' + had_error);
self.emit('ami_socket_close', had_error);
if(self.reconnect){
self.debug('Reconnecting to AMI in ' + self.reconnect_after);
setTimeout(function() {
self.connect(connect_cb, data_cb);
}, self.reconnect_after);
}
});
}
AsteriskManager.prototype.disconnect = function(){
this.reconnect = false;//just in case we wanted it to reconnect before, we've asked for it to be closed this time so make sure it doesnt reconnect
this.socket.end(this.generateSocketData({Action: 'Logoff'}));
}
AsteriskManager.prototype.destroy = function(){
this.socket.destroy();
}
AsteriskManager.prototype.processData = function(data, cb){
/*
Thanks to mscdex for this bit of code that takes many lots of data and sorts them out into one if needed!
https://github.com/mscdex/node-asterisk/blob/master/asterisk.js
*/
data = data.toString();
if (data.substr(0, 21) == "Asterisk Call Manager"){
data = data.substr(data.indexOf(this.CRLF)+2); // skip the server greeting when first connecting
}
this.buffer += data;
var iDelim, info, headers, kv, type, all_events = [];
while ((iDelim = this.buffer.indexOf(this.END)) > -1) {
info = this.buffer.substring(0, iDelim+2).split(this.CRLF);
this.buffer = this.buffer.substr(iDelim + 4);
result = {}; type = ""; kv = [];
for (var i=0,len=info.length; i<len; i++) {
if (info[i].indexOf(": ") == -1){
continue;
}
kv = info[i].split(": ", 2);
kv[0] = kv[0].toLowerCase().replace("-", "");
if (i==0){
type = kv[0];
}
result[kv[0]] = kv[1];
}
if(this.identifier){
result.identifier = this.identifier;
}
all_events.push(result);
}
return all_events;
}
AsteriskManager.prototype.debug = function(data){
if(this.enable_debug){
console.log(data);
}
}
AsteriskManager.prototype.generateRandom = function(){
return Math.floor(Math.random()*100000000000000000);
}
AsteriskManager.prototype.generateSocketData = function(obj){
var str = '';
for(var i in obj){
str += (i + ': ' + obj[i] + this.CRLF);
}
return str + this.CRLF;
}
AsteriskManager.prototype.send = function(obj, cb) {
//check state of connection here, if not up then bail out
if(!obj.ActionID){
obj.ActionID = this.generateRandom();
}
//maybe i should be checking if this socket is writeable
if(this.socket != null && this.socket.writable){
this.debug(obj);
this.socket.write(this.generateSocketData(obj), this.ami_encoding, cb);
}else{
this.debug('cannot write to Asterisk Socket');
this.emit('ami_socket_unwritable');
}
}
As the error message says "Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment"
ami.on('ami_data', Meteor.bindEnvironment( function(data){
console.log(data); // <- this works fine
// the following causes the error
EventsLog.insert({ timestamp: (new Date()).getTime(),
data: data});
}, function( error) { console.log( error);})
);
There are a lot of other examples around.
If the server code above is not in a Fiber you might get "Meteor code must always run within a Fiber" error.

Real time data and retrieval plotting

So my question is as follows: I'm working on a mobile application that takes data from a vital sign sensor and sends to a telehealth server, so that a physician is able to retrieve the data from the server in real time as a plotted curve.
As I have a very weak background on this, my question is of two parts: a) how do I retrieve the data from the server in real time and b) can I use HTML5 libs or anything similar like HighCharts or Meteor charts or ZingCharts to have them plotted or is it impossible? Please be very specific as again I have a weak background on this :)
In ZingChart, you can do this in two ways:
Method 1 - Via Websockets - EX: http://www.zingchart.com/dataweek/presentation/feed.html
The websocket transport is part of the refresh/feed section, its attribute can be found here: Graph >> Refresh section of the ZingChart JSON docs. In addition, a server socket component is required and it has to follow some standard protocol in order to allow connectivity and transport with the client socket.
To get specific:
###############################
# NodeJS code
###############################
#!/usr/bin/env node
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
response.writeHead(404);
response.end();
});
server.listen(8888, function() {
console.log((new Date()) + ' Server is listening on port 8888');
});
wsServer = new WebSocketServer({
httpServer: server,
autoAcceptConnections: false
});
function originIsAllowed(origin) {
return true;
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var type = '',
method = '',
status = 0;
var connection = request.accept('zingchart', request.origin);
connection.on('message', function(message) {
function startFeed() {
console.log('start feed');
status = 1;
if (method == 'push') {
sendFeedData();
}
}
function stopFeed() {
console.log('stop feed');
status = 0;
}
function sendFeedData() {
if (method == 'push') {
var ts = (new Date()).getTime();
var data = {
"scale-x": ts,
"plot0": [ts, parseInt(10 + 100 * Math.random(), 10)]
};
console.log('sending feed data (push)');
connection.sendUTF(JSON.stringify(data));
if (status == 1) {
iFeedTick = setTimeout(sendFeedData, 500);
}
} else if (method == 'pull') {
var data = [];
var ts = (new Date()).getTime();
for (var i = -5; i <= 0; i++) {
data.push({
"scale-x": ts + i * 500,
"plot0": [ts + i * 500, parseInt(10 + 100 * Math.random(), 10)]
});
}
console.log('sending feed data (pull)');
connection.sendUTF(JSON.stringify(data));
}
}
function sendFullData() {
var data = {
type: "bar",
series: [{
values: [
[(new Date()).getTime(), parseInt(10 + 100 * Math.random(), 10)]
]
}]
};
console.log('sending full data');
connection.sendUTF(JSON.stringify(data));
if (status == 1) {
if (method == 'push') {
setTimeout(sendFullData, 2000);
}
}
}
if (message.type === 'utf8') {
console.log('************************ ' + message.utf8Data);
switch (message.utf8Data) {
case 'zingchart.full':
type = 'full';
break;
case 'zingchart.feed':
type = 'feed';
break;
case 'zingchart.push':
method = 'push';
break;
case 'zingchart.pull':
method = 'pull';
break;
case 'zingchart.startfeed':
startFeed();
break;
case 'zingchart.stopfeed':
stopFeed();
break;
case 'zingchart.getdata':
status = 1;
if (type == 'full') {
sendFullData();
} else if (type == 'feed') {
sendFeedData();
}
break;
}
}
});
connection.on('close', function(reasonCode, description) {
status = 0;
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
###############################################
# Sample JSON settings for socket transport
###############################################
refresh: {
type: "feed",
transport: "websockets",
url: "ws://198.101.197.138:8888/",
method: "push",
maxTicks: 120,
resetTimeout: 2400
}
or
refresh: {
type: "feed",
transport: "websockets",
url: "ws://198.101.197.138:8888/",
method: "pull",
interval: 3000,
maxTicks: 120,
resetTimeout: 2400
}
Method 2 - Via API - EX: http://www.zingchart.com/dataweek/presentation/api.html
In the case you described, this would involve setting intervals of time at which you would like to retrieve data from your server, and then pass that data via the API. Check out the "Feed" section in API-Methods section of the ZingChart docs.

Resources