Quantcast
Channel: Intel Developer Zone Articles
Viewing all articles
Browse latest Browse all 3384

Getting Started with Intel® Context Sensing SDK for Linux* and Go*

$
0
0

Before you Begin

The Intel® Context Sensing SDK for Linux* is a Node.js*, Go*, and Python*-based framework supporting the collection, storage, sharing, analysis, and use of sensor information. 

This getting started guide contains steps to set up the broker and Go framework supported by the SDK, then run a sample provided in the SDK. 

Additionally, this document contains tutorials to create a simple provider, sample application using the provider, a microservice to run the application, and steps to run the microservice to publish events to the broker.

Every command or chunk of code can be copy-pasted directly from the document without any required modifications unless explicitly stated.

Requirements

Software

  • OS: Ubuntu* 14.04 or 16.04
  • Go: 1.8.3
  • Docker*: 17.0.3

Network

The document assumes Intel proxies are configured on the host machine. 
Verify you have access to below URLs:
  • hub.docker.intel.com
  • hub.docker.com

Getting Started

Setting up the Broker

There are two options to set up the broker:

  • Dockerized: Using the context repo from hub.docker.intel.com(preferred)
  • Non-dockerized: Using the context-broker-VERSION.tgz file 

This document only covers the preferred Dockerized method. 

The section assumes you have Docker already set up with Intel credentials. (Refer: Setting up Docker)

The broker requires a running instance of MongoDB*.

  • Use Docker to pull the mongo image onto your machine:
    docker pull mongo
  • Create a container named mymongodb and run it  for the very first time:
    docker run --name=mymongodb -d mongo

Note: For subsequent runs, use: docker start mymongodb

  • Pull the broker image:
    docker pull hub.docker.intel.com/context/context-broker:v0.10.5
  • Create a container named contextbroker and run it for the very first time:
    docker run --name contextbroker -it -p 8888:8888 --link mymongodb -e MONGODB_HOST=mymongodb hub.docker.intel.com/context/context-broker:v0.10.5

Note: For subsequent runs, use: docker start -i contextbroker
-i or -it is used to run in the foreground to see the output in the current terminal.

To stop the context broker instance, use CTRL+C to interrupt when running foreground or docker stop contextbroker when running in background.

In order to remove the container if it's preventing the use of Docker, use: docker rm –f contextbroker

Setting up the SDK for Go

If you haven’t set up the required Go environment on your machine (Refer: Setting up the Go Environment)

Use the command go env to ensure both $GOPATH and $GOROOT are populated with paths for Go projects and Go distribution, respectively.

  • Download the Go X Net Package:
    go get golang.org/x/net
  • Download the Logrus* package:
    go get github.com/sirupsen/logrus

Note: In some cases you may encounter the error 'can't load package: package golang.org/x/net: no buildable Go source files in $GOPATH/src/golang.org/x/net'. Verify your setup by checking if $GOPATH/src/golang.org/x/net actually contains items from https://github.com/golang/net repo.

  • Copy the context_linux_go directory from the extracted release package to the $GOPATH/src directory.

Running an SDK Sample

Make sure a broker instance is running.

  • To run the local_ticktock sample, navigate to the $GOPATH/context_linux_go/samples/local_ticktock directory and enter: go run main.go

Note: All the providers and samples provided in the SDK can be found in the $GOPATH/context_linux_go/providers and $GOPATH/context_linux_go/samples directories respectively.

Tutorials

The tutorials showcase how to use the SDK to create a provider, a sample application that utilizes the provider, and a microservice that can run the sample application.
 

Creating a Simple Provider

Next, we'll create a provider that takes a time period in milliseconds as options and publishes the string “Hello World” to the broker at the supplied interval. 
  • Create a directory named simpleprovider in the $GOPATH/context_linux_go/providers directory. 
  • Create a file named simpleprovider.go inside the directory.
A provider requires implementing functions and structs required by the context core. The below steps showcase the minimum steps required to create a basic provider, with only the createItem function being specific to this tutorial. 
In the following steps, you'll be adding lines of code to the simpleprovider.go file:
  1. Encapsulate all the contents of the provider in a package:
    package simpleprovider
  2. Import the required packages, time and core:
    import (
         "context_linux_go/core"     "time"
    )
  3. Declare a constant identifier that other providers can use to identify the data coming from our simpleprovider:
    const (
         // SimpleProviderType is the URN for a data from this provider
         SimpleProviderType string = "urn:x-intel:context:thing:simpleprovider"
    )
  4. Define a schema to register with the broker. 
    This will enable the broker to identify the unique identifier and perform necessary schema validation:
    // SimpleProviderSchema schema satisfied by this provider, the value is placed in the “data"
    var SimpleProviderSchema = core.JSONSchema{
         "type": SimpleProviderType,
         "schema": core.JSONSchema{
              "type": "object",
              "properties": core.JSONSchema{
                   "data ": core.JSONSchema{
                        "type": "string",
                   },
              },
         },
         "descriptions": core.JSONSchema{
              "en": core.JSONSchema{
                   "documentation": "Simple string producer",
                   "short_name":    "SimpleString",
              },
         },
    }
  5. Define a struct that holds an instance of the provider. 
    We will use the stopChan variable to start/stop the provider and also provide a reference to the additional options that the provider can accept: 
    // Provider holds an instance of the simple provider. 
    // Methods defined for this type must implement core.ProviderInterface
    type Provider struct {
         ticker   *time.Ticker
         stopChan chan bool
         options  *Options
    }
  6. Define the options for this provider. 
    We will supply the time interval after which the string should be published:
    // Options that are provider specific
    type Options struct {
         core.ProviderOptions
         Period int // Period of ticking in milliseconds
    }
  7. We can supply multiple URN identifiers in a single provider. Define a static function to return all the types supported in this provider:
    // Types is a static function that returns the types this Provider supports (URN and schema)
    func Types() []core.ProviderType {
         return []core.ProviderType{
              core.ProviderType{URN: SimpleProviderType, Schema: SimpleProviderSchema}}
    }
  8. Define a function that can return the Types supported:
    // Types is a provider specific function that queries the type of an ProviderInterface instance
    func (p *Provider) Types() []core.ProviderType {
         return Types()
    }
  9. Define the New function, which can set options called from our sample:
    // New creates a new simpleprovider.Provider with the specified options
    func New(options *Options) *Provider {
         var dp Provider
         dp.options = options
         dp.stopChan = make(chan bool)
         return &dp
    }
  10. Implement the Start function. In this email, we'll supply the ItemData to publish and also decide when to publish with the help of the ticker:
    // Start begins producing events on the item and error channels
    func (p *Provider) Start(onItem core.ProviderItemChannel, onErr core.ErrorChannel) {
         p.ticker = time.NewTicker(time.Millisecond * time.Duration(p.options.Period))
         go func() {
              for {
                   select {
                   case <-p.ticker.C:
                        onItem <- p.createItem()
                   case <-p.stopChan:
                        close(onItem)
                        close(onErr)
                        return
                   }
              }
         }()
    }
  11. Implement the createItem function. This function populates the ItemDatawith our string:
    // Generates a new simple provider item
    func (p *Provider) createItem() *core.ItemData {
         var item = core.ItemData{
              Type: SimpleProviderType,
              // Value map must match the schema
              Value: map[string]interface{}{"data": "Hello World"},
         }
         return &item
    }
  12. Implement the GetItem function:
    // GetItem returns a new simple provider item. Returns nil if itemType is not recognized
    func (p *Provider) GetItem(itemType string) *core.ItemData {
         if itemType != SimpleProviderType {
              return nil
         }
         return p.createItem()
    }
  13. Implement the Stop function to stop producing items:
    func (p *Provider) Stop() {
         p.stopChan <- true
         if p.ticker != nil {
              p.ticker.Stop()
          }
    }
  14. We must implement the GetOptions function to return a pointer to ProviderOptions in the Sensing core:
    // GetOptions returns a pointer to the core options for use within the Sensing core
    func (p *Provider) GetOptions() *core.ProviderOptions {
         return &p.options.ProviderOptions
    }

Creating a Sample Application Utilizing a Provider

A basic sample application utilizing a provider requires creating channels for onStart, onError and onItem to interface with the provider. Additionally, the Sensing API takes options, onStart, and onError as input. We can also supply options required as input for the provider itself.
  • Create a directory named simpleProviderSample in the $GOPATH/context_linux_go/samples directory
  • Create a file named main.go inside the directory. 

In the following steps, you'll be adding code to the main.go file:

  1. Encapsulate all the contents of our sample in a package:
    package main
  2. Import the required package: core, sensing, our simpleprovider, and fmt (to print to the terminal):
    import (
    	"context_linux_go/core""context_linux_go/core/sensing""context_linux_go/providers/simpleprovider""fmt"
    )
  3. Implement the main function. We will supply the channels for onStart, onError, and onItem from the context core:
    func main() {
    	onStart := make(core.SensingStartedChannel, 5)
    	onError := make(core.ErrorChannel, 5)
    	onItem := make(core.ProviderItemChannel, 5)
  4. Supply the provider options in the main function for the sensing core such as broker ipAddress and port, an indicator to publish to the broker, the name of our sample application, onStart, and onError:
    	options := core.SensingOptions{
    		Server:      "localhost:8888",
    		Publish:     true,
    		Application: "go_simpleprovider_application",
    		OnStarted:   onStart,
    		OnError:     onError,
    	}
  5. Create a new instance of Sensing and provide the sensing options in the main function:
    	sensing := sensing.NewSensing()
    	sensing.Start(options)
  6. Create an instance of the simpleprovider and supply the time period in the provider options in the main function:
    	spProvider := simpleprovider.New(&simpleprovider.Options{Period: 1000, ProviderOptions: core.ProviderOptions{Publish: true}})

    Note: The above line is a single line of code.

  7. Enable sensing and provide a reference to our provider instance. In this example, we'll print the URN type and actual data every time our provider generates ItemData. We'll stop our provider if any error is detected.
    	for {
    		select {
    		case <-onStart:
    			fmt.Println("Started sensing")
    			sensing.EnableSensing(spProvider, onItem, onError)
    		case item := <-onItem:
    			fmt.Println(item.Type, item.Value)
    		case err := <-onError:
    			fmt.Println("Error", err)
    			sensing.Stop()
    			return
    		}
    	}
    } //end of main function

Creating a Microservice

We can encapsulate an application and other dependencies inside a single service using Docker.

Dockerizing our application helps to secure the implementation (source code) and dynamically configure connections to other services, such as the broker, without modifying the source code on host machines.

  1. Create a file named SimpleProviderDockerfile in the $GOPATH/context_linux_go directory. You'll be editing this file in the steps below.

    Note: There is no extension in the name of the file.

  2. Provide the dependencies required by the SDK, as well as the Intel proxy information:
    FROM golang:1.8.3-alpine3.5
    
    RUN mkdir /app
    ADD ./samples /app/
    ADD . /go/src/context_linux_go/
    
    ENV http_proxy=http://proxy-chain.intel.com:911
    ENV https_proxy=http://proxy-chain.intel.com:912
    
    RUN apk add --no-cache git \
        && go get golang.org/x/net/websocket \
        && go get github.com/sirupsen/logrus \
        && apk del git
    
    WORKDIR /app/.
    
  3. Provide a name (simple_provider_client) and a path to our sample application (simpleProviderSample/main.go), then run the sample application:
    RUN go build -o simple_provider_client simpleProviderSample/main.go
    
    CMD ["./simple_provider_client"]
    

Running your micro service

Ensure the broker is running on your machine (Refer: Setting up the Broker).

  1. Build the image locally with a tag using the Docker file.
    docker build --tag smp:latest -f SimpleProviderDockerfile . 

    Note: The DOT at the end is required in the above command.

  2. Create a container named smp, tagged as latest. Run the container for the very first time:
    docker run --name=smp --network host -e http_proxy=”” -e https_proxy=”” smp:latest 

    Note: For subsequent runs use: docker start -i smp
    -i or -it is used to run in the foreground to see the output in the current terminal.

To stop the smp instance, use CTRL+C to interrupt when running in the  foreground or docker stop smp when running in the background. In order to remove the container if it's preventing the use of Docker, use: docker rm –f smp

Miscellaneous

For your convenience, this section contains topics out of the scope of this document for your convenience, but that may be listed in the requirements. 

Setting up Docker

If an install script was provided with this document, simply run it in the terminal: ./install_docker.sh If not, below are steps that need to be completed to successfully install Docker:

  1. Follow the Docker manual installation instructions: https://docs.docker.com/engine/installation/linux/ubuntu/#install-using-the-repository
  2. If you are behind a corporate proxy ,you may need to set Docker's proxy and DNS settings: Proxy Instructions
  3. Determine your host machine's DNS servers:
    nmcli dev show | grep 'IP4.DNS'
  4. Set up daemon.json with the 'dns' key and your DNS addresses:
    Example: { "dns" : [ "10.0.0.2" , "8.8.8.8" ] }
  5. Add your user to the docker group:
    sudo groupadd docker
    sudo gpasswd -a ${USER} docker
    sudo service docker restart
    newgrp docker
  6. Make sure you have access to hub.docker.intel.com by trying to log in in the web portal: https://hub.docker.intel.com
  7. Associate Docker on your machine with your user account:
    docker login hub.docker.intel.com

Setting up the Go Environment

  1. Fetch the Golang distribution package:
    wget -c https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
  2. Extract the contents:
    sudo tar -C /usr/local -xvzf go1.8.3.linux-amd64.tar.gz
  3. Append the below line into your .bashrc file, usually located at $Home/.bashrc
    export PATH=$PATH:/usr/local/go/bin
  4. Apply the changes to the current session:
    source ~/.bashrc

Accessing Go Documentation in your Browser

Access the Go documentation for the SDK from your browser to view additional API information and samples that are not demonstrated in this document.

  1. Navigate to $GOPATH/context_linux_go and enter:
    godoc -http=:6060
  2. In a web browser, enter the URL:
    http://localhost:6060/
  3. Click on Packages from the menu on top of the webpage.

You should now be able to view the documentation contents of context_linux_go under standard packages section of the webpage.


Viewing all articles
Browse latest Browse all 3384

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>