Gateways

Custom gateways lets you connect any network of devices to Span. You run the gateways yourself on premises (or another place in the cloud). Whenever the gateway or devices change in Span the gateway will get a notification of the changes.

Gateway Overview

This is a blog post with deeper discussion for LoRaWAN

Connecting to the gateway endpoint

The gateways use a gRPC interface and connects to gw.lab5e.com:6674

Sample code

Connecting to the gateway endpoint is relatively straightforward; use the certificates from Span (a client certificate, a certificate chain and a private key for the client certificate) to set up the TLS credentials, then use that to connect to the endpoint as usual.

The full gateway sample (and library) for Go is available in the spangw repository at GitHub

import (
    // ....
	"github.com/lab5e/spangw/pkg/pb/gateway/v1"
)

const (
    certFile = "clientcert.crt"
    chainFile = "chain.crt"
    keyFile = "private.key"
)

func ConnectToSpan() (gateway.UserGatewayServiceClient, error) {
    	certs, err := os.ReadFile(chainFile)
	if err != nil {
		return nil, err
	}
	certPool := x509.NewCertPool()
	certPool.AppendCertsFromPEM(certs)

	cCert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		return nil, err
	}
	creds := credentials.NewTLS(&tls.Config{
		Certificates: []tls.Certificate{cCert},
		GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
			return &cCert, nil
		},
		RootCAs: certPool,
	})

	cc, err := grpc.Dial("gw.lab5e.com:667", grpc.WithTransportCredentials(creds))
	if err != nil {
		return nil, err
	}

	gw := gateway.NewUserGatewayServiceClient(cc)
	stream, err := demoGW.ControlStream(context.Background())
	if err != nil {
		return bil, err
	}
    return gw, nil
}