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.
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
}