blob: f0210a90c6b6f841f72157ba67e0253478f81f70 [file] [log] [blame]
Constantin Ziesche857c7ab2020-02-25 11:24:51 +01001/*******************************************************************************
2* Copyright (c) 2020 Robert Bosch GmbH
3* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
4*
5* This program and the accompanying materials are made available under the
6* terms of the Eclipse Distribution License 1.0 which is available at
7* https://www.eclipse.org/org/documents/edl-v10.html
8*
9*
10*******************************************************************************/
11using BaSyx.API.AssetAdministrationShell;
12using BaSyx.API.Components;
13using BaSyx.Models.Connectivity;
14using BaSyx.Models.Core.AssetAdministrationShell.Enums;
15using BaSyx.Models.Core.AssetAdministrationShell.Generics;
16using BaSyx.Models.Core.AssetAdministrationShell.Generics.SubmodelElementTypes;
17using BaSyx.Models.Core.AssetAdministrationShell.Identification;
18using BaSyx.Models.Core.AssetAdministrationShell.Implementations;
19using BaSyx.Models.Core.AssetAdministrationShell.Implementations.SubmodelElementTypes;
20using BaSyx.Models.Core.AssetAdministrationShell.References;
21using BaSyx.Models.Core.AssetAdministrationShell.Semantics;
22using BaSyx.Models.Core.Common;
23using BaSyx.Models.Extensions;
24using BaSyx.Models.Extensions.Semantics.DataSpecifications;
25using BaSyx.Utils.Client;
26using BaSyx.Utils.Client.Mqtt;
Constantin Zieschefa612082020-04-03 09:54:56 +020027using BaSyx.Utils.ResultHandling;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010028using System;
29using System.Collections.Generic;
30using System.Threading;
31using System.Threading.Tasks;
32
33namespace HelloAssetAdministrationShell
34{
35 public class HelloAssetAdministrationShellService : AssetAdministrationShellServiceProvider
36 {
37 public override IAssetAdministrationShell AssetAdministrationShell { get; protected set; }
38
39 private SubmodelServiceProvider helloSubmodelServiceProvider;
40 private SubmodelServiceProvider assetIdentificationSubmodelProvider;
41
42 private IMessageClient messageClient;
43 private CancellationTokenSource cancellationToken;
44
45 public HelloAssetAdministrationShellService()
46 {
47 helloSubmodelServiceProvider = new SubmodelServiceProvider();
48 helloSubmodelServiceProvider.BindTo(AssetAdministrationShell.Submodels["HelloSubmodel"]);
49 helloSubmodelServiceProvider.RegisterMethodCalledHandler("HelloOperation", HelloOperationHandler);
50 helloSubmodelServiceProvider.RegisterPropertyHandler("HelloProperty",
51 new PropertyHandler(HelloPropertyGetHandler, HelloPropertySetHandler));
52 helloSubmodelServiceProvider.ConfigureEventHandler(messageClient);
53 this.RegisterSubmodelServiceProvider("HelloSubmodel", helloSubmodelServiceProvider);
54
55 assetIdentificationSubmodelProvider = new SubmodelServiceProvider();
56 assetIdentificationSubmodelProvider.BindTo(AssetAdministrationShell.Submodels["AssetIdentification"]);
57 assetIdentificationSubmodelProvider.UseInMemoryPropertyHandler();
58 this.RegisterSubmodelServiceProvider("AssetIdentification", assetIdentificationSubmodelProvider);
59
60
61
62 InitializeMessageClient();
63
64 cancellationToken = new CancellationTokenSource();
65 Task.Factory.StartNew(async() =>
66 {
67 while(!cancellationToken.IsCancellationRequested)
68 {
69 Run();
70 await Task.Delay(5000);
71 }
72 }, cancellationToken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
73 }
74
75 private void InitializeMessageClient()
76 {
77 messageClient = new SimpleMqttClient(
78 new MqttConfig(
79 Guid.NewGuid().ToString(),
80 "mqtt://127.0.0.1:1883"));
81 messageClient.Start();
82 }
83
84 public void Run()
85 {
86 helloSubmodelServiceProvider.ThrowEvent(new PublishableEvent()
87 {
Constantin Ziesche02817f12020-08-04 21:40:43 +020088 EventReference = new Reference<IEvent>(AssetAdministrationShell.Submodels["HelloSubmodel"].SubmodelElements["HelloEvent"].Cast<IEvent>()),
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010089 Originator = "HelloAssetAdministrationShell",
90 Timestamp = DateTime.Now.ToString(),
91 Message = "Pew Pew",
92 }, "/" + AssetAdministrationShell.IdShort + "/submodels/HelloSubmodel/HelloEvent", null, 2);
93 }
94
95 private void HelloPropertySetHandler(IProperty property, IValue value)
96 {
Constantin Ziesche02817f12020-08-04 21:40:43 +020097 AssetAdministrationShell.Submodels["HelloSubmodel"].SubmodelElements["HelloProperty"].Cast<IProperty>().Value = value.Value;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010098 }
99
100 private IValue HelloPropertyGetHandler(IProperty property)
101 {
Constantin Ziesche02817f12020-08-04 21:40:43 +0200102 var localProperty = AssetAdministrationShell.Submodels["HelloSubmodel"].SubmodelElements["HelloProperty"].Cast<IProperty>();
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100103 return new ElementValue(localProperty.Value, localProperty.ValueType);
104 }
105
Constantin Zieschefa612082020-04-03 09:54:56 +0200106 private Task<OperationResult> HelloOperationHandler(IOperation operation, IOperationVariableSet inputArguments, IOperationVariableSet outputArguments)
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100107 {
108 if (inputArguments?.Count > 0)
109 {
110 outputArguments.Add(
111 new Property<string>()
112 {
113 IdShort = "ReturnValue",
Constantin Ziesche02817f12020-08-04 21:40:43 +0200114 Value = "Hello '" + inputArguments["Text"].Cast<IProperty>().ToObject<string>() + "'"
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100115 });
116 return new OperationResult(true);
117 }
118 return new OperationResult(false);
119 }
120
121 public override IAssetAdministrationShell GenerateAssetAdministrationShell()
122 {
123 AssetAdministrationShell aas = new AssetAdministrationShell();
124
125 aas.IdShort = "HelloAAS";
126 aas.Identification = new Identifier("http://basys40.de/shells/HelloAAS/" + Guid.NewGuid().ToString(), KeyType.IRI);
127 aas.Description = new LangStringSet() { new LangString("en-US", "This is an exemplary Asset Administration Shell for starters") };
128
129 aas.Asset = new Asset()
130 {
131 Description = new LangStringSet() { new LangString("en-US", "This is an exemplary Asset reference from the Asset Administration Shell") },
132 IdShort = "HelloAsset",
133 Identification = new Identifier("http://basys40.de/assets/HelloAsset/" + Guid.NewGuid().ToString(), KeyType.IRI),
134 Kind = AssetKind.Instance,
135 SemanticId = new Reference(new GlobalKey(KeyElements.Asset, KeyType.IRI, "urn:basys:org.eclipse.basyx:assets:HelloAsset:1.0.0"))
136 };
137
138 Submodel helloSubmodel = new Submodel
139 {
140 Description = new LangStringSet() { new LangString("en-US", "This is an exemplary Submodel") },
141 IdShort = "HelloSubmodel",
142 Identification = new Identifier("http://basys40.de/submodels/HelloSubmodel/" + Guid.NewGuid().ToString(), KeyType.IRI),
143 Kind = ModelingKind.Instance,
144 SemanticId = new Reference(new GlobalKey(KeyElements.Submodel, KeyType.IRI, "urn:basys:org.eclipse.basyx:submodels:HelloSubmodel:1.0.0"))
145 };
146
147 helloSubmodel.SubmodelElements = new ElementContainer<ISubmodelElement>();
148 helloSubmodel.SubmodelElements.Add(new Property<string>()
149 {
150 Description = new LangStringSet() { new LangString("en-US", "This is an exemplary property") },
151 IdShort = "HelloProperty",
152 Kind = ModelingKind.Instance,
153 Value = "TestValue",
154 SemanticId = new Reference(new GlobalKey(KeyElements.Property, KeyType.IRI, "urn:basys:org.eclipse.basyx:dataElements:HelloProperty:1.0.0"))
155 });
156
157 helloSubmodel.SubmodelElements.Add(new File()
158 {
159 Description = new LangStringSet() { new LangString("en-US", "This is an exemplary file attached to the Asset Administration Shell")},
160 IdShort = "HelloFile",
161 Kind = ModelingKind.Instance,
162 MimeType = "application/pdf",
163 Value = "/HelloAssetAdministrationShell.pdf"
164 });
165
166
167 var helloOperation_ConceptDescription = new ConceptDescription()
168 {
169 Identification = new Identifier("urn:basys:org.eclipse.basyx:dataSpecifications:EndpointSpecification:1.0.0", KeyType.IRI),
170 EmbeddedDataSpecifications = new List<IEmbeddedDataSpecification>()
171 {
172 new EndpointSpecification(
173 new EndpointSpecificationContent()
174 {
175 Endpoints = new List<IEndpoint>() { new OpcUaEndpoint("opc.tcp://127.0.0.1:4840/Objects/1:HelloAAS/1:SERVICE/1:TestOperation") }
176 })
177 }
178 };
179
180 helloSubmodel.SubmodelElements.Add(new Operation()
181 {
182 Description = new LangStringSet() { new LangString("en-US", "This is an exemplary operation returning the input argument with 'Hello' as prefix") },
183 IdShort = "HelloOperation",
184 InputVariables = new OperationVariableSet() { new Property<string>() { IdShort = "Text" } },
185 OutputVariables = new OperationVariableSet() { new Property<string>() { IdShort = "ReturnValue" } },
186 ConceptDescription = helloOperation_ConceptDescription
187 });
188
189 helloSubmodel.SubmodelElements.Add(new Event()
190 {
191 Description = new LangStringSet() { new LangString("en-US", "This is an exemplary event with only one property as event payload") },
192 IdShort = "HelloEvent",
193 Kind = ModelingKind.Template,
194 DataElements = new ElementContainer<ISubmodelElement>()
195 {
196 new Property<string>()
197 {
198 IdShort = "HelloEvent_Property",
199 Kind = ModelingKind.Template
200 }
201 }
202
203 });
204
205 aas.Submodels = new ElementContainer<ISubmodel>();
206 aas.Submodels.Add(helloSubmodel);
207
208 var assetIdentificationSubmodel = new Submodel();
209 assetIdentificationSubmodel.IdShort = "AssetIdentification";
210 assetIdentificationSubmodel.Identification = new Identifier(Guid.NewGuid().ToString(), KeyType.Custom);
211 assetIdentificationSubmodel.Kind = ModelingKind.Instance;
212 assetIdentificationSubmodel.Parent = new Reference<IAssetAdministrationShell>(aas);
213
214 var productTypeProp = new Property<string>()
215 {
216 IdShort = "ProductType",
217 Kind = ModelingKind.Instance,
218 SemanticId = new Reference(
219 new GlobalKey(
220 KeyElements.Property,
221 KeyType.IRDI,
222 "0173-1#02-AAO057#002")),
223 Value = "HelloAsset_ProductType"
224 };
225
226 ConceptDescription orderNumberCD = new ConceptDescription()
227 {
228 Identification = new Identifier("0173-1#02-AAO689#001", KeyType.IRDI),
229 EmbeddedDataSpecifications = new List<IEmbeddedDataSpecification>()
230 {
231 new DataSpecificationIEC61360(new DataSpecificationIEC61360Content()
232 {
233 PreferredName = new LangStringSet { new LangString("EN", "identifying order number") },
234 Definition = new LangStringSet { new LangString("EN", "unique classifying number that enables to name an object and to order it from a supplier or manufacturer") },
235 DataType = DataTypeIEC61360.STRING
236 })
237 }
238 };
239
240 var orderNumber = new Property<string>()
241 {
242 IdShort = "OrderNumber",
243 Kind = ModelingKind.Instance,
244 SemanticId = new Reference(
245 new GlobalKey(
246 KeyElements.Property,
247 KeyType.IRDI,
248 "0173-1#02-AAO689#001")),
249 Value = "HelloAsset_OrderNumber",
250 ConceptDescription = orderNumberCD
251 };
252
253 var serialNumber = new Property<string>()
254 {
255 IdShort = "SerialNumber",
256 Kind = ModelingKind.Instance,
257 Value = "HelloAsset_SerialNumber"
258 };
259
260 assetIdentificationSubmodel.SubmodelElements.Add(productTypeProp);
261 assetIdentificationSubmodel.SubmodelElements.Add(orderNumber);
262 assetIdentificationSubmodel.SubmodelElements.Add(serialNumber);
263
264 (aas.Asset as Asset).AssetIdentificationModel = new Reference<ISubmodel>(assetIdentificationSubmodel);
265
266 aas.Submodels.Add(assetIdentificationSubmodel);
267
268 return aas;
269 }
270 }
271}