This section talks about how to push the data from the device to the cloud. Data is pushed to the cloud in Streams.

To push data you need to write an application that connects to uplink over TCP and pushes data to it. Uplink then in turn pushes the data to the cloud over MQTT.

As an example, this guide assumes you are pushing temperature data to Bytebeam.

Create a stream on the cloud

First, let us create a stream called temperature on the Bytebeam cloud. First, go to Bytebeam Cloud. Now, click on your username in the top right corner and navigate to the “Settings” section.

Next, select Streams and Click on “Create Stream”.

Now, enter the stream name and column name. In this example, we have chosen the data type of temperature as Float64. Click on the “Submit” button.

The temperature stream should be visible under the “Streams” section.

Configuration on the device side

You can now write to uplink from your application. Below you can see samples for some popular languages.

:::codeblocktabs

import socket
import json
import time
from gpiozero import CPUTemperature

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 5050))


# Constructs a payload and sends it over TCP to uplink
def send_data(s, payload):
    send = json.dumps(payload) + "\n"
    s.sendall(bytes(send, encoding="utf-8"))


# Send the temperature data
def send_temperature_stream(s, sequence):
    cpu_temperature = CPUTemperature().temperature
    timestamp = int(time.time() * 1000)
    payload = {
        "stream": "temperature",
        "sequence": sequence,
        "timestamp": timestamp,
        "temp": cpu_temperature,
    }
    print(payload)
    send_data(s, payload)


print("Starting Uplink Bridge App")

sequence = 1
while True:
    time.sleep(5)
    send_temperature_stream(s, sequence)
    sequence += 1

const net = require("net");
const util = require("util");
const exec = util.promisify(require("child_process").exec);

// Connect to the server
const client = new net.Socket();
client.connect(5050, "localhost", () => {
  console.log("Connected to server");
});

// Constructs a payload and sends it over TCP to uplink
function sendData(payload) {
  const send = JSON.stringify(payload) + "\n";
  client.write(send);
}

async function getCPUTemperature() {
  try {
    const { stdout } = await exec("cat /sys/class/thermal/thermal_zone0/temp");
    const temperature = parseFloat(stdout) / 1000;
    return temperature;
  } catch (error) {
    console.error("Error:", error.message);
    return null;
  }
}

async function sendTemperatureStream(sequence) {
  const cpuTemperature = await getCPUTemperature();
  if (cpuTemperature !== null) {
    const timestamp = Date.now();
    const payload = {
      stream: "temperature",
      sequence: sequence,
      timestamp: timestamp,
      temp: cpuTemperature,
    };
    console.log(payload);
    sendData(payload);
  } else {
    console.log("Failed to retrieve CPU temperature.");
  }
}

console.log("Starting Uplink Bridge App");

let sequence = 1;
setInterval(() => {
  sendTemperatureStream(sequence++);
}, 5000);

use tokio::net::TcpStream;
use tokio::prelude::*;
use tokio::time::{self, Duration};
use serde_json::json;
use std::fs;

async fn send_data(mut stream: &TcpStream, payload: serde_json::Value) {
    let send = format!("{}\n", payload.to_string());
    stream.write_all(send.as_bytes()).await.unwrap();
}

fn read_cpu_temperature() -> f32 {
    let contents = fs::read_to_string("/sys/class/thermal/thermal_zone0/temp")
        .unwrap_or_else(|_| "0".to_string());
    let temperature = contents.trim().parse::<f32>().unwrap_or(0.0);
    temperature / 1000.0
}

async fn send_temperature_stream(mut stream: &TcpStream, sequence: u64) {
    let cpu_temperature = read_cpu_temperature();
    let timestamp = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)
        .unwrap()
        .as_millis();

    let payload = json!({
        "stream": "temperature",
        "sequence": sequence,
        "timestamp": timestamp,
        "temp": cpu_temperature
    });

    println!("{:?}", payload);
    send_data(&mut stream, payload).await;
}

#[tokio::main]
async fn main() {
    let addr = "localhost:5050";
    let mut stream = TcpStream::connect(&addr).await.unwrap();

    println!("Starting Uplink Bridge App");

    let mut sequence = 1;
    let mut interval = time::interval(Duration::from_secs(5));
    loop {
        interval.tick().await;
        send_temperature_stream(&stream, sequence).await;
        sequence += 1;
    }
}
package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"strconv"
	"time"
)

func readCPUTemperature() float64 {
	data, err := ioutil.ReadFile("/sys/class/thermal/thermal_zone0/temp")
	if err != nil {
		fmt.Println("Error reading temperature:", err)
		return 0.0
	}
	tempStr := string(data)
	tempInt, err := strconv.Atoi(tempStr[:len(tempStr)-1])
	if err != nil {
		fmt.Println("Error parsing temperature:", err)
		return 0.0
	}
	return float64(tempInt) / 1000.0
}

func sendData(conn net.Conn, payload map[string]interface{}) {
	data, _ := json.Marshal(payload)
	fmt.Println(string(data))
	conn.Write(append(data, '\n'))
}

func main() {
	conn, err := net.Dial("tcp", "localhost:5050")
	if err != nil {
		fmt.Println("Error connecting:", err.Error())
		os.Exit(1)
	}
	defer conn.Close()

	fmt.Println("Starting Uplink Bridge App")
	sequence := 1
	for {
		time.Sleep(5 * time.Second)
		temp := readCPUTemperature()
		t := time.Now().UnixNano() / int64(time.Millisecond)
		payload := map[string]interface{}{
			"stream":    "temperature",
			"sequence":  sequence,
			"timestamp": t,
			"temp":      temp,
		}
		sendData(conn, payload)
		sequence++
	}
}

:::

If you do not see your favorite language do not worry. You can write to uplink in 2 easy steps:

  1. Create a TCP socket and connect to localhost and port 5050
  2. Periodically write data in the below JSON format to the port (NOTE: newline delimited)
{
  "stream": "temperature",
  "sequence": 1,
  "timestamp": 1698806057153,
  "temp": 17.0,
}

In the above JSON you need to auto-increment the sequence for each packet and the timestamp needs to be in milliseconds

The temperature data should now be visible on the cloud. Head over to Bytebeam Cloud and go to Device Management -> Device tab. Now click on the device and Select “Show Streams”.

Select “temperature” stream.

The temperature data should be visible on the cloud now.