Skip to content

Latest commit

 

History

History
171 lines (148 loc) · 6.03 KB

HowTo_Go_3_Cumulocity_REST.md

File metadata and controls

171 lines (148 loc) · 6.03 KB

Container Application Development with Go

Accessing the Cumulocity REST-API - Part 1

Introduction

This demo shows how to consume a JSON-based REST-API with Go. In this demonstration we use the Cumulocity REST-API to add a new measurement to an existing device. The main purpose of this sample is to show how to convert data to JSON and access a REST-API with Go. The JSON output we send to the Cumulocity server should look like this:

{
    "source":
    {
        "id": "<my-device-id>"
    },
    "time": "2016-09-21T20:18:30.323634999+02:00",
    "type": "MyWeatherMeasurementDemo",
    "WeatherData":
    {
        "Weather Station Regensburg":
        {
            "unit": "°C",
            "value": 20.9
        }
    }
}

INFO Cumulocity provides a very complex and powerful REST interface. To keep things simple we declare our JSON schema statically. This is not the recommended way to access Cumulocity because of it's dynamic nature. A future demo will explain the data structure of Cumulocity and shows a dynamic approach how to access the Cumulocity REST-API properly.

REQUIREMENTS You need a Cumulocity account and a device in your inventory. Cumulocity offers a 30 day free trial at www.cumulocity.com. After successful registration you can add a new device with a simple REST-API call. Use "curl" or the Postman add-on for Google Chrome. Please read the Cumulocity Hello REST! developers guide

To run this sample application you need:

  • a Cumulocity sub-domain <my-subdomain>
  • a Cumulocity username <my-username>
  • a Cumulocity password <my-password>
  • a Cumulocity device ID <my-device-id>

Sample application

The following sample application adds a new measurement through the Cumulocity REST-API to a device. Everything you need to run this application is already included in Go. First we describe our data structure with Go. Inside main we are populating the data structure with real data and convert it to JSON. We're creating a HTTP request with all required settings, especially the HTTP header variables and the authentication settings. If everything is setup right, the HTTP call runs without errors and a few seconds later you can see a new measurement on the Cumulocity UI.

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"
)

// SourceObject is a reference to a Cumulocity managedObject
// Inside the Cumulocity UI a managedObject is a device
type SourceObject struct {
	ID  string `json:"id"`
	URI string `json:"self,omitempty"`
}

// MeasurementHeader contains all mandatory data fields that are included
// in a measurement struct
type MeasurementHeader struct {
	ID        string       `json:"id,omitempty"`
	URI       string       `json:"self,omitempty"`
	Source    SourceObject `json:"source"`
	TimeStamp string       `json:"time"`
	Type      string       `json:"type"`
}

// MeasurementValue stores a value of a measurement
type MeasurementValue struct {
	Unit  string  `json:"unit"`
	Value float32 `json:"value"`
}

// MyWeatherData is the dynamic part of a measurement request
type MyWeatherData struct {
	MyWeatherStation MeasurementValue `json:"Weather Station Regensburg"`
}

// MyWeatherMeasurementDemo JSON request
type MyWeatherMeasurementDemo struct {
	MeasurementHeader               // Inherit all fields from MeasurementHeader
	Data              MyWeatherData `json:"WeatherData"`
}

func main() {
	// Populate a weather measurement object
	m := MyWeatherMeasurementDemo{}
	m.Source.ID = "<my-device-id>" // Set your Device-ID here
	m.TimeStamp = time.Now().Format(time.RFC3339Nano)
	m.Type = "MyWeatherMeasurementDemo" // Our user-defined type
	m.Data.MyWeatherStation.Unit = "°C"
	m.Data.MyWeatherStation.Value = 20.9

	// Create the request body data
	body := new(bytes.Buffer)
	err := json.NewEncoder(body).Encode(m)
	if err != nil {
		log.Fatalf("Could not marshal data to JSON.")
	}

	// This line prints out the marshalled JSON data. It should equals
	// the JSON output as described in the example documentation.
	log.Printf("MyWeatherMeasurementDemo JSON data: %v", body.String())

	// Initialize the HTTP POST request.
	// Replace the Cumulocity domain name with your settings.
	url := "http://<my-subdomain>.cumulocity.com/measurement/measurements/"
	client := &http.Client{}
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		log.Fatalf("Could not create a HTTP request object. Error: %v", err)
	}

	// Set your credentials to access
	req.SetBasicAuth("<my-username>", "<my-password>")

	// This setting is needed to create a measurement request.
	// Please read the Cumulocity REST-API documentation for more informations.
	req.Header.Set("Content-Type", "application/vnd.com.nsn.cumulocity.measurement+json;charset=UTF-8;ver=0.9")

	// Call the Cumulocity REST-API function to add the measurement
	_, err = client.Do(req)
	if err != nil {
		log.Fatalf("The HTTP request failed. Error: %v", err)
	}

	fmt.Println("Succesfully added the measurement to Cumulocity.")
}

Run this application inside your container

You need to build a ARM binary as described in the Quick Start Guide. In case of a Mac OS X based development workstation run:

$ env GOOS=linux GOARCH=arm GOARM=7 go build -v /Users/maxmuster/go/src/github.com/maxmuster.de/cumulocity/cumulocity.go
$ scp cumulocity root@<your-container-ip-address>:~/
$ ssh root@<your-container-ip-address>
password: *****
root@container-1234 ~  $ ./cumulocity
2016/09/21 21:20:48 MyWeatherMeasurementDemo JSON data: {"source":{"id":"*****"},"time":"2016-09-21T21:20:48.98678944+02:00","type":"MyWeatherMeasurementDemo","WeatherData":{"Weather Station Regensburg":{"unit":"°C","value":10.8}}}
Successfully added the measurement to Cumulocity.

IMPORTANT Don't use a HTTPS (SSL) connection at the moment. There's an error inside the container when trying to access the Cumulocity through HTTPS. We're working on this issue.