Appearance
Getting Started
Early Access
The Smart Core API, source code, this guide, and all associated resources and tools are currently in Early Access. What this means is that unless you are granted access you won't be able to run through this guide yourself.
To request access, please contact the Smart Core team.
Prerequisites
This tutorial assumes awareness of concepts like APIs, networks, servers, and programming languages. It references protocol buffers and gRPC and shows examples in common programming languages like Go, Java, and NodeJS.
Playground
The Smart core Playground App creates a virtual smart building for you do develop and test your application against.
Install
The easiest way to get the playground app is to download the latest release.
If you have issues, or would prefer to manually install it, you can do so using golang:
shell
go install https://github.com/smart-core-os/sc-playground@latest
Make sure your GOBIN folder is in your PATH env var.
If you want/need to build it from source, follow the instructions in the repo readme: https://github.com/smart-core-os/sc-playground#developers
Run
Run the playground app using
shell
sc-playground
Using your web browser, navigate to https://localhost:8443 - this will provide an interface for configuring and monitoring your virtual smart building.
Configure
You'll need to create a virtual device for us to talk to in the rest of this tutorial:
- From the 'Traits' page, click the '+' button in the bottom-right, and select 'trait'
- This will prompt you to create a virtual device - use the name
my-device
, and enable thesmartcore.traits.OnOff
trait - You should now see a my-device OnOff trait card, showing the current state as
OFF
Talk to Smart Core
Now that we have a smart core server up and running with a virtual device, we'll need some client code to connect to and control the device. This section guides you through that using your preferred language out of Go, Java, or NodeJS.
If you'd prefer to see all the example code in one go, here it is, or keep reading to see the important bits.
All the code
go
package main
import (
"context"
"crypto/tls"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"github.com/smart-core-os/sc-api/go/traits"
)
func main() {
// #region connect
// Dial the Smart Core server.
// This doesn't actually connect, but does setup connection pools used by the clients.
conn, err := grpc.Dial(
"localhost:23557",
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
InsecureSkipVerify: true, // DANGER: skip TLS cert verification
})),
)
// #endregion connect
if err != nil {
fmt.Printf("connection error: %s\n", err.Error())
}
defer conn.Close()
// #region create-client
// create a trait client
onOffClient := traits.NewOnOffApiClient(conn)
// #endregion create-client
// #region update
// turn my-device on
res, err := onOffClient.UpdateOnOff(context.Background(), &traits.UpdateOnOffRequest{
Name: "my-device", // The device name, most Smart Core requests have this property
OnOff: &traits.OnOff{
State: traits.OnOff_ON,
},
})
if err != nil {
fmt.Printf("request error: %s\n", err.Error())
}
fmt.Printf("my-device is now %v", res.GetState())
// Outputs: my-device is now ON
// #endregion update
// #region pull
// subscribe to change stream from the server
stream, err := onOffClient.PullOnOff(context.Background(), &traits.PullOnOffRequest{
Name: "my-device",
})
// process change stream
for {
// wait for the next message sent by the server
res, err := stream.Recv()
if err != nil {
fmt.Printf("stream error: %s\n", err.Error())
break
}
// inspect each of the changes the server sent
for _, change := range res.Changes {
fmt.Printf("my-device is now %s\n", change.OnOff.State)
// prints 'my-device is now [ON,OFF]'
}
}
// #endregion pull
}
Setup
The first step is to add one of the prebuilt libraries as a dependency to your project.
shell
go get github.com/smart-core-os/sc-api/go@latest
If your programming platform isn't pre-built you can clone the Smart Core repository and run the protoc
tool against the source .proto
files as needed.
Using the API follows standard gRPC patterns for your chosen platform, read the gRPC docs for details.
Connect
The first step is to setup a connection to the Smart Core server. These examples connect to the Smart Core Playground, but any Smart Core server will do so long as it has the correct device. By default Smart Core servers use port 23557
for their API. 23557
decimal is is 5C05
hex, or SC OS.
go
// Dial the Smart Core server.
// This doesn't actually connect, but does setup connection pools used by the clients.
conn, err := grpc.Dial(
"localhost:23557",
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
InsecureSkipVerify: true, // DANGER: skip TLS cert verification
})),
)
Insecure Connection
The example above skips the security verification due to the playground using a self-signed cert by default that isn't trusted by your system. This approach should NOT BE USED IN PRODUCTION, instead please see the auth section for how to correctly set this up.
Followed by creating the type-safe client for the API you want to use, in our case for the OnOffApi but all Smart Core APIs are created in the same way:
go
// create a trait client
onOffClient := traits.NewOnOffApiClient(conn)
Control
With our client we can start to talk to devices managed by the Smart Core server. We start by changing the state of device my-device
to ON
:
go
// turn my-device on
res, err := onOffClient.UpdateOnOff(context.Background(), &traits.UpdateOnOffRequest{
Name: "my-device", // The device name, most Smart Core requests have this property
OnOff: &traits.OnOff{
State: traits.OnOff_ON,
},
})
if err != nil {
fmt.Printf("request error: %s\n", err.Error())
}
fmt.Printf("my-device is now %v", res.GetState())
// Outputs: my-device is now ON
Subscribe
We can also subscribe to changes in device state via the Pull
method on the API client.
go
// subscribe to change stream from the server
stream, err := onOffClient.PullOnOff(context.Background(), &traits.PullOnOffRequest{
Name: "my-device",
})
// process change stream
for {
// wait for the next message sent by the server
res, err := stream.Recv()
if err != nil {
fmt.Printf("stream error: %s\n", err.Error())
break
}
// inspect each of the changes the server sent
for _, change := range res.Changes {
fmt.Printf("my-device is now %s\n", change.OnOff.State)
// prints 'my-device is now [ON,OFF]'
}
}
You can then toggle the OnOff state for my-device
in the playground app (or using the update code from the previous section) and you will receive these changes through the stream.
Next steps
Make sure you're familiar with all of the basic concepts.