public void ProcProdSched_WriteSchedulingParameters() { // Testing the writing of scheduling parameters // Creating a schedule to be serialised var schedule = new ProductionSchedule(); var testObject1 = new ProcessProductionSchedule(); testObject1.ProductionSchedules.Add(schedule); var schedulingParameters = new CMeas.Item_DataRecord() { { "myparam", new CMeas.Item_Count(3) } }; // Creating a production request with scheduling parameters var productionRequest = new ProductionRequest { // Setting scheduling parameters. Not testing the parameters thorougly // because the data record is tested elsewhere. SchedulingParameters = schedulingParameters.ToDataRecordPropertyProxy() }; schedule.ProductionRequests.Add(productionRequest); // Serialising validating and deserialising. The test will likely fails here if it fails. var xmlData = testObject1.ToXmlBytes(); var xmlString = System.Text.Encoding.UTF8.GetString(xmlData); // Just for debugging Validate(xmlData); // Asserting AssertSchedulingParameters(new ProcessProductionSchedule(xmlData)); }
public void Observation() { // Observation test // Creating an observation for testing var dataRecord = new MsgMeas.Item_DataRecord() { { "mass", new MsgMeas.Item_Measurement("t", 1.2) }, { "thickness", new MsgMeas.Item_Measurement("cm", 3.5) } }; var observation = new MsgMeas.Observation(dataRecord) { Name = "Some name" }; var msg = observation.ToXmlBytes(); // Extracting metadata var testObject = MetadataExtractor.Build(msg); Assert.AreEqual(ContentTypeType.Xml, testObject.ContentType); Assert.AreEqual("Some name", testObject.Name); Assert.AreEqual("Data record (2 fields)", testObject.PayloadSummary); Assert.AreEqual(PayloadTypeType.ObservationXml, testObject.PayloadType); }
private void AddOneProductionRequest(ItemsControl parent, MsgBiz.ProductionRequest req, int nr) { var prodReqNode = AddNodeToTreeview(parent, "ProductionRequest " + nr); // Add hierarchy scope and identifier var hierarchyScope = req.HierarchyScopeObj ?? null; AddHierarchyScopeIfNotNull(prodReqNode, req.HierarchyScopeObj); AddIdentifierIfNotNull(prodReqNode, "ID", req.Identifier); // Add segment requirements for (int a = 0; a < req.SegmentRequirements.Count; ++a) { AddSegmentRequirement(prodReqNode, req.SegmentRequirements[a], a + 1); } // Add scheduling params if (req.SchedulingParameters != null) { try { // Expecting a data record var paramsDataRec = new MsgMeas.Item_DataRecord((System.Xml.XmlNode[])req.SchedulingParameters); AddNodeToTreeview(prodReqNode, "SchedulingParameters", paramsDataRec); } catch (Exception e) { AddNodeToTreeview(prodReqNode, "SchedulingParameters failed to show: " + e.Message); HandleBug(e); } } }
public void Get() { // Creating a request object var requestObj = new MsgMeas.GetObservationRequest(); // Setting the conditions of the request requestObj.FeaturesOfInterest.Add("myplant/myprocess/mytemperature"); // Adding a data record; use this to whatever additional parameters you need. // This naturally depends on the server. var extensionObj = new MsgMeas.Item_DataRecord() { { "parameter_x", new MsgMeas.Item_Count(3) } }; requestObj.Items.Add(extensionObj); // Adding a temporal filter: retrieve all observation after given time var tempFilter1 = new MsgMeas.TemporalFilter( MsgMeas.TemporalFilter.ValueReferenceType.PhenomenonTime, MsgMeas.TemporalFilter.OperatorType.After, new MsgMeas.Item_TimeInstant(DateTime.Parse("2018-05-18T08:05:44Z").ToUniversalTime()) ); requestObj.TemporalFilters.Add(tempFilter1); // Serialising the request object byte[] requestXml = requestObj.ToXmlBytes(); // Sending the requestXml to the server and waiting for a response... SendRequest(requestXml); byte[] responseXml = WaitForResponse(); // Processing the response MsgMeas.GetObservationResponse responseObj; try { responseObj = new MsgMeas.GetObservationResponse(responseXml); } catch (MsgMeas.Neutral.InvalidMessageException e) { throw new InvalidOperationException("Failed to read server response: " + e.Message, e); } if (responseObj.RequestResult != MsgMeas.RequestResultType.Ok) { throw new InvalidOperationException("Unexpected response from server"); } foreach (var obs in responseObj.Observations) { // Processing the observations... // ... } }
private void AssertSchedulingParameters(ProcessProductionSchedule testObjectIn) { // Use a separate function for assert to prevent asserting the wrong object. // Asserting parameters. Just a simple assert, because Item_DataRecord // is tested elsewhere. var paramNodes = (SXml.XmlNode[])testObjectIn.ProductionSchedules[0].ProductionRequests[0].SchedulingParameters; var paramsRecord = new CMeas.Item_DataRecord(paramNodes); Assert.AreEqual(1, paramsRecord.ItemNames.Count); Assert.AreEqual(3, ((CMeas.Item_Count)paramsRecord["myparam"]).Value); }
private void ReadFeatureOfInterest(XsdNs.OM_ObservationType observationRaw) { var featureProxy = observationRaw.featureOfInterest; // Feature of interest specified? if (featureProxy == null) { // No feature of interest specified at all FeatureOfInterest = null; FeatureOfInterestDetails = new Item_DataRecord(); return; } // Consistency check: there must not be both xlink attrs and a complex feature of interest if (featureProxy.AbstractFeature != null && featureProxy.XLinkHelperObj.XLinkSpecified) { throw new XNeut.InvalidMessageException("Inconsistent feature of interest: complex feature must not have xlink attributes"); } // Simple feature of interest? if (featureProxy.Title != null) { // No additional metadata expected, just reading the xlink:title attribute FeatureOfInterest = featureProxy.Title; FeatureOfInterestDetails = new Item_DataRecord(); return; } if (featureProxy.AbstractFeature == null) { // No feature of interest specified at all FeatureOfInterest = null; FeatureOfInterestDetails = new Item_DataRecord(); return; } try { // Processing complex feature of interest var featureCasted = (XsdNs.SweDataComponentAsFeatureType)featureProxy.AbstractFeature; var dataRecordRaw = featureCasted.DataRecord; FeatureOfInterestDetails = new Item_DataRecord(dataRecordRaw); FeatureOfInterest = FeatureOfInterestDetails.Identifier; } catch (Exception e) { throw new XNeut.InvalidMessageException(ErrorMsgPopulation + " (failed to process complex feature)", e); } }
private byte[] GetObservation(int taskId) { // Fabricating a message var dataRecord = new MsgMeas.Item_DataRecord() { { "TaskId", new MsgMeas.Item_Text(taskId.ToString()) }, { "SomeField", new MsgMeas.Item_Category("my-category") } }; var observation = new MsgMeas.Observation(dataRecord) { Name = "Task " + taskId }; return(observation.ToXmlBytes()); }
private void ReadTaskingRequestItemsFromProxy(XsdNs.TaskingRequestType proxy) { // Setting defaults Parameters = new Item_DataRecord(); // Reading procedure ProcedureId = proxy.procedure; // Parameters defined in the proxy? if (proxy.taskingParameters != null && proxy.taskingParameters.ParameterData != null) { Parameters = new TaskingParameterProcessor(proxy.taskingParameters.ParameterData).Parameters; } }
/// <summary> /// Reads values from the XML proxy. /// </summary> /// <param name="proxy">Proxy.</param> protected void ReadExtensibleResponseItemsFromProxy(XsdNs.ExtensibleResponseType proxy) { // The default result is "unknown" when reading from XML RequestResult = RequestResultType.Unknown; // Checking if the status data record is there if (proxy.Extension != null && proxy.Extension.Length > 0) { foreach (var ext in proxy.Extension) { // Is it a data record? if (!(ext is XsdNs.DataRecordPropertyType dataRecordProp)) { continue; } // Does the data record have a body with the expected identifier? if (dataRecordProp.DataRecord == null || dataRecordProp.DataRecord.identifier == null || !dataRecordProp.DataRecord.identifier.Equals(IDENTIFIER)) { continue; } // Processing the data record var dataRecord = new Item_DataRecord(dataRecordProp); // Getting status information if (dataRecord.ItemNames.Contains(RESULT_FIELD_NAME)) { RequestResult = ParseRequestResult(dataRecord[RESULT_FIELD_NAME]); } else { RequestResult = RequestResultType.Unknown; } // Getting status message if (dataRecord.ItemNames.Contains(MESSAGE_FIELD_NAME)) { RequestResultMessage = GetStatusMessage(dataRecord[MESSAGE_FIELD_NAME]); } } } }
/// <summary> /// This method populates the base class data to the given proxy. /// </summary> /// <param name="proxy">Proxy.</param> protected void PopulateExtensibleResponseToProxy(XsdNs.ExtensibleResponseType proxy) { // Creating a data record to enclose result information var record = new Item_DataRecord(); var resultItem = new Item_Category(RequestResult.ToString()); record.Add(RESULT_FIELD_NAME, resultItem); var messageItem = new Item_Text(RequestResultMessage); record.Add(MESSAGE_FIELD_NAME, messageItem); // Creating a proxy and adding it as an extension proxy.Extension = new object[1]; var recordProp = (XsdNs.DataRecordPropertyType)record.GetObjectForXml_Result("ExtResp_"); recordProp.DataRecord.identifier = IDENTIFIER; proxy.Extension[0] = recordProp; }
/// <summary> /// Constructor. /// </summary> /// <param name="proxy">Proxy with parameter data.</param> /// <exception cref="XNeut.InvalidMessageException">Thrown if an error is encountered.</exception> public TaskingParameterProcessor(XsdNs.ParameterDataType proxy) { // Setting defaults Parameters = new Item_DataRecord(); // Parameters defined in the proxy? // The values are mandatory but, for robustness, just skipping if empty if (proxy.values != null) { // Reading parameters; expecting a data record if (!(proxy.values is XsdNs.DataRecordPropertyType paramProxy)) { throw new XNeut.InvalidMessageException("Unexpected type of tasking parameters; expected swe:DataRecord"); } else { Parameters = new Item_DataRecord(paramProxy); } }
public void ProcProdSched_ReadSchedulingParameters() { // Testing the reading of scheduling parameters var filepath = TestCommon.TestHelper.TestFileFolder + "\\ProcessProductionSchedule_SchedulingParams.xml"; var xmlBytes = System.IO.File.ReadAllBytes(filepath); var testObject = new ProcessProductionSchedule(xmlBytes); // Get the parameters data record var productionReq = testObject.ProductionSchedules[0].ProductionRequests[0]; var parameters = new CMeas.Item_DataRecord((SXml.XmlNode[])productionReq.SchedulingParameters); // Asserting just one parameter, because the Item_DataRecord class is // not a part of this application. var parameter = (CMeas.Item_Measurement)parameters["SomeParam1"]; Assert.AreEqual(10.6, parameter.Value, 0.0001); Assert.AreEqual("t/h", parameter.UnitOfMeasure); }
/// <summary> /// Constructor. /// </summary> /// <param name="taskId">The ID of the related task.</param> /// <param name="procId">The ID of the procedure being executed or asked to be executed.</param> public TaskStatusReport(string taskId, string procId) { // #1 in XML schema: task // The schema requires a value for this field. TaskId = taskId; // #5 in XML schema: procedure // The schema requires a value for this field. ProcedureId = procId; // Setting defaults (in the order the fields appear in the XML schema) // #2 in XML schema: estimatedToC EstimatedTimeOfCompletion = null; // #3 in XML schema: event (not implemented) // #4 in XML schema: percentCompletion PercentCompletion = null; // #6 in XML schema: requestStatus // The schema requires a value for this field. RequestStatus = TaskingRequestStatusCodeType.Accepted; // #7 in XML schema: statusMessage StatusMessages = new System.Collections.Generic.List <string>(); // #8 in XML schema: taskStatus TaskStatusCode = TaskStatusCodeType.Unknown; // #9 in XML schema: updateTime // The schema requires a value for this field. UpdateTime = DateTime.Now.ToUniversalTime(); // #10 in XML schema: alternative (not implemented) // #11 in XML schema: taskingParameters TaskingParameters = new Item_DataRecord(); }
private void SendMeasurement(Rmq.IModel channel) { // In this example, sending an imaginary tank state that consists of a few measurements. // Changing tank measurements randomly. m_tankTemperature = ChangeValueRandomly(m_tankTemperature, 6, 19, 49); m_tankLiquidLevel = ChangeValueRandomly(m_tankLiquidLevel, 27, 12, 100); // Creating state object. var tankStateValues = new MsgMeas.Item_DataRecord() { // Adding measurements. { "TI-300", new MsgMeas.Item_Measurement("Cel", m_tankTemperature) }, { "LI-300", new MsgMeas.Item_Measurement("cm", m_tankLiquidLevel) }, // Adding state. { "state", new MsgMeas.Item_Category(GetRandomTankState()) }, // Adding alarms. These alarms depend on the level value. { "LA-300", new MsgMeas.Item_Boolean(m_tankLiquidLevel < 30) }, { "LA+300", new MsgMeas.Item_Boolean(m_tankLiquidLevel > 70) } }; // Creating an Observation to enable encoding to XML and adding metadata. var timestamp = DateTime.Now; var observation = new MsgMeas.Observation(tankStateValues) { Name = "T300", Description = "State of T300 at " + timestamp.ToString(), FeatureOfInterest = "t300", ObservedProperty = "state", // By default, PhenomenonTime is always the creation time, but assigning it explicitly PhenomenonTime = timestamp.ToUniversalTime() }; // Sending the message to the message bus. SendToMessageBus(channel, TopicNameTankState, observation.ToXmlBytes()); }
// This example shows // 1) How to create an Item_DataRecord object and enclose it in an Observation // 2) How to read an Item_DataRecord enclosed in an Observation public void Create() { // This example creates a data record with the following structure: // - dataRecord // - MyMeas: Item_Measurement, 45.3 s, good quality (implicit) // - MyTime: Item_TimeInstant, 2018-03-02T14:22:05Z, bad quality (explicit) // - NestedRecord: Item_DataRecord // - NestedMeas: Item_Measurement, -0.34 m, good quality (implicit) // The easiest way to add fields is to use the collection initialiser as below. // In each row, the items are as follows: // 1) the name of the data record field, // 2) the related Item_* object, // 3) data quality information (optional) var dataRecord = new MsgMeas.Item_DataRecord() { // Adding a measurement value { "MyMeas", new MsgMeas.Item_Measurement("s", 45.3) }, // Adding a time instant { "MyTime", new MsgMeas.Item_TimeInstant(DateTime.Parse("2018-03-02T14:22:05Z").ToUniversalTime()), MsgMeas.DataQuality.CreateBad() } }; // You can also use the "Add" method. The code below shows this. In addition, // it shows that a data record can nest another data record. var nestedDataRecord = new MsgMeas.Item_DataRecord() { { "NestedMeas", new MsgMeas.Item_Measurement("m", -0.34) } }; dataRecord.Add("NestedRecord", nestedDataRecord); // Now, you can include the data record in an Observation, for instance. var observation = new MsgMeas.Observation(dataRecord); var xmlBytes = observation.ToXmlBytes(); // Send XML bytes to network... }
private MsgMeas.TaskStatusReport GetStatusReport() { var taskingParams = new MsgMeas.Item_DataRecord { { "myparam", new MsgMeas.Item_Category("myctg") } }; var statusReport = new MsgMeas.TaskStatusReport(CurrentTaskId, MySupportedProcedure) { EstimatedTimeOfCompletion = DateTime.Now.AddMinutes(4).ToUniversalTime(), PercentCompletion = 3.2, RequestStatus = MsgMeas.TaskingRequestStatusCodeType.Accepted, StatusMessages = new SysColl.List <string>() { "Creation was successful", "Start was successful" }, TaskStatusCode = CurrentTaskStatus, UpdateTime = DateTime.Now.ToUniversalTime(), TaskingParameters = taskingParams }; return(statusReport); }
/// <summary> /// Constructor. /// </summary> /// <param name="pm">Parameter values.</param> public TaskingParameterProcessor(Item_DataRecord pm) { Parameters = pm; }
private void ReadFieldValuesFromXmlDoc(XsdNs.StatusReportType proxy) { try { // #1 in XML schema: task // The schema requires a value for this field. TaskId = proxy.task; // #2 in XML schema: estimatedToC if (proxy.estimatedToCSpecified) { EstimatedTimeOfCompletion = XNeut.Helper.DateTimeToUtcIfPossible(proxy.estimatedToC); } else { EstimatedTimeOfCompletion = null; } // #3 in XML schema: event (not implemented) // #4 in XML schema: percentCompletion if (proxy.percentCompletionSpecified) { PercentCompletion = proxy.percentCompletion; } else { PercentCompletion = null; } // #5 in XML schema: procedure // The schema requires a value for this field. ProcedureId = proxy.procedure; // #6 in XML schema: requestStatus // The schema requires a value for this field. try { RequestStatus = (TaskingRequestStatusCodeType)Enum.Parse(typeof(TaskingRequestStatusCodeType), proxy.requestStatus); } catch (ArgumentException e) { throw new XNeut.InvalidMessageException("Failed to parse request status", e); } // #7 in XML schema: statusMessage StatusMessages = new System.Collections.Generic.List <string>(); if (proxy.statusMessage != null) { foreach (var s in proxy.statusMessage) { StatusMessages.Add(s.Value.Trim()); } } // #8 in XML schema: taskStatus try { if (!string.IsNullOrEmpty(proxy.taskStatus)) { TaskStatusCode = (TaskStatusCodeType)Enum.Parse(typeof(TaskStatusCodeType), proxy.taskStatus); } else { // Default TaskStatusCode = TaskStatusCodeType.Unknown; } } catch (ArgumentException e) { throw new XNeut.InvalidMessageException("Failed to parse task status", e); } // #9 in XML schema: updateTime // The schema requires a value for this field. UpdateTime = XNeut.Helper.DateTimeToUtcIfPossible(proxy.updateTime); // #10 in XML schema: alternative (not implemented) // Tasking parameters defined? // #11 in XML schema: taskingParameters if (proxy.taskingParameters != null && proxy.taskingParameters.ParameterData != null) { var paramsProxy = proxy.taskingParameters.ParameterData; TaskingParameters = new TaskingParameterProcessor(paramsProxy).Parameters; } else { TaskingParameters = new Item_DataRecord(); } } catch (NullReferenceException e) { throw new XNeut.InvalidMessageException("Failed to read status report from XML (something required missing?)", e); } }
private void ProcessOneField(XsdNs.DataRecordTypeField field) { string fieldName = field.name; var fieldObj = field.dataComponent; Item itemRead = null; DataQuality dataQuality = null; var simpleComponent = true; try { if (fieldObj is XsdNs.AbstractSimpleComponentType) { // Simple component (as of SWE schemata) simpleComponent = true; itemRead = ReadSimpleData(field); } else { // Complex component simpleComponent = false; switch (field.dataComponentTypeInfo) { case XsdNs.DataRecordFieldTypeType.DataRecord: var dataRec = (XsdNs.DataRecordType)fieldObj; itemRead = new Item_DataRecord(dataRec); break; case XsdNs.DataRecordFieldTypeType.AbstractGmlAsSweDataComponent: itemRead = ProcessTimeSeriesField((XsdNs.AbstractGmlAsSweDataComponentType)fieldObj); break; case XsdNs.DataRecordFieldTypeType.DataArray: itemRead = new Item_Array((XsdNs.DataArrayType)fieldObj); break; default: // For robustness, just skip unknown field types itemRead = null; break; } } } // Datetime values catch (FormatException e) { throw new XNeut.InvalidMessageException("Data record field is invalid: " + fieldName, e); } // Other errors catch (XNeut.InvalidMessageException e) { throw new XNeut.InvalidMessageException("Data record field is invalid: " + fieldName, e); } if (itemRead == null) { // Unknown field type -> skip for robustness return; } if (simpleComponent) { // Getting data quality var simpleComp = (XsdNs.AbstractSimpleComponentType)fieldObj; if (simpleComp.quality != null && simpleComp.quality.Length > 0) { var qualityProp = simpleComp.quality[0]; dataQuality = new DataQuality(qualityProp.Title); } } if (dataQuality == null) { Add(fieldName, itemRead); } else { Add(fieldName, itemRead, dataQuality); } }
private void SendSchedule(Rmq.IModel channel) { // Creating an imaginary schedule for two tanks, T300 and T400. // It helps to create a "base DateTime", because the message API requires all DateTimes in UTC var dateTimeBase = DateTime.Now.ToUniversalTime(); // Creating material requirements for the production requests var matReqLoad = CreateMaterialReqForSchedule(MsgBiz.MaterialUseType.Consumed, "liquid_422", 1.3); var matReqUnload = CreateMaterialReqForSchedule(MsgBiz.MaterialUseType.Produced, "liquid_429", 1.1); // Creating scheduling parameters var schedulingParams = new MsgMeas.Item_DataRecord() { { "scheduling-method", new MsgMeas.Item_Category("default") }, { "scheduling-horizon", new MsgMeas.Item_Measurement("min", 120) } }; // Creating production requests var prodReqT300 = new MsgBiz.ProductionRequest() { HierarchyScopeObj = new MsgBiz.HierarchyScope( new MsgBiz.IdentifierType("T300"), MsgBiz.EquipmentElementLevelType.ProcessCell ), SegmentRequirements = new SysColl.List <MsgBiz.SegmentRequirement>() { CreateSegmentForSchedule(dateTimeBase.AddMinutes(29), dateTimeBase.AddMinutes(49), "load", matReqLoad), CreateSegmentForSchedule(dateTimeBase.AddMinutes(62), dateTimeBase.AddMinutes(82), "unload", matReqUnload), }, SchedulingParameters = schedulingParams.ToDataRecordPropertyProxy() }; var prodReqT400 = new MsgBiz.ProductionRequest() { HierarchyScopeObj = new MsgBiz.HierarchyScope( new MsgBiz.IdentifierType("T400"), MsgBiz.EquipmentElementLevelType.ProcessCell ), SegmentRequirements = new SysColl.List <MsgBiz.SegmentRequirement>() { CreateSegmentForSchedule(dateTimeBase.AddMinutes(19), dateTimeBase.AddMinutes(39), "load", matReqLoad), CreateSegmentForSchedule(dateTimeBase.AddMinutes(52), dateTimeBase.AddMinutes(72), "unload", matReqUnload), }, SchedulingParameters = schedulingParams.ToDataRecordPropertyProxy() }; // Creating a request to process the schedule var processScheduleRequest = new MsgBiz.ProcessProductionSchedule() { // This is the current time by default, but setting it explicitly CreationDateTime = DateTime.Now.ToUniversalTime(), ProductionSchedules = new SysColl.List <MsgBiz.ProductionSchedule> { new MsgBiz.ProductionSchedule() } }; // Adding the production requests to the message processScheduleRequest.ProductionSchedules[0].ProductionRequests.Add(prodReqT300); processScheduleRequest.ProductionSchedules[0].ProductionRequests.Add(prodReqT400); // Sending the message to the message bus SendToMessageBus(channel, TopicNameSchedules, processScheduleRequest.ToXmlBytes()); }