application-developer-training

Basics

In this chapter you will learn the basics of MORYX and how it helps you to set up a production.

Use Case

Your costumer Pencilla Inc. produces pencils. The production needs prepared material - wooden slats and graphite - and consists of the following four steps:​

Each step is executed on a separate workstation, where a worker has to follow instructions and may operate a machine.

For more information about pencil production, look here.

Setup

To setup a new project, you need the MORYX CLI installed. If you have installed VisualStudio already, you would use dotnet tools:

$ dotnet tool install -g moryx.cli

Use moryx new to create a new MORYX application. It bootstraps a new C# solution using the provided name and optionally takes additional parameters like --steps, --products. Thus, it enables you to initialize everything you need in a single command:

$ moryx new <NAME> --steps <LIST-OF-STEPS> --products <LIST-OF-PRODUCTS>

Considering Pencilla Inc. to apply MORYX to the whole factory, you decide to use PencilFactory as the project name but it could also be a machine name, for example. Optionally you can provide the steps and products already to the new command. The products (GraphitePencil, made from Slat and Graphite) have already been identified, but only GraphitePencil is needed so far. Even though, there are four production steps, in the first iteration, only the Assembling step should be covered by MORYX. These information result in the following command:

$ moryx new PencilFactory --steps Assembling --products GraphitePencil

This should not only leave you with a solution PencilFactory.sln inside the new folder PencilFactory. It also does some initial configuration and ships empty databases.

That means, you can directly open it in Visual Studio and dig into it. Before you run the app, you might need to install licenses.

Run the application (press F5).

Note Starting it for the first time will restore NuGet packages.That can take a few minutes.

Application dashboard

Now, that you have a running MORYX instance, you need to create some databases. To skip the UI here and speed things up, you’ll use the MORYX CLI again.

While the application is still running, moryx exec post-setup will create empty databases and restart dependent modules. If your application runs on a different host than https://localhost:5000, you can specify that by the --endpoint <URL> option.

$ moryx exec post-setup

Products

At first, you will model products. Products represent the articles to be manufactured. MORYX differentiates between ProductType and ProductInstance. The ProductType is what you can order in a catalog, while the ProductInstance is what you would receive after ordering: an instance of the product with its unique serialnumber. In order for a ProductType to be produced, it needs a corresponding ProductInstance. For further information on how to create a product see this.

Let’s take a look at the composition of the pencil Pencilla Inc. produces.

Note that, when defining the hardness of pencils, the number (degree) is put first (2B, 2H, etc.). Since this can’t be represented in code, it is switched for names, while for everything else the official format is used. If you are interested, you will find more about grading and classification here.

From the details above, the GraphitePencilType needs

You will find the GraphitePencilType among all other <Product>Types in the PencilFactory package within the Products folder.

For properties to be shown on the UI, add the EntrySerialize attribute. For properties to be saved in the database, use the DataMember attribute.

public PencilColor Color { get; set; }

public GraphiteHardness Hardness { get; set; }

To make the code compile so far, you still need to implement the enums PencilColor and GraphiteHardness. You can do that easily by moving the cursor to the red underlined name, press Ctrl + . and select Generate class 'PencilColor' in new file. Then, go to that file, change class to enum and add the required attributes:

public enum PencilColor
{
    Green = 1,
    Brown = 2,
}

Do the same for GraphiteHardness.

public enum GraphiteHardness
{
    [Display(Name = "B")]
    B = 1,
    [Display(Name = "HB")]
    HB = 2
}

Create Products

To create a product, you need to run the application now and head to the Products UI.

Click on the plus button to open the ‘Product Importer’ menu. This title may sound a bit confusing, but it let’s you add new products.

Note The naming here comes from the fact, that you wouldn’t necessarily add products here, but ‘import’ them from other systems.

New product

Graphite GP-1B

Repeat the same step for a second product:

If you did everything correctly you should end up with something more or less similar to the image below.

Products list

Now you should have your products 100001-00 Brown Pencil GP-1B and 100002-00 Green Pencil GP-HB. The next challenge is to actually let a resource produce the pencils. So far there is no script that describes how the pencils are produced. Therefore, the next step is to model a resource after which we can create a Recipe and a Workplan.

Resources

We begin with modelling the assembling station, used to assemble the pencils. This is where resources come into play.

Resources represent physical assets and logical objects like robots or drivers within a cyber physical system. They can be coupled with active devices or represent passive objects like a table. The main advantage of this concept is that the resource interface and implementation structure is the same for all resources. So accessing a resource is done in an abstract and general way. Processing, configuring and visualization of a resource is done in the same way with the
same classes. Extending a default resource can be done in a standard way and includes expansion of the default UI as well.

Together with the customer you have figured out the following requirements as the first steps to digitalize their factory:

Based on these requirements

Add worker support

The AssemblingCell, you will find it in PencilFactory.Resources, already has an instructor.

[ResourceReference(ResourceRelationType.Extension)]
public IVisualInstructor Instructor { get; set; }

IVisualInstructor is the interface for a digital resource displaying the visual instructions on a screen and requires workers to interact by pressing buttons.

ResourceReference is an attribute that links two or more resources together. It’s a mechanism that is used to save and load the source and the target relationship in the database.

You can start now to map the real world into digital twins using MORYX. As a recap, the following is planned for the pencil factory:

There should be one assembling station (cell), which will have a monitor to show instructions to a worker. So the following resources are needed:

You will setup these in MORYX within the Resources UI by clicking the “+” button and selecting the required cell.

Note Make sure to deselect all cells before adding more, so that they will be added to the root level and not as children of other resources. Even though, that wouldn’t do any harm.

Create resources

In the following dialog it is ok to go with just the typename as the cell identifier.

If you then select the AssemblingCell and click the edit button, you can assign the previously created VisualInstructor to its Instructor property.

Create resources

Sessions

Cell and Instructor are now connected, but they do not interact with each other. Therefor, you need to implement the cells session handling. But before you do, you will get a short introduction about how this works in theory and the vocabulary that is used within MORYX.

Sessions are considered the sum of all tasks a resource (in this case a cell) has to perform on a single product instance. A session may consist of multiple sequences, which contain a single activity.

While sessions and activities are represented by types, sequences are more of a concept.

Usually a session (and with it a sequence) is started by a resource, telling the process engine, that it is ReadyToWork.

Then with ActivityStart() the process engine can tell a resource, that it should start working on a product. After the resource has finished it’s job, it will signal this with ActivityCompleted().

When the process engine has processed the ActivityResult (submitted by ActivityCompleted), it will “close” the sequence with SequenceCompleted().

Then, the resource could continue the current session (ContinueSession) with another sequence or start a whole new session by signalling ReadyToWork.

Activities, Sequences and Sessions

Now, you will convert theory into practice and begin with starting a session. To do so, update the ControlSystemAttached() method to the following:

public override IEnumerable<Session> ControlSystemAttached()
{
    yield return Session.StartSession(ActivityClassification.Production, ReadyToWorkType.Push);
}

ControlSystemAttached() gets called in the event of the ControlSystem being attached to the resource, which is, when the application gets started.

In here you will yield return a new session using Session.StartSession() and thus signal ReadyToWork to the ProcessEngine.

Since that should result in an ActivityStarted event, the next thing to be implemented will be the ActivityStarted() function. Find the comment /* Start execution here */ and replace it so that the whole function looks like this:

public override void StartActivity(ActivityStart activityStart)
{
    _currentSession = activityStart;
    switch (activityStart.Activity)
    {
        case  AssemblingActivity activity:
            VisualInstructor.Execute(Name, activityStart, CompleteInstruction);
            break;
    }
}

That wouldn’t compile so far, because there is no CompleteInstruction right now, which is provided as a delegate to Instructor.Execute. That means, you have to implement CompleteInstruction(), that gets called, when an instruction has finished, i.e.: When a worker has finished their task.

private void CompleteInstruction(int instructionResult, ActivityStart activity)
{
    var result = activity.CreateResult(instructionResult);
    _currentSession = result;
    PublishActivityCompleted(result);
}

These previous lines will complete the activity by publishing an ActivityResult to the ControlSystem.

And finally, the method that gets called on a cell after completing work is SequenceCompleted(). In here you start a ReadyToWork session again, using PublishReadyToWork() and update _currentSession.

public override void SequenceCompleted(SequenceCompleted completed)
{
    _currentSession = completed;

    var rtw = Session.StartSession(ActivityClassification.Production, ReadyToWorkType.Push);
    PublishReadyToWork(rtw);
    _currentSession = rtw;
}

Start production

Create a Workplan

In order to produce pencils, you have to establish the connection between cells and products: MORYX needs to know, how a product flows through the production line. This is not done in the code, but modelled within Workplans.

This allows you to define in a rather abstract way, what needs to be done without going much more into details. MORYX will find the way later, how this is done for a running order.

Start the application, go to Wokplans and click on the plus button.

Create new workplan

Drag an Assembling Task step to the workplan and connect the inputs and outputs.

The available Steps correlate to the code, that has been generated and was shipped together with the assembling resources.

Whole workplan

You want to configure the text that is displayed on the worker instruction. Click on the Assembling Task step to edit it and configure it as shown in the screenshot below. The text to put in could be Put the graphite into the slats and glue them together. Then cut the result into pieces and shape each of them. But could be anything you want.

Configure tasks

When you are done, modeling your workflow, you have to save the workplan.

Add a Recipe

In order to make the connection between aProduct and the Workplan you just created, you need a Recipe.

Go to Products and select the Product you want to produce, that is the GraphitePencil. Click on the Recipes tab and the edit button located on the top right corner. Click the Add Recipe button, located on the bottom left corner to add a new recipe.

Add a new recipe

Create a new recipe

Select recipe classification

Start production

To create a new Order. Navigate to the Orders UI.

Orders

Fill in the details of the Order:

Click on the plus button to add this as an operation to the order. One order can have multiple operations, but this is not needed here. Click CREATE to create the order.

Orders List

Begin Production

Now the production is running!

Production Running

That’s it, you should now be able to let the pencils flow through the assembling cell.

In order to see the visual instructions, got to the module Worker Support and select for VisualInstructor as Display

Select Display

Use the SUCCESS and FAILED action to make the products flow through the production line

Troubleshooting

Here you will find a list of common problems, that might occur, and how to fix them.

Encountering WupiExceptions

WupiException: Der CmContainer-Eintrag wurde nicht gefunden, Fehler 200.

The application depends on MORYX modules, that are licensed. But no worries: They ship with developer licenses, that need to be activated:

Activate developer licenses