diff --git a/docs/source/CspSubElementSubarray.rst b/docs/source/CspSubElementSubarray.rst
new file mode 100644
index 0000000000000000000000000000000000000000..3eeacf603e8612efe131ea96f7b22de08b07741c
--- /dev/null
+++ b/docs/source/CspSubElementSubarray.rst
@@ -0,0 +1,19 @@
+.. LMC Base Classes documentation master file, created by
+   sphinx-quickstart on Fri Jan 11 10:03:42 2019.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+SKA CSP Sub-element Subarray
+============================================
+This module implements a generic Subarray device for a CSP Sub-element.
+The scope of this module is to provide a uniform access to a CSP Sub-element 
+subarray from the CSP.LMC side.
+
+
+.. toctree::
+   :maxdepth: 2
+
+.. automodule:: ska.base.csp_subelement_subarray
+.. autoclass:: ska.base.CspSubElementSubarray
+   :members:
+   :undoc-members:
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 9fb2dc81ca0ec270ab34d32fa4fe67ee55e90070..fcff7dc568d2e8df07f5cbc28324b7ddc3aa222b 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -22,6 +22,7 @@ Welcome to LMC Base Classes documentation!
 
    Device:  SKA CSP Sub-element Master<CspSubElementMaster>
    Device:  SKA CSP Sub-element ObsDevice<CspSubElementObsDevice>
+   Device:  SKA CSP Sub-element Subarray<CspSubElementSubarray>
 
    SKA Control Model<Control_Model>
    SKA Commands<Commands>
diff --git a/pogo/CspSubElementSubarray.xmi b/pogo/CspSubElementSubarray.xmi
new file mode 100644
index 0000000000000000000000000000000000000000..f12f30e02e72eeea08bea282b713d566e52f83b8
--- /dev/null
+++ b/pogo/CspSubElementSubarray.xmi
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="ASCII"?>
+<pogoDsl:PogoSystem xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pogoDsl="http://www.esrf.fr/tango/pogo/PogoDsl">
+  <classes name="CspSubElementSubarray" pogoRevision="9.6">
+    <description description="Subarray device for SKA CSP SubElement" title="CspSubElementSubarray" sourcePath="/home/toor/ska-git/lmc-base-classes/pogo" language="PythonHL" filestogenerate="XMI   file,Code files,Protected Regions" license="BSD3" copyright="" hasMandatoryProperty="false" hasConcreteProperty="false" hasAbstractCommand="false" hasAbstractAttribute="false">
+      <inheritances classname="Device_Impl" sourcePath=""/>
+      <inheritances classname="SKAObsDevice" sourcePath="./"/>
+      <inheritances classname="SKASubarray" sourcePath="/home/toor/ska-git/lmc-base-classes/pogo"/>
+      <identification contact="at inaf.it - elisabetta.giani" author="elisabetta.giani" emailDomain="inaf.it" classFamily="SkaBase" siteSpecific="" platform="All Platforms" bus="Not Applicable" manufacturer="none" reference=""/>
+    </description>
+    <deviceProperties name="CapabilityTypes" description="List of Capability types e.g. capCorr, capPss,&#xA;capPstBf, capVlbi, this will be used to dynamically&#xA;define groups for subarray.">
+      <type xsi:type="pogoDsl:StringVectorType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </deviceProperties>
+    <deviceProperties name="LoggingLevelDefault" description="Default logging level at device startup.&#xA;(0=OFF, 1=FATAL, 2=ERROR, 3=WARNING, 4=INFO, 5=DEBUG)">
+      <type xsi:type="pogoDsl:UShortType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <DefaultPropValue>4</DefaultPropValue>
+    </deviceProperties>
+    <deviceProperties name="LoggingTargetsDefault" description="Default logging targets at device startup.&#xA;Each item has the format:  target_type::target_name.&#xA;To log to stdout, use 'console::cout'.&#xA;To log to syslog, use 'syslog::&lt;address>',&#xA;  where &lt;address> is a file path,&#xA;  for example 'syslog::/var/run/rsyslog/dev/log'.&#xA;To log to a file, use 'file::&lt;path>',&#xA;  where &lt;path> is a file path,&#xA;  for example 'file::/tmp/my_dev.log'.">
+      <type xsi:type="pogoDsl:StringVectorType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </deviceProperties>
+    <deviceProperties name="GroupDefinitions" description="Each string in the list is a JSON serialised dict defining the ``group_name``,&#xA;``devices`` and ``subgroups`` in the group.  A TANGO Group object is created&#xA;for each item in the list, according to the hierarchy defined.  This provides&#xA;easy access to the managed devices in bulk, or individually.&#xA;&#xA;The general format of the list is as follows, with optional ``devices`` and&#xA;``subgroups`` keys:&#xA;    [ {``group_name``: ``&lt;name>``,&#xA;       ``devices``: [``&lt;dev name>``, ...]},&#xA;      {``group_name``: ``&lt;name>``,&#xA;       ``devices``: [``&lt;dev name>``, ``&lt;dev name>``, ...],&#xA;       ``subgroups`` : [{&lt;nested group>},&#xA;                              {&lt;nested group>}, ...]},&#xA;      ...&#xA;      ]&#xA;&#xA;For example, a hierarchy of racks, servers and switches:&#xA;    [ {``group_name``: ``servers``,&#xA;       ``devices``: [``elt/server/1``, ``elt/server/2``,&#xA;                       ``elt/server/3``, ``elt/server/4``]},&#xA;      {``group_name``: ``switches``,&#xA;       ``devices``: [``elt/switch/A``, ``elt/switch/B``]},&#xA;      {``group_name``: ``pdus``,&#xA;       ``devices``: [``elt/pdu/rackA``, ``elt/pdu/rackB``]},&#xA;      {``group_name``: ``racks``,&#xA;      ``subgroups``: [&#xA;            {``group_name``: ``rackA``,&#xA;             ``devices``: [``elt/server/1``, ``elt/server/2``,&#xA;                               ``elt/switch/A``, ``elt/pdu/rackA``]},&#xA;            {``group_name``: ``rackB``,&#xA;             ``devices``: [``elt/server/3``, ``elt/server/4``,&#xA;                              ``elt/switch/B``, ``elt/pdu/rackB``],&#xA;             ``subgroups``: []}&#xA;       ]} ]">
+      <type xsi:type="pogoDsl:StringVectorType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </deviceProperties>
+    <deviceProperties name="SkaLevel" description="Indication of importance of the device in the SKA hierarchy &#xA;to support drill-down navigation: 1..6, with 1 highest.&#xA;Default is 4, making provision for &#xA;EltMaster, EltAlarms, EltTelState = 1&#xA;SubEltMaster = 2&#xA;Subarray, Capability = 2/3&#xA;Others = 4 (or 5 or 6)">
+      <type xsi:type="pogoDsl:ShortType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <DefaultPropValue>4</DefaultPropValue>
+    </deviceProperties>
+    <deviceProperties name="SubID" description="Unique identifier of the subarray device.">
+      <type xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </deviceProperties>
+    <commands name="Abort" description="Change obsState to ABORTED." execMethod="abort" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="Configure" description="Configures the scan for this subarray" execMethod="configure" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="The scan configuration, formatted as a JSON string">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="GetVersionInfo" description="Array of version strings of all entities modelled by this device. &#xA;(One level down only)&#xA;Each string in the array lists the version info for one entity&#xA;managed by this device. &#xA;The first entry is version info for this TANGO Device itself.&#xA;The entities may be TANGO devices, or hardware LRUs or &#xA;anything else this devices manages/models.&#xA;The intention with this command is that it can provide more &#xA;detailed information than can be captured in the versionId &#xA;and buildState attributes, if necessary.&#xA;In the minimal case the GetVersionInfo will contain only the &#xA;versionId and buildState attributes of the next lower level&#xA;entities." execMethod="get_version_info" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="[ name: EltTelState">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="Status" description="This command gets the device status (stored in its device_status data member) and returns it to the caller." execMethod="dev_status" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="none">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="Device status">
+        <type xsi:type="pogoDsl:ConstStringType"/>
+      </argout>
+      <status abstract="true" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="State" description="This command gets the device state (stored in its device_state data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="none">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="Device state">
+        <type xsi:type="pogoDsl:StateType"/>
+      </argout>
+      <status abstract="true" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="AssignResources" description="" execMethod="assign_resources" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="List of Resources to add to subarray.">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="End" description="Change obsState to IDLE." execMethod="end" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="EndScan" description="Terminate scan." execMethod="end_scan" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="ReleaseAllResources" description="Remove all resources to tear down to an empty subarray." execMethod="release_all_resources" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="ReleaseResources" description="Delta removal of assigned resources." execMethod="release_resources" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="List of resources to remove from the subarray.">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="Reset" description="Reset device to its default state" execMethod="reset" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="ObsReset" description="Reset observation state machine to its default state" execMethod="obs_reset" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="Restart" description="Restart the observation state machine" execMethod="restart" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="Scan" description="Starts the scan." execMethod="scan" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="true" concrete="true"/>
+    </commands>
+    <commands name="ConfigureScan" description="Configure a complete scan for the subarray." execMethod="configure_scan" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
+      <argin description="A Json-encoded string with the scan configuration.">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="A tuple containing a return code and a string message indicating status.&#xA;The message is for information purpose only.">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <commands name="GoToIdle" description="Transit the subarray from READY to IDLE obsState." execMethod="go_to_idle" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="A tuple containing a return code and a string  message indicating status.&#xA;The message is for information purpose only.">
+        <type xsi:type="pogoDsl:LongStringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <attributes name="activationTime" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:DoubleType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Time of activation in seconds since Unix epoch." label="" unit="s" standardUnit="s" displayUnit="s" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="adminMode" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" memorized="true" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:EnumType"/>
+      <changeEvent fire="true" libCheckCriteria="true"/>
+      <archiveEvent fire="true" libCheckCriteria="true"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="The admin mode reported for this device. It may interpret the current device condition &#xA;and condition of all managed devices to set this. Most possibly an aggregate attribute." label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="buildState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Build state of this device" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="configurationDelayExpected" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:UShortType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Configuration delay expected in seconds" label="" unit="seconds" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="configurationProgress" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:UShortType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <status abstract="false" inherited="true" concrete="true" concreteHere="false"/>
+      <properties description="Percentage configuration progress" label="" unit="%" standardUnit="" displayUnit="" format="" maxValue="100" minValue="0" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="controlMode" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" memorized="true" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:EnumType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="The control mode of the device. REMOTE, LOCAL&#xA;TANGO Device accepts only from a &#x2018;local&#x2019; client and ignores commands and queries received from TM&#xA;or any other &#x2018;remote&#x2019; clients. The Local clients has to release LOCAL control before REMOTE clients&#xA;can take control again." label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="healthState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:EnumType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="The health state reported for this device. It interprets the current device condition &#xA;and condition of all managed devices to set this. Most possibly an aggregate attribute." label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="loggingLevel" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:EnumType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Current logging level for this device - initialises to LoggingLevelDefault on startup" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="obsMode" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:EnumType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Observing Mode" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="obsState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:EnumType"/>
+      <changeEvent fire="true" libCheckCriteria="true"/>
+      <archiveEvent fire="true" libCheckCriteria="true"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Observing State" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="simulationMode" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" memorized="true" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:EnumType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Reports the simulation mode of the device. Some devices may implement both modes,&#xA;while others will have simulators that set simulationMode to True while the real&#xA;devices always set simulationMode to False." label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="testMode" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" memorized="true" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:EnumType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="The test mode of the device. &#xA;Either no test mode (empty string) or an indication of the test mode." label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="versionId" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Build state of this device" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="scanID" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:ULongType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The scan identification number to be inserted in the output products." label="scanID" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="configurationID" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The configuration ID specified into the JSON configuration." label="configurationID" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="sdpDestinationAddresses" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="JSON formatted string.&#xA;Report the list of all the SDP addresses provided by SDP to receive the output products.&#xA;Specifies the Mac, IP, Port for each resource:CBF visibility channels, Pss pipelines, PSTBeam" label="sdpDestinationAddresses" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="outputDataRateToSdp" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:FloatType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The output data rate (GB/s) on the link for each scan." label="outputDataRateToSdp" unit="GB/s" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="lastScanConfiguration" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The last valid scan configuration." label="lastScanConfiguration" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="configureScanMeasuredDuration" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:FloatType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The measured time (sec) taken to execute the ConfigureScan command." label="configureScanMeasuredDuration" unit="sec" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="listOfDevicesCompletedTasks" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="JSON formatted string reporting for each task/command the list of devices&#xA;that completed successfully the task.&#xA;Ex.&#xA;{``cmd1``: [``device1``, ``device2``], ``cmd2``: [``device2``, ``device3``]}" label="listOfDevicesCompletedTasks" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="assignResourcesMaximumDuration" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:FloatType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The maximum expected command duration." label="assignResourcesMaximumDuration" unit="sec" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="assignResourcesMeasuredDuration" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:FloatType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The measured command execution duration." label="assignResourcesMeasuredDuration" unit="sec" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="assignResourcesProgress" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:UShortType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The percentage progress of the command in the [0,100]." label="assignResourcesProgress" unit="" standardUnit="" displayUnit="" format="" maxValue="100" minValue="0" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="releaseResourcesMaximumDuration" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:FloatType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The maximum expected command duration." label="releaseResourcesMaximumDuration" unit="sec" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="releaseResourcesMeasuredDuration" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:FloatType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The measured command execution duration." label="releaseResourcesMeasuredDuration" unit="sec" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="releaseResourcesProgress" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:UShortType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="The percentage progress of the command in the [0,100]." label="releaseResourcesProgress" unit="" standardUnit="" displayUnit="" format="" maxValue="100" minValue="0" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="configureScanTimeoutExpiredFlag" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:BooleanType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="Flag reporting  ConfigureScan command timeout expiration." label="configureScanTimeoutExpiredFlag" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="assignResourcesTimeoutExpiredFlag" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:BooleanType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="Flag reporting  AssignResources command timeout expiration." label="assignResourcesTimeoutExpiredFlag" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="releaseResourcesTimeoutExpiredFlag" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:BooleanType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="Flag reporting  ReleaseResources command timeout expiration." label="ReleaseResourcesTimeoutExpiredFlag" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="assignedResources" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="100" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <status abstract="false" inherited="true" concrete="true" concreteHere="false"/>
+      <properties description="The list of resources assigned to the subarray." label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="configuredCapabilities" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="10" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <status abstract="false" inherited="true" concrete="true" concreteHere="false"/>
+      <properties description="A list of capability types with no. of instances in use on this subarray; e.g.&#xA;Correlators:512, PssBeams:4, PstBeams:4, VlbiBeams:0." label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="loggingTargets" attType="Spectrum" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="3" maxY="" allocReadMember="true">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <status abstract="false" inherited="true" concrete="true"/>
+      <properties description="Logging targets for this device, excluding ska_logging defaults - &#xA;initialises to LoggingTargetsDefault on startup" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <attributes name="sdpLinkActive" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="100" maxY="" allocReadMember="true" isDynamic="false">
+      <dataType xsi:type="pogoDsl:BooleanType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="Flag reporting if the SDP links are active." label="sdpLinkActive" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <states name="ON" description="This state could have been called OK or OPERATIONAL. It means that the device is in its operational state. (E.g. the power supply is giving its nominal current, th motor is ON and ready to move, the instrument is operating). This state is modified by the Attribute alarm checking of the DeviceImpl:dev_state method. i.e. if the State is ON and one attribute has its quality factor to ATTR_WARNING or ATTR_ALARM, then the State is modified to ALARM.">
+      <status abstract="false" inherited="true" concrete="true"/>
+    </states>
+    <states name="OFF" description="The device is in normal condition but is not active. E.g. the power supply main circuit breaker is open; the RF transmitter has no power etc...">
+      <status abstract="false" inherited="true" concrete="true"/>
+    </states>
+    <states name="FAULT" description="The device has a major failure that prevents it to work. For instance, A power supply has stopped due to over temperature A motor cannot move because it has fault conditions. Usually we cannot get out from this state without an intervention on the hardware or a reset command.">
+      <status abstract="false" inherited="true" concrete="true"/>
+    </states>
+    <states name="INIT" description="This state is reserved to the starting phase of the device server. It means that the software is not fully operational and that the user must wait">
+      <status abstract="false" inherited="true" concrete="true"/>
+    </states>
+    <states name="ALARM" description="ALARM - The device is operating but&#xA;at least one of the attributes is out of range. It can be linked to alarm conditions set by attribute properties or a specific case. (E.g. temperature alarm on a stepper motor, end switch pressed on a stepper motor, up water level in a tank, etc....). In alarm, usually the device does its job, but the operator has to perform an action to avoid a bigger problem that may switch the state to FAULT.">
+      <status abstract="false" inherited="true" concrete="true"/>
+    </states>
+    <states name="UNKNOWN" description="The device cannot retrieve its state. It is the case when there is a communication problem to the hardware (network cut, broken cable etc...) It could also represent an incoherent situation">
+      <status abstract="false" inherited="true" concrete="true"/>
+    </states>
+    <states name="STANDBY" description="Equates to LOW-POWER mode. This is the initial transition from INIT if the device supports a low-power mode. The device is not fully active but is ready to operate.">
+      <status abstract="false" inherited="true" concrete="true"/>
+    </states>
+    <states name="DISABLE" description="The device cannot be switched ON for an external reason. E.g. the power supply has its door open, the safety conditions are not satisfactory to allow the device to operate.">
+      <status abstract="false" inherited="true" concrete="true"/>
+    </states>
+    <preferences docHome="./doc_html" makefileHome="/usr/local/share/pogo/preferences"/>
+  </classes>
+</pogoDsl:PogoSystem>
diff --git a/setup.py b/setup.py
index 2de15f7e7f73a797cd36b3e229786de54576f93f..a172135c7528c117b5e85a8a0ce0c2a8c8648294 100644
--- a/setup.py
+++ b/setup.py
@@ -50,6 +50,7 @@ setuptools.setup(
             "SKATelState=ska.base.tel_state_device:main",
             "CspSubelementMaster=ska.base.csp_subelement_master:main",
             "CspSubelementObsDevice=ska.base.csp_subelement_obsdevice:main",
+            "CspSubelementSubarray=ska.base.csp_subelement_subarray:main",
         ]
     },
     keywords="lmc base classes ska",
diff --git a/src/ska/base/__init__.py b/src/ska/base/__init__.py
index 9a392d890a071afc3f974f193d0da0ab1a033ad7..f0d311b608b95dfaa22d38851086d7e87646b513 100644
--- a/src/ska/base/__init__.py
+++ b/src/ska/base/__init__.py
@@ -18,6 +18,7 @@ __all__ = (
     "CspSubElementMaster",
     "CspSubElementObsDevice",
     "CspSubElementObsDeviceStateModel",
+    "CspSubElementSubarray",
 )
 
 # Note: order of imports is important - start with lowest in the hierarchy
@@ -39,6 +40,7 @@ from .subarray_device import (
 )
 # CspSubElement classes
 from .csp_subelement_master import CspSubElementMaster
+from .csp_subelement_subarray import CspSubElementSubarray
 from .csp_subelement_obsdevice import (
         CspSubElementObsDevice,
         CspSubElementObsDeviceStateModel,
diff --git a/src/ska/base/csp_subelement_subarray.py b/src/ska/base/csp_subelement_subarray.py
new file mode 100644
index 0000000000000000000000000000000000000000..e34dc1e9099be1c90c4f49607226e8ab0cadaf18
--- /dev/null
+++ b/src/ska/base/csp_subelement_subarray.py
@@ -0,0 +1,608 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of the CspSubElementSubarray project
+#
+#
+# Distributed under the terms of the BSD3 license.
+# See LICENSE.txt for more info.
+
+""" CspSubElementSubarray
+
+Subarray device for SKA CSP SubElement
+"""
+
+# PROTECTED REGION ID(CspSubElementSubarray.additionnal_import) ENABLED START #
+import json
+from json.decoder import JSONDecodeError
+from collections import defaultdict
+# Tango imports
+import tango
+from tango import DebugIt
+from tango.server import run
+from tango.server import Device
+from tango.server import attribute, command
+from tango.server import device_property
+from tango import AttrQuality, DispLevel, DevState
+from tango import AttrWriteType, PipeWriteType
+
+# SKA import
+from ska.base import SKASubarray
+from ska.base.commands import ResultCode, ActionCommand
+from ska.base.control_model import ObsState
+# Additional import
+# PROTECTED REGION END #    //  CspSubElementSubarray.additionnal_import
+
+__all__ = ["CspSubElementSubarray", "main"]
+
+
+class CspSubElementSubarray(SKASubarray):
+    """
+    Subarray device for SKA CSP SubElement
+    """
+    # PROTECTED REGION ID(CspSubElementSubarray.class_variable) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubElementSubarray.class_variable
+
+    # -----------------
+    # Device Properties
+    # -----------------
+
+    # ----------
+    # Attributes
+    # ----------
+
+    scanID = attribute(
+        dtype='DevULong64',
+        label="scanID",
+        doc="The scan identification number to be inserted in the output products.",
+    )
+
+    configurationID = attribute(
+        dtype='DevString',
+        label="configurationID",
+        doc="The configuration ID specified into the JSON configuration.",
+    )
+
+    sdpDestinationAddresses = attribute(
+        dtype='DevString',
+        access=AttrWriteType.READ_WRITE,
+        label="sdpDestinationAddresses",
+        doc="JSON formatted string.\nReport the list of all the SDP addresses provided by SDP to receive the output products.\nSpecifies the Mac, IP, Port for each resource:CBF visibility channels, Pss pipelines, PSTBeam",
+    )
+
+    outputDataRateToSdp = attribute(
+        dtype='DevFloat',
+        label="outputDataRateToSdp",
+        unit="GB/s",
+        doc="The output data rate (GB/s) on the link for each scan.",
+    )
+
+    lastScanConfiguration = attribute(
+        dtype='DevString',
+        label="lastScanConfiguration",
+        doc="The last valid scan configuration.",
+    )
+
+    sdpLinkActive = attribute(
+        dtype=('DevBoolean',),
+        max_dim_x=100,
+        label="sdpLinkActive",
+        doc="Flag reporting if the SDP links are active.",
+    )
+
+    listOfDevicesCompletedTasks = attribute(
+        dtype='DevString',
+        label="listOfDevicesCompletedTasks",
+        doc="JSON formatted string reporting for each task/command the list of devices\nthat completed successfully the task.\nEx.\n{``cmd1``: [``device1``, ``device2``], ``cmd2``: [``device2``, ``device3``]}",
+    )
+    
+    configureScanMeasuredDuration = attribute(
+        dtype='DevFloat',
+        label="configureScanMeasuredDuration",
+        unit="sec",
+        doc="The measured time (sec) taken to execute the command",
+    )
+
+    configureScanTimeoutExpiredFlag = attribute(
+        dtype='DevBoolean',
+        label="configureScanTimeoutExpiredFlag",
+        doc="Flag reporting  ConfigureScan command timeout expiration.",
+    )
+
+    assignResourcesMaximumDuration = attribute(
+        dtype='DevFloat',
+        access=AttrWriteType.READ_WRITE,
+        label="assignResourcesMaximumDuration",
+        unit="sec",
+        doc="The maximum expected command duration.",
+    )
+
+    assignResourcesMeasuredDuration = attribute(
+        dtype='DevFloat',
+        label="assignResourcesMeasuredDuration",
+        unit="sec",
+        doc="The measured command execution duration.",
+    )
+
+    assignResourcesProgress = attribute(
+        dtype='DevUShort',
+        label="assignResourcesProgress",
+        max_value=100,
+        min_value=0,
+        doc="The percentage progress of the command in the [0,100].",
+    )
+
+    assignResourcesTimeoutExpiredFlag = attribute(
+        dtype='DevBoolean',
+        label="assignResourcesTimeoutExpiredFlag",
+        doc="Flag reporting  AssignResources command timeout expiration.",
+    )
+
+
+    releaseResourcesMaximumDuration = attribute(
+        dtype='DevFloat',
+        access=AttrWriteType.READ_WRITE,
+        label="releaseResourcesMaximumDuration",
+        unit="sec",
+        doc="The maximum expected command duration.",
+    )
+
+    releaseResourcesMeasuredDuration = attribute(
+        dtype='DevFloat',
+        label="releaseResourcesMeasuredDuration",
+        unit="sec",
+        doc="The measured command execution duration.",
+    )
+
+    releaseResourcesProgress = attribute(
+        dtype='DevUShort',
+        label="releaseResourcesProgress",
+        max_value=100,
+        min_value=0,
+        doc="The percentage progress of the command in the [0,100].",
+    )
+
+    releaseResourcesTimeoutExpiredFlag = attribute(
+        dtype='DevBoolean',
+        label="timeoutExpiredFlag",
+        doc="Flag reporting  command timeout expiration.",
+    )
+
+    # ---------------
+    # General methods
+    # ---------------
+
+    def init_command_objects(self):
+        """
+        Sets up the command objects
+        """
+        super().init_command_objects()
+        device_args = (self, self.state_model, self.logger)
+        self.register_command_object(
+            "ConfigureScan", self.ConfigureScanCommand(*device_args)
+        )
+        self.register_command_object(
+            "GoToIdle", self.GoToIdleCommand(*device_args)
+        )
+    
+    class InitCommand(SKASubarray.InitCommand):
+        """
+        A class for the CspSubElementObsDevice's init_device() "command".
+        """
+
+        def do(self):
+            """
+            Stateless hook for device initialisation.
+
+            :return: A tuple containing a return code and a string
+                message indicating status. The message is for
+                information purpose only.
+            :rtype: (ResultCode, str)
+            """
+            super().do()
+
+            device = self.target
+            device._scan_id = 0
+
+            device._sdp_addresses = {"outputHost":[], "outputMac": [], "outputPort":[]}
+            device._sdp_links_active = [False,]
+            device._sdp_output_data_rate = 0.
+
+            device._config_id = ''
+            device._last_scan_configuration = ''
+            
+            # _list_of_devices_completed_task: for each task/command reports
+            # the list of the devices that successfully completed the task.
+            # Implemented as a defualt dictionary:
+            # keys: the command name in lower case (configurescan, assignresources, etc.)
+            # values: the list of devices' FQDN
+            device._list_of_devices_completed_task = defaultdict(list)
+            
+            # _cmd_progress: command execution's progress percentage
+            # implemented as a default dictionary:
+            # keys: the command name in lower case(configurescan,..)
+            # values: the progress percentage (default 0)
+            device._cmd_progress = defaultdict(int)
+            
+            # _cmd_maximun_duration: command execution's expected maximum duration (sec.)
+            # implemented as a default dictionary:
+            # keys: the command name in lower case(configurescan, assignresources,..)
+            # values: the expected maximum duration in sec.
+            device._cmd_maximum_duration = defaultdict(float)
+
+            # _cmd_measure_duration: command execution's measured duration (sec.) 
+            # implemented as a default dictionary:
+            # keys: the command name in lower case(configurescan, assignresources,..)
+            # values: the measured execution time (sec.)
+            device._cmd_measured_duration = defaultdict(float)
+            
+            # _timeout_expired: boolean flag to signal timeout during command execution.
+            # To check and reset before a command execution.
+            # keys: the command name in lower case(configurescan, assignresources,..)
+            # values: True/False
+            device._timeout_expired = defaultdict(bool)
+            # configure the flags to push event from the device server
+            device.set_change_event('configureScanTimeoutExpiredFlag', True, True)
+            device.set_archive_event('configureScanTimeoutExpiredFlag', True, True)
+            device.set_change_event('assignResourcesTimeoutExpiredFlag', True, True)
+            device.set_archive_event('assignResourcesTimeoutExpiredFlag', True, True)
+            device.set_change_event('releaseResourcesTimeoutExpiredFlag', True, True)
+            device.set_archive_event('releaseResourcesTimeoutExpiredFlag', True, True)
+            
+
+            message = "CspSubElementSubarray Init command completed OK"
+            device.logger.info(message)
+            return (ResultCode.OK, message)
+
+    def always_executed_hook(self):
+        """Method always executed before any TANGO command is executed."""
+        # PROTECTED REGION ID(CspSubElementSubarray.always_executed_hook) ENABLED START #
+        # PROTECTED REGION END #    //  CspSubElementSubarray.always_executed_hook
+
+    def delete_device(self):
+        """Hook to delete resources allocated in init_device.
+
+        This method allows for any memory or other resources allocated in the
+        init_device method to be released.  This method is called by the device
+        destructor and by the device Init command.
+        """
+        # PROTECTED REGION ID(CspSubElementSubarray.delete_device) ENABLED START #
+        # PROTECTED REGION END #    //  CspSubElementSubarray.delete_device
+    
+    # ------------------
+    # Attributes methods
+    # ------------------
+
+    def read_scanID(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.scanID_read) ENABLED START #
+        """Return the scanID attribute."""
+        return self._scan_id
+        # PROTECTED REGION END #    //  CspSubElementSubarray.scanID_read
+
+    def read_configurationID(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.configurationID_read) ENABLED START #
+        """Return the configurationID attribute."""
+        return self._config_id
+        # PROTECTED REGION END #    //  CspSubElementSubarray.configurationID_read
+
+    def read_sdpDestinationAddresses(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.sdpDestinationAddresses_read) ENABLED START #
+        """Return the sdpDestinationAddresses attribute."""
+        return self._sdp_addresses
+        # PROTECTED REGION END #    //  CspSubElementSubarray.sdpDestinationAddresses_read
+
+    def write_sdpDestinationAddresses(self, value):
+        # PROTECTED REGION ID(CspSubElementSubarray.sdpDestinationAddresses_write) ENABLED START #
+        """Set the sdpDestinationAddresses attribute."""
+        self._sdp_addresses = value
+        # PROTECTED REGION END #    //  CspSubElementSubarray.sdpDestinationAddresses_write
+
+    def read_outputDataRateToSdp(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.outputDataRateToSdp_read) ENABLED START #
+        """Return the outputDataRateToSdp attribute."""
+        return self._sdp_output_data_rate
+        # PROTECTED REGION END #    //  CspSubElementSubarray.outputDataRateToSdp_read
+
+    def read_lastScanConfiguration(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.lastScanConfiguration_read) ENABLED START #
+        """Return the lastScanConfiguration attribute."""
+        return self._last_scan_configuration
+        # PROTECTED REGION END #    //  CspSubElementSubarray.lastScanConfiguration_read
+
+    def read_configureScanMeasuredDuration(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.configureScanMeasuredDuration_read) ENABLED START #
+        """Return the configureScanMeasuredDuration attribute."""
+        return self._cmd_measured_duration['configurescan']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.configureScanMeasuredDuration_read
+        
+    def read_configureScanTimeoutExpiredFlag(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.configureScanTimeoutExpiredFlag_read) ENABLED START #
+        """Return the configureScanTimeoutExpiredFlag attribute."""
+        return self._timeout_expired['configurescan']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.configureScanTimeoutExpiredFlag_read
+
+    def read_listOfDevicesCompletedTasks(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.listOfDevicesCompletedTasks_read) ENABLED START #
+        """Return the listOfDevicesCompletedTasks attribute."""
+        dict_to_string = json.dumps(self._list_of_devices_completed_task)
+        return dict_to_string
+        # PROTECTED REGION END #    //  CspSubElementSubarray.listOfDevicesCompletedTasks_read
+
+    def read_assignResourcesMaximumDuration(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.assignResourcesMaximumDuration_read) ENABLED START #
+        """Return the assignResourcesMaximumDuration attribute."""
+        return self._cmd_maximum_duration['assignresources']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.assignResourcesMaximumDuration_read
+
+    def write_assignResourcesMaximumDuration(self, value):
+        # PROTECTED REGION ID(CspSubElementSubarray.assignResourcesMaximumDuration_write) ENABLED START #
+        """Set the assignResourcesMaximumDuration attribute."""
+        self._cmd_maximum_duration['assignresources'] = value
+        # PROTECTED REGION END #    //  CspSubElementSubarray.assignResourcesMaximumDuration_write
+
+    def read_assignResourcesMeasuredDuration(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.assignResourcesMeasuredDuration_read) ENABLED START #
+        """Return the assignResourcesMeasuredDuration attribute."""
+        return self._cmd_measured_duration['assignresources']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.assignResourcesMeasuredDuration_read
+
+    def read_assignResourcesProgress(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.assignResourcesProgress_read) ENABLED START #
+        """Return the assignResourcesProgress attribute."""
+        return self._cmd_progress['assignresources']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.assignResourcesProgress_read
+
+    def read_assignResourcesTimeoutExpiredFlag(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.assignResourcesTimeoutExpiredFlag_read) ENABLED START #
+        """Return the assignResourcesTimeoutExpiredFlag attribute."""
+        return self._timeout_expired['assignresources']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.assignResourcesTimeoutExpiredFlag_read
+
+    def read_releaseResourcesMaximumDuration(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.releaseResourcesMaximumDuration_read) ENABLED START #
+        """Return the releaseResourcesMaximumDuration attribute."""
+        return self._cmd_maximum_duration['releaseresources']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.releaseResourcesMaximumDuration_read
+
+    def write_releaseResourcesMaximumDuration(self, value):
+        # PROTECTED REGION ID(CspSubElementSubarray.releaseResourcesMaximumDuration_write) ENABLED START #
+        """Set the releaseResourcesMaximumDuration attribute."""
+        self._cmd_maximum_duration['releaseresources'] = value
+        # PROTECTED REGION END #    //  CspSubElementSubarray.releaseResourcesMaximumDuration_write
+
+    def read_releaseResourcesMeasuredDuration(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.releaseResourcesMeasuredDuration_read) ENABLED START #
+        """Return the releaseResourcesMeasuredDuration attribute."""
+        return self._cmd_measured_duration['releaseresources']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.releaseResourcesMeasuredDuration_read
+
+    def read_releaseResourcesProgress(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.releaseResourcesProgress_read) ENABLED START #
+        """Return the releaseResourcesProgress attribute."""
+        return self._cmd_progress['releaseresources']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.releaseResourcesProgress_read
+    
+    def read_releaseResourcesTimeoutExpiredFlag(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.releaseResourcesTimeoutExpiredFlag_read) ENABLED START #
+        """Return the releaseResourcesTimeoutExpiredFlag attribute."""
+        return self._timeout_expired['releaseresources']
+        # PROTECTED REGION END #    //  CspSubElementSubarray.releaseResourcesTimeoutExpiredFlag_read
+
+    def read_sdpLinkActive(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.sdpLinkActive_read) ENABLED START #
+        """Return the sdpLinkActive attribute."""
+        return (False,)
+        # PROTECTED REGION END #    //  CspSubElementSubarray.sdpLinkActive_read
+
+    # --------
+    # Commands
+    # --------
+
+    class ConfigureScanCommand(ActionCommand):
+        """
+        A class for the CspSubElementObsDevices's ConfigureScan command.
+        """
+        def __init__(self, target, state_model, logger=None):
+            """
+            Constructor for ConfigureScanCommand
+
+            :param target: the object that this command acts upon; for
+                example, the CspSubElementObsDevice device for which this class
+                implements the command
+            :type target: object
+            :param state_model: the state model that this command uses
+                 to check that it is allowed to run, and that it drives
+                 with actions.
+            :type state_model: :py:class:`SKASubarrayStateModel`
+            :param logger: the logger to be used by this Command. If not
+                provided, then a default module logger will be used.
+            :type logger: a logger that implements the standard library
+                logger interface
+            """
+            super().__init__(
+                target, state_model, "configure", start_action=True, logger=logger
+            )
+
+        def do(self, argin):
+            """
+            Stateless hook for ConfigureScan() command functionality.
+
+            :param argin: The configuration as JSON formatted string
+            :type argin: str
+
+            :return: A tuple containing a return code and a string
+                message indicating status. The message is for
+                information purpose only.
+            :rtype: (ResultCode, str)
+            """
+            device = self.target
+            result_code, msg = self.validate_input(argin)
+            if result_code == ResultCode.FAILED:
+                return (result_code, msg)
+            # store the configuration on command success
+            device._last_scan_configuration = argin
+            return (ResultCode.OK, "Configure command completed OK")
+
+        def validate_input(self, argin):
+            """
+            Validate the configuration parameters against allowed values, as needed.
+            :param argin: The JSON formatted string with configuration for the device.
+            :type argin: 'DevString'
+            :return: A tuple containing a return code and a string message.
+            :rtype: (ResultCode, str)
+            """
+            device = self.target
+            try: 
+                configuration_dict = json.loads(argin)
+                device._config_id = configuration_dict['id']
+                return (ResultCode.OK, "Configuration validated with success")
+            except (KeyError, JSONDecodeError) as err:
+                msg = "Validate configuration failed with error:{}".format(err)
+            except Exception as other_errs:
+                msg = "Validate configuration failed with unknown error:{}".format(other_errs)
+            self.logger.error(msg)
+            return (ResultCode.FAILED, msg)
+
+
+    class GoToIdleCommand(ActionCommand):
+        """
+        A class for the CspSubElementObsDevices's GoToIdle command.
+        """
+        def __init__(self, target, state_model, logger=None):
+            """
+            Constructor for GoToIdle Command.
+
+            :param target: the object that this command acts upon; for
+                example, the CspSubElementObsDevice device for which this class
+                implements the command
+            :type target: object
+            :param state_model: the state model that this command uses
+                 to check that it is allowed to run, and that it drives
+                 with actions.
+            :type state_model: :py:class:`SKASubarrayStateModel`
+            :param logger: the logger to be used by this Command. If not
+                provided, then a default module logger will be used.
+            :type logger: a logger that implements the standard library
+                logger interface
+            """
+            super().__init__(
+                target, state_model, "end", logger=logger
+            )
+
+        def do(self):
+            """
+            Stateless hook for GoToIdle() command functionality.
+
+            :return: A tuple containing a return code and a string
+                message indicating status. The message is for
+                information purpose only.
+            :rtype: (ResultCode, str)
+            """
+            device = self.target
+            # reset to default values the configurationID and scanID
+            device._config_id = ''
+            device._scan_id = 0
+            return (ResultCode.OK, "GoToIdle command completed OK")
+        
+    @command(
+        dtype_in='DevString',
+        doc_in="A Json-encoded string with the scan configuration.",
+        dtype_out='DevVarLongStringArray',
+        doc_out="A tuple containing a return code and a string message indicating status."
+                "The message is for information purpose only.",
+    )
+    @DebugIt()
+    def ConfigureScan(self, argin):
+        # PROTECTED REGION ID(CspSubElementSubarray.ConfigureScan) ENABLED START #
+        """
+        Configure a complete scan for the subarray.
+
+        :param argin: JSON formatted string with the scan configuration.
+        :type argin: 'DevString'
+
+        :return:
+            A tuple containing a return code and a string message indicating status. 
+            The message is for information purpose only.
+        :rtype: (ResultCode, str)
+        """
+        command = self.get_command_object("ConfigureScan")
+        (return_code, message) = command(argin)
+        return [[return_code], [message]]
+        # PROTECTED REGION END #    //  CspSubElementSubarray.Configure
+
+    @command(
+        dtype_in='DevString',
+        doc_in="A Json-encoded string with the scan configuration.",
+        dtype_out='DevVarLongStringArray',
+        doc_out="A tuple containing a return code and a string message indicating status."
+                "The message is for information purpose only.",
+    )
+    @DebugIt()
+    def Configure(self, argin):
+        # PROTECTED REGION ID(CspSubElementSubarray.Configure) ENABLED START #
+        """
+        Redirect to ConfigureScan method.
+        Configure a complete scan for the subarray.
+
+        :return:'DevVarLongStringArray'
+            A tuple containing a return code and a string message indicating status.
+            The message is for information purpose only.
+        """
+        command = self.get_command_object("ConfigureScan")
+        (return_code, message) = command(argin)
+        return [[return_code], [message]]
+        # PROTECTED REGION END #    //  CspSubElementSubarray.Configure
+
+    @command(
+        dtype_out='DevVarLongStringArray',
+        doc_out="A tuple containing a return code and a string  message indicating status."
+                "The message is for information purpose only.",
+    )
+    @DebugIt()
+    def GoToIdle(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.GoToIdle) ENABLED START #
+        """
+        Transit the subarray from READY to IDLE obsState.
+
+        :return:'DevVarLongStringArray'
+            A tuple containing a return code and a string  message indicating status.
+            The message is for information purpose only.
+        """
+        command = self.get_command_object("GoToIdle")
+        (return_code, message) = command()
+        return [[return_code], [message]]
+
+    @command(
+        dtype_out='DevVarLongStringArray',
+        doc_out="A tuple containing a return code and a string  message indicating status."
+                "The message is for information purpose only.",
+    )
+    @DebugIt()
+    def End(self):
+        # PROTECTED REGION ID(CspSubElementSubarray.End) ENABLED START #
+        """
+        Transit the subarray from READY to IDLE obsState.
+        Redirect to GoToIdle command.
+
+        :return:'DevVarLongStringArray'
+            A tuple containing a return code and a string  message indicating status.
+            The message is for information purpose only.
+        """
+        command = self.get_command_object("GoToIdle")
+        (return_code, message) = command()
+        return [[return_code], [message]]
+        # PROTECTED REGION END #    //  CspSubElementSubarray.End
+
+# ----------
+# Run server
+# ----------
+
+
+def main(args=None, **kwargs):
+    """Main function of the CspSubElementSubarray module."""
+    # PROTECTED REGION ID(CspSubElementSubarray.main) ENABLED START #
+    return run((CspSubElementSubarray,), args=args, **kwargs)
+    # PROTECTED REGION END #    //  CspSubElementSubarray.main
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/test_csp_subelement_subarray.py b/tests/test_csp_subelement_subarray.py
new file mode 100644
index 0000000000000000000000000000000000000000..6ee89588774806c028782dfb3dbacd18d5b92af1
--- /dev/null
+++ b/tests/test_csp_subelement_subarray.py
@@ -0,0 +1,352 @@
+#########################################################################################
+# -*- coding: utf-8 -*-
+#
+# This file is part of the CspSubelementSubarray project
+#
+#
+#
+#########################################################################################
+"""Contain the tests for the CspSubelementSubarray and the State model implemented by
+   such device.
+"""
+# Imports
+import logging
+import re
+import pytest
+import json
+
+from tango import DevState, DevFailed
+
+# PROTECTED REGION ID(CspSubelementSubarray.test_additional_imports) ENABLED START #
+from ska.base import SKASubarray, CspSubElementSubarray
+from ska.base.commands import ResultCode
+from ska.base.faults import StateModelError
+from ska.base.control_model import (
+    ObsState, AdminMode, ControlMode, HealthState, SimulationMode, TestMode
+)
+from .conftest import load_state_machine_spec, StateMachineTester
+# PROTECTED REGION END #    //  CspSubElementSubarray.test_additional_imports
+
+
+# Device test case
+# PROTECTED REGION ID(CspSubElementSubarray.test_CspSubelementSubarray_decorators) ENABLED START #
+# PROTECTED REGION END #    // CspSubelementSubarray.test_CspSubelementSubarray_decorators
+
+class TestCspSubElementSubarray(object):
+    """Test case for CSP SubElement Subarray class."""
+
+    properties = {
+        'SkaLevel': '4',
+        'LoggingTargetsDefault': '',
+        'GroupDefinitions': '',
+        }
+
+    @classmethod
+    def mocking(cls):
+        """Mock external libraries."""
+        # Example : Mock numpy
+        # cls.numpy = CspSubelementSubarray.numpy = MagicMock()
+        # PROTECTED REGION ID(CspSubelementSubarray.test_mocking) ENABLED START #
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_mocking
+
+    @pytest.mark.skip(reason="Not implemented")
+    def test_properties(self, tango_context):
+        # Test the properties
+        # PROTECTED REGION ID(CspSubelementSubarray.test_properties) ENABLED START #
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_properties
+        pass
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_State_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_State_decorators
+    def test_State(self, tango_context):
+        """Test for State"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_State) ENABLED START #
+        assert tango_context.device.State() == DevState.OFF
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_State
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_Status_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_Status_decorators
+    def test_Status(self, tango_context):
+        """Test for Status"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_Status) ENABLED START #
+        assert tango_context.device.Status() == "The device is in OFF state."
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_Status
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_GetVersionInfo_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_GetVersionInfo_decorators
+    def test_GetVersionInfo(self, tango_context):
+        """Test for GetVersionInfo"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_GetVersionInfo) ENABLED START #
+        versionPattern = re.compile(
+            r'CspSubElementSubarray, lmcbaseclasses, [0-9].[0-9].[0-9], '
+            r'A set of generic base devices for SKA Telescope.')
+        versionInfo = tango_context.device.GetVersionInfo()
+        assert (re.match(versionPattern, versionInfo[0])) is not None
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_GetVersionInfo
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_configurationProgress_decorators) ENABLED START #
+    def test_buildState(self, tango_context):
+        """Test for buildState"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_buildState) ENABLED START #
+        buildPattern = re.compile(
+            r'lmcbaseclasses, [0-9].[0-9].[0-9], '
+            r'A set of generic base devices for SKA Telescope')
+        assert (re.match(buildPattern, tango_context.device.buildState)) is not None
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_buildState
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_versionId_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_versionId_decorators
+    def test_versionId(self, tango_context):
+        """Test for versionId"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_versionId) ENABLED START #
+        versionIdPattern = re.compile(r'[0-9].[0-9].[0-9]')
+        assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_versionId
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_healthState_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_healthState_decorators
+    def test_healthState(self, tango_context):
+        """Test for healthState"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_healthState) ENABLED START #
+        assert tango_context.device.healthState == HealthState.OK
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_healthState
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_adminMode_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_adminMode_decorators
+    def test_adminMode(self, tango_context):
+        """Test for adminMode"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_adminMode) ENABLED START #
+        assert tango_context.device.adminMode == AdminMode.MAINTENANCE
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_adminMode
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_controlMode_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_controlMode_decorators
+    def test_controlMode(self, tango_context):
+        """Test for controlMode"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_controlMode) ENABLED START #
+        assert tango_context.device.controlMode == ControlMode.REMOTE
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_controlMode
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_simulationMode_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_simulationMode_decorators
+    def test_simulationMode(self, tango_context):
+        """Test for simulationMode"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_simulationMode) ENABLED START #
+        assert tango_context.device.simulationMode == SimulationMode.FALSE
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_simulationMode
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_testMode_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_testMode_decorators
+    def test_testMode(self, tango_context):
+        """Test for testMode"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_testMode) ENABLED START #
+        assert tango_context.device.testMode == TestMode.NONE
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_testMode
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_scanID_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_scanID_decorators
+    def test_scanID(self, tango_context):
+        """Test for scanID"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_scanID) ENABLED START #
+        assert tango_context.device.scanID == 0
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_scanID
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_sdpDestinationAddresses_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_sdpDestinationAddresses_decorators
+    def test_sdpDestinationAddresses(self, tango_context):
+        """Test for sdpDestinationAddresses"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_sdpDestinationAddresses) ENABLED START #
+        addresses_dict = {'outputHost': [], 'outputMac': [], 'outputPort': []}
+        tango_context.device.sdpDestinationAddresses = json.dumps(addresses_dict)
+        assert tango_context.device.sdpDestinationAddresses == json.dumps(addresses_dict)
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_sdpDestinationAddresses
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_sdpLinkActive_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_sdpLinkActive_decorators
+    def test_sdpLinkActivity(self, tango_context):
+        """Test for sdpLinkActive """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_sdpLinkActive) ENABLED START #
+        actual = tango_context.device.sdpLinkActive
+        n_links = len(actual)
+        expected  = [ False for i in range(0, n_links)]
+        assert all([a == b for a, b in zip(actual, expected)])
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_sdpLinkActive
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_outputDataRateToSdp_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_outputDataRateToSdp_decorators
+    def test_outputDataRateToSdp(self, tango_context):
+        """Test for outputDataRateToSdp """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_outputDataRateToSdp) ENABLED START #
+        assert tango_context.device.outputDataRateToSdp == 0
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_outputDataRateToSdp
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_listOfDevicesCompletedTasks_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_listOfDevicesCompletedTasks_decorators
+    def test_listOfDevicesCompletedTasks(self, tango_context):
+        """Test for listOfDevicesCompletedTasks """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_listOfDevicesCompletedTasks) ENABLED START #
+        attr_value_as_dict = json.loads(tango_context.device.listOfDevicesCompletedTasks)
+        assert not bool(attr_value_as_dict)
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_listOfDevicesCompletedTasks
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan_decorators
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesMaximumDuration_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_assignResourcesMaximumDuration_decorators
+    def test_assignResourcesMaximumDuration(self, tango_context):
+        """Test for assignResourcesMaximumDuration """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesMaximumDuration) ENABLED START #
+        tango_context.device.assignResourcesMaximumDuration = 5
+        assert tango_context.device.assignResourcesMaximumDuration == 5
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_assignResourcesMaximumDuration
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_configureScanMeasuredDuration_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_configureScanMeasuredDuration_decorators
+    def test_configureScanMeasuredDuration(self, tango_context):
+        """Test for configureScanMeasuredDuration """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_configureScanMeasuredDuration) ENABLED START #
+        assert tango_context.device.configureScanMeasuredDuration == 0
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_configureScanMeasuredDuration
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_configurationProgress_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_configurationProgress_decorators
+    def test_configurationProgress(self, tango_context):
+        """Test for configurationProgress """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_configurationProgress) ENABLED START #
+        assert tango_context.device.configurationProgress == 0
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_configurationProgress
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesMeasuredDuration_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_assignResourcesMeasuredDuration_decorators
+    def test_assignResourcesMeasuredDuration(self, tango_context):
+        """Test for assignResourcesMeasuredDuration """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesMeasuredDuration) ENABLED START #
+        assert tango_context.device.assignResourcesMeasuredDuration == 0
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_assignResourcesMeasuredDuration
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesProgress_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_assignResourcesProgress_decorators
+    def test_assignResourcesProgress(self, tango_context):
+        """Test for assignResourcesProgress """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesProgress) ENABLED START #
+        assert tango_context.device.assignResourcesProgress == 0
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_assignResourcesProgress
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesMaximumDuration_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_releaseResourcesMaximumDuration_decorators
+    def test_releaseResourcesMaximumDuration(self, tango_context):
+        """Test for releaseResourcesMaximumDuration """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesMaximumDuration) ENABLED START #
+        tango_context.device.releaseResourcesMaximumDuration = 5
+        assert tango_context.device.releaseResourcesMaximumDuration == 5
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_releaseResourcesMaximumDuration
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesMeasuredDuration_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_releaseResourcesMeasuredDuration_decorators
+    def test_releaseResourcesMeasuredDuration(self, tango_context):
+        """Test for releaseResourcesMeasuredDuration """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesMeasuredDuration) ENABLED START #
+        assert tango_context.device.releaseResourcesMeasuredDuration == 0
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_releaseResourcesMeasuredDuration
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesProgress_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_releaseResourcesProgress_decorators
+    def test_releaseResourcesProgress(self, tango_context):
+        """Test for releaseResourcesProgress """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesProgress) ENABLED START #
+        assert tango_context.device.releaseResourcesProgress == 0
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_releaseResourcesProgress
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_timeoutExpiredFlag_decorators
+    def test_configureScanTimeoutExpiredFlag(self, tango_context):
+        """Test for timeoutExpiredFlag """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START #
+        assert tango_context.device.configureScanTimeoutExpiredFlag == False
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_timeoutExpiredFlag
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_timeoutExpiredFlag_decorators
+    def test_assignResourcesTimeoutExpiredFlag(self, tango_context):
+        """Test for timeoutExpiredFlag """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START #
+        assert tango_context.device.assignResourcesTimeoutExpiredFlag == False
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_timeoutExpiredFlag
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_timeoutExpiredFlag_decorators
+    def test_releaseResourcesTimeoutExpiredFlag(self, tango_context):
+        """Test for timeoutExpiredFlag """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START #
+        assert tango_context.device.releaseResourcesTimeoutExpiredFlag == False
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_timeoutExpiredFlag
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan_decorators
+    @pytest.mark.parametrize("command_alias", ["Configure", "ConfigureScan"])
+    def test_ConfigureScan(self, tango_context, tango_change_event_helper, command_alias):
+        """Test for ConfigureScan"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan) ENABLED START #
+        tango_context.device.On()
+        tango_context.device.AssignResources('{"example": [1,2,3]}')
+        obs_state_callback = tango_change_event_helper.subscribe("obsState")
+        scan_configuration = '{"id":"sbi-mvp01-20200325-00002"}'
+        tango_context.device.command_inout(command_alias, (scan_configuration))
+        obs_state_callback.assert_calls([ObsState.IDLE,ObsState.CONFIGURING])
+        assert tango_context.device.configurationID == "sbi-mvp01-20200325-00002"
+        assert tango_context.device.lastScanConfiguration == scan_configuration
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state_decorators
+    def test_ConfigureScan_when_in_wrong_state(self, tango_context):
+        """Test for ConfigureScan when the device is in wrong state"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state) ENABLED START #
+        # The device in in OFF/EMPTY state, not valid to invoke ConfigureScan.
+        with pytest.raises(DevFailed, match="Error executing command ConfigureScanCommand"):
+            tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}')
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_wrong_configId_key_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan_with_wrong_configId_key_decorators
+    def test_ConfigureScan_with_wrong_configId_key(self, tango_context):
+        """Test for ConfigureScan when json configuration specifies a wrong key for 
+           configuration ID
+        """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_wrong_configId_key) ENABLED START #
+        tango_context.device.On()
+        tango_context.device.AssignResources('{"example": [1,2,3]}')
+        # wrong configurationID key
+        wrong_configuration = '{"subid":"sbi-mvp01-20200325-00002"}'
+        result_code, msg = tango_context.device.ConfigureScan(wrong_configuration)
+        assert result_code == ResultCode.FAILED
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan_with_wrong_configId_key
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_json_syntax_error) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan_with_json_syntax_error_decorators
+    def test_ConfigureScan_with_json_syntax_error(self, tango_context):
+        """Test for ConfigureScan when syntax error in json configuration """
+        # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_json_syntax_error) ENABLED START #
+        tango_context.device.On()
+        tango_context.device.AssignResources('{"example": [1,2,3]}')
+        result_code, msg = tango_context.device.ConfigureScan('{"foo": 1,}')
+        assert result_code == ResultCode.FAILED
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_ConfigureScan_with_json_syntax_error
+
+    # PROTECTED REGION ID(CspSubelementSubarray.test_GoToIdle_decorators) ENABLED START #
+    # PROTECTED REGION END #    //  CspSubelementSubarray.test_GoToIdle_decorators
+    @pytest.mark.parametrize("command_alias", ["GoToIdle", "End"])
+    def test_GoToIdle(self, tango_context, tango_change_event_helper, command_alias):
+        """Test for GoToIdle"""
+        # PROTECTED REGION ID(CspSubelementSubarray.test_GoToIdle) ENABLED START #
+        tango_context.device.On()
+        tango_context.device.AssignResources('{"example": [1,2,3]}')
+        obs_state_callback = tango_change_event_helper.subscribe("obsState")
+        tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}')
+        obs_state_callback.assert_calls([ObsState.IDLE,ObsState.CONFIGURING, ObsState.READY])
+        tango_context.device.command_inout(command_alias)
+        obs_state_callback.assert_call(ObsState.IDLE)
+        assert tango_context.device.scanID == 0
+        assert tango_context.device.configurationID == ''
+        # PROTECTED REGION END #    //  CspSubelementSubarray.test_GoToIdle