每个 PubNub 消息使用多个 JSON 数据对象呈现 PubNub / Eon Chart LiveStream

Rendering PubNub / Eon Chart LiveStream using Multiple JSON Data Objects per Every PubNub Message

PubNub 的 Eon 图表为每个单独的 PubNub 消息查找 一个 JSON 对象数据集。请参阅 git 中心上的 Eon-Chart pubnub-c3.js。

要了解可能会收到什么样的数据,您可以查看 PubNub 的一些示例。 PubNub 传感器网络示例显示了预期的数据流格式,每条消息有一个对象:https://www.pubnub.com/developers/realtime-data-streams/sensor-network/

传入单个消息 JSON 的示例如下所示(实时数据见上文 URL):

{"timestamp":1466007459,"radiation_level":"202","humidity":"79.3726","ambient_temperature":"19.48","sensor_uuid":"probe-180ea910","photosensor":"857.83"}

当您每 100 毫秒左右发布一次数据时,这非常有效,但是当您处理更快的采样率(每 10 到 20 毫秒采样一次)时,有时形成一个对象数组然后发送多个对象更有利单个 PubNub 消息中的数据对象。

My question centers around the ability to send an Array of multiple JSON objects, inside a single PubNub message, to be parsed and then rendered by eon-charts, each JSON Array Object containing it's own data key / value pair and their own time stamp.

对于那些以前没有使用过 PubNub Eon-Chart 库的人,这里是 PubNub 建议使用上述实时数据流的示例客户端代码:

<html>
  <head>

    <script type="text/javascript" src="http://pubnub.github.io/eon/v/eon/0.0.11/eon.js"></script>
    <link type="text/css" rel="stylesheet" href="http://pubnub.github.io/eon/v/eon/0.0.11/eon.css" />

  </head>
  <body>
    <div id="chart"></div>
    <script>
    // using the example stream from 
    // http://www.pubnub.com/developers/data-streams/sensor-network
    var pubnub = PUBNUB.init({
        subscribe_key: 'sub-c-5f1b7c8e-fbee-11e3-aa40-02ee2ddab7fe',
        ssl: true
    });
    eon.chart({
        pubnub: pubnub,
        history: false,
        channel: 'pubnub-sensor-network',
        limit: 100,
        rate: 10,
        ssl: true,
        debug: true,
        generate: {
            transition: {
                duration: 3
            },
            bindto: '#chart',
            data: {
                x: 'x'
            },
            axis: {
                x: {
                    type: 'timeseries',
                    tick: {
                        format: '%H:%m:%S'
                    }
                }
            }
        },
        transform: function(m) {
            return {
                eon: {
                    'Humidy': m.humidity,
                    'Temperature': m.ambient_temperature,
                    'Light': m.photosensor
                }
            }
        }
    });
    </script>
  </body>
</html>

在上面的示例中,调用 eon.chart(使用列出的选项)使用提供的订阅密钥订阅列出的频道 ('pubnub-sensor-network')。在该 pubnub 订阅上收到新消息后,它会使用转换函数转换数据:

transform: function(m) {
            return {
                eon: {
                    'Humidy': m.humidity,
                    'Temperature': m.ambient_temperature,
                    'Light': m.photosensor
                }
            }
        }

这会将可能不是 Eon-chart 期望的任何 JSON 转换为它可以理解的格式,并在处理数据/用于更新图表之前调用它。

My feeling / guess is that the iteration code that I would like to use to loop through each JSON object (of which multiple will be contained within every PubNub message) should probably be added within the transform function which is called every time a new PubNub message is received.

pubnub-c3.js 中包含的 eon-chart 主要功能还包括检索历史记录的 pubnub 消息数组的选项(假设您为 pubnub 密钥/频道启用了历史记录)。

之所以重要,是因为启用历史选项会触发导致 PubNub 发送对象数组的功能,然后 eon-chart 客户端遍历它们以填充图表。

这几乎正是我们正在尝试做的。唯一的区别是我们正在尝试遍历每个结果PubNub 消息,而不是专门迭代历史记录的消息,然后(完成后)交换以呈现来自新传入消息的数据。

The goal is to combine the two concepts (transform function and history iteration concept).

与历史功能相关的代码(在 pubnub_c3.js 内部)如下所示:

self.pubnub.history({
          count: options.limit,
          channel: options.channel,
          end: timetoken,
          include_token: true,
          callback: function(payload) {

            var msgs = payload[0]; //data is here
            var start = payload[1]; 
            var end = payload[2];

            clog('History:', msgs.length + ' messages found');

            clog('History:', 'Complete... Rendering');

            i = 0;
            while (i < msgs.length) {

              var a = msgs[i];
              a.message = options.transform(a.message);

              if(a.message && a.message.eon) {
                a = appendDate(a.message.eon, a.timetoken);
                storeData(a, true); 
              } else {
                clog('Rejecting history message as improper format supplied.');
              }

              i++;

            }

            if (msgs.length > 1 && object.json.length < options.limit - 1) {
              page(end);
            } else {
              loadData(object);
              done();
            }

所以。有了所有这些背景(抱歉!)我将这个问题视为两个问题:

  1. 传出 PubNub JSON 数据的正确格式。
  2. 在当前 pubnub_c3.js 函数中正确放置解析/迭代代码。

For the purposes of answering this question I have created an instance on hyperdev.space which you can access over here (has all of my code built out): https://hyperdev.com/#!/project/coal-weaver

我的转换代码目前如下所示:

transform : function(data) { //I believe any code to itterate through data will happen here
      jsonTimeStampTest.innerText = data[0].vibeTimeStamp; //we properly get the time stamp
      jsonTimeStampTest.innerText = data[0].vibeValue; //we properly get the reading: 12
      jsonLength.innerText = data.length;  //we properly get 10

        var z = 0;
        for(z=0; z<10; z++)
          {
          return { columns : [
              ['x', data[z].vibeTimeStamp,
              'Value', data[z].vibeValue]
            ]};
          }
    }

...但我最终在控制台中遇到错误: eon.js:8015 Eon 消息必须采用正确的格式。例如: 对象 {eon: Array[3]} eon:Array[3]

尝试了许多不同的变体,但似乎无法获得转换代码以正确地将值添加到 eon-chart。在此希望大家能有所帮助。

每个有效载荷多个点

每个负载可以发布多个绘图点。不要使用对象名称 eon,而是使用名称 eons 并提供一个 Array。因为您使用 eons 属性 名称,库将知道遍历数组并绘制每个点。

请注意,如果每个负载发布多个点,您必须使用 x_type: "custom" 并提供 x_id

eons: [
  {
    x: new Date().getTime(),
    value: 1
  },
  {
    x: new Date().getTime(),
    value: 2
  }
] 

这是一个以 100 毫秒为增量收集的数据示例,但每 1,000 毫秒才发布一次。每个有效负载包括 10 个点,分辨率为 100 毫秒。 See a full example here.

setInterval(function(){

  var data = [];
  var date = new Date().getTime();

  for(var i = 0; i < 10; i++) {
      data.push({
          'pub_time': date + (100 * i),
          'Austin': Math.floor(Math.random() * 99)
      });
  }

  pubnub.publish({
    channel: channel,
    message: {
      eons: data
    }
  });

}, 1000);