Skip to content
Snippets Groups Projects
Commit f343ed09 authored by Bob Flynn's avatar Bob Flynn Committed by Miguel Angel Reina Ortega
Browse files

Save edits

parent 7c785239
No related branches found
No related tags found
1 merge request!3TDE-2024-0007-Semantics_Deployment
Pipeline #753 passed
......@@ -41,11 +41,11 @@ The information provided in this document is directed solely to professionals wh
NO REPRESENTATION OR WARRANTY IS MADE THAT THE INFORMATION IS TECHNICALLY ACCURATE OR SUFFICIENT OR CONFORMS TO ANY STATUTE, GOVERNMENTAL RULE OR REGULATION, AND FURTHER, NO REPRESENTATION OR WARRANTY IS MADE OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR AGAINST INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS. NO oneM2M PARTNER TYPE 1 SHALL BE LIABLE, BEYOND THE AMOUNT OF ANY SUM RECEIVED IN PAYMENT BY THAT PARTNER FOR THIS DOCUMENT, WITH RESPECT TO ANY CLAIM, AND IN NO EVENT SHALL oneM2M BE LIABLE FOR LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES. oneM2M EXPRESSLY ADVISES ANY AND ALL USE OF OR RELIANCE UPON THIS INFORMATION PROVIDED IN THIS DOCUMENT IS AT THE RISK OF THE USER.
### Contents
# Contents
# Scope
# 1 Scope
The present document provides a simple use case for guiding application developers to model physical devices in oneM2M and adding semantic annotations that will enable interoperability of devices that are modelled in oneM2M:
......@@ -56,14 +56,14 @@ The present document provides a simple use case for guiding application develope
- The semantic queries that can be used to discover device capabilities and enable interoperability,
- The call flows for implementation of the use case with a focus on the semantic aspects.
# References
# 2 References
## Normative references
## 2.1 Normative references
Normative references are not applicable in the present document.
## Informative references
## 2.2 Informative references
References are either specific (identified by date of publication and/or edition number or version number) or nonspecific. For specific references, only the cited version applies. For non-specific references, the latest version of the referenced document (including any amendments) applies.
The following referenced documents are not necessary for the application of the present document but they assist the user with regard to a particular subject area.
......@@ -80,7 +80,7 @@ The following referenced documents are not necessary for the application of the
- <a name="_ref_i.7">[i.7]</a> oneM2M TS-0009: "HTTP Protocol Binding".
- <a name="_ref_i.8">[i.8]</a> ETSI TS(R) 103 783: SAREF: SDT interoperability and oneM2M base ontology alignment
# Definitions
# 3 Definitions
For the purposes of the present document, the terms and definitions given in oneM2M TS-0011 <a href="#_ref_i.2">[i.2]</a> apply.
......@@ -95,34 +95,29 @@ nodn non-oneM2M device node
SAREF Smart Applications REFerence ontology
# Conventions
# 4 Conventions
The key words "Shall", "Shall not", "May", "Need not", "Should", "Should not" in the present document are to be interpreted as described in the oneM2M Drafting Rules <a href="#_ref_i.1">[i.1]</a>.
# Motivation
# 5 Motivation
The assumption of many existing oneM2M applications is that they interact with other oneM2M applications through known resource structures. They either create the resources themselves or are configured to use specific resources. Information is typically stored in containers, sometimes as base64-encoded content instances, with the implicit assumption that applications have a-priori knowledge of the syntax and semantics of this information.
Depending on a-priori knowledge of the structures and data works well for small-scale vertical deployments of IoT devices. When the deployment evolves to include new devices, the existing applications change to reflect the new additions. However, in larger systems of IoT devices where the IoT devices may be a part of a legacy deployment or more than a single vertical solution, changes to all existing applications may become impractical. To enable growth and diversity of IoT devices in large heterogenous settings, applications need to be able to discover the structure and meaning of data from devices and how to use the services of the devices. In oneM2M Release 1 support for discovery of resources based on specific attribute values and the use of labels was defined. The agreement of a fixed set of labels (using a-priori knowledge) can be a viable solution for small deployments.
<p align="center">
<strong>Figure 1: Semantic understanding of device and data in IoT deployments</strong>
<br>
<img src="media/image2.png" alt="__CAPTION__">
</p>
![Figure 1: Semantic understanding of device and data in IoT deployments](media/image2.png)
**Figure 1: Semantic understanding of device and data in IoT deployments**
For medium or large deployments of heterogeneous IoT devices a more expressive approach for describing and discovering IoT devices is provided by oneM2M. Each type of device in a heterogeneous deployment can model services and data in the oneM2M Service Layer using different structures and syntax of data. For example, temperature sensors may report measurements using different units such as Celsius, Fahrenheit and Kelvin. Additionally, those IoT devices may measure different aspects, such as indoor temperature, outdoor temperature, refrigerator temperature, etc., and the representation of the measurement may differ as well.<br />
<p align="center">
<strong>Figure 2: Meaningfulness of data from IoT devices</strong>
<br>
<img src="media/image3.png" alt="__CAPTION__">
</p>
![Figure 2: Meaningfulness of data from IoT devices](media/image3.png)
**Figure 2: Meaningfulness of data from IoT devices**
With semantic annotations in oneM2M, all the different aspects of IoT devices can be described using RDF triples, which is a standard semantic format. The vocabulary used for a semantic description can be defined according to an ontology such as SAREF. With semantic discovery, applications can describe precisely what information they need or can deal with. This is powered by specifying a semantic filter using the SPARQL query language. The SPARQL filter is matched against the respective semantic annotations of each resource within the discovery scope. This feature in oneM2M helps applications to properly handle the data from the IoT devices.
......@@ -131,9 +126,9 @@ Besides differences in the data from an IoT device in oneM2M the information mod
With all these options available to model a device the ability to have a-priori knowledge of a device model becomes less likely as IoT deployments scale beyond small vertical use cases. The oneM2M Base Ontology addresses this and enables developers of these different models to make them interoperable if the appropriate semantic annotations are made and semantic filtering is used to discover the appropriate API for a model. The focus of the remainder of this developer guide is to demonstrate this process.
# System Description
# 6 System Description
## Use case
## 6.1 Use case
The example scenario describes a clothes-washing machine and an application to monitor and control the IoT enabled product. This clause will show three different oneM2M resource tree models of the clothes washing machine and the call flows to create those models. The logic and call flows necessary for a client application to control and monitor the status of the clothes-washing machine is also described. In the next clause the washing machine capabilities are described using the SAREF ontology so that the client application can discover the washing machines. Additionally, the oneM2M Base Ontology describes how to use the device and commands that these clothes washing machines offer so that the client application can control any of them without regard to which resource tree model represents them.
This simplified clothes-washing machine has enough features to demonstrate the difference between the different modelling approaches supported in oneM2M. The concepts shown here can be applied to a full featured clothes-washing machine or any other IoT enabled device for that matter. The features and capabilities that are modelled are:
......@@ -146,21 +141,19 @@ This simplified clothes-washing machine has enough features to demonstrate the d
- The washing machine supports three commands: ON, OFF, Toggle
- The washing machine is in My_Bathroom.
<p align="center">
<strong>Figure 3: Functional Architecture for Smart Clothes Washing Machine</strong>
<br>
<img src="media/image4.png" alt="__CAPTION__">
</p>
![Figure 3: Functional Architecture for Smart Clothes Washing Machine](media/image4.png)
**Figure 3: Functional Architecture for Smart Clothes Washing Machine**
The clothes-washing machine is modelled as a non-oneM2M device (nodn) for all three models. However, everything in this guide applies equally if these were modelled as native oneM2M devices. There is no difference in the model or the call flows for everything to the right of the Interworking Proxy Element (IPE) shown in the figure below. Figure 4 shows a generic set of oneM2M call flow for the clothes washing machine (and the IPE) and the client application communicating through the oneM2M CSE. The level of detail provided here applies to all the different modelling approaches for the clothes washing machine. Differences in the call flows that are dependent on the model used, shown in blue shading, are further detailed where the specific models are described.
<p align="center">
<strong>Figure 4: Generic oneM2M Call Flows</strong>
<br>
<img src="media/image5.png" alt="__CAPTION__">
</p>
![Figure 4: Generic oneM2M Call Flows](media/image5.png)
**Figure 4: Generic oneM2M Call Flows**
The messages shown in Figure 4 are further described here:
......@@ -178,23 +171,21 @@ The messages shown in Figure 4 are further described here:
- **Generate notification** for clothes washing machine. When the client application sends a oneM2M primitive to a resource that controls the clothes washing machine, a notification is generated (assuming notifications were created). In our scenario, since the clothes washing machine and the IPE are behind a firewall and therefore not reachable, the notification for the IPE are stored in the CSE and made available to the IPE via the long polling process.
- **Poll for notifications**. Because the IPE cannot receive notifications directly, it must use the long polling procedure to retrieve its notifications from the CSE. The IPE processes notifications by sending commands to the clothes washing machine using the API of the clothes washing machine.
## Device models using a Custom Model
## 6.2 Device models using a Custom Model
Using oneM2M to represent devices allows for unlimited flexibility. A device model can be customized to support the needs of the manufacturer or system architecture. The resource tree structure shown here represents a custom model that has a single container for reading the status of the washing machine and a separate container to set or command the washing machine.
<p align="center">
<strong>Figure 4: Custom washing machine model</strong>
<br>
<img src="media/image6.png" alt="__CAPTION__">
</p>
<p align="center">
<strong>Figure 5: Custom Model oneM2M Call Flows</strong>
<br>
<img src="media/image7.png" alt="Custom washing machine model">
</p>
![Figure 5: Custom washing machine model](media/image6.png)
**Figure 5: Custom washing machine model**
![Figure 6: Custom Model oneM2M Call Flows](media/image7.png)
**Figure 6: Custom Model oneM2M Call Flows**
Only the messages highlighted in light blue are described here as the rest of the messages are the same as in the general call flow described in clause 6.1.
......@@ -224,7 +215,7 @@ Only the messages highlighted in light blue are described here as the rest of th
## Device models using Semantic Modelling
## 6.3 Device models using Semantic Modelling
A SAREF description of the washing machine is mapped to the resource structure shown in Figure 6 using the rules described in TS-0030 and TS-0012. A complete derivation of this example is shown in [ref to TS-0012] Annex B.1.3.3.
The description of our (simplified) washing machine using SAREF ontology is expanded upon here:
......@@ -278,11 +269,12 @@ sn:WASH_XYZ-StartStopFunction a saref:ActuatingFunction ;
<p align="center">
<strong>Figure 6: SAREF Washing Machine Model</strong>
<br>
<img src="media/image8.png" alt="__CAPTION__">
</p>
![Figure 7: SAREF Washing Machine Model](media/image8.png)
**Figure 7: SAREF Washing Machine Model**
- The procedure defined in TS-0012 require the IPE to parse the semantic description to generate a total of three custom &lt;flexContainer> definitions to support the structure shown in Figure 7. The schemas generated are added as the content of a &lt;contentInstance> resource under a container for these custom definitions. The locations of these schemas are referenced in the container definition attribute of the respective &lt;flexContainer>.
- two &lt;flexContainer> child-resources for Services and their &lt;semanticDescriptor>s are used for modelling the services SwitchOnService and MonitorService;
- the SwitchOnService in turn has a child resource of type &lt;flexContainer> for Operations which exposes the Toggle_Command;
......@@ -293,6 +285,7 @@ sn:WASH_XYZ-StartStopFunction a saref:ActuatingFunction ;
![Figure 8: SAREF Model oneM2M Call Flows](media/image9.png)
**Figure 8: SAREF Model oneM2M Call Flows**
......@@ -326,17 +319,13 @@ Only the messages highlighted in light blue are described here as the rest of th
## Device models using Smart Device Template
## 6.4 Device models using Smart Device Template
TS-0023 defines a framework for developing common standardized models of devices. There are multiple device specific domains defined and new models and domains are added in each release of oneM2M. The Home Domain contains a deviceClothesWasher model that aligns with the device that we are trying to model. The resource tree structure of the deviceClothesWasher is shown in Figure 5. There are many more potential services exposed in this model than our example simplified washing machine provides. The elements in bold are required for a compliant SDT model. Services in the model that are not supported by our simple clothes-washing machine are not implemented unless they are required. It should be noted that using an SDT model is the only model that can be certified by a certification authority.
![Figure 9: SDT washing machine model](media/image10.png)
<p align="center">
<strong>Figure 7: SDT washing machine model</strong>
<br>
<img src="media/image10.png" alt="__CAPTION__">
</p>
**Figure 9: SDT washing machine model**
When using a SDT model from TS-0023 to represent a physical device it is necessary to map the functionality of the device to be modelled with the existing modules defined for the SDT device.
......@@ -351,11 +340,10 @@ When using a SDT model from TS-0023 to represent a physical device it is necessa
|Location |My_Bathroom |The SDT model does not have an attribute specifically for Location. |
<p align="center">
<strong>Figure 10: SDT model oneM2M Call Flows</strong>
<br>
<img src="media/image11.png" alt="__CAPTION__">
</p>
![Figure 10: SDT model oneM2M Call Flows](media/image11.png)
**Figure 10: SDT model oneM2M Call Flows**
Only the messages highlighted in light blue are described here as the rest of the messages are the same as in the general call flow described in clause 6.1.
......@@ -385,9 +373,9 @@ Only the messages highlighted in light blue are described here as the rest of th
# Semantic Annotation in oneM2M
# 7 Semantic Annotation in oneM2M
## Semantic description of services using SAREF Ontology
## 7.1 Semantic description of services using SAREF Ontology
The Smart Applications REFerence ontology (SAREF) is intended to enable interoperability between solutions from different providers and among various activity sectors in the Internet of Things (IoT), thus contributing to the development of the global digital market. SAREF explicitly specifies the recurring core concepts in the Smart Applications domain, the main relationships between these concepts, and axioms to constrain the usage of these concepts and relationships. SAREF is based on the fundamental principles of reuse and alignment of concepts and relationships that are defined in existing assets, modularity to allow separation and recombination of different parts of the ontology depending on specific needs, extensibility to allow further growth of the ontology, and maintainability to facilitate the process of identifying and correcting defects, accommodate new requirements, and cope with changes in (parts of) SAREF.
We can use the SAREF ontology to describe the services of the washing machine and the oneM2M Base Ontology to describe the oneM2M interface for the services.
......@@ -420,9 +408,9 @@ sn:WASH_XYZ_RESOURCE_ID a <http://www.XYZ.com/WashingMachines#XYZ_Cool> ;
These triples will be placed into a &lt;semanticDescription> resource in each of the models. Notice that these triples have a token "RESOURCE_ID" in several places that will be replaced at execution time with a resource identifier or resource address related to the parent of this particular &lt;semanticDescriptor>.
## Describing oneM2M APIs with the oneM2M Base Ontology
## 7.2 Describing oneM2M APIs with the oneM2M Base Ontology
## Clothes Washing Machine APIs using oneM2M
## 7.2.1 Clothes Washing Machine APIs using oneM2M
Because the resource tree structure for each of the models is different the oneM2M primitives needed to access the services of the clothes washing machine will also be different. However, the goal for interworking device models is to allow a user to issue the same command to perform an operation regardless of which model is used. This can be approximated in a dynamic manner using the oneM2M base ontology to describe each of the services offered by the device and the resources that provide access to those services. For example, the washing machine that we have described offers the following operations:
- TURN ON WASHING MACHINE
......@@ -453,7 +441,7 @@ Similarly, to command the washing machine to STOP the following oneM2M primitive
## Custom Model API semantic description
## 7.2.2 Custom Model API semantic description
The specific primitive requests described in clause 7.2.1 are described in RDF triples using the oneM2M base ontology. The classes of interest in the oneM2M base ontology are: m2m:oneM2MTargetURI, m2m:hasDataRestriction, m2m:oneM2MMethod.
```
......@@ -486,7 +474,7 @@ sn:WASH_XYZ-MonitoringFunction-WashingMachineStatus_RESOURCE_ID a m2m:Operation,
```
## Semantic Model annotation
## 7.2.3 Semantic Model annotation
The specific primitive requests described in clause 7.2.1 are described in RDF triples using the oneM2M base ontology. The classes of interest in the oneM2M base ontology are: m2m:oneM2MTargetURI, m2m:hasDataRestriction, m2m:oneM2MMethod and m2m:oneM2Mattribute.
......@@ -517,7 +505,7 @@ sn:WASH_XYZ-MonitoringFunction-WashingMachineStatus_RESOURCE_ID a m2m:Operation,
```
## SDT model annotation
## 7.2.4 SDT model annotation
The specific primitive requests described in clause 7.2.1 are described in RDF triples using the oneM2M base ontology. The classes of interest in the oneM2M base ontology are: m2m:oneM2MTargetURI, m2m:hasDataRestriction, m2m:oneM2MMethod and m2m:oneM2Mattribute.
```
......@@ -550,11 +538,11 @@ sn:WASH_XYZ-MonitoringFunction-WashingMachineStatus a m2m:Operation ;
m2m:oneM2MMethod "RETRIEVE" .
```
# Semantic Queries
# 8 Semantic Queries
This section describes the semantic queries and how the responses can be used to achieve interoperability. Generally, these queries are executed by an application that is designed to use the IoT devices.
## Discovery Queries
## 8.1 Discovery Queries
By using the oneM2M Base Ontology in the &lt;semanticDescriptor> resources we can send queries to the oneM2M CSE to find the services offered by a device and further query those services to discover the oneM2M primitives to access those services.
Here is a list of queries that we will support for all three of the models:
......@@ -616,7 +604,7 @@ This lists the operations and commands and functions associated with the command
## Interoperability Queries
## 8.2 Interoperability Queries
The following queries demonstrate how interoperability is achieved using semantics in oneM2M. Using the results of the queries above we can issue the following types of queries to determine exactly how to use the services of the washing machines, without regard the way it was modeled. This query shows how to use the saref:GetCommand for the SDT model of the washing machine
......@@ -690,24 +678,22 @@ The SPARQL query that is used is a critical component of the ability to dynamica
If we were designing a smartphone application to control the washing machine it might look like the wireframe shown below.
<p align="center">
<strong>Figure 11: Sample application wireframe</strong>
<br>
<img src="media/image12.png" alt="__CAPTION__">
</p>
![Figure 11: Sample application wireframe](media/image12.png)
**Figure 11: Sample application wireframe**
# Procedures
# 9 Procedures
## Introduction
## 9.1 Introduction
Previous clauses describe the use case, the call flows, the semantic description of our device and the SPARQL queries that we can use based on the semantic description that we created. As you will see in this section, the values returned from a query are fully dependent on the query issued. The oneM2M CSE will pass the query results back in the format defined by SPARQL query results. This example receives a JSON response (the query is sent using XML just to highlight that this can be done).
This clause will show the actual oneM2M primitives that implement the use case described above. This guide will focus on the semantic description resources and the semantic queries. The specific primitives needs to create the &lt;AE>, &lt;container>, and &lt;flexcontainer> resources have been covered in other documents in oneM2M.
## Implementation
## 9.2 Implementation
## Semantics Description Utilities
## 9.2.1 Semantics Description Utilities
The requirements for the creation of a &lt;semanticDescription> resource include base64 encoding the 'dsp' attribute. There are many libraries that do this operation and for this example python was used.
```
......@@ -727,7 +713,7 @@ def smdDecode(message):
```
## Semantic Query Utilities
## 9.2.2 Semantic Query Utilities
When sending a SPARQL query as a request parameter for a oneM2M primitive, the query must be "url" encoded. There are many libraries that do this operation and for this example python was used.
```
import urllib.parse
......@@ -736,14 +722,17 @@ def encodedSparqlQuery(query):
return urllib.parse.quote(query, safe='')
```
## Semantics representations and primitives
## 9.2.3 Semantics representations and primitives
In oneM2M the &lt;semanticDescriptor> resource is used to provide semantic annotations, such as the ones in clause 7. Semantic annotations can use the oneM2M base ontology as well as external ontologies, such as SAREF. The oneM2M base ontology is primarily used to discover how to use the APIs for devices that are modelled in oneM2M. External Ontologies are used to describe the capabilities of the device being models or other features of data that is available in oneM2M, i.e., ontologies could describe the content of data or metadata. A &lt;semanticDescriptor> resource can be a child of &lt;AE>, &lt;container>, &lt;contentInstance>, &lt;group>, &lt;node>, &lt;flexContainer>, &lt;timeSeries>, &lt;mgmtObj> resources.
The semantic annotations in a &lt;semanticDescription> can apply to the parent resource or other resources. There are two types of semantic searches that can be performed; 1) semantic discovery and 2) semantic query. A semantic discovery will find matching &lt;semanticDescriptor> resources and provide the URI of the parent resource of the &lt;semanticDescriptor> resources that match the query. A semantic query request will return the response to the SPARQL query in the format defined in the query. These differences may impact the decision regarding what parent resource to target for a &lt;semanticDescriptor> resource.
The representation of a &lt;semanticDescriptor> resource must be in one of the supported semantic formats supported in oneM2M. The supported formats from TS-0004 are:
![__CAPTION__](media/image13.png)
![Figure 12: <semanticDescriptor> Resource](media/image13.png)
**Figure 12: &lt;semanticDescriptor> Resource**
In this use case we use RDF/XML in the primitives as that is supported by the test implementation. The semantic annotations shown in clause 7 are written in RDF/Turtle. A convenient utility to convert the RDF/Turtle is available at [https://www.easyrdf.org/converter]() or the python rdflib library.
......@@ -756,7 +745,7 @@ Since the &lt;semanticDescriptor> resource is separate from the resources that i
## Create &lt;semanticDescriptor>
## 9.2.4 Create &lt;semanticDescriptor>
The &lt;semanticDescriptor> resource can be created by the entity that is creating the model or by a separate client entity, depending on the &lt;accessControlPolicies> of the parent resource. This example shows the create &lt;semanticDescriptor> for the Custom Model. The RDF triples that we used to semantically describe the washing machine were first converted to RDF/XML and then base64 encoded. The result of that encoding is used for the "dsp" attribute of the &lt;semanticDescriptor>.
The following code is written using python and use the utilities available here [reference to ACME tutorial].
......@@ -855,7 +844,7 @@ Body
The code above is repeated for each &lt;semanticDescriptor> resource that is created. For this use case, there are six &lt;semanticdescriptor> resources created. Three &lt;semanticDescriptor> resources that describe the capabilities of the washing machine are identical except for the "RESOURCE_ID" token that is replaced with the appropriate value. The other three &lt;semanticDescriptor> resources describe the API of the model and therefore have different values for the oneM2M baseOntology classes.
## Semantic Query
## 9.2.5 Semantic Query
When a SPARQL query is created, it can be passed in the "semanticFilter" request parameter, shown below with the shortname form of the request parameter of "smf". The query must first be ascii encoded. Using python, the following code will execute query 4 from above to dynamically determine all four primitives needed to use the SDT model of the washing machine. Additionally, the "Semantic Query Indicator", "sqi", is set to "1" to distinguish this query request from a semantic discovery request. A semantic discovery request will return a list of URIs that match the query rather than a query response.
......@@ -899,7 +888,7 @@ RETRIEVE (
The resulting oneM2M primitive request and response using the HTTP protocol binding and JSON payload binding is shown below. It is important to note the JSON response to the query. An application will have to parse the response from the query to get the desired information.
```
```
Sending request to
http://localhost:50000/oneM2M-semantics?fu=1&sqi=1&smf=PREFIX sn%3A&lt;http%3A%2F%2Fwww.XYZ.com%2FWashingMachines%23> PREFIX m2m%3A &lt;https%3A%2F%2Fgit.onem2m.org%2FMAS%2FBaseOntology%2Fraw%2Fmaster%2Fbase_ontology.owl%23> PREFIX saref%3A &lt;https%3A%2F%2Fsaref.etsi.org%2Fcore%2F> SELECT %3FsarefCommand %3Fmethod %3FtargetURI %3Fattr %3Fres WHERE { %3Fwm m2m%3AhasOperation %3Foperation . %3Foperation a m2m%3AOperation . %3Foperation m2m%3AoneM2MMethod %3Fmethod . optional {%3Foperation m2m%3AhasDataRestriction %3Fres} . optional {%3Foperation m2m%3AoneM2Mattribute %3Fattr} . %3Foperation a %3FsarefCommand . %3Foperation m2m%3AoneM2MTargetURI %3FtargetURI . VALUES %3Fwm {&lt;http%3A%2F%2Fwww.XYZ.com%2FWashingMachines%23XYZ_CoolWASH_XYZ_deviceClothesWasher>} . VALUES %3FsarefCommand {saref%3AGetCommand saref%3AOnCommand saref%3AOffCommand saref%3AToggleCommand} } ORDER BY %3FsarefCommand
......@@ -997,7 +986,7 @@ code here
# History
# 10 History
|Publication history |Publication history |Publication history |
|-|-|-|
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment