Edge SDK -- Connector Service
The ConnectorService interface gives an edge adapter access to the platform's asset registry over gRPC. It covers what an adapter itself needs — registering and updating its own asset(s), resolving and updating the task it's currently executing, looking up schedulers and organization info, and reporting which commands it supports. Creating mission/task records, and managing missions at all, stays a Client SDK (customer application) concern — see Tasks below for the precise, code-verified boundary.
Full method-by-method reference: Connector API Reference.
Table of Contents
- Overview
- Asset Management
- Asset Payloads
- Tasks
- Schedulers
- Organization
- Capabilities
- Error Handling
- Configuration
- Usage Examples
Overview
From the edge adapter, you use ConnectorService to:
- Register your asset when the adapter starts, and deregister it on shutdown.
- Update asset state as it changes.
- Resolve a task the platform handed you, and write adapter-computed fields or a status change back onto it.
- Fetch a scheduler's definition and the organization it belongs to.
- Store and retrieve asset payloads (arbitrary versioned metadata blobs, e.g. calibration data).
- Report which commands your adapter currently supports, by implementing
getCapabilitiesonEdgeAdapterService— this is what lets the Admin Console show only the controls an asset actually implements.
The SDK provides a ready-to-use implementation (ConnectorServiceImpl) that handles gRPC communication and Proto-to-DTO mapping.
Asset Management
Register an Asset
import com.zqnt.utils.asset.domains.AssetDTO;
AssetDTO asset = new AssetDTO();
asset.setSn("YOUR_DEVICE_SN");
asset.setName("Dock Alpha");
asset.setAssetType("ASSET_TYPE_DOCK");
asset.setVendor("DJI");
connectorService.registerAsset(asset)
.thenAccept(registered -> log.info("Asset registered with ID: {}", registered.getId()))
.exceptionally(err -> {
log.error("Failed to register asset", err);
return null;
});
Get Asset by Serial Number / ID
connectorService.getAssetBySn("YOUR_DEVICE_SN")
.thenAccept(asset -> log.info("Found asset: {} (ID: {})", asset.getName(), asset.getId()));
connectorService.getAssetById("550e8400-e29b-41d4-a716-446655440000")
.thenAccept(asset -> log.info("Asset SN: {}", asset.getSn()));
Get Sub-Asset by Serial Number
Retrieve a sub-asset (e.g. the drone paired to a dock):
connectorService.getSubAssetBySn("YOUR_DEVICE_SNXXX")
.thenAccept(subAsset -> log.info("Sub-asset model: {}", subAsset.getModel()));
Update an Asset
AssetDTO update = new AssetDTO();
update.setSn("YOUR_DEVICE_SN");
update.setName("Dock Alpha -- Updated");
connectorService.updateAsset("550e8400-e29b-41d4-a716-446655440000", update)
.thenAccept(updated -> log.info("Asset updated"));
Deregister an Asset
connectorService.deRegisterAsset("550e8400-e29b-41d4-a716-446655440000")
.thenAccept(success -> {
if (success) log.info("Asset deregistered");
});
Asset Payloads
Store arbitrary metadata alongside an asset or sub-asset — for example, a generated flight-plan artifact or calibration data.
connectorService.upsertAssetPayload("YOUR_DEVICE_SN", null, payloadDTO)
.thenAccept(saved -> log.info("Payload stored: {}", saved.getId()));
Tasks
EdgeAdapterService's prepareTask/startTask receive only a task ID (see
Edge Adapter Reference — Task Execution) — resolve it with
getTaskById, then write back onto that same record with updateTask as your adapter learns more
(e.g. a generated flight-plan file's URL) or as the task's status changes:
connectorService.getTaskById(taskId)
.thenCompose(taskDTO -> {
// ... generate and upload your flight plan from taskDTO.getConfig() ...
WaypointTaskConfig config = (WaypointTaskConfig) taskDTO.getConfig();
config.setFileUrl(uploadedFileUrl);
config.setFileMd5(uploadedFileMd5);
// Persist it — the platform's response to updateTask does not echo these fields back,
// so re-fetching afterward would lose them. Keep using this same in-memory taskDTO.
return connectorService.updateTask(taskDTO.getId().toString(), taskDTO);
})
.thenAccept(updated -> log.info("Task prepared: {}", updated.getId()));
taskDTO.setStatus(TaskStatus.TASK_RUNNING);
connectorService.updateTask(taskDTO.getId().toString(), taskDTO)
.thenAccept(updated -> {
// Now actually trigger the flight on your hardware.
});
createTask/deleteTask exist on the interface but have no confirmed real-adapter usage —
creating and deleting task records is a Client SDK (customer application) responsibility. The same
holds for every Mission method (getMissionById/createMission/updateMission/deleteMission) —
mission management stays client-side entirely.
Schedulers
Schedulers define when and how often a task or command runs.
connectorService.getSchedulerById("scheduler-uuid")
.thenAccept(scheduler -> log.info("Scheduler: {}", scheduler));
connectorService.createScheduler(schedulerDTO)
.thenAccept(created -> log.info("Scheduler created: {}", created.getId()));
connectorService.updateScheduler("scheduler-uuid", updatedScheduler)
.thenAccept(updated -> log.info("Scheduler updated"));
connectorService.deleteScheduler("scheduler-uuid")
.thenAccept(success -> {
if (success) log.info("Scheduler deleted");
});
Organization
connectorService.getOrganizationById("org-uuid")
.thenAccept(org -> log.info("Organization: {}", org.getName()));
Capabilities
An adapter reports which commands it supports by implementing getCapabilities(String sn) on
EdgeAdapterService, returning a CurrentCapabilities of Capability entries. The platform calls
this when it needs to know what an asset can do — for example so the Admin Console can hide
controls an asset does not support, rather than failing at execution time.
@Override
public CompletableFuture<CurrentCapabilities> getCapabilities(String sn) {
Capability takeoff = new Capability("takeOff", "Take off to a target point",
true, null, Map.of("source", "adapter"));
takeoff.setTargetType(CapabilityTargetType.CAPABILITY_TARGET_TYPE_ASSET);
takeoff.setInputSchema(Map.of("type", "object"));
return CompletableFuture.completedFuture(
CurrentCapabilities.of(sn, AssetTypeEnum.ASSET_TYPE_AIRCRAFT, Set.of(takeoff)));
}
Return CurrentCapabilities.empty(sn) for an asset you do not recognise. See
Edge Adapter for the full EdgeAdapterService surface.
Beta preview — 2.0.x, not yet released. An unmerged branch adds Skill Registry self-reporting to this interface (beyond the live
getCapabilitiessnapshot above) and removes every Mission/Task method outright. See the 2.0.x migration guide for what replaces them, or the 2.0.x reference for the exact methods.
Error Handling
All ConnectorServiceImpl methods follow a consistent error handling pattern:
- The gRPC response includes a
hasErrorsflag. - If
hasErrorsistrue, the method logs the error and returnsnull(for entity methods) orfalse(for delete methods). - If the gRPC call itself fails (network error, timeout), the
CompletableFuturecompletes exceptionally.
connectorService.getAssetBySn("SOME_SN")
.thenAccept(asset -> {
if (asset == null) {
log.warn("Asset not found or server error");
return;
}
// use asset
})
.exceptionally(err -> {
log.error("gRPC call failed", err);
return null;
});
Configuration
quarkus.grpc.clients.connector-service.host=localhost
quarkus.grpc.clients.connector-service.port=8010
quarkus.grpc.clients.connector-service.keep-alive-without-calls=true
See the Configuration Guide for the complete reference.
Usage Examples
Startup Registration Pattern
import io.quarkus.runtime.StartupEvent;
import io.quarkus.runtime.ShutdownEvent;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@ApplicationScoped
public class AssetRegistration {
private final ConnectorService connectorService;
private final EdgeClientConfig config;
private String registeredAssetId;
public AssetRegistration(ConnectorService connectorService, EdgeClientConfig config) {
this.connectorService = connectorService;
this.config = config;
}
void onStart(@Observes StartupEvent event) {
AssetDTO asset = new AssetDTO();
asset.setSn(config.sn());
asset.setAssetType(config.assetType().name());
asset.setVendor(config.assetVendor().name());
connectorService.registerAsset(asset)
.thenAccept(registered -> {
registeredAssetId = registered.getId();
log.info("Asset registered: {}", registeredAssetId);
})
.exceptionally(err -> {
log.error("Asset registration failed", err);
return null;
});
}
void onStop(@Observes ShutdownEvent event) {
if (registeredAssetId != null) {
connectorService.deRegisterAsset(registeredAssetId).join();
log.info("Asset deregistered");
}
}
}
See also
- Connector API Reference — every method, including which ones have confirmed real-adapter usage and which don't
- Edge Adapter Reference — Task Execution — how
prepareTask/startTask/stopTaskreach your adapter in the first place