2.1. Basic Concepts and Objects in Manufacturing

The goal of the Internet of Things is to create a digital image of the real world and its entities. These entities act as specific material objects on one hand and abstract concepts on the other. An Internet of Things, for the field of manufacturing, generates a digital image of both the machines and tools used at the production plant, as well as the concepts that dominate the everyday production such as production orders and operations.

2.1.1. Entities from the Field of Manufacturing

2.1.1.1. Production Orders

If a certain product is to be produced at a certain point with a specified quantity. The production planning system issues the generation of a production order. The template for the production order is the routing, which contains each step (operation) required to produce the final product. The routing defines at which kind of workplace or machines the operation is to be carried out, as well as how much time and which components are required.

The scenario for the creation of a production order is as follows:

1. The company receives one or multiple customer orders to produce a certain product or wants to produce a certain quantity of it in stock.

2. A new production order with its own number is created in the ERP system which contains all the information from the routing.

3. In addition to the information in the routing, the production order also contains the specification of the quantity of the product to be produced, the so-called target quantity.

4. Finally, the delivery date is used to create a basic finish date for the production order and the result of material requirements planning is a basic start date. The latter corresponds to the point in time at which all of the components required for processing of the production order are available.

2.1.1.2. Operations

An operation describes a single step that is required to process a production order. Each operation produces a specific material in a specified quantity (target quantity of the operation). This involves either a material that is processed further as a component in a subsequent operation or, in the case of the last operation, by the end product of the production order.

The standard values stored in the operation include …

  • The material to be manufactured.
  • The target quantity is the quantity of the material to be produced. This can differ from the target quantity of the production order (for example, 4 doors that must be produced in one operation in order to finally produce an automobile).
  • The quantity unit of the target quantity (for example, piece, meter, kilogram, …)
  • The workplace or a group of equivalent workplaces, at which the operation is to be processed.
  • The target time per unit, i.e. the time required for the production of a unit of the material to be produced.
  • The target processing time is the time that is used for the entire processing time of the operation. It is the product of target quantity and target time per unit.
  • The target setup time is the time scheduled for the setup of the workplace.
  • The target teardown time is the time scheduled for the teardown of the workplace.
  • The target move time is the time scheduled for the transfer to the next workplace.
  • The target wait time is the time scheduled for e.g. cooling, drying or curing of the material to be produced.
  • The components needed in order to produce the material.
  • The production resources and tools (e.g. tools, equipment or documents) that are needed at the workplace in order to execute the operation.

2.1.1.2.1. Operation Phases

The operation phases describe the state of an operation, from the release by the ERP system to the completion and booking of the output quantities of the operation back to the ERP system.

2.1.1.3. Workplaces

Each operation is executed at at least one workplace. A workplace can be a simple manual workplace or a workplace with an automated production line (machine).

2.1.1.4. Workplace Groups

Workplaces are often lodged in ERP systems as a single workplace with a number of capacities. In Bridge API, each workplace is displayed individually and is then assigned to a specific capacity group or production line, respectively.

  • Capacity groups
    are workplaces at which the same production procedure is executed and which are therefore summarized. E.g. an injection molding workplace belongs to a capacity group injection molding machines.
  • Production lines
    are different workplaces that map a complete production process for a product. They use the procedures line production or mass production. Here, the different production stations are not connected by a timing (production cycle). Buffer stocks catch the time differences during processing between neighboring stations. Thus, for example, a faulty product can be removed from the production flow to be reworked, without disturbing the production process.

Each workplace can be assigned to exactly one capacity group and at most to one production line.

2.1.1.5. Staff Members

The staff is the production personnel, which is divided into shifts and can be assigned to the respective workplaces. Apart from his personnel data, an employee carries additional information like e.g. qualifications, posted vacation, … - that are important for the scheduling and flow of the production.

2.1.1.6. Tools

Production tools are needed at machine workplaces to properly complete an operation. A tool is e.g. the die casting mold of an injection molding system. The tool has a storage location, current site of operation and a lifespan. The lifespan describes how much time is left until the tool has to be replaced.

2.1.1.7. Documents

The documents that are required for the execution of an operation are stored in production folders. These documents usually originate from the product life cycle system. The documents can be NC programs for controlling machine tools, but also other documents such as test plans, assembly instructions or assembly sketches. If documents are changed, the IoT platform automatically creates a new version.

All documents belonging to an operation are displayed in the Shop Floor Terminal. From there, the NC programs from the production folder can also be loaded into the machine control.

2.1.1.8. Devices

Device refers to all devices that are connected to the IoT platform. These include in particular the programmable logic controller of the connected machines and production plants. These are permanently assigned to a specific workplace. By calling

GET/workplaces/{workplaceId}/devices

you get a list of all devices which are available at a workplace/a machine. All recorded process and sensor data can be queried for the devices.

2.1.2. The Digital Image in FORCE Bridge API

Bridge API maps the complete digital image of a production plant. The RESTful [1] webservice can be called directly via a web browser to interact with the resources provided in the API.

Swagger UI

2.1.1 Accessing the API resources through the Swagger UI

2.1.2.1. The Entry Point and the Top-Level Resources

A RESTful Webservice usually has only one Entry Point (API Base), from which all other outgoing resources can be retrieved from. Therefore it is important that the uniform resource indicator (URI) is correctly communicating with the REST clients, so they can find the API resources.

Bridge API Version 2

2.1.2 Graphical representation of the FORCE Bridge API Version 2.0

In this chapter the following top-level resources will be discussed in further detail:

productionOrders/
Production orders from the ERP system.
operations/
Operations of the production orders.
workplaces/
Workplaces (machines or manual workplaces) on which the operations are executed.
workplaceGroups/
Capacity groups (functionally identical machines) or production lines.
staffMembers/
The staff available for the execution of operations.
tools/
The tools available for the execution of operations.
documents/
Documents important to the entire production plant.
devices/
Devices such as the programmable logic controllers of machines.

2.1.3. Using the Application Development Kit

2.1.3.1. Retrieving the Entry Point

Java

You will need to instantiate a BridgeAPI class with the URL to the webservice and its credentials you want to interact with.

1
2
3
4
5
6
7
    String url = "http://localhost:24080";
    String user = "myUser";
    String secret = "mySecret";

    BridgeAPI api = new BridgeAPI(url, user, secret);

    /* ... */

Afterwards you can retrieve the individual clients - for one of the specific top-level resource mentioned in section The Entry Point and the top-level resources - from the newly instantiated object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    IProductionOrderClient productionOrderClient = api.getProductionOrderClient();
    IOperationClient operationClient = api.getOperationClient();
    IWorkplaceClient workplaceClient = api.getWorkplaceClient();
    IWorkplaceGroupClient workplaceGroupClient = api.getWorkplaceGroupClient();

    IDeviceClient deviceClient = api.getDeviceClient();
    IToolClient toolClient = api.getToolClient();
    IMasterDataClient masterDataClient = api.getMasterDataClient();

    IStaffMemberClient staffMemberClient = api.getStaffMemberClient();

    IOperationPlanningClient planningScenarioClient = api.getPlanningScenarioClient();

    IEventClient eventClient = api.getEventClient();
    ICallbackClient callbackClient = api.getCallbackClient();

    ICommandClient commandClient = api.getCommandClient();
    ICommandClientAsync commandClientAsync = api.getCommandClientAsync();

    IMachineClient machineClient = api.getMachineClient();
    IMachineStateDetailClient machineStateDetailClient = api.getMachineStateDetailClient();
    IStatusDefinitionClient statusDefinitionClient = api.getStatusDefinitionClient();
    IMiscellaneousClient miscClient = api.getMiscellaneousClient();

Note

The authorization happens automatically when a request is sent.

CURL

1
2
3
4
5
6
curl -X POST http(s)://$HOST:$PORT/ffwebservices/oauth/token \
     --header "accept:application/x-www-urlencode" \
     -d "client_id=$CLIENT_ID" \
     -d "client_secret=$CLIENT_SECRED" \
     -d "grant_type=client_credentials" \
     -d "scope=read%20write" 

Important

Keep in mind that a valid authorization token is required for every resource access !

2.1.3.2. Retrieving Resources

Every resource can be retrieved as follows.

Java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
    final GetProductionOrdersRequest ordersRequest = new GetProductionOrdersRequest();
    final Page<ProductionOrderResponse> orderResponsePage = productionOrderClient.getProductionOrders(ordersRequest);

    /* Retrieve the elements of the first page */
    final List<ProductionOrderResponse> orderResponses = orderResponsePage.getElements();

    for (ProductionOrderResponse orderResponse : orderResponses) {
        final OrderPropertiesWSModel orderProperties = orderResponse.getProperties();

        final String id = orderProperties.getId();
        final String description = orderProperties.getDescription();
        /* ... */
    }

CURL

curl -X POST "http(s)://$HOST:$PORT/ffwebservices/api/v2/$resource"
  -H "Authorization: Bearer $TOKEN"
  -H "Accept-Language: en-US"

2.1.3.4. Embedding resources

Java

Sub-resources can be embedded and retrieved as follows. The following example specifically embeds the operations for the production orders.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    IProductionOrderClient productionOrderClient = api.getProductionOrderClient();

    GetProductionOrdersRequest ordersRequest = new GetProductionOrdersRequest();
    ordersRequest.embed(new ProductionOrderEmbed().operations(true));

    Page<ProductionOrderResponse> productionOrders = productionOrderClient.getProductionOrders(ordersRequest);

    List<OperationPropertiesWSModel> operations = productionOrders
        .streamForward()
        .flatMap(productionOrderResponse -> productionOrderResponse
            .getOperations()
            .stream())
        .map(LinkEmbeddedWSModel::getEmbedded)
        .collect(Collectors.toList());

curl

1
2
3
curl -X GET "http://$HOST:$PORT/ffwebservices/api/v2/$resource?embed=$embedableResource" \
    --header  "accept: application/json;charset=UTF-8" \
    --header  "authorization: Bearer $TOKEN"

2.1.4. Tutorials

Tutorial 1

Find and list each manual labor and machine workplace.

Solution: show/hide

Java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
        final IWorkplaceClient workplaceClient = api.getWorkplaceClient();

        try {
            final Page<WorkplaceResponse> workplaceResponsePage = workplaceClient.getWorkplaces(new GetWorkplacesRequest());

            final Pagination pagination = workplaceResponsePage
                .getResponse()
                .getPagination();

            final long totalWorkplaces = pagination.getTotal();

            final Map<Boolean, List<WorkplaceResponse>> groups = workplaceResponsePage
                .streamForward()
                .collect(Collectors.partitioningBy(workplaceResponse -> workplaceResponse
                    .getProperties()
                    .isIsManualWorkplace()));

            for (Map.Entry<Boolean, List<WorkplaceResponse>> entry : groups.entrySet()) {

                final Boolean isManualWorkplace = entry.getKey();
                final List<WorkplaceResponse> responses = entry.getValue();
                final int sumWorkplaces = responses.size();

                if (isManualWorkplace) {
                    System.out.println("Manual Workplaces: (" + sumWorkplaces + "/" + totalWorkplaces + ")");
                } else {
                    System.out.println("Machine Workplaces: (" + sumWorkplaces + "/" + totalWorkplaces + ")");
                }

                responses.forEach(workplaceResponse -> {
                    final WorkplacePropertiesWSModel properties = workplaceResponse.getProperties();

                    System.out.printf("\t %5s - %s%n", properties.getNumber(), properties.getDescription());
                });

                System.out.println();
            }
        } catch (ForceAPIException e) {
            LOGGER.error(e.getMessage());
        }

Tutorial 2

Find and list all manual labor workplaces in every capacity group.

Solution: show/hide

Java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
        final IWorkplaceGroupClient workplaceGroupClient = api.getWorkplaceGroupClient();
        final IWorkplaceClient workplaceClient = api.getWorkplaceClient();

        try {

            final GetWorkplaceGroupsRequest workplaceGroupsRequest = new GetWorkplaceGroupsRequest();
            workplaceGroupsRequest.setType(WorkplaceGroupType.CAPACITY_GROUP);

            final Page<WorkplaceGroupResponse> workplaceGroupResponsePage = workplaceGroupClient.getWorkplaceGroups(workplaceGroupsRequest);
            final List<String> capacityGroupIds = workplaceGroupResponsePage
                .streamForward()
                .map(workplaceGroups -> workplaceGroups
                    .getProperties()
                    .getId())
                .collect(Collectors.toList());

            if (capacityGroupIds.isEmpty()) {
                System.out.println("No Capacity Groups!");
                return;
            }

            Map<String, List<WorkplaceResponse>> capacityGroupManualWorkplaces = capacityGroupIds
                .stream()
                .collect(Collectors.toMap(capacityGroupId -> capacityGroupId, capacityGroupId -> {

                    GetWorkplacesRequest workplacesRequest = new GetWorkplacesRequest();
                    workplacesRequest.setWorkplaceGroupNumber(capacityGroupId);
                    List<WorkplaceResponse> collect = new ArrayList<>();
                    try {
                        collect.addAll(workplaceClient
                                           .getWorkplaces(workplacesRequest)
                                           .streamForward()
                                           .filter(workplace -> workplace
                                               .getProperties()
                                               .isIsManualWorkplace())
                                           .collect(Collectors.toList()));
                    } catch (ForceAPIException e) {
                        LOGGER.error(e.getMessage());
                    }
                    return collect;
                }));

            System.out.println("Manual Workplaces for");
            capacityGroupManualWorkplaces.forEach((capacityGroupId, workplaceResponses) -> {
                System.out.printf("\tCapacity Group [%s]\n", capacityGroupId);
                workplaceResponses
                    .stream()
                    .map(WorkplaceResponse::getProperties)
                    .forEach(p -> System.out.printf("\t\tWorkplace %s [%s]\n", p.getNumber(), p.getId()));
            });

        } catch (ForceAPIException e1) {
            e1.printStackTrace();
        }

/../_code/java/src/main/java/com/forcam/apps/ManualLaborWorkplacesInCapacityGroups.java

Tutorial 3

Find all production orders of the current week for which all operations are completed.

Solution: show/hide

Java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        IProductionOrderClient productionOrderClient = api.getProductionOrderClient();

        Interval currentWeek = Interval.getWeekInterval(1, 0);

        try {
            GetProductionOrdersRequest ordersRequest = new GetProductionOrdersRequest();
            ordersRequest.setStartDate(currentWeek.getStartDate());
            ordersRequest.setEndDate(currentWeek.getEndDate());
            ordersRequest.embed(new ProductionOrderEmbed().operations(true));
            Page<ProductionOrderResponse> orderResponses = productionOrderClient.getProductionOrders(ordersRequest);

            List<ProductionOrderResponse> productionOrderResponses = orderResponses.getElements();

            List<ProductionOrderResponse> completedProductionOrdersResponses = productionOrderResponses
                .stream()
                .filter(productionOrderResponse -> productionOrderResponse
                    .getOperations()
                    .stream()
                    .map(LinkEmbeddedWSModel::getEmbedded)
                    .noneMatch(operationProperties -> operationProperties.getOperationPhaseId() != OperationPhase.COMPLETED))
                .collect(Collectors.toList());

            printProductionOrders(completedProductionOrdersResponses);

        } catch (ForceAPIException e) {
            LOGGER.error(e.getMessage());
        }

/../_code/java/src/main/java/com/forcam/apps/CompletedProductionOrders.java

Tutorial 4

Find which operating states all workplaces reside in and what percentage of workplaces reside in the operating state production.

Solution: show/hide

Java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
        final IWorkplaceClient workplaceClient = api.getWorkplaceClient();

        try {
            final GetWorkplacesRequest workplacesRequest = new GetWorkplacesRequest();
            final Page<WorkplaceResponse> workplaceResponsePage = workplaceClient.getWorkplaces(workplacesRequest);
            final Pagination pagination = workplaceResponsePage
                .getResponse()
                .getPagination();

            final long totalNumberOfWorkplaces = pagination.getTotal();

            workplaceResponsePage
                .streamBackward()
                .map(WorkplaceResponse::getProperties)
                .forEach(workplace -> System.out.printf("Workplace %s: %s%n",
                                                        workplace.getNumber(),
                                                        workplace
                                                            .getOperatingState()
                                                            .getDescription()));

            final long numberOfWorkplacesInProduction = workplaceResponsePage
                .streamForward()
                .map(WorkplaceResponse::getProperties)
                .filter(properties -> properties
                    .getOperatingState()
                    .getWorkplaceStateId()
                    .equals(WorkplaceState.PRODUCTION))
                .count();

            float workplacesInProduction = ((float) numberOfWorkplacesInProduction / (float) totalNumberOfWorkplaces) * 100;
            System.out.printf("Workplaces in Production %.2f %%%n", workplacesInProduction);

        } catch (ForceAPIException e) {
            LOGGER.error(e.getMessage());
        }

/../_code/java/src/main/java/com/forcam/apps/OperatingStatesOfWorkplaces.java

Tutorial 5

Figure out which operation phase each operation currently resides in and calculate the percentage of how many running operations are in the phase setup and in the phase processing respectively.

Solution: show/hide

Java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
        final IOperationClient operationClient = api.getOperationClient();

        try {
            final GetOperationsRequest operationsRequest = new GetOperationsRequest();
            final Page<OperationResponse> operationResponsePage = operationClient.getOperations(operationsRequest);

            final Pagination pagination = operationResponsePage
                .getResponse()
                .getPagination();

            final long totalNumberOfOperations = pagination.getTotal();
            System.out.println("Number of Operations: " + totalNumberOfOperations);

            final Map<OperationPhase, List<OperationResponse>> groups = operationResponsePage
                .streamForward()
                .collect(Collectors.groupingBy(e -> e
                    .getProperties()
                    .getOperationPhaseId()));

            int numberOfOperationsInSetup = 0;
            int numberOfOperationsInProcessing = 0;

            if (groups.containsKey(OperationPhase.SETUP)) {
                numberOfOperationsInSetup = groups
                    .get(OperationPhase.SETUP)
                    .size();
            }
            if (groups.containsKey(OperationPhase.PROCESSING)) {
                numberOfOperationsInProcessing = groups
                    .get(OperationPhase.PROCESSING)
                    .size();
            }

            float percentageOperationsInProcessing = ((float) numberOfOperationsInProcessing / totalNumberOfOperations) * 100;
            float percentageOperationsInSetup = ((float) numberOfOperationsInSetup / totalNumberOfOperations) * 100;
            System.out.printf("Percentage of Operations in Phase Setup: %.2f %%%n", percentageOperationsInSetup);
            System.out.printf("Percentage of Operations in Phase Processing: %.2f %%%n", percentageOperationsInProcessing);

        } catch (ForceAPIException e) {
            LOGGER.error(e.getMessage());
        }

/../_code/java/src/main/java/com/forcam/apps/OperationPhasesOfOperations.java

Footnotes

[1]RESTful are applications or web services which offer states and functionalities as a set of resources and which can also be changed via them.