Skip to content

Commit df9e1e9

Browse files
Merge pull request #100 from PHOENIXCONTACT/feature/process-holder-extensions
Port: Add further process holder, process, job and session extensions
2 parents e1dbcf2 + c379e7f commit df9e1e9

File tree

6 files changed

+527
-93
lines changed

6 files changed

+527
-93
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright (c) 2024, Phoenix Contact GmbH & Co. KG
2+
// Licensed under the Apache License, Version 2.0
3+
4+
using Moryx.AbstractionLayer.Recipes;
5+
using Moryx.AbstractionLayer;
6+
using Moryx.AbstractionLayer.Products;
7+
using Moryx.ControlSystem.Recipes;
8+
using System;
9+
using Moryx.ControlSystem.Processes;
10+
11+
namespace Moryx.ControlSystem.Cells
12+
{
13+
/// <summary>
14+
/// Extension methods on the <see cref="Session"/> to get product related information, activity details or just provide shortcuts based on the actual session type
15+
/// </summary>
16+
public static class SessionExtensions
17+
{
18+
/// <summary>
19+
/// Extension method to get the <see cref="ProductInstance"/> from the <see cref="Process"/> of the <paramref name="session"/>
20+
/// </summary>
21+
/// <typeparam name="TProductInstance">Type of the <see cref="ProductInstance"/> that is expected.</typeparam>
22+
/// <param name="session">The sesion to get the <see cref="ProductInstance"/> from</param>
23+
/// <returns>
24+
/// The <see cref="ProductInstance"/> in the session, if the <paramref name="session"/> belongs to a
25+
/// <see cref="ProductionProcess"/> and the <see cref="ProductionProcess"/> holds a <typeparamref name="TProductInstance"/>;
26+
/// Otherwise returns null
27+
/// </returns>
28+
public static TProductInstance GetProductInstance<TProductInstance>(this Session session) where TProductInstance : ProductInstance
29+
{
30+
if (session.Process is not ProductionProcess process) return null;
31+
32+
return process.ProductInstance as TProductInstance;
33+
}
34+
35+
/// <summary>
36+
/// Modifies the <see cref="IProductInstance"/> of type <typeparamref name="TInstance"/>
37+
/// on the <see cref="IProcess"/> of the <paramref name="session"/> using the given
38+
/// <paramref name="setter"/>.
39+
/// </summary>
40+
/// <typeparam name="TInstance">The expected type of the product instance</typeparam>
41+
/// <param name="session">The sessopm holding the product instance</param>
42+
/// <param name="setter">The action to be executed on the product instance</param>
43+
/// <example>
44+
/// <code>
45+
/// <![CDATA[
46+
/// session.ModifyProductInstance<MyProductInstance>((var instance) => instance.MyProperty = 1)
47+
/// ]]>
48+
/// </code>
49+
/// </example>
50+
/// <exception cref="InvalidCastException">Thrown if the <see cref="IProcess"/> of the
51+
/// <paramref name="session"/> does not hold a product instance of type <typeparamref name="TInstance"/>
52+
/// </exception>
53+
/// <exception cref="InvalidOperationException">Thrown if the <see cref="IProcess"/> of the
54+
/// <paramref name="session"/> is no <see cref="ProductionProcess"/></exception>
55+
public static TInstance ModifyProductInstance<TInstance>(this Session session, Action<TInstance> setter)
56+
where TInstance : IProductInstance => session.Process.ModifyProductInstance(setter);
57+
58+
/// <summary>
59+
/// Tries to modifies the <see cref="IProductInstance"/> of type <typeparamref name="TInstance"/>
60+
/// on the <see cref="IProcess"/> of the <paramref name="session"/> using the given
61+
/// <paramref name="setter"/>. Returns false, if the
62+
/// operation could not be executed.
63+
/// </summary>
64+
/// <typeparam name="TInstance">The expected type of the product instance</typeparam>
65+
/// <param name="session">The sessopm holding the product instance</param>
66+
/// <param name="setter">The action to be executed on the product instance</param>
67+
/// <example>
68+
/// <code>
69+
/// <![CDATA[
70+
/// session.TryModifyingProductInstance<MyProductInstance>((var instance) => instance.MyProperty = 1)
71+
/// ]]>
72+
/// </code>
73+
/// </example>
74+
public static bool TryModifyProductInstance<TInstance>(this Session session, Action<TInstance> setter)
75+
where TInstance : IProductInstance => session.Process.TryModifyProductInstance(setter);
76+
77+
/// <summary>
78+
/// Extension method to get the <see cref="Activity"/> from the <paramref name="session"/>
79+
/// </summary>
80+
/// <typeparam name="TActivityType">Type of the <see cref="Activity"/> that is expected.</typeparam>
81+
/// <param name="session">The sesion to get the <see cref="Activity"/> from</param>
82+
/// <returns>
83+
/// The <see cref="Activity"/> in the session, if the <paramref name="session"/> currently handles an
84+
/// Activity of type <typeparamref name="TActivityType"/>; Otherwise returns null
85+
/// </returns>
86+
public static TActivityType GetActivity<TActivityType>(this Session session) where TActivityType : Activity
87+
{
88+
if (session is ActivityCompleted completed)
89+
return completed.CompletedActivity as TActivityType;
90+
if (session is ActivityStart start)
91+
return start.Activity as TActivityType;
92+
93+
return null;
94+
}
95+
96+
/// <summary>
97+
/// Extension method to get the last <see cref="Activity"/> from the <paramref name="session"/>
98+
/// </summary>
99+
/// <typeparam name="TActivityType">Type of the <see cref="Activity"/> that is expected.</typeparam>
100+
/// <param name="session">The sesion to get the <see cref="Activity"/> from</param>
101+
/// <returns>
102+
/// The last <see cref="Activity"/> in the session, if the <paramref name="session"/> currently handles an
103+
/// Activity of type <typeparamref name="TActivityType"/>; Otherwise returns null
104+
/// </returns>
105+
public static TActivityType GetLastActivity<TActivityType>(this Session session) where TActivityType : Activity
106+
=> session.Process.LastActivity<TActivityType>() as TActivityType;
107+
108+
/// <summary>
109+
/// Extension method to get the <see cref="ProductType"/> from the <paramref name="session"/>
110+
/// </summary>
111+
/// <typeparam name="TProductType">Type of the <see cref="ProductType"/> that is expected.</typeparam>
112+
/// <param name="session">The session to get the <see cref="ProductType"/> from</param>
113+
/// <returns>
114+
/// The target <see cref="ProductType"/> in the session, if it belongs to a <see cref="ProductionProcess"/>
115+
/// or holds an <see cref="ISetupRecipe"/> with a <typeparamref name="TProductType"/>; Otherwise returns null.
116+
/// </returns>
117+
public static TProductType GetProductType<TProductType>(this Session session) where TProductType : ProductType
118+
{
119+
if (session.Process.Recipe is ISetupRecipe setupRecipe)
120+
return setupRecipe.TargetRecipe.Target as TProductType;
121+
122+
if (session.Process.Recipe is IProductRecipe prodcutRecipe)
123+
return prodcutRecipe.Target as TProductType;
124+
125+
return default;
126+
}
127+
}
128+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) 2024, Phoenix Contact GmbH & Co. KG
2+
// Licensed under the Apache License, Version 2.0
3+
4+
using Moryx.AbstractionLayer.Recipes;
5+
using Moryx.ControlSystem.Recipes;
6+
using Moryx.ControlSystem.Setups;
7+
8+
namespace Moryx.ControlSystem.Jobs
9+
{
10+
/// <summary>
11+
/// Extensions methods for <see cref="Job"/>s.
12+
/// </summary>
13+
public static class JobExtensions
14+
{
15+
/// <summary>
16+
/// Checks whether the <paramref name="job"/> is an <see cref="IPredictiveJob"/>
17+
/// and gets the predicted failure count; otherwise returns 0.
18+
/// </summary>
19+
public static int CountPredictedFailures(this Job job)
20+
{
21+
if (job is IPredictiveJob predictiveJob)
22+
return predictiveJob.PredictedFailures.Count;
23+
24+
return 0;
25+
}
26+
27+
/// <summary>
28+
/// Checks if the <paramref name="job"/> references an <see cref="IProductionRecipe"/>
29+
/// </summary>
30+
public static bool IsProduction(this Job job) => job.Recipe is IProductionRecipe;
31+
32+
/// <summary>
33+
/// Checks if the <paramref name="job"/> references an <see cref="ISetupRecipe"/>
34+
/// </summary>
35+
public static bool IsSetup(this Job job) => job.Recipe is ISetupRecipe;
36+
37+
/// <summary>
38+
/// Checks if the <paramref name="job"/> holds an <see cref="ISetupRecipe"/>
39+
/// that is set to be executed <see cref="SetupExecution.BeforeProduction"/>
40+
/// </summary>
41+
public static bool IsPreparingSetup(this Job job)
42+
=> job.Recipe is ISetupRecipe setup && setup.Execution == SetupExecution.BeforeProduction;
43+
44+
/// <summary>
45+
/// Checks if the <paramref name="job"/> holds an <see cref="ISetupRecipe"/>
46+
/// that is set to be executed <see cref="SetupExecution.AfterProduction"/>
47+
/// </summary>
48+
public static bool IsCleaningUpSetup(this Job job)
49+
=> job.Recipe is ISetupRecipe setup && setup.Execution == SetupExecution.AfterProduction;
50+
}
51+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using Moryx.AbstractionLayer.Products;
2+
using Moryx.AbstractionLayer;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Text;
6+
7+
namespace Moryx.ControlSystem.Processes
8+
{
9+
/// <summary>
10+
/// Extensions on an <see cref="IProcess"/>
11+
/// </summary>
12+
public static class IProcessExtensions
13+
{
14+
/// <summary>
15+
/// Modifies the <see cref="IProductInstance"/> of type <typeparamref name="TInstance"/>
16+
/// on the <see cref="IProcess"/> using the given <paramref name="setter"/>.
17+
/// </summary>
18+
/// <typeparam name="TInstance">The expected type of the product instance</typeparam>
19+
/// <param name="process">The process holding the product instance</param>
20+
/// <param name="setter">The action to be executed on the product instance</param>
21+
/// <example>
22+
/// <code>
23+
/// <![CDATA[
24+
/// process.ModifyProductInstance<MyProductInstance>((var instance) => instance.MyProperty = 1)
25+
/// ]]>
26+
/// </code>
27+
/// </example>
28+
/// <exception cref="InvalidCastException">Thrown if the given <paramref name="process"/> does
29+
/// not hold a product instance of type <typeparamref name="TInstance"/></exception>
30+
/// <exception cref="InvalidOperationException">Thrown if the given <paramref name="process"/>
31+
/// is no <see cref="ProductionProcess"/></exception>
32+
public static TInstance ModifyProductInstance<TInstance>(this IProcess process, Action<TInstance> setter)
33+
where TInstance : IProductInstance
34+
{
35+
if (process is not ProductionProcess productionProcess)
36+
throw new InvalidOperationException($"Cannot modify an {nameof(IProductInstance)} on a process of type {process.GetType()}");
37+
if (productionProcess.ProductInstance is not TInstance instance)
38+
throw new InvalidCastException($"Cannot cast {nameof(ProductionProcess.ProductInstance)} of type " +
39+
$"{productionProcess?.ProductInstance?.GetType()} to {typeof(TInstance)}");
40+
setter.Invoke(instance);
41+
return instance;
42+
}
43+
44+
/// <summary>
45+
/// Tries to modifies the <see cref="IProductInstance"/> of type <typeparamref name="TInstance"/>
46+
/// on the <see cref="IProcess"/> using the given <paramref name="setter"/>. Returns false, if the
47+
/// operation could not be executed.
48+
/// </summary>
49+
/// <typeparam name="TInstance">The expected type of the product instance</typeparam>
50+
/// <param name="process">The process holding the product instance</param>
51+
/// <param name="setter">The action to be executed on the product instance</param>
52+
/// <example>
53+
/// <code>
54+
/// <![CDATA[
55+
/// process.TryModifyingProductInstance<MyProductInstance>((var instance) => instance.MyProperty = 1)
56+
/// ]]>
57+
/// </code>
58+
/// </example>
59+
public static bool TryModifyProductInstance<TInstance>(this IProcess process, Action<TInstance> setter)
60+
where TInstance : IProductInstance
61+
{
62+
if (process is not ProductionProcess productionProcess)
63+
return false;
64+
if (productionProcess.ProductInstance is not TInstance instance)
65+
return false;
66+
setter.Invoke(instance);
67+
return true;
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)