title: How to plot real time line chart for mqtt data without having to refresh the chart
body: <p>I tried to fetch streaming data from mosquito test server for creating a real time line chart. I checked some examples of real time chart, but I couldn't seem to achieve the same objective. The chart is updated real time but it always refreshes.</p>
  
  <p>Here is the script I edited from one example:</p>
  
  <pre><code>library(shiny)
  library(magrittr)
  library(mqtt)
  library(jsonlite)
  ui &lt;- shinyServer(fluidPage(
  plotOutput("plot")
  ))
  server &lt;- shinyServer(function(input, output, session){
  myData &lt;- data.frame()
  # Function to get new observations
  get_new_data &lt;- function(){
  d &lt;- character()
  mqtt::topic_subscribe(host = "test.mosquitto.org", port = 1883L, client_id       = "dcR", topic = "IoTDemoData", 
                        message_callback = 
                          function(id, topic, payload, qos, retain) {
                              if (topic == "IoTDemoData") {
  
                                d &lt;&lt;- readBin(payload, "character")
                                # print(received_payload)
                                # received_payload &lt;- fromJSON(received_payload)
                                # print(d)                                  
                                return("quit")
                              }
                            }
                          )
  
  d &lt;- fromJSON(d)
  d &lt;- as.data.frame(d)
  return(d)
  # data &lt;- rnorm(5) %&gt;% rbind %&gt;% data.frame
  # return(data)
  }
  
  # Initialize my_data
  myData &lt;- get_new_data()
  
  # Function to update my_data
  update_data &lt;- function(){
  myData &lt;&lt;- rbind(get_new_data(), myData)
  }
  
  # Plot the 30 most recent values
  output$plot &lt;- renderPlot({
  invalidateLater(1000, session)
  update_data()
  print(myData)
  plot(temperature ~ 1, data=myData[1:30,], ylim=c(-20, -10), las=1, type="l")
  })
  })
  
  shinyApp(ui=ui,server=server)
  </code></pre>
  
  <p>I have been struggling with creating real time chart for days. If anyone can point out the problem why the line chart is always refreshed and the solution, it will be highly appreciated!</p>
  
  <p>Below are the revised working script based on Florian's answer:</p>
  
  <pre><code>library(shiny)
  library(mqtt)
  library(jsonlite)
  library(ggplot2)
  
  
  ui &lt;- shinyServer(fluidPage(
  plotOutput("mqttData")
  ))
  
  server &lt;- shinyServer(function(input, output, session){
  myData &lt;- reactiveVal()
  get_new_data &lt;- function(){
  d &lt;- character()
  mqtt::topic_subscribe(host = "localhost", port = 1883L, client_id = "dcR",       topic = "IoTDemoData", 
  message_callback = 
  function(id, topic, payload, qos, retain) {
  if (topic == "IoTDemoData") {
  d &lt;&lt;- readBin(payload, "character")
  return("quit")
  }
  }
  )
  d &lt;- fromJSON(d)
  d &lt;- as.data.frame(d)
  return(d)
  }
  
  observe({
  invalidateLater(1000, session)
  isolate({    
  # fetch the new data
  new_data &lt;- get_new_data()
  # If myData is empty, we initialize it with just the new data.
  if(is.null(myData()))
  myData(new_data)
  else # row bind the new data to the existing data, and set that as the new    value.
  myData(rbind(myData(),new_data))
  })
  })
  
  output$mqttData &lt;- renderPlot({
  ggplot(mapping = aes(x = c(1:nrow(myData())), y = myData()$temperature)) +
  geom_line() +
  labs(x = "Second", y = "Celsius")
  })
  })
  
  shinyApp(ui=ui,server=server) 
  </code></pre>
  
  <p>However, after adding a second plot, the flickering began. When I commented out one of the plots, the plot works great without the need to refresh.
  library(shiny)
      library(mqtt)
      library(jsonlite)
      library(ggplot2)</p>
  
  <pre><code>ui &lt;- shinyServer(fluidPage(
    plotOutput("mqttData"),
    plotOutput("mqttData_RH")
  ))
  
  server &lt;- shinyServer(function(input, output, session){
    myData &lt;- reactiveVal()
    get_new_data &lt;- function(){
      d &lt;- character()
      mqtt::topic_subscribe(host = "test.mosquitto.org", port = 1883L, client_id = "dcR", topic = "IoTDemoData", 
      # mqtt::topic_subscribe(host = "localhost", port = 1883L, client_id = "dcR", topic = "IoTDemoData", 
                        message_callback = 
                          function(id, topic, payload, qos, retain) {
                              if (topic == "IoTDemoData") {
                                d &lt;&lt;- readBin(payload, "character")
                                return("quit")
                              }
                            }
                          )
      d &lt;- fromJSON(d)
      d &lt;- as.data.frame(d)
      d$RH &lt;- as.numeric(as.character( d$RH))
  
      return(d)
    }
  
    observe({
      invalidateLater(10000, session)
      isolate({    
        # fetch the new data
        new_data &lt;- get_new_data()
        # If myData is empty, we initialize it with just the new data.
        if(is.null(myData()))
      myData(new_data)
        else # row bind the new data to the existing data, and set that as the new value.
      myData(rbind(myData(),new_data))
      })
    })
  
    output$mqttData &lt;- renderPlot({
      ggplot(mapping = aes(x = c(1:nrow(myData())), y = myData()$temperature)) +
        geom_line() +
        labs(x = "Second", y = "Celsius")
    })
    output$mqttData_RH &lt;- renderPlot({
      ggplot(mapping = aes(x = c(1:nrow(myData())), y = myData()$RH)) +
        geom_line() +
        labs(x = "Second", y = "RH %")
    })
  })
  
  shinyApp(ui=ui,server=server)
  </code></pre>
  
  <p>One solution I found plot the charts in one renderPlot object. The flickering reduces.</p>
  
  <pre><code>output$mqttData &lt;- renderPlot({
      myData() %&gt;% 
        gather('Var', 'Val', c(temperature, RH)) %&gt;% 
        ggplot(aes(timestamp,Val, group = 1))+geom_line()+facet_grid(Var ~ ., scales="free_y")
    })
  </code></pre>
  
  <p>However, I wonder if there is way to plot the charts separately without flickering / refreshing.</p>
  
  <p>I found one github example put data to ggplot2 using pipe %>% (<a href="https://github.com/mokjpn/R_IoT" rel="nofollow noreferrer">https://github.com/mokjpn/R_IoT</a>) and modified it to plot separated charts.</p>
  
  <pre><code>library(shiny)
  library(ggplot2)
  library(tidyr)
  
  # Dashboard-like layout
  ui &lt;- shinyServer(fluidPage(
    fluidRow(
      column(
        6,
        plotOutput("streaming_data_1")
      ),
      column(
        6,
        plotOutput("streaming_data_2")
      )
    ),
    fluidRow(
      column(
        6,
        plotOutput("streaming_data_3")
      ),
      column(
        6,
        plotOutput("streaming_data_4")
      )
    )
  ))
  
  server &lt;- shinyServer(function(input, output, session){
    myData &lt;- reactiveVal()
    # show the first and last timestamp in the streaming charts
    realtime_graph_x_labels &lt;- reactiveValues(first = "",last ="")
  
    get_new_data &lt;- function(){
      epochTimeStamp &lt;- as.character(as.integer(Sys.time()))
      sensor_1 &lt;- -runif(1,min = 10, max = 30)
      sensor_2 &lt;- runif(1,min = 0,max = 100)
      sensor_3 &lt;- runif(1,min = 0,max = 100000)
      sensor_4 &lt;- runif(1,min = 0,max = 10)
      newData &lt;- data.frame(ts = epochTimeStamp, val_1 = sensor_1, val_2 = sensor_2, val_3 = sensor_3, val_4 = sensor_4)
      return(newData)
    }
  
    observe({
      invalidateLater(1000, session)
      isolate({    
        # fetch the new data
        new_data &lt;- get_new_data()
        # If myData is empty, we initialize it with just the new data.
        if(is.null(myData()))
        {
      myData(new_data)
      realtime_graph_x_labels$first &lt;- as.character(head(myData()$ts,1))
        }
        else # row bind the new data to the existing data, and set that as the new value.
      myData(rbind(myData(),new_data))
  
        realtime_graph_x_labels$last &lt;- as.character(tail(myData()$ts,1))
      })
    })
  
    # When displaying two charts, there is no flickering / refreshing, which is desired
    output$streaming_data_1 &lt;- renderPlot({
      myData() %&gt;% 
        ggplot(aes(ts,val_1, group = 1))+geom_line() +
        scale_x_discrete(breaks = c(realtime_graph_x_labels$first, realtime_graph_x_labels$last), labels = c(realtime_graph_x_labels$first, realtime_graph_x_labels$last)) +
        labs(title ="Sensor 1") +
        theme(plot.margin = unit(c(1,4,1,1),"lines"))
    })
    output$streaming_data_2&lt;- renderPlot({
      myData() %&gt;% 
        ggplot(aes(ts,val_2, group = 1))+geom_line() +
        scale_x_discrete(breaks = c(realtime_graph_x_labels$first, realtime_graph_x_labels$last), labels = c(realtime_graph_x_labels$first, realtime_graph_x_labels$last)) +
        labs(title ="Sensor 2") +
        theme(plot.margin = unit(c(1,4,1,1),"lines"))
    })
    # When adding the 3rd chart, every charts start to flicker / refresh when ploting new value
    output$streaming_data_3&lt;- renderPlot({
      myData() %&gt;%
        ggplot(aes(ts,val_3, group = 1))+geom_line() +
        scale_x_discrete(breaks = c(realtime_graph_x_labels$first, realtime_graph_x_labels$last), labels = c(realtime_graph_x_labels$first, realtime_graph_x_labels$last)) +
        labs(title ="Sensor 3") +
        theme(plot.margin = unit(c(1,4,1,1),"lines"))
    })
    output$streaming_data_4&lt;- renderPlot({
      myData() %&gt;%
        ggplot(aes(ts,val_4, group = 1))+geom_line() +
        scale_x_discrete(breaks = c(realtime_graph_x_labels$first, realtime_graph_x_labels$last), labels = c(realtime_graph_x_labels$first, realtime_graph_x_labels$last)) +
        labs(title ="Sensor 4") +
        theme(plot.margin = unit(c(1,4,1,1),"lines"))
    })
  
  })
  
  shinyApp(ui=ui,server=server)
  </code></pre>
  
  <p>The solution works when there are only two charts and starts flickering / refreshing when adding the 3rd.</p>