5.8 Device Management
5.8.0 Introduction
The entities that are specified in this clause allow performing classical Device Management (DM) functions: rebooting a device, upgrading it, reading / setting its configuration, monitoring its logs, checking its memory or battery status, managing its firmware or its software modules, etc. They belong to the "management" domain.
In the case of a NoDN, it is the IPE in charge of exposing the device to oneM2M that creates / implements these modules. It may rely on external Device Management techniques like e.g. LwM2M (from OMA) or USP (from BBF), or any other technique, proprietary or standardized, that allows performing at least some DM functions, for instance a reboot.
The architecture of IPE-based Device Management is presented in oneM2M TS-0001 [3] clause 6.2.4.1, and the details of CRUD operations on the resources defined here are defined in oneM2M TS-0033 [21] clause 8. A developer's guide on Device Management can be found in oneM2M TR-0035 [i.13].
Editor note: Some attributes are missing from the short name tables in 6.3
5.8.1 flexNode
This flexContainer specialization is the root for SDT-based Device Maagement modules.
The containerDefinition attribute of this specialization shall be "org.onem2m.management.device.flexNode".
This resource is a <flexContainer> child of the <node> resource targeted by the nodeLink attribute of <flexContainer> SDT devices (see in clause 6.2.2 the rule 1.7).
Table 5.8.1-1: Child resources of [flexNode] resource
Child Resources of [flexNode] | Child Resource Type | Multiplicity | Description |
---|---|---|---|
dmAreaNwkInfo_<i> | [dmAreaNwkInfo]] | 0..n | See clause 5.8.9. |
dmAgent | [dmAgent] | 0..1 | See clause 5.8.2. |
dmDeviceInfo | [dmDeviceInfo] | 1 | See clause 5.8.3. |
dmDataModelIO_<i> | [dmDataModelIO] | 0..N | See clause 5.8.4. |
dmFirmware_<i> | [dmFirmware] | 1..N | See clause 5.8.5. |
dmSoftware_<i> | [dmSoftware] | 0..N | See clause 5.8.6. |
dmEventLog_<i> | [dmEventLog] | 0..N | See clause 5.8.7. |
dmPackage_<i> | [dmPackage]] | 0..N | See clause 5.8.8, |
battery_<i> | [battery] | 0..N | See clause 5.3.1.10. |
dmCapability_<i> | [dmCapability]] | 0..N | See clause 5.8.11. |
dmStorage_<i> | [dmStorage]] | 0..N | See clause 5.8.12. |
NOTE 1: The notation '<i>' for child resources indicates that the resource name is the name of the child ModuleClass or SubDevice flexContainer, appended with an underscore '_' and an incrementing index so that it is unique in the [flexNode] children (e.g. "dmFirmware_0", "dmFirmware_1", etc.). The index shall not have leading 0's.
NOTE 2: The current list of modules for Device Management is not fixed and can evolve with new optional features.
5.8.2 dmAgent
This ModuleClass is the entry point module of [flexNode]; it provides capabilities to control and monitor the Device Management of the device.
Table 5.8.2-1 Actions of dmAgent ModuleClass
Return Type | Name | Arguments | Optional | Description |
---|---|---|---|---|
none | reboot | rebootType: hd:enumRebootType | false | Execute a reboot or a factory reset |
M2MID | deployPackage | name: xs:string version: xs:string url: xs:url |
true | Create a dmPackage. Return the ID of the created package. |
The deployPackage action allows creating a new [dmPackage] module class (see clause 5.8.8), child of this dmAgent's parent flexNode. The returned value is the ID of this created <flexContainer>. The created dmPackage is in NotInstalled state. The DataPoints of dmAgent Module Class are as follows:
- 'state' represents the state of the agent for DM purposes (ready, sleeping, etc.).
- some optional device properties which can be used for Device Management purpose. The dmAgent can be seen as a 'dashboard' that gathers common information such as battery level, memory or CPU usage, etc.
Table 5.8.2-2 DataPoints of dmAgent ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
state | hd:enumDmAgentState | R | false | The current state of the agent (ready, error, etc.) | |
storageAvailable | xs:integer | R | true | KB | The size of available storage memory. |
storageTotal | xs:integer | R | true | KB | The size of total storage memory. |
ramAvailable | xs:integer | R | true | KB | The size of available RAM memory. |
ramTotal | xs:integer | R | true | KB | Total size of the RAM memory. |
powerStatus | hd:enumPowerState | R | true | The status of the electrical power. | |
cpuUsage | xs:integer | R | true | pct | Current CPU usage in percent. |
systemTime | m2m:timestamp | RW | true | Reference time for the device. |
5.8.3 dmDeviceInfo
This ModuleClass is used to share static information regarding the device.
Table 5.8.3-1 DataPoints of dmDeviceInfo ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
serialNumber | xs:string | R | true | Unique device label assigned by the manufacturer. The value of the datapoint typically exposes the device's serial number that is specific to a manufacturer. |
|
manufacturer | xs:string | R | true | The name/identifier of the device manufacturer. | |
manufacturerDetailsLink | xs:anyURI | RW | true | URL to manufacturer's website. | |
manufacturingDate | m2m:timestamp | R | true | Manufacturing date of device. | |
model | xs:string | R | true | The name/identifier of the device model assigned by the manufacturer. | |
subModel | xs:string | R | true | Device sub-model name. | |
hwVersion | xs:string | R | true | The hardware version / revision of the device. | |
osVersion | xs:string | R | true | Version of the operating system (defined by manufacturer). | |
country | m2m:countryCode | R | true | Country code of the device. It could be manufacturing country, deployment country or procurement country. | |
supportURL | xs:anyURI | RW | true | URL that points to product support information of the device. | |
presentationURL | xs:anyURI | RW | true | To quote UpnP: "the control point can retrieve a page from this URL, load the page into a web browser, and depending on the capabilities of the page, allow a user to control the device and/or view device status. The degree to which each of these can be accomplished depends on the specific capabilities of the presentation page and device". | |
friendlyName | xs:string | RW | true | The device friendly name. | |
description | xs:string | RW | true | A human readable description of the device (e.g. Alice's cell phone, kitchen's fridge, etc.) |
NOTE: Although all datapoints are optional, depending on the underlying DM technology, some datapoints should be filled, for instance serialNumber, manufacturer and model when this information is available.
5.8.4 dmDataModelIO
This ModuleClass provides capabilities to handle the device's Data Model for cases where the underlying Device Management technology supports APIs that are not directly reflected in the flexNode modules.
Table 5.8.4-1 Actions of dmDataModelIO ModuleClass
Return Type | Name | Arguments | Optional | Description |
---|---|---|---|---|
xs:string | readIO | address: xs:string | true | Read the current values of parameters. Argument: the list of the parameter names. Returns a JSON serialization of the parameters (see Rules 3-2 and 3-6 in clause 6.2.4). |
xs:string | writeIO | address: xs:string payload: xs:string |
true | Update the current values of parameters. Arguments: 'address': the list of the parameter names, 'payload': the list of the parameter values. Returns the list of the modified parameter names. |
Table 5.8.4-2 DataPoints of dmDataModelIO ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
dataModelType | hd:enumDataModelType | R | false | The type of the data model (OMA DM, OMA LwM2M, BBF TR-181, etc.). |
The readIO and writeIO actions are defined for handling parameters of the underlying Device Management protocol using the APIs defined by those technologies. The values used in the address argument are dependent on the value of the dataModelType data point of the dmAgent ModuleClass.
Example of address values could be 'Device.WiFi.SSID.1' if dataModelType=6
(BBF TR-181 USP) or '/9/1/1' if dataModelType=4
(OMA LwM2M).
These address and payload argument can contain several values separated by a comma ','. The payload argument's value types are the valid JSON primitive types (string, number, boolean, null).
EXAMPLES:
readIO(address="Device.WiFi.SSID.SSID")
-> {"Device.WiFi.SSID.SSID": "SSIDName"}
readIO(address="/3/0/1,/3/0/2")
-> {"/3/0/1":"MyCompany","/3/0/2":"SN376575A86"}
writeIO(address="Device.DeviceInfo.FriendlyName,Device.WiFi.SSID.SSID", payload="my device,my ssid"}
-> {"Device.DeviceInfo.FriendlyName,Device.WiFi.SSID.SSID"}
writeIO(address="/3/0/15", payload="[Europe/Paris](Europe/Paris)")
-> {"/3/0/15"}
NOTE: Some datapoints of the dmAgent and dmDeviceInfo ModuleClasses correspond to fixed parameters in OMA & BBF data models. The corresponding concepts in OMA DM / LwM2M data models (resp. BBF TR-181 [i.12]) are specified in oneM2M TS-0005 (resp. TS-0006 [i.15]). For instance the datapoint memAvailable corresponds to 'Device.DeviceInfo.MemoryStatus.Free'
in BBF TR-181 [i.12] (see oneM2M TS-0006 [i.15] clause 7.3) and to '/3/0/10'
in LwM2M (oneM2M TS-0005 clause 6.3.4).
5.8.5 dmFirmware
This ModuleClass provides Device Management capabilities to control and monitor the firmware of a device.
The device can contain multiple components (a graphic card for instance) that can have individual firmwares, and they need to be managed separately. The [flexNode] allows one [dmFirmware] module per component plus one 'major' [dmFirmware] for the device itself.
Individual firmwares are managed using the [dmFirmware] actions presented in Table 5.8.-1.
Table 5.8.5-1 Actions of dmFirmware ModuleClass
Return Type | Name | Argument | Optional | Description |
---|---|---|---|---|
xs:string | updateFirmware | url: xs:url version: xs:string |
true | Downloads a new firmware to the device / sub-component. In case of devices that do support toggling between multiple preinstalled firmware versions it also starts the firmware flashing/installation process. The updateFirmware action as it results returns an AE/IPE message indicating if the action was successful or not. |
xs:string | toggle | none | true | Toggles between the firmware versions installed on a device/sub-component. In case of devices that do not support such toggling, it triggers the firmware flashing/installation process. The toggle action as it results returns an AE/IPE message indicating if the action was successful or not. |
The abstraction model used for [dmFirmware] manages the firmware through two images: a primary firmware image and a secondary one. Despite the naming both images are equivalent and a secondary image can be actively used by a device just like the primary one.
Using an abstraction model based on two firmware images it is possible to effectively manage firmware on devices with different firmware capabilities. The state machine for firmware management using two images is shown in Figure 5.8.5-1 for devices that do support toggling between multiple preinstalled firmware versions and in Figure 5.8.5-2 for devices that can have only one firmware version installed.
Table 5.8.5-2 DataPoints of dmFirmware ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
multiFirmware | xs:boolean | R | false | Indicates if the device/sub-component supports toggling between multiple preinstalled firmware versions. | |
primaryState | hd:enumFirmwareState | R | false | The current state of the primary firmware image (active, downloading, etc.). | |
primaryName | xs:string | R | false | The name of the primary firmware image. | |
primaryVersion | xs:string | R | false | The version of the primary firmware image. | |
primaryUrl | xs:url | R | true | The URL from which the primary firmware image was downloaded. | |
secondaryState | hd:enumFirmwareState | R | true | The current state of the secondary firmware image (active, downloading, etc.). Mandatory when updateFirmware is available. | |
secondaryName | xs:string | R | true | The name of the secondary firmware image. | |
secondaryVersion | xs:string | R | true | The version of the secondary firmware image. | |
secondaryUrl | xs:url | R | true | The URL from which the secondary firmware image was downloaded. | |
component | xs:string | R | true | Allows to identify the sub-component that uses this firmware. This datapoint is mandatory if this is a sub-component firmware. |
NOTE 1: Both primary and secondary firmware image related dataPoints are mandatory when updateFirmware is available, however depending on the device capabilities one of the two state machines - the one presented in Figure 5.8.5-1 or the one shown in Figure 5.8.5-2 should be used.
Figure 5.8.5-1: Lifecycle of a dmFirmware for devices that support toggling between preinstalled firmware images
For devices that support toggling between multiple preinstalled firmware images the following rules apply:
- There is always one firmware image that is in "Active" state.
- Toggling between firmware images is only possible if one image is in "Ready" state and the other image is in "Active" state.
- updateFirmware action is always performed on the image that is in "Ready" or "Failure" state.
NOTE 2: It is the AE/IPE responsibility to provide the appropriate action result pointing if the action was triggered on the device or not (e.g. if the current firmware state did not allow it).
Figure 5.8.5-2: Lifecycle of a dmFirmware for devices that can have only one firmware version installed
In case of a device that can have only one firmware version installed the additional firmware image is used differently. First of all it is treated as a temporary storage for the updateFirmware action that triggers the download process. When the download process is finished the status of the firmware image is changed to "Ready". It is important to note that in this case the installation/flashing process is started after the toggle action is issued, making it a "long toggle". At the very same moment the toggle is issued, the previously active firmware image is moved to "Archival" state, making it a historical record that cannot be restored. The reason why it cannot be restored is trivial - it was just overwritten by the flashing process.
For devices that can have only one firmware version installed the following rules apply:
- There is always no more than one firmware image that is in "Active" or "Installing" state.
- Toggling between firmware images is only possible if one image is in "Ready" state and the other image is in "Active" state.
- The toggle action moves the image that was previously in "Active" state to the "Archival" state.
- The toggle action moves the image that was previously in "Ready" state to the "Installing" state.
- updateFirmware action is always performed on the image that is in "Archival" or "Failure" state.
If one image is in "Archival" state and the other is in "Failure" state the updateFirmware action is always performed on the image that is in "Archival" state.
NOTE 3: It is the AE/IPE responsibility to provide the appropriate action result pointing if the action was triggered on the device or not (e.g. if the current firmware state did not allow it).
5.8.6 dmSoftware
This ModuleClass provides DM capabilities to control and monitor software modules of the device.
An instance of this ModuleClass represents a software module hosted by the device.
A [dmSoftware] module is created on a Hosting CSE by the IPE in charge of the device, either at the initialization if it represents a software module that is pre-installed on the device, or after installation of one or more [5.8.8 dmPackage] modules (see clause 5.8.8) that have been dynamically created (for instance a software image with associated configuration files and libraries).
The association between one or more dmPackage modules and a dmSoftware module are under the responsibility of the IPE: dmSoftware modules are created, deleted or updated only by the IPE (for instance updating a dmPackage can trigger the modification of the version datapoint of an associated dmSoftware).
From external applications, [dmSoftware] modules can only be discovered from the parent [flexNode], not created, and afterwards they can only be activated / deactivated. They can be seen as 'high level' information ("there is such software that is running on the device"), whereas dmPackage are 'low level' information ("there is such executable file that is deployed on the device").
Table 5.8.6-1 Actions of dmSoftware ModuleClass
Return Type | Name | Argument | Optional | Description |
---|---|---|---|---|
none | activate | none | true | Activate the software module. |
none | deactivate | none | true | Deactivate the software module. |
Table 5.8.6-2 DataPoints of dmSoftware ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
state |
hd:enumSoftwareState | R | false | The current state of the software module (see clause 5.6.47). | |
name | xs:string | R | true | The name of the software module. | |
version | xs:string | R | true | The version of the software module. |
5.8.7 dmEventLog
This ModuleClass provides DM capabilities to control and monitor event logs of the device.
Table 5.8.7-1 Actions of dmEventLog ModuleClass
Return Type | Name | Arguments | Optional | Description |
---|---|---|---|---|
none | retrieveLog | start: xs:datetime end: xs:datetime |
true | Upload from the device the logging data between 'start' and 'end'. 'start' shall be a date before 'end', and is optional. The default is beginning of time. 'end' shall be a date after 'start' and is optional. The default is the timestamp of the last available log entry. |
This action, if provided, requests the IPE to read logging data on the device. This log is then stored in the 'data' datapoint. It is only valid when the 'enabled' datapoint is true. The start and end arguments are only indications of the timeframe for the log retrieval. If a target device can deliver only partial logs for a given timeframe, for example when the start argument is too far in the past and logs are not available for that time anymore, then the device shall deliver logs from the earliest available point in time on.
Table 5.8.7-2 DataPoints of dmEventLog ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
type | m2m:logTypeId | R | false | The type of the log (e.g. security log, system log, etc). | |
data | xs:string | R | false | Raw data of last event. No format specified. | |
status | m2m:logStatus | R | false | The current status of the logging process (Started, Stopped, Error, etc.) | |
enabled | xs:boolean | RW | false | Start / stop logging. |
For devices using the dmEventLog ModuleClass, the following rules apply:
- The actual logging process on the device (if any), and the retrieval of device logging data by the IPE, are out of scope of the present document.
- Instances of this module should only be created by the IPE (one per log type supported by the device for instance).
- The IPE can create a [dmEventLog] instance with status datapoint 'NotPresent' for a given log type, to indicate that this log type is not supported by the device. Otherwise status should have value 'Started' (resp. 'Stopped') if the enabled datapoint is set to true (resp. false). The status datapoint can be given 'Error' value if the log processing dysfunctions.
- The IPE should use the <flexContainerInstance> history mechanism (see oneM2M TS-0001 clause 9.6.59) by setting on [dmEventLog] at least one attribute maxNrOfInstances, maxByteSize or maxInstanceAge. Then for each log event read by the IPE from the device, and if the enabled datapoint has value true, a <flexContainerInstance> resource shall be created, child of this module <flexContainer>. The [dmEventLog] module itself just contains the last logged event from the device for this log type.
- The [dmEventLog] <flexContainer>, and therefore its <flexContainerInstance> children resources, should have a dataGenerationTime custom attribute that indicates the time the event was logged on the device (see Rule 2-5 in clause 6.2.3).
When the enabled datapoint is set to false, the IPE shall set the status datapoint to 'Stopped' and shall not modify the data datapoint of the module, and therefore shall not create any <flexContainerInstance> child resource.
5.8.8 dmPackage
This ModuleClass provides DM capabilities to deploy, control and monitor packages of the device.
- These packages can be simple resource files such as software libraries, configuration files, etc. In this case the softwares datapoint will be empty.
- They also can correspond to software images, in which case their installation will trigger the creation by the IPE of one or more [dmSoftware] SDT modules classes that can be activated / deactivated (see clause 5.8.6). In this case the softwares datapoint will contain the list of IDs of this(these) dmSoftware module(s).
- Instances of the dmPackage module class can be dynamically created by the "deployPackage" action of the dmAgent module class (see clause 5.8.2).
Table 5.8.8-1 Actions of dmPackage ModuleClass
Return Type | Name | Argument | Optional | Description |
---|---|---|---|---|
none | install | none | false | Download if needed and install the package. |
none | uninstall | none | false | Uninstall the package. |
none | update | version: xs:string url: xs:string |
false | Update the package. |
Editor's note: update is missing in Table 6.3.2-4
NOTE:
- The package can be pre-downloaded when the [dmPackage] resource is created.
- In the update action, the arguments version and url can be empty strings (case for instance of updating a package on a Linux-type system).
- When the [dmPackage] resource is deleted, the package shall be removed from the device.
Table 5.8.8-2 DataPoints of dmPackage ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
type | hd:enumPackageType | R | false | The type of the package (software, library, config file, web content, etc. See clause 5.6.49) | |
state | hd:enumPackageState | R | false | The current state of the package (see clause 5.6.48) | |
name | xs:string | R | true | The name of the package. | |
version | xs:string | R | true | The version of the package. | |
url | xs:url | R | true | The URL from which the package can be downloaded | |
softwares | m2m:listOfM2MID | R | true | The list of dmSoftware modules, if any, that are associated with this [dmPackage] module |
NOTE:
- The [dmPackage] name and version datapoints are optional because they can be deduced from the downloaded resource. The url datapoint is optional because the package can be pre-installed or downloaded from a default repository (for instance a package on a Linux-type system).
- The possible dependencies between [dmPackage] modules (for instance the [dmPackage] of an executable software image depends on the deployment of other dmPackage that correspond to libraries needed by this software) is out of scope of the present document.
The control of the association between a dmPackage and an associated dmSoftware module, for instance updating a [dmPackage] when the dmSoftware is active, is out of scope of the present document.
5.8.9 dmAreaNwkInfo
A dmAreaNwkInfo is a SDT SubDevice entity, mapped as a <flexContainer> resource that expresses the information about the devices in a M2M Area Network managed by the parent flexNode.
Table 5.8.9-1: Properties of dmAreaNwkInfo model
Property Name | Property Type | Multiplicity | Description |
---|---|---|---|
propAreaNwkType | xs :string | 1 | Indicates the type of M2M Area Network |
Table 5.8.9-2: Modules of dmAreaNwkInfo model
Module Instance Name | Module Class Name | Multiplicity | Description |
---|---|---|---|
dmAreaNwkDeviceInfo | dmAreaNwkDeviceInfo | 0..N | See clause 5.8.10. |
5.8.10 dmAreaNwkDeviceInfo
This ModuleClass is used to share information regarding the devices in the M2M Area Network.
Table 5.8.10-1 DataPoints of dmAreaNwkDeviceInfo ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
devId | xs:string | R | false | Indicates the id of the device. It could be the id of the hardware or nodeId. | |
devType | xs:string | R | false | Indicates the type of the device. The attribute also indicates the functions or services that are provided by the device. Examples include temperature sensor, actuator, IEEE 802.15.4 (tm) coordinator or router. | |
sleepInterval | xs:integer | R | true | seconds | The interval between two sleeps. |
sleepDuration | xs:integer | R | true | seconds | The time duration of each sleep. |
status | xs:string | R | true | The status of the device (sleeping or waked up). |
5.8.11 dmCapability
This ModuleClass is used to model the service capabilities of a managed device.
Table 5.8.11-1: Actions of dmCapability ModuleClass
Return Type | Name | Argument | Optional | Documentation |
---|---|---|---|---|
m2m:status | enable | none | true | The action that allows enabling the device capability. Returns the status of the action. |
m2m:status | disable | none | true | The action that allows disabling the device capability. Returns the status of the action. |
Table 5.8.11-2 DataPoints of dmCapability ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
name | xs:string | R | false | The name of the device capability. | |
attached | xs:boolean | R | false | Indicates whether the capability is currently attached to the device or not. | |
currentState | xs:boolean | R | false | Indicates the current state of the capability (e.g. enabled or disabled). |
5.8.12 dmStorage
This ModuleClass is used to model the storage on a managed device.
Table 5.8.12-1: Actions of dmStorage ModuleClass
Return Type | Name | Argument | Optional | Documentation |
---|---|---|---|---|
none | format | none | true | The action that allows to format the mounted storage. |
none | unmount | none | true | The action that allows to safety eject storage device. |
Table 5.8.12-2 DataPoints of dmStorage ModuleClass
Name | Type | R/W | Optional | Unit | Description |
---|---|---|---|---|---|
UUID | xs:string | R | true | The uuid of the storage device. | |
type | xs:integer | R | true | Indicates the type of storage. 0 indicates internal and 1 indicates external. | |
name | xs:string | RW | true | Indicates name of the mounted storage. | |
writeSpeed | xs:integer | R | true | Indicates the write speed of storage device. | |
readSpeed | xs:integer | R | true | Indicates the read speed of storage device. | |
availStorage | xs:integer | R | false | MB | Indicates the current available amount of memory. |
totalStorage | xs:integer | R | false | MB | Indicates the total amount of memory available. |
presence | xs:integer | R | true | Indicates current presence status of memory card. 0 indicates card is ejected, 1 indicates card is inserted. | |
status | xs:integer | R | true | Indicates current operation status of storage. 1 -indicates storage is ready, 0 indicates storage is busy. | |
mounts | xs:integer | R | true | Indicates number of successful mounts of the storage. | |
forcedUnmounts | xs:integer | R | true | Indicates number of forced unmounts of the storage. | |
fileSystem | xs:string | RW | true | Indicates the filesystem type used on the mounted storage. | |
mountingPoint | xs:string | RW | true | Indicates mounting point of the mounted storage. | |
mountOptions | xs:string | R | true | Indicates additional file system specific and file system independent mount options that indicate specific behaviours of the mount point as well as the capabilities of the underlying file system. | |
writable | xs:boolean | R | false | Indicates whether the storage volume is mounted as read/write ("TRUE") or read-only ("FALSE"). |