<repo_name>wagmarcel/oisp-sdk-go<file_sep>/cmd/test_api.go
package main

import (
	"fmt"
	"os"

	"github.com/oisp-sdk-go/pkg/oispapi"
)

func main() {

	username := os.Getenv("OISP_USERNAME")
	password := os.Getenv("OISP_PASSWORD")
	url := os.Getenv("OISP_URL")

	api, err := oispapi.NewOispAPIFromUser(username, password, url)
	if err != nil {
		fmt.Println("Error while trying to get token", err)
	}
	fmt.Println("Received token ", api)

	api, err = oispapi.NewOispAPIFromToken(api.GetToken(), url)
	if err != nil {
		fmt.Println("Error while trying to get token", err)
	}
	fmt.Println("Received token ", api)

	devices, err := api.GetDevices()
	if err != nil {
		fmt.Println("Error while trying to get devices", err)
	}
	fmt.Println("Retrieved devices: ", devices)

	device := oispapi.Device{
		DeviceID:  "11-22-33-44-55-66",
		Name:      "MyGoDevice",
		Tags:      []string{"hello", "world"},
		GatewayID: "mygogateway",
	}

	err = api.CreateDevice(&device)
	if err != nil {
		fmt.Println("Error while creating device:", err)
	} else {
		fmt.Println("Device created successfully")
	}

	newdevice, err := api.GetDevice(device.DeviceID)
	if err != nil {
		fmt.Println("Error while retrieving device: ", err)
	}
	fmt.Println("Device retrieved: ", newdevice)

	updateDevice := oispapi.Device{
		DeviceID:  device.DeviceID,
		Name:      "MyGoDevice2",
		Tags:      []string{"hello2", "world2"},
		GatewayID: "mygogateway2",
	}
	err = api.UpdateDevice(&updateDevice)
	if err != nil {
		fmt.Println("Error while updating device:", err)
	} else {
		fmt.Println("Device updated successfully")
	}

	err = api.DeleteDevice(device.DeviceID)
	if err != nil {
		fmt.Println("Error deleting device:", err)
	} else {
		fmt.Println("Device deleted successfully")
	}
}
<file_sep>/pkg/oispapi/auth.go
package oispapi

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
)

type getTokenRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
}
type getTokenResponse struct {
	Token string `json:"token"`
}

type getAuthTokenInfoResponse struct {
	Payload struct {
		UserID   string    `json:"sub"`
		Accounts []Account `json:"accounts"`
	} `json:"payload"`
}

const getTokenPath = "/v1/api/auth/token"
const getAuthTokenInfoPath = "/v1/api/auth/tokenInfo"

//GetUserToken is creating the user token from username and password
//Caution: Should not be used for long term services! The token is only valid
//for limited time (e.g. 1h)
func (o *Oispapi) getUserToken(username string, password string) error {

	body := &getTokenRequest{Username: username, Password: <PASSWORD>}
	jsonValue, _ := json.Marshal(body)
	response, err := http.Post(o.url+getTokenPath, "application/json", bytes.NewBuffer(jsonValue))
	if err != nil {
		return err
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	if response.StatusCode != 200 {
		return errors.New(string(responseData))
	}
	responseObject := getTokenResponse{}

	json.Unmarshal(responseData, &responseObject)
	o.token = responseObject.Token
	return nil
}

//getAuthTokenInfo is retrieving the details of a token
func (o *Oispapi) getAuthTokenInfo() error {

	client := &http.Client{}
	req, _ := http.NewRequest("GET", o.url+getAuthTokenInfoPath, nil)
	setHeaders(req, o.token)
	response, err := client.Do(req)
	if err != nil {
		return err
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	if response.StatusCode != 200 {
		return errors.New(string(responseData))
	}
	responseObject := getAuthTokenInfoResponse{}

	json.Unmarshal(responseData, &responseObject)
	o.accounts = responseObject.Payload.Accounts
	o.userID = responseObject.Payload.UserID
	return nil
}
<file_sep>/pkg/oispapi/devices.go
package oispapi

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
)

const getDevicesPath = "/v1/api/accounts/{accountId}/devices"
const getOneDevicePath = "/v1/api/accounts/{accountId}/devices/{deviceId}"

//GetDevices is retrieving the list of devices of active account
func (o *Oispapi) GetDevices() (*[]Device, error) {
	client := &http.Client{}
	replacements := map[string]string{"accountId": o.accounts[o.activAccount].ID}
	url := makeURL(o.url, getDevicesPath, replacements)
	req, _ := http.NewRequest("GET", url, nil)
	setHeaders(req, o.token)
	response, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	if response.StatusCode != 200 {
		return nil, errors.New(string(responseData))
	}
	responseObject := []Device{}
	json.Unmarshal(responseData, &responseObject)
	return &responseObject, nil
}

//CreateDevice is creating a new device
func (o *Oispapi) CreateDevice(device *Device) error {
	client := &http.Client{}

	replacements := map[string]string{"accountId": o.accounts[o.activAccount].ID}
	url := makeURL(o.url, getDevicesPath, replacements)
	jsonBody, _ := json.Marshal(device)
	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
	setHeaders(req, o.token)
	response, err := client.Do(req)
	if err != nil {
		return err
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	if response.StatusCode != 201 {
		return errors.New(string(responseData))
	}
	responseObject := []Device{}
	json.Unmarshal(responseData, &responseObject)
	return nil
}

//GetDevice is retrieving the list of devices of active account
func (o *Oispapi) GetDevice(deviceID string) (*Device, error) {
	client := &http.Client{}
	replacements := map[string]string{
		"accountId": o.accounts[o.activAccount].ID,
		"deviceId":  deviceID,
	}
	url := makeURL(o.url, getOneDevicePath, replacements)
	req, _ := http.NewRequest("GET", url, nil)
	setHeaders(req, o.token)
	response, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	if response.StatusCode != 200 {
		return nil, errors.New(string(responseData))
	}
	responseObject := Device{}
	json.Unmarshal(responseData, &responseObject)
	return &responseObject, nil
}

//UpdateDevice is updating a new device
func (o *Oispapi) UpdateDevice(device *Device) error {
	client := &http.Client{}

	replacements := map[string]string{"accountId": o.accounts[o.activAccount].ID,
		"deviceId": device.DeviceID,
	}
	url := makeURL(o.url, getOneDevicePath, replacements)
	updatedDevice := Device(*device)
	updatedDevice.DeviceID = ""
	jsonBody, _ := json.Marshal(updatedDevice)
	req, _ := http.NewRequest("PUT", url, bytes.NewBuffer(jsonBody))
	setHeaders(req, o.token)
	response, err := client.Do(req)
	if err != nil {
		return err
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	if response.StatusCode != 200 {
		return errors.New(string(responseData))
	}
	responseObject := []Device{}
	json.Unmarshal(responseData, &responseObject)
	return nil
}

//DeleteDevice is deleting a device
func (o *Oispapi) DeleteDevice(deviceID string) error {
	client := &http.Client{}
	replacements := map[string]string{
		"accountId": o.accounts[o.activAccount].ID,
		"deviceId":  deviceID,
	}
	url := makeURL(o.url, getOneDevicePath, replacements)
	req, _ := http.NewRequest("DELETE", url, nil)
	setHeaders(req, o.token)
	response, err := client.Do(req)
	if err != nil {
		return err
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	if response.StatusCode != 204 {
		return errors.New(string(responseData))
	}

	return nil
}
<file_sep>/pkg/oispapi/oispapi.go
package oispapi

import (
	"net/http"
	"regexp"
)

// Oispapi is managing an API session
type Oispapi struct {
	token        string
	url          string
	accounts     []Account
	userID       string
	activAccount int
}

// Account contains the detail of one account
type Account struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	Role string `json:"role"`
}

// Device contains the device details
type Device struct {
	DeviceID    string            `json:"deviceId,omitempty"`
	Name        string            `json:"name,omitempty"`
	GatewayID   string            `json:"gatewayId,omitempty"`
	DomainID    string            `json:"domainId,omitempty"`
	Status      string            `json:"status,omitempty"`
	Created     int64             `json:"created,omitempty"`
	Attributes  map[string]string `json:"attributes,omitempty"`
	Tags        []string          `json:"tags,omitempty"`
	Components  []Component       `json:"components,omitempty"`
	Contact     string            `json:"contact,omitempty"`
	Loc         []float64         `json:"loc,omitempty"`
	Description string            `json:"desription,omitempty"`
}

// Component reprecents a single device component
type Component struct {
	CID             string        `json:"cid"`
	Name            string        `json:"name"`
	ComponentTypeID string        `json:"componentTypeId"`
	Type            string        `json:"type"`
	ComponentType   ComponentType `json:"componentType"`
}

// ComponentType describe the details of a component type
type ComponentType struct {
	CTID        string `json:"_id"`
	ID          string `json:"id"`
	DomainID    string `json:"domainID"`
	Dimension   string `json:"dimension"`
	Default     string `json:"default"`
	Display     string `json:"display"`
	Format      string `json:"format"`
	Measureunit string `json:"measureunit"`
	Version     string `json:"version"`
	Type        string `json:"type"`
	DataType    string `json:"dataType"`
	Min         string `json:"min"`
	Max         string `json:"max"`
}

func setHeaders(req *http.Request, token string) {
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json")
}

// NewOispAPIFromToken is initiating the Oispapi struct from a user token
func NewOispAPIFromToken(token string, url string) (*Oispapi, error) {

	o := &Oispapi{
		token: token,
		url:   url,
	}

	err := o.getAuthTokenInfo()
	if err != nil {
		return nil, err
	}
	return o, nil
}

// NewOispAPIFromUser is initiating the Oispapi struct from username/password
func NewOispAPIFromUser(username string, password string, url string) (*Oispapi, error) {
	o := &Oispapi{
		url: url,
	}
	err := o.getUserToken(username, password)
	if err != nil {
		return nil, err
	}
	err = o.getAuthTokenInfo()
	if err != nil {
		return nil, err
	}
	return o, nil
}

func makeURL(url string, path string, replacements map[string]string) string {
	replaced := path
	for k, v := range replacements {
		re := regexp.MustCompile(`(\{` + k + `\})`)
		replaced = re.ReplaceAllString(replaced, v)
	}
	return url + replaced
}

// GetToken returns the access token value
func (o *Oispapi) GetToken() string {
	return o.token
}
