Gateway protocol

The gateway protocol is relatively simple and consists of a single RPC call to establish a bidirectional stream of messages:

service UserGatewayService {
    rpc ControlStream(stream ControlStreamRequest) returns (stream ControlStreamResponse);

The control stream consists of a ControlStreamRequest message that the gateway sends to Span:

message ControlStreamRequest {
    oneof msg {
        ConfigRequest config  = 1;
        UpstreamMessage upstream_message = 2;
        Keepalive keepalive = 3;
        GatewayMetadataUpdate gateway_metadata = 4;
        DeviceUpdate device_update = 5;

Span will then respond with a ControlStreamResponse message:

Control stream responses

message ControlStreamResponse {
    oneof msg {
        DeviceConfigUpdate device_update = 1;
        GatewayConfigUpdate gateway_update = 2;
        DeviceRemoved device_removed = 3;
        DownstreamMessage downstream_message = 4;
        KeepaliveResponse keepalive_response = 5;


When the gateway starts it should request a configuration update from Span via the ConfigRequest message New or changed gateway configuration. Span will then respond with two kinds of messages - a single GatewayConfigUpdate message and zero or more DeviceConfigUpdate messages, one for each device.

The GatewayConfigUpdate message contains the updated gateway configuration. The tags field is for informational purposes only and may be ignored by the gateway.

message GatewayConfigUpdate {
    string gateway_id = 1;
    map<string,string> config = 2;
    map<string, string> tags = 3;

If a device is changed in Span (or the gateway sends a ConfigRequest message) Span will send a DeviceConfigUpdate message. This message is sent every time a device is created or updated:

message DeviceConfigUpdate {
    string device_id = 1;
    map<string, string> config = 2;
    map<string, string> tags = 3;    

As with the gateway configuration the tags field is for informational purposes only.

If a device is removed in Span the DeviceRemoved message is sent to the Gateway:

// This message is sent when a device is removed via the API
message DeviceRemoved {
    string device_id = 1;

The configuraton settings are maps with strings of strings. The interpretation and semantics of the configuration settings is at the gateway’s discretion.

Passing messages

Upstream messages (messages sent from the devices to the gateway and then Span) is sent from the gateway with the UpstreamMessage message object. The payload is an opaque byte buffer that is set via the usual Span API call. The metadata field can be populated to set device metadata that will be visible via the Span API:

message UpstreamMessage {
    string device_id = 1;
    bytes payload = 2;
    map<string,string> metadata = 3;

In a similar vein the downstream messages (messages that should be sent from the gateway to the devices) uses the DownstreamMessage message object. The payload is an opaque byte buffer.

message DownstreamMessage {
    string message_id = 1;
    string device_id = 2;
    bytes payload = 3;

Implementation notes

The connection might be dropped from time to time. The gateway may do periodic keepalive checks by sending a KeepaliveRequest message to Span. Span will then respond with a KeepaliveResponse message. If the connection is dropped the gateway should reconnect automatically. The gateway will always initiate the connection to Span so there’s no need to open firewall ports on the server that runs the gateway service.