blob: 9b2543b58b852e1d5099d840012f30dd00ff1525 [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 Public License 2.0 which is available at
7* http://www.eclipse.org/legal/epl-2.0
8*
9* SPDX-License-Identifier: EPL-2.0
10*******************************************************************************/
11using BaSyx.API.AssetAdministrationShell;
12using BaSyx.Models.Core.AssetAdministrationShell.Generics;
13using BaSyx.Models.Core.AssetAdministrationShell.Implementations;
14using BaSyx.Utils.ResultHandling;
15using BaSyx.Utils.Client;
16using System.Collections.Generic;
17using System;
18using Newtonsoft.Json;
19using System.Reflection;
20using System.Linq.Expressions;
21using System.Linq;
22using BaSyx.Models.Extensions;
23using BaSyx.Models.Connectivity.Descriptors;
24using BaSyx.Models.Core.Common;
25using BaSyx.Models.Core.AssetAdministrationShell.Generics.SubmodelElementTypes;
26
27namespace BaSyx.API.Components
28{
29 public class SubmodelServiceProvider : ISubmodelServiceProvider
30 {
31 public static JsonSerializerSettings JsonSerializerSettings { get; set; }
32 static SubmodelServiceProvider()
33 {
34 JsonSerializerSettings = new JsonStandardSettings();
35 }
36
37 public ISubmodel Submodel { get; protected set; }
38 public ISubmodelDescriptor ServiceDescriptor { get; internal set; }
39
40 private Dictionary<string, Delegate> methodCalledHandler;
41 private Dictionary<string, PropertyHandler> propertyHandler;
42 private Dictionary<string, Action<IValue>> updateFunctions;
43 private Dictionary<string, EventDelegate> eventDelegates;
44
45 private IMessageClient messageClient;
46
47 private readonly GetPropertyValueHandler GenericPropertyGetHandler = de => { return new ElementValue(de.Value, de.ValueType); };
48 private readonly SetPropertyValueHandler GenericPropertySetHandler = (de, val) => { de.Value = val.Value; };
49
50 public SubmodelServiceProvider()
51 {
52 methodCalledHandler = new Dictionary<string, Delegate>();
53 propertyHandler = new Dictionary<string, PropertyHandler>();
54 updateFunctions = new Dictionary<string, Action<IValue>>();
55 eventDelegates = new Dictionary<string, EventDelegate>();
56 }
57
58 public SubmodelServiceProvider(ISubmodel submodel) : this()
59 {
60 BindTo(submodel);
61 }
62 public SubmodelServiceProvider(ISubmodel submodel, ISubmodelDescriptor submodelDescriptor) : this()
63 {
64 Submodel = submodel;
65 ServiceDescriptor = submodelDescriptor;
66 }
67
68 public void BindTo(ISubmodel element)
69 {
70 Submodel = element;
71 ServiceDescriptor = new SubmodelDescriptor(element, null);
72 }
73 public ISubmodel GetBinding()
74 {
75 return Submodel;
76 }
77
78 public void UseInMemoryPropertyHandler()
79 {
80 if(Submodel.Properties?.Count() > 0)
81 foreach (var property in Submodel.Properties)
82 {
83 RegisterPropertyHandler(property.IdShort,
84 new PropertyHandler(property.Get ?? GenericPropertyGetHandler, property.Set ?? GenericPropertySetHandler));
85 }
86 }
87
88 public void UsePropertyHandler(PropertyHandler propertyHandler)
89 {
90 if (Submodel.Properties?.Count() > 0)
91 foreach (var property in Submodel.Properties)
92 RegisterPropertyHandler(property.IdShort, propertyHandler);
93 }
94
95 public void UseOperationHandler(MethodCalledHandler methodCalledHandler)
96 {
97 if (Submodel.Operations?.Count() > 0)
98 foreach (var operation in Submodel.Operations)
99 RegisterMethodCalledHandler(operation.IdShort, methodCalledHandler);
100 }
101
102 public IResult<IEvent> CreateEvent(IEvent eventable)
103 {
104 if (Submodel == null)
105 return new Result<IEvent>(false, new NotFoundMessage("Submodel"));
106
107 return Submodel.SubmodelElements.Create(eventable);
108 }
109
110 public IResult<IOperation> CreateOperation(IOperation operation)
111 {
112 if (Submodel == null)
113 return new Result<IOperation>(false, new NotFoundMessage("Submodel"));
114
115 return Submodel.SubmodelElements.Create(operation);
116 }
117
118 public IResult<IProperty> CreateProperty(IProperty property)
119 {
120 if (Submodel == null)
121 return new Result<IProperty>(false, new NotFoundMessage("Submodel"));
122
123 RegisterPropertyHandler(property.IdShort,
124 new PropertyHandler(property.Get ?? GenericPropertyGetHandler, property.Set ?? GenericPropertySetHandler));
125
126 return Submodel.SubmodelElements.Create(property);
127 }
128
129 public IResult DeleteEvent(string eventId)
130 {
131 if (Submodel == null)
132 return new Result(false, new NotFoundMessage("Submodel"));
133
134 if (Submodel.Events == null)
135 return new Result(false, new NotFoundMessage(eventId));
136 return Submodel.SubmodelElements.Delete(eventId);
137 }
138
139 public IResult DeleteOperation(string operationId)
140 {
141 if (Submodel == null)
142 return new Result(false, new NotFoundMessage("Submodel"));
143
144 if (Submodel.Operations == null)
145 return new Result(false, new NotFoundMessage(operationId));
146 return Submodel.SubmodelElements.Delete(operationId);
147 }
148
149 public IResult DeleteProperty(string propertyId)
150 {
151 if (Submodel == null)
152 return new Result(false, new NotFoundMessage("Submodel"));
153
154 if (Submodel.Properties == null)
155 return new Result(false, new NotFoundMessage(propertyId));
156
157 if (propertyHandler.ContainsKey(propertyId))
158 propertyHandler.Remove(propertyId);
159
160 return Submodel.SubmodelElements.Delete(propertyId);
161 }
162
163 public MethodCalledHandler RetrieveMethodCalledHandler(string operationId)
164 {
165 if (methodCalledHandler.TryGetValue(operationId, out Delegate handler))
166 return (MethodCalledHandler)handler;
167 else
168 return null;
169 }
170
171 public Delegate RetrieveMethodDelegate(string operationId)
172 {
173 if (methodCalledHandler.TryGetValue(operationId, out Delegate handler))
174 return handler;
175 else
176 return null;
177 }
178
179 public PropertyHandler RetrievePropertyHandler(string propertyId)
180 {
181 if (propertyHandler.TryGetValue(propertyId, out PropertyHandler handler))
182 return handler;
183 else
184 return null;
185 }
186
187 public void RegisterPropertyHandler(string propertyId, PropertyHandler handler)
188 {
189 if (!propertyHandler.ContainsKey(propertyId))
190 propertyHandler.Add(propertyId, handler);
191 else
192 propertyHandler[propertyId] = handler;
193 }
194
195 public void RegisterMethodCalledHandler(string operationId, MethodCalledHandler handler)
196 {
197 if (!methodCalledHandler.ContainsKey(operationId))
198 methodCalledHandler.Add(operationId, handler);
199 else
200 methodCalledHandler[operationId] = handler;
201 }
202
203 public void RegisterMethodCalledHandler(string operationId, Delegate handler)
204 {
205 if (!methodCalledHandler.ContainsKey(operationId))
206 methodCalledHandler.Add(operationId, handler);
207 else
208 methodCalledHandler[operationId] = handler;
209 }
210
211 public void RegisterEventDelegate(string eventId, EventDelegate eventDelegate)
212 {
213 if (!eventDelegates.ContainsKey(eventId))
214 eventDelegates.Add(eventId, eventDelegate);
215 else
216 eventDelegates[eventId] = eventDelegate;
217 }
218
219 public void RegisterMethodCalledHandler(string operationId, MethodInfo methodInfo, object target)
220 {
221 var parameters = from parameter in methodInfo.GetParameters() select parameter.ParameterType;
222 Delegate del = methodInfo.CreateDelegate(Expression.GetDelegateType(parameters.Concat(new[] { methodInfo.ReturnType }).ToArray()), target);
223 RegisterMethodCalledHandler(operationId, del);
224 }
225
226 public IResult InvokeOperation(string operationId, IOperationVariableSet inputArguments, IOperationVariableSet outputArguments, int timeout)
227 {
228 if (Submodel == null)
229 return new Result(false, new NotFoundMessage("Submodel"));
230
231 var operation_Retrieved = RetrieveOperation(operationId);
232 if (operation_Retrieved.Success && operation_Retrieved.Entity != null)
233 {
234 if (operation_Retrieved.Entity.OnMethodCalled != null)
235 {
236 var result = operation_Retrieved.Entity.OnMethodCalled.Invoke(operation_Retrieved.Entity, inputArguments, outputArguments);
237 return result;
238 }
239 else if (methodCalledHandler.TryGetValue(operationId, out Delegate handler))
240 {
241 var result = (IResult)handler.DynamicInvoke(operation_Retrieved.Entity, inputArguments, outputArguments);
242 return result;
243 }
244 }
245 outputArguments = null;
246 return operation_Retrieved;
247 }
248
249 public IResult ThrowEvent(IPublishableEvent publishableEvent, string topic = "/", Action<IMessagePublishedEventArgs> MessagePublished = null, byte qosLevel = 2, bool retain = false)
250 {
251 if (messageClient == null || !messageClient.IsConnected)
252 return new Result(false, new Message(MessageType.Warning, "MessageClient is not initialized or not connected"));
253
254 if (publishableEvent == null)
255 return new Result(new ArgumentNullException("publishableEvent"));
256
257 if (eventDelegates.TryGetValue(publishableEvent.Name, out EventDelegate eventDelegate))
258 eventDelegate.Invoke(this, publishableEvent);
259
260 string message = JsonConvert.SerializeObject(publishableEvent, JsonSerializerSettings);
261 return messageClient.Publish(topic, message, MessagePublished, qosLevel, retain);
262 }
263
264 public IResult<IEvent> RetrieveEvent(string eventId)
265 {
266 if (Submodel == null)
267 return new Result<IEvent>(false, new NotFoundMessage("Submodel"));
268
269 if (Submodel.Events == null)
270 return new Result<IEvent>(false, new NotFoundMessage(eventId));
271 return Submodel.SubmodelElements.Retrieve<IEvent>(eventId);
272 }
273
274 public IResult<IElementContainer<IEvent>> RetrieveEvents()
275 {
276 if (Submodel == null)
277 return new Result<ElementContainer<IEvent>>(false, new NotFoundMessage("Submodel"));
278
279 if(Submodel.Events == null)
280 return new Result<ElementContainer<IEvent>>(false, new NotFoundMessage("Events"));
281 return Submodel.SubmodelElements.RetrieveAll<IEvent>();
282 }
283
284 public IResult<IOperation> RetrieveOperation(string operationId)
285 {
286 if (Submodel == null)
287 return new Result<IOperation>(false, new NotFoundMessage("Submodel"));
288
289 if (Submodel.Operations == null)
290 return new Result<IOperation>(false, new NotFoundMessage(operationId));
291 return Submodel.SubmodelElements.Retrieve<IOperation>(operationId);
292 }
293
294 public IResult<IElementContainer<IOperation>> RetrieveOperations()
295 {
296 if (Submodel == null)
297 return new Result<ElementContainer<IOperation>>(false, new NotFoundMessage("Submodel"));
298
299 if (Submodel.Operations == null)
300 return new Result<ElementContainer<IOperation>>(false, new NotFoundMessage("Operations"));
301 return Submodel.SubmodelElements.RetrieveAll<IOperation>();
302 }
303
304 public IResult<IElementContainer<IProperty>> RetrieveProperties()
305 {
306 if (Submodel == null)
307 return new Result<ElementContainer<IProperty>>(false, new NotFoundMessage("Submodel"));
308
309 if (Submodel.Properties == null)
310 return new Result<ElementContainer<IProperty>>(false, new NotFoundMessage("Properties"));
311 return Submodel.SubmodelElements.RetrieveAll<IProperty>();
312 }
313
314 public IResult<IProperty> RetrieveProperty(string propertyId)
315 {
316 if (Submodel == null)
317 return new Result<IProperty>(false, new NotFoundMessage("Submodel"));
318
319 if (Submodel.Properties == null)
320 return new Result<IProperty>(false, new NotFoundMessage(propertyId));
321 return Submodel.SubmodelElements.Retrieve<IProperty>(propertyId);
322 }
323
324 public IResult<IValue> RetrievePropertyValue(string propertyId)
325 {
326 if (Submodel == null)
327 return new Result<IValue>(false, new NotFoundMessage("Submodel"));
328
329 if (propertyHandler.TryGetValue(propertyId, out PropertyHandler handler) && handler.GetHandler != null)
330 {
331 var property = RetrieveProperty(propertyId);
332 if(property.Success && property.Entity != null)
333 return new Result<IValue>(true, handler.GetHandler.Invoke(property.Entity));
334 else
335 return new Result<IValue>(false, new Message(MessageType.Error, "property not found"));
336 }
337 else
338 return new Result<IValue>(false, new Message(MessageType.Error, "propertyHandler or GetHandler not found"));
339 }
340
341
342 public IResult UpdatePropertyValue(string propertyId, IValue value)
343 {
344 if (Submodel == null)
345 return new Result(false, new NotFoundMessage("Submodel"));
346
347 if (propertyHandler.TryGetValue(propertyId, out PropertyHandler handler) && handler.SetHandler != null)
348 {
349 var property = RetrieveProperty(propertyId);
350 if (property.Success && property.Entity != null)
351 {
352 handler.SetHandler.Invoke(property.Entity, value);
353 return new Result(true);
354 }
355 else
356 return new Result<IValue>(false, new Message(MessageType.Error, "property not found"));
357 }
358 else
359 return new Result<IValue>(false, new Message(MessageType.Error, "propertyHandler or SetHandler not found"));
360 }
361
362 public virtual void ConfigureEventHandler(IMessageClient messageClient)
363 {
364 this.messageClient = messageClient;
365 }
366
367 public virtual void SubscribeUpdates(string propertyId, Action<IValue> updateFunction)
368 {
369 if (!updateFunctions.ContainsKey(propertyId))
370 updateFunctions.Add(propertyId, updateFunction);
371 else
372 updateFunctions[propertyId] = updateFunction;
373 }
374
375 public virtual void PublishUpdate(string propertyId, IValue value)
376 {
377 if (updateFunctions.TryGetValue(propertyId, out Action<IValue> updateFunction))
378 updateFunction.Invoke(value);
379
380 }
381
382 public IResult<ISubmodel> RetrieveSubmodel()
383 {
384 var submodel = GetBinding();
385 return new Result<ISubmodel>(submodel != null, submodel);
386 }
387
388 public IResult<ISubmodelElement> CreateSubmodelElement(ISubmodelElement submodelElement)
389 {
390 if (Submodel == null)
391 return new Result<ISubmodelElement>(false, new NotFoundMessage("Submodel"));
392
393 return Submodel.SubmodelElements.Create(submodelElement);
394 }
395
396 public IResult<IElementContainer<ISubmodelElement>> RetrieveSubmodelElements()
397 {
398 if (Submodel == null)
399 return new Result<ElementContainer<ISubmodelElement>>(false, new NotFoundMessage("Submodel"));
400
401 if (Submodel.SubmodelElements == null)
402 return new Result<ElementContainer<ISubmodelElement>>(false, new NotFoundMessage("SubmodelElements"));
403 return Submodel.SubmodelElements.RetrieveAll();
404 }
405
406 public IResult<ISubmodelElement> RetrieveSubmodelElement(string submodelElementId)
407 {
408 if (Submodel == null)
409 return new Result<ISubmodelElement>(false, new NotFoundMessage("Submodel"));
410
411 if (Submodel.SubmodelElements == null)
412 return new Result<ISubmodelElement>(false, new NotFoundMessage(submodelElementId));
413 return Submodel.SubmodelElements.Retrieve(submodelElementId);
414 }
415
416 public IResult<IValue> RetrieveSubmodelElementValue(string submodelElementId)
417 {
418 if (Submodel == null)
419 return new Result<IValue>(false, new NotFoundMessage("Submodel"));
420
421 if (Submodel.SubmodelElements == null)
422 return new Result<IValue>(false, new NotFoundMessage(submodelElementId));
423
424 return new Result<IValue>(true,
425 new ElementValue(
426 (Submodel.SubmodelElements[submodelElementId] as dynamic).Value,
427 (Submodel.SubmodelElements[submodelElementId] as dynamic).ValueType as DataType));
428 }
429
430 public IResult UpdateSubmodelElement(string submodelElementId, ISubmodelElement submodelElement)
431 {
432 if (Submodel == null)
433 return new Result(false, new NotFoundMessage("Submodel"));
434
435 if (Submodel.SubmodelElements == null)
436 return new Result(false, new NotFoundMessage(submodelElementId));
437
438 return Submodel.SubmodelElements.Update(submodelElementId, submodelElement);
439 }
440
441 public IResult DeleteSubmodelElement(string submodelElementId)
442 {
443 if (Submodel == null)
444 return new Result(false, new NotFoundMessage("Submodel"));
445
446 if (Submodel.SubmodelElements == null)
447 return new Result(false, new NotFoundMessage(submodelElementId));
448
449 return Submodel.SubmodelElements.Delete(submodelElementId);
450 }
451 }
452}