classdef NETFrameConfig < zigbee.internal.SecurityConfig
  %NETFrameConfig Configuration for ZigBee NET-layer frames
  %   FRAMECONFIG = NETFRAMECONFIG creates a configuration object for
  %   ZigBee NET frames.
  %
  %   FRAMECONFIG = NETFRAMECONFIG(Name,Value) creates a ZigBee NET frame
  %   configuration object with the specified property Name set to the
  %   specified Value. You can specify additional name-value pair arguments
  %   in any order as (Name1,Value1,...,NameN,ValueN).
  %
  %   NETFrameConfig properties:
  %
  %   FrameType               - The type of the network-layer frame
  %   CommandType             - The type of the network command
  %   ProtocolVersion         - ZigBee standard compliant with frame
  %   DiscoverRoute           - Request for route discovery
  %   Security                - Indication of secure frame
  %   IEEEAddressing          - Presence of 64-bit source/destination IEEE address 
  %   DestinationAddress      - Destination address
  %   DestinationIEEEAddress  - Destination IEEE address
  %   SourceAddress           - Source address
  %   SourceIEEEAddress       - Source IEEE address
  %   Radius                  - Range of radius-limited transmission
  %   SequenceNumber          - The frame sequence number
  %   Multicast               - Indication of multicast frame
  %   MulticastMode           - Member or non-member multicast mode
  %   NonMemberRadius         - Range of member multicast relayed by non-members
  %   MaxNonMemberRadius      - Max range of member multicast relayed by non-members
  %   SourceRouting           - Presence of a source routing sub-frame
  %   RelayIndex              - Index (in relay list) of next hop
  %   RelayList               - Route description as a relay list
  %   Security                - Indication of secure frame
  %   DataEncryption          - Indication of encrypted payload
  %   MICLength               - Length of message integrity code (MIC)
  %   KeyIdentifier           - Key type
  %   ExtendedNonce           - Presence of sender address in auxiliary (security) header
  %   FrameCounter            - Frame counter
  %   SecuritySourceAddress   - Source address in auxiliary (security) header
  %   KeySequence             - Key sequence number
  %
  %   See also zigbee.NETFrameGenerator, zigbee.NETFrameDecoder.
  
  %   Copyright 2017-2023 The MathWorks, Inc.
  
  properties
    %FrameType The type of the network-layer (NET) frame
    % Specify the type of the network-layer (NET) frame as one of 'Data' |
    % 'NET command'. The default is 'Data'.
    FrameType = 'Data'
    
    %CommandType The name of the network-layer command
    % Specify the name of the NET command as one of 'Route request' |
    % 'Route reply' | 'Network status' | 'Leave' | 'Route record' | 'Rejoin
    % request' | 'Rejoin response' | 'Link status' | 'Network report' |
    % 'Network update'. The default is 'Route request'.
    CommandType = 'Route request'
    
    %ProtocolVersion Protocol version of the frame
    % Specify ProtocolVersion as one of 'ZigBee 2004' | 'ZigBee 2007'. The
    % default is 'ZigBee 2007'. The 'ZigBee 2007' specification is not
    % backwards compatible with the 'ZigBee 2004' specification.
    ProtocolVersion = 'ZigBee 2007'
    
    %DiscoverRoute Enable route discovery
    % Specify DiscoverRoute as a logical scalar indicating whether route
    % discovery is enabled. The default is false.
    DiscoverRoute = false
    
    %SequenceNumber The frame sequence number
    % Specify SequenceNumber as a scalar non-negative real integer that is
    % not greater than 255. The default is 0.
    SequenceNumber = 0
    
    %SourceAddress Source address
    % Specify the source address as a string denoting a hexadecimal number.
    % SourceAddress must be 4 characters long. The default is '0000'.
    SourceAddress = '0000'
    
    %DestinationAddress Destination address
    % Specify the destination address as a string denoting a hexadecimal
    % number. DestinationAddress must be 4 characters long. The default is
    % '0001'.
    DestinationAddress = '0001'
    
    %IEEEAddressing IEEE addressing of source and destination
    % Specify IEEEAddressing as one of 'None' | 'Source'| 'Destination' |
    % 'Both'. If enabled, the 64-bit IEEE address of the source or
    % destination is also included in the frame. The default is 'None'.
    IEEEAddressing = 'None'
    
    %SourceIEEEAddress IEEE address of source device
    % Specify the 64-bit IEEE source address as a 16-character long array
    % denoting a hexadecimal number. The default is '0000000000000000'.
    SourceIEEEAddress = '0000000000000000'
    
    %DestinationIEEEAddress IEEE address of destination device
    % Specify the 64-bit IEEE destination address as a 16-character long
    % array denoting a hexadecimal number. The default is
    % '0000000000000001'.
    DestinationIEEEAddress = '0000000000000001'
         
    %Radius Range of radius-limited transmission
    % Specify Radius as a scalar integer. The default is 1.
    Radius = 1
  
    %Multicast Indication of multicast frame
    % Specify Multicast as a scalar logical. A false value specifies a
    % unicast or broadcast frame and a true value specifies a multicast
    % frame. The default is false.
    Multicast = false
    
    %MulticastMode Member or non-member multicast mode
    % Specify MulticastMode as one of 'Member' | 'Non-member'. In 'Member'
    % mode the multicast frame originates from a device that is a member of
    % the multicast group. In 'Non-member' mode, the originator does not
    % belong in the multicast group. The default is 'Member'.
    MulticastMode = 'Member'
        
    %NonMemberRadius Range of member multicast relayed by non-members
    % Specify NonMemberRadius as a scalar integer. NonMemberRadius is
    % initialized to the MaxNonMemberRadius value and decreases by 1 by
    % each non-member device that is relaying the frame. The default is 1.
    NonMemberRadius = 1   
    
    %MaxNonMemberRadius Max range of member multicast relayed by non-members
    % Specify MaxNonMemberRadius as a scalar integer. NonMemberRadius is
    % initialized to the MaxNonMemberRadius value and decreases by 1 by
    % each non-member device that is relaying the frame. The default is 1.
    MaxNonMemberRadius = 1   
      
    %SourceRouting Presence of a source routing sub-frame
    % Specify SourceRouting as a scalar logical. If true, the source
    % determines the end-to-end route and includes it in the frame. The
    % default is false.
    SourceRouting = false
    
    %RelayIndex Index (in relay list) of next hop
    % Specify RelayIndex as a scalar positive integer denoting the 1-based
    % index of the next-hop device given the relay list RelayList. The
    % default is 1.
    RelayIndex = 1
    
    %RelayList Route description as a relay list
    % Specify relay list as a Nx4 character matrix denoting the source
    % route. The number of rows is the length of the route, and each row is
    % a 4-character vector denoting a relay's 16-bit address as a
    % hexadecimal number. The default is [].
    RelayList = [];
  end
  
  properties(Constant, Hidden)
    FrameTypeValues    = {'Data', 'NET command'}
    CommandTypeValues = {'Route request', 'Route reply', 'Network status', 'Leave', ...
      'Route record', 'Rejoin request', 'Rejoin response', 'Link status', 'Network report', 'Network update'}
    ProtocolVersionValues = {'ZigBee 2004', 'ZigBee 2007'}
    IEEEAddressingValues = {'None', 'Source', 'Destination', 'Both'}
    MulticastModeValues = {'Member', 'Non-member'}
  end
  
  methods
    function obj = NETFrameConfig(varargin)
      % Apply constructor name value pairs:
      for i = 1:2:nargin
          obj.(varargin{i}) = varargin{i+1};
      end
    end
    
    % For auto-completion:
    function v = set(obj, prop)
      v = obj.([prop, 'Values']);
    end
    
    function obj = set.FrameType(obj, value)
      obj.FrameType = validatestring(value, obj.FrameTypeValues, '', 'FrameType');
    end
    
    function obj = set.CommandType(obj, value)
      obj.CommandType = validatestring(value, obj.CommandTypeValues, '', 'CommandType');
    end
    
    function obj = set.ProtocolVersion(obj, value)
      obj.ProtocolVersion = validatestring(value, obj.ProtocolVersionValues, '', 'ProtocolVersion');
    end
    
    function obj = set.IEEEAddressing(obj, value)
      obj.IEEEAddressing = validatestring(value, obj.IEEEAddressingValues, '', 'IEEEAddressing');
    end
    
    function obj = set.MulticastMode(obj, value)
      obj.MulticastMode = validatestring(value, obj.MulticastModeValues, '', 'MulticastMode');
    end
    
    function obj = set.DiscoverRoute(obj, value)
      validateattributes(value, {'logical'}, {'scalar'}, '', 'DiscoverRoute');
      obj.DiscoverRoute = value;
    end
    
    function obj = set.Multicast(obj, value)
      validateattributes(value, {'logical'}, {'scalar'}, '', 'Multicast');
      obj.Multicast = value;
    end
    
    function obj = set.SourceRouting(obj, value)
      validateattributes(value, {'logical'}, {'scalar'}, '', 'SourceRouting');
      obj.SourceRouting = value;
    end
    
    function obj = set.SequenceNumber(obj, value)
      validateattributes(value, {'numeric'}, {'scalar', 'integer', 'nonnegative', 'real'}, '', 'SequenceNumber');
      obj.SequenceNumber = value;
    end
        
    function obj = set.SourceAddress(obj, value)
      value = convertStringsToChars(value);  
      validateattributes(value, {'char'}, {'row', 'numel', 4}, '', 'SourceAddress');
      obj.SourceAddress = value;
    end
    
    function obj = set.DestinationAddress(obj, value)
      value = convertStringsToChars(value);
      validateattributes(value, {'char'}, {'row', 'numel', 4}, '', 'DestinationAddress');
      obj.DestinationAddress = value;
    end
        
    function obj = set.SourceIEEEAddress(obj, value)
      value = convertStringsToChars(value);
      validateattributes(value, {'char'}, {'row', 'numel', 16}, '', 'SourceIEEEAddress');
      obj.SourceIEEEAddress = value;
    end
    
    function obj = set.DestinationIEEEAddress(obj, value)
      value = convertStringsToChars(value);
      validateattributes(value, {'char'}, {'row', 'numel', 16}, '', 'DestinationIEEEAddress');
      obj.DestinationIEEEAddress = value;
    end

    function obj = set.Radius(obj, value)
      validateattributes(value, {'numeric'}, {'scalar', 'integer', 'nonnegative', 'real'}, '', 'Radius');
      obj.Radius = value;
    end
    
    function obj = set.NonMemberRadius(obj, value)
      validateattributes(value, {'numeric'}, {'scalar', 'integer', 'nonnegative', 'real'}, '', 'NonMemberRadius');
      obj.NonMemberRadius = value;
    end
    
    function obj = set.MaxNonMemberRadius(obj, value)
      validateattributes(value, {'numeric'}, {'scalar', 'integer', 'nonnegative', 'real'}, '', 'MaxNonMemberRadius');
      obj.MaxNonMemberRadius = value;
    end
        
    function obj = set.RelayIndex(obj, value)
      validateattributes(value, {'numeric'}, {'scalar', 'integer', 'nonnegative', 'real'}, '', 'RelayIndex');
      obj.RelayIndex = value;
    end
    
    function obj = set.RelayList(obj, value)
      value = convertStringsToChars(value);
      if ~isempty(value)
        validateattributes(value, {'char'}, {'ncols', 4}, '', 'RelayIndex');
      end
      obj.RelayList = value;
    end
  end
  
  methods (Access=protected)
    
    function groups = getPropertyGroups(obj)
      
      propList1  = {'FrameType'; 'CommandType'; 'ProtocolVersion'; ...
                    'SequenceNumber'; };
      activeIdx1 = true(size(propList1));

      for n = 1:numel(propList1)
          if isInactiveProperty(obj,propList1{n})
              activeIdx1(n) = false;
          end
      end
      groups = coder.nullcopy(repmat(matlab.mixin.util.PropertyGroup(propList1(activeIdx1)), 1, 4));
      groups(1) = matlab.mixin.util.PropertyGroup(propList1(activeIdx1));
      
      propList2  = {'SourceAddress'; 'DestinationAddress'; 'IEEEAddressing'; ...
                    'SourceIEEEAddress'; 'DestinationIEEEAddress'};
      title2 = getString(message('lrwpan:ZigBee:AddressingTitle'));
      activeIdx2 = true(size(propList2));

      for n = 1:numel(propList2)
          if isInactiveProperty(obj,propList2{n})
              activeIdx2(n) = false;
          end
      end
      
      groups(2) = matlab.mixin.util.PropertyGroup(propList2(activeIdx2), title2);
      
      groups(3) = getPropertyGroups@zigbee.internal.SecurityConfig(obj);
      
      propList4  = {'Radius'; 'DiscoverRoute'; 'SourceRouting'; 'RelayIndex'; 'RelayList';};
      title4 = getString(message('lrwpan:ZigBee:RoutingTitle'));
      activeIdx4 = true(size(propList4));

      for n = 1:numel(propList4)
          if isInactiveProperty(obj,propList4{n})
              activeIdx4(n) = false;
          end
      end
      
      groups(4) = matlab.mixin.util.PropertyGroup(propList4(activeIdx4), title4);
      
      propList5  = {'Multicast'; 'MulticastMode'; 'NonMemberRadius'; 'MaxNonMemberRadius';};
      title5 = getString(message('lrwpan:ZigBee:MulticastTitle'));
      activeIdx5 = true(size(propList5));

      for n = 1:numel(propList5)
          if isInactiveProperty(obj,propList5{n})
              activeIdx5(n) = false;
          end
      end
      
      groups(5) = matlab.mixin.util.PropertyGroup(propList5(activeIdx5), title5);
    end
    
    function flag = isInactiveProperty(obj, prop)
      % Controls the conditional display of properties

      % search if property is one of the inactive base properties:
      flag = isInactiveProperty@zigbee.internal.SecurityConfig(obj, prop);

      if strcmp(prop, 'CommandType')
        flag = ~strcmp(obj.FrameType, 'NET command');
      
      elseif strcmp(prop, 'SourceIEEEAddress')
        flag = ~any(strcmp(obj.IEEEAddressing, {'Source', 'Both'}));
      
      elseif strcmp(prop, 'DestinationIEEEAddress')
        flag = ~any(strcmp(obj.IEEEAddressing, {'Destination', 'Both'}));
      
      elseif any(strcmp(prop, {'RelayIndex', 'RelayList'}))
        flag = ~obj.SourceRouting;
   
      elseif any(strcmp(prop, {'MulticastMode', 'NonMemberRadius', 'MaxNonMemberRadius'}))
        flag = ~obj.Multicast;
      end
    end
  end
  
end

