In this chapter you will learn the basics of MORYX and how it helps you to set up a production.
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.
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.
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
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
}
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.
100001
0
GP-1B
100001-00 GP-1B
Color
dropdown choose Green
Hardness
dropdown choose B
as the hardness, which represent 1B
in this case.Repeat the same step for a second product:
GraphitePencilType
100002
0
BP-HB
HB
Brown
If you did everything correctly you should end up with something more or less similar to the image below.
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.
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
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:
AssemblingCell
VisualInstructor
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.
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.
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
.
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.
ReadyToWorkType.Pull
is used to retrieve an activity, that is assigned to
the cell. If there is no activity, it would result in a SequenceCompleted()
.
This is typically used to start activities if a product is already âinâ a
cell.ReadyToWorkType.Push
wonât result in a SequenceCompleted()
, but would
âwaitâ for an acitvity, like subscribing for push notifications.ActivityClassification.Production
is used to notify that the cell is ready to
work on an Activity
of type production
.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;
}
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.
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.
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.
When you are done, modeling your workflow, you have to save the workplan.
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.
PencilRecipe
and select
your created workplan Workplan
.Default
Classification.100002-00 Green Pencil GP-HB
.To create a new Order
. Navigate to the Orders UI.
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.
1
as the Partial Amount
.Now the production is 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
Use the SUCCESS
and FAILED
action to make the products flow through the production line
Here you will find a list of common problems, that might occur, and how to fix them.
WupiException
s
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:
.WibuCmRau
files onto it