Edge SDK -- Quickstart Guide

This guide walks you through creating a new edge adapter project from scratch using the Zequent Edge SDK. By the end, you will have a running Quarkus application that receives commands from the platform and can push telemetry data.

Prerequisites

  • Java 25
  • Maven 3.9.9 or higher
  • Docker or Podman (for running platform services)
  • GitHub account with access to the Zequent packages repository

Step 1: Create a New Quarkus Project

mvn io.quarkus:quarkus-maven-plugin:3.17.4:create \
    -DprojectGroupId=com.example.edge \
    -DprojectArtifactId=my-edge-adapter \
    -Dextensions="grpc,smallrye-health,arc"

cd my-edge-adapter

Step 2: Add the Edge SDK Dependency

Open pom.xml and add the Edge SDK and the GitHub Packages repository:

<dependencies>
    <!-- Zequent Edge SDK -->
    <dependency>
        <groupId>com.zequent.framework.edge.sdk</groupId>
        <artifactId>java-edge-sdk</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

<repositories>
    <repository>
        <id>github</id>
        <url>https://maven.pkg.github.com/Zequent/zequent-framework</url>
    </repository>
</repositories>

Make sure your ~/.m2/settings.xml has the GitHub credentials:

<settings>
  <servers>
    <server>
      <id>github</id>
      <username>YOUR_GITHUB_USERNAME</username>
      <password>YOUR_GITHUB_TOKEN</password>
    </server>
  </servers>
</settings>

Step 3: Configure the Adapter

Create or edit src/main/resources/application.properties:

# Application
quarkus.application.name=my-edge-adapter
quarkus.http.host=0.0.0.0
quarkus.http.port=9001

# Edge Identity
zequent.edge.endpoint=localhost:9001
zequent.edge.sn=YOUR_DEVICE_SERIAL_NUMBER
zequent.edge.asset-type=ASSET_TYPE_DOCK
zequent.edge.asset-vendor=DJI

# Platform Services
quarkus.grpc.clients.live-data-service.host=localhost
quarkus.grpc.clients.live-data-service.port=8003
quarkus.grpc.clients.live-data-service.keep-alive-without-calls=true

quarkus.grpc.clients.connector-service.host=localhost
quarkus.grpc.clients.connector-service.port=8010
quarkus.grpc.clients.connector-service.keep-alive-without-calls=true

# gRPC server shares HTTP port
quarkus.grpc.server.use-separate-server=false

Step 4: Implement the EdgeAdapterService

Create your adapter class. You only need to override the commands that your hardware supports:

package com.example.edge;

import com.zequent.framework.edge.sdk.interfaces.EdgeAdapterService;
import com.zequent.framework.edge.sdk.models.*;
import jakarta.enterprise.context.ApplicationScoped;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CompletableFuture;

@Slf4j
@ApplicationScoped
public class MyDeviceAdapter implements EdgeAdapterService {

    @Override
    public CompletableFuture<CommandResult> takeOff(TakeOffRequest request) {
        log.info("Takeoff requested for SN: {}", request.getSn());

        // Replace with your actual device API call
        boolean success = true;

        if (success) {
            return CompletableFuture.completedFuture(
                CommandResult.success("Takeoff initiated", request.getTid(), request.getSn())
            );
        } else {
            return CompletableFuture.completedFuture(
                CommandResult.error("Takeoff failed", request.getSn())
            );
        }
    }

    @Override
    public CompletableFuture<CommandResult> returnToHome(ReturnToHomeRequest request) {
        log.info("Return to home for SN: {}", request.getSn());
        return CompletableFuture.completedFuture(
            CommandResult.success("Returning to home", request.getTid(), request.getSn())
        );
    }

    @Override
    public CompletableFuture<CommandResult> openCover(String sn) {
        log.info("Opening cover for SN: {}", sn);
        return CompletableFuture.completedFuture(
            CommandResult.success("Cover opening", sn)
        );
    }

    // All other commands default to NOT_IMPLEMENTED and that is fine.
    // Override more as your hardware supports them.
}

Step 5: Push Telemetry Data (Optional)

If your device produces telemetry, inject the LiveDataService and push data:

package com.example.edge;

import com.zequent.framework.edge.sdk.interfaces.LiveDataService;
import com.zequent.framework.edge.sdk.models.TelemetryRequestData;
import com.zequent.framework.common.proto.LiveDataType;
import com.zequent.framework.utils.edge.sdk.dto.AssetTelemetryData;
import jakarta.enterprise.context.ApplicationScoped;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.util.UUID;

@Slf4j
@ApplicationScoped
public class TelemetryProducer {

    private final LiveDataService liveDataService;

    public TelemetryProducer(LiveDataService liveDataService) {
        this.liveDataService = liveDataService;
    }

    public void sendAssetTelemetry(String sn) {
        AssetTelemetryData assetData = new AssetTelemetryData();
        assetData.setLatitude(47.3769f);
        assetData.setLongitude(8.5417f);
        assetData.setAbsoluteAltitude(450.0f);
        assetData.setEnvironmentTemp(22.5f);
        assetData.setHumidity(65.0f);

        TelemetryRequestData data = TelemetryRequestData.builder()
            .sn(sn)
            .tid(UUID.randomUUID().toString())
            .timestamp(LocalDateTime.now())
            .type(LiveDataType.ASSET_TELEMETRY)
            .assetTelemetry(assetData)
            .build();

        liveDataService.produceTelemetryData(data)
            .subscribe().with(
                ignored -> log.debug("Telemetry sent for {}", sn),
                err -> log.error("Telemetry error", err)
            );
    }
}

Step 6: Start Platform Services

Before running your adapter, start the required platform services. Use the provided Docker Compose file from the framework root or create a minimal one:

# docker-compose.yml
version: "3.8"

services:
  zequent_db:
    image: docker.io/library/postgres:latest
    environment:
      POSTGRES_DB: zequent_db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    ports:
      - "5433:5432"

  redis:
    image: docker.io/library/redis:latest
    command: ["redis-server", "--appendonly", "yes"]
    ports:
      - "6379:6379"

  connector-service:
    depends_on:
      - zequent_db
      - redis
    image: ghcr.io/zequent/connector-service:latest
    ports:
      - "8080:8080"
    environment:
      - QUARKUS_REDIS_HOSTS=redis://redis:6379
      - QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://zequent_db:5432/zequent_db
      - QUARKUS_DATASOURCE_USERNAME=postgres
      - QUARKUS_DATASOURCE_PASSWORD=postgres

  live-data-service:
    depends_on:
      - redis
    image: ghcr.io/zequent/live-data-service:latest
    ports:
      - "8003:8003"
    environment:
      - QUARKUS_REDIS_HOSTS=redis://redis:6379

Start the services:

docker-compose up -d

Step 7: Run Your Adapter

./mvnw quarkus:dev

You should see output similar to:

Listening on: http://0.0.0.0:9001
gRPC Server started on 0.0.0.0:9001

Your adapter is now running and ready to receive commands from the platform via gRPC.


Step 8: Test with the Simulator

You can use the framework's built-in simulator (simulator/) to send test commands to your adapter. Alternatively, test with grpcurl:

# Install grpcurl if needed
# brew install grpcurl  (macOS)
# go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest  (Go)

# List available services
grpcurl -plaintext localhost:9001 list

# Call takeOff
grpcurl -plaintext -d '{
  "base": {
    "sn": "YOUR_DEVICE_SN",
    "tid": "test-123",
    "timestamp": {"seconds": 1700000000}
  },
  "request": {
    "latitude": 47.3769,
    "longitude": 8.5417,
    "altitude": 100.0
  }
}' localhost:9001 com.zequent.framework.sdks.edge.proto.EdgeAdapterService/TakeOff

Project Structure

After completing this guide, your project should look like this:

my-edge-adapter/
  pom.xml
  src/
    main/
      java/
        com/example/edge/
          MyDeviceAdapter.java        # Your EdgeAdapterService implementation
          TelemetryProducer.java      # Optional: telemetry push logic
      resources/
        application.properties        # Configuration
  docker-compose.yml                  # Platform services (dev)

Next Steps

For a real-world implementation example, see the edge-adapters/edge-dji module in the framework repository.

Was this page helpful?