vda-5050-lib
Version:
Universal VDA 5050 library for Node.js and browsers
350 lines (349 loc) • 16 kB
TypeScript
/*! Copyright (c) 2021 Siemens AG. Licensed under the MIT License. */
import { Action, ActionState, AgvId, ClientOptions, Edge, Error, Headerless, InstantActions, MasterControlClient, Node, Order, State } from "..";
/**
* Represents context information of an order event.
*
* @category Master Controller
*/
export interface OrderContext {
/**
* The originally assigned order (without header information).
*/
readonly order: Headerless<Order>;
/**
* Identifies the AGV this state originates from.
*/
readonly agvId: AgvId;
/**
* The associated raw State object as published by the AGV.
*/
readonly state: State;
}
/**
* A subset of `State` properties for which changes are reported while an edge
* is being traversed (used by callback `OrderEventHandler.edgeTraversing`).
*/
export type EdgeStateChanges = Partial<Pick<State, "distanceSinceLastNode" | "driving" | "newBaseRequest" | "operatingMode" | "paused" | "safetyState">>;
/**
* Defines distinct callback functions invoked by the master controller whenever
* the state of an assigned order changes.
*
* @category Master Controller
*/
export interface OrderEventHandler {
/**
* Invoked once when the assigned order has been processed successfully,
* canceled successfully (by instant action "cancelOrder"), or rejected with
* an error in the first place because the order is not executable by the
* AGV.
*
* @remarks
* An order is processed if all the order's base nodes/edges have been
* traversed and all base node/edge actions have been finished or failed.
* Yet, the order may still be active if it contains horizon nodes/edges. In
* such a case, you can then assign an order update or cancel the order.
*
* After this callback has been invoked, no more callbacks related to the
* assigned order are invoked afterwards. Events on a subsequent order
* update are emitted on the event handlers of the newly assigned order
* update.
*
* @param withError an Error object if order has been rejected in the first
* place because it is not executable; otherwise `undefined`
* @param byCancelation `true` if executing order has been canceled before
* this callback is invoked; otherwise `false`
* @param active `true` if order is still active after processing, otherwise
* `false`
* @param context context information of the order event
*/
onOrderProcessed(withError: Error, byCancelation: boolean, active: boolean, context: OrderContext): void;
/**
* Invoked whenever an order's node has been traversed (optional).
*
* An order (base) node is traversed when the AGV has reached the node's
* target position and the node's actions are being triggered.
*
* @remarks This callback is only triggered for base nodes, not for horizon
* nodes.
*
* @param node the target node
* @param nextEdge the released or unreleased edge following the traversed
* node or `undefined` if no such edge exists.
* @param nextNode the released or unreleased end node of the edge following
* the traversed node or `undefined` if no such node exists.
* @param context context information of the order event
*/
onNodeTraversed?(node: Node, nextEdge: Edge, nextNode: Node, context: OrderContext): void;
/**
* Invoked to report changes in certain State properties while an order's
* edge is being traversed (optional).
*
* Changes are being reported for the following State properties:
* - `distanceSinceLastNode`
* - `driving`
* - `newBaseRequest`
* - `operatingMode`
* - `paused`
* - `safetyState`
*
* Note that only the delta changes are reported relative to the previous
* edgeTraversing event. On the first event, the current values of all State
* properties as defined above are reported.
*
* @remarks The first invocation of this event handler is triggered as soon
* as the AGV is ready to traverse the edge. In this case, the driving state
* can still be false.
*
* @param edge the traversing edge
* @param startNode the start node of the traversing edge
* @param endNode the end node of the traversing edge
* @param stateChanges edge-related State properties that have changed
* @param invocationCount the one-based number of invocations of this
* callback for the current traversing edge (starts with 1 for the first
* invocation)
* @param context context information of the order event
*/
onEdgeTraversing?(edge: Edge, startNode: Node, endNode: Node, stateChanges: EdgeStateChanges, invocationCount: number, context: OrderContext): void;
/**
* Invoked whenever an order's edge has been traversed (optional).
*
* An order (base) edge is traversed when the AGV has reached the edge's end
* node target position and all the edge's active actions are being
* terminated.
*
* @remarks This callback is only triggered for base edges, not for horizon
* edges.
*
* @param edge the traversed edge
* @param startNode the start node of the traversed edge
* @param endNode the end node of the traversed edge
* @param context context information of the order event
*/
onEdgeTraversed?(edge: Edge, startNode: Node, endNode: Node, context: OrderContext): void;
/**
* Invoked whenever an order's node or edge action state has changed
* (optional).
*
* @remarks
* If action state changes to FAILED, an accompanying error object may be
* reported by the AGV. However, if an order is rejected because an order
* action is not executable in the first place, this error is reported by
* the `onOrderProcessed` callback.
*
* To check whether the action is on a node or on an edge and to use the
* `target` parameter in a type-safe way, discriminate by `("nodeId" in
* target)` or `("edgeId" in target)`, respectively.
*
* @param actionState the new action state
* @param withError an Error object in case a failed action reports an
* error; otherwise undefined
* @param action the related action
* @param target the node or edge related to the action
* @param context context information of the order event
*/
onActionStateChanged?(actionState: ActionState, withError: Error, action: Action, target: Node | Edge, context: OrderContext): void;
/**
* Invoked whenever a new state update is received from the AGV for the current order.
*
* @remarks
* This callback is triggered each time the AGV sends a state update related to the
* current order. It provides real-time feedback on the order's execution, including
* the AGV's current position, status, and any changes in the order's progress.
*
* The frequency of this callback invocation depends on how often the AGV sends
* state updates, which can vary based on the AGV's configuration and the complexity
* of the current task.
*
* This callback is useful for applications that need to monitor the order's progress
* in real-time, update user interfaces, or make dynamic decisions based on the
* AGV's current state.
*
* @param context The current OrderContext, providing the latest state
* information directly from the AGV, including the original order details
* and the AGV's current state.
*/
onStateUpdate?(context: OrderContext): void;
}
/**
* Defines distinct callback functions invoked by the master controller whenever
* the state of an initiated instant action changes.
*
* @category Master Controller
*/
export interface InstantActionEventHandler {
/**
* Invoked whenever an instant action state has changed.
*
* If action state changes to FAILED, an accompanying error object may be
* reported by the AGV.
*
* @param actionState the new action state
* @param withError an Error object in case a failed action reports an
* error; otherwise undefined
* @param action the related instant action
* @param agvId identifies the AGV this state change originates from
* @param state the associated raw State object as published by the AGV
*/
onActionStateChanged(actionState: ActionState, withError: Error, action: Action, agvId: AgvId, state: State): void;
/**
* Invoked whenever an error is reported for an instant action that is
* rejected because it cannot be executed by the AGV in the first place.
*
* @remarks If the action starts executing and eventually fails with an
* error, such an error is reported by the handler `onActionStateChanged`.
*
* @param error the Error object
* @param action the related instant action
* @param agvId identifies the AGV this error originates from
* @param state the associated raw State object as published by the AGV
*/
onActionError(error: Error, action: Action, agvId: AgvId, state: State): void;
}
/**
* Defines configuration options of a master controller.
*
* @category Master Controller
*/
export interface MasterControllerOptions {
/**
* Identity of the AGV(s) which should be controlled by this master
* controller (optional).
*
* If not specified, the value defaults to `{}`, i.e. to all AGVs within the
* common communication namespace as defined by
* `ClientOptions.interfaceName`.
*/
targetAgvs?: Partial<AgvId>;
}
/**
* Implements the common control logic and interaction flows on the coordination
* plane (master control) as defined by the VDA 5050 specification. This
* includes assigning orders and initiating instant actions, as well as
* reporting back their execution state.
*
* Together with its counterpart on the vehicle plane, it builds a high-level
* abstraction layer of the complex control logic defined in the VDA 5050
* specification.
*
* @remarks
* This VDA 5050 implementation requires Node, Edge, and Action objects to
* specify unique IDs. You should always use the `createUuid` function to create
* such an ID as it generates globally unique IDs.
*
* This VDA 5050 implementation requires order rejection errors related to
* non-supported or non-executable node or edge actions to report an error with
* `errorType: "orderError"`, whereas order action errors reported for failed
* actions must specify a different error type (e.g. `errorType:
* "orderActionError"`) to make them distinguishable.
*
* @category Master Controller
*/
export declare class MasterController extends MasterControlClient {
private readonly _currentOrders;
private readonly _currentInstantActions;
private _currentInstantActionsRef;
private _currentInstantActionsValidationErrors;
private readonly _controllerOptions;
/**
* Creates an instance of `MasterController`, a subclass of
* `MasterControlClient`.
*
* @param clientOptions configuration options for the `MasterControlClient`
* @param controllerOptions configuration options for the `MasterController`
*/
constructor(clientOptions: ClientOptions, controllerOptions: MasterControllerOptions);
/**
* Gets the master controller configuration options as a readonly object
* with default values filled in for options not specified.
*/
get controllerOptions(): Readonly<Required<MasterControllerOptions>>;
/**
* Assign an order (including an order update or a stitching order) to be
* executed by an AGV and report back changes in the order's execution
* state.
*
* An assigned order must fulfil the following characteristics to be
* executable by an AGV:
* - New order: Previously assigned order (if any) has terminated and new
* order has different orderId.
* - Order update: Previously assigned order has terminated and order update
* has same orderId, a greater orderUpdateId, and a first base node
* matching lastNodeId/lastNodeSequenceId of current State followed by
* other base/horizon nodes.
* - Stitching order: Previously assigned order has not yet terminated and
* the stitching order extends the base of it thereby specifying either a
* new orderId or reusing the previous orderId with a greater
* orderUpdateId.
*
* @remarks
* If a stitching order is assigned, the event handler callbacks of the
* previously assigned order are just triggered for State events still
* emitted on the previous order. Any State events triggered on the new
* order are emitted on the event handler callbacks of the newly assigned
* stitching order. Note that Node, Edge, and Action objects passed by these
* event handlers may refer to the order context of the previous order.
*
* Any order that has the same AGV target and the same orderId and
* orderUpdateId as a currently active order will be discarded, resolving
* `undefined`. The given event handler callbacks will never be invoked.
* Instead, the previously registered callbacks continue to be invoked.
*
* Any Node, Edge, Action, and Order object passed to order event handler
* callbacks is guaranteed to be reference equal to the original object
* passed to this method. However, AgvId objects passed are never reference
* equal, but value equal.
*
* @param agvId identifies the target AGV
* @param order the headerless order to be executed
* @param eventHandler callbacks that report order-related events
* @returns a promise that resolves the order object with header when
* published successfully or `undefined` when order has been discarded, and
* rejects if order is not valid or controller has not been started
*/
assignOrder(agvId: AgvId, order: Headerless<Order>, eventHandler: OrderEventHandler): Promise<Order>;
/**
* Initiate instant actions to be executed by an AGV and report back changes
* on the execution state of the actions.
*
* @remarks Any Action and AgvId object passed to instant action event
* handler callbacks is guaranteed to be reference equal to the original
* object passed to this method.
*
* @param agvId identifies the target AGV
* @param instantActions a headerless instant actions object
* @param eventHandler callback that reports instant action related events
* @returns a promise that resolves an instant actions object with header
* when published successfully and rejects if given instant actions object
* is not valid or controller has not been started
*/
initiateInstantActions(agvId: AgvId, instantActions: Headerless<InstantActions>, eventHandler: InstantActionEventHandler): Promise<InstantActions>;
/**
* Whenever master controller starts up it subscribes to State topics of the
* target AGVs configured in controller options.
*/
protected onStarted(): Promise<void>;
private _controllerOptionsWithDefaults;
private _dispatchState;
private _dispatchOrderState;
private _addOrderStateCache;
private _removeOrderStateCache;
private _getOrderStateCache;
private _getLastAssignedOrderStateCache;
private _getLastActiveOrderStateCache;
private _initCachedActions;
private _isOrderProcessed;
private _isOrderCanceling;
private _getNode;
private _getNextEdge;
private _getNextReleasedEdge;
private _getEdgeStartNode;
private _getEdgeEndNode;
private _areAllBlockingActionsEnded;
private _updateEdgeStateChanges;
private _dispatchInstantActionState;
private _dispatchInstantActionError;
private _removeInstantActionStateCache;
private _getInstantActionsValidationError;
private _updateInstantActionsValidationError;
private _getActionError;
}