classdef bluetoothMeshFriendshipConfig < comm.internal.ConfigBase
    %bluetoothMeshFriendshipConfig Bluetooth mesh friendship configuration
    %parameters
    %   MESHFRNDSHIPCONFIG = bluetoothMeshFriendshipConfig creates a
    %   default Bluetooth(R) mesh friendship configuration object,
    %   specifying the friendship properties in a Bluetooth low energy (LE)
    %   node.
    %
    %   MESHFRNDSHIPCONFIG = bluetoothMeshFriendshipConfig(Name=Value)
    %   creates a Bluetooth mesh profile configuration object, MESHCONFIG,
    %   with the specified property Name set to the specified Value. You
    %   can specify additional name-value arguments in any order as
    %   (Name1=Value1, ..., NameN=ValueN).
    %
    %   bluetoothMeshFriendshipConfig properties:
    %
    %   ReceiveDelay  - Receive delay requested by low power node (LPN),
    %                   in seconds
    %   ReceiveWindow - Receive window supported by the Friend node,
    %                   in seconds
    %   PollTimeout   - Timeout to terminate friendship between LPN and
    %                   Friend node, in seconds
    %
    %   bluetoothMeshFriendshipConfig methods:
    %
    %   configureFriendship - Configure friendship between LPN and
    %                         Friend node
    %
    %   % Example 1:
    %   % Create Bluetooth mesh friendship configuration object
    %   friendshipConfig = bluetoothMeshFriendshipConfig(ReceiveDelay=0.04,...
    %                                                    ReceiveWindow=0.130,...
    %                                                    PollTimeout=5)
    %
    %   % Example 2:
    %   % Check if the Communications Toolbox(TM) Wireless Network Simulation
    %   % Library support package is installed. If the support package is not
    %   % installed, MATLAB(R) returns an error with a link to download and install
    %   % the support package.
    %   wirelessnetworkSupportPackageCheck
    %
    %   % Create a Bluetooth mesh Friend node and a LPN, with element
    %   % addresses "000A" and "000F" respectively. Establish the
    %   % friendship between the Friend node and the LPN by enabling the
    %   % support for Friend feature. Set the friendship timing properties,
    %   % poll timeout, receive delay and receive window values as 3 seconds,
    %   % 50 milliseconds, and 180 milliseconds, respectively.
    %
    %   % Create and configure mesh profile configuration object for Friend
    %   % node
    %   meshFNCfg = bluetoothMeshProfileConfig(ElementAddress="000A",Friend=true);
    %
    %   % Create and configure mesh profile configuration object for LPN
    %   meshLPNCfg = bluetoothMeshProfileConfig(ElementAddress="000F",LowPower=true);
    %
    %   % Create Bluetooth LE mesh Friend node
    %   meshFN = bluetoothLENode("broadcaster-observer",MeshConfig=meshFNCfg);
    %
    %   % Create Bluetooth LE mesh LPN
    %   meshLPN = bluetoothLENode("broadcaster-observer",MeshConfig=meshLPNCfg);
    %
    %   % Create a configuration object to enable friendship between Friend node and LPN.
    %   friendshipConfig = bluetoothMeshFriendshipConfig(ReceiveDelay=0.05,...
    %                                                    ReceiveWindow=0.180,...
    %                                                    PollTimeout=3);
    %   % Configure the friendship between Friend node and LPN.
    %   configureFriendship(friendshipConfig, meshFN, meshLPN);
    %
    %   See also bluetoothMeshProfileConfig, bluetoothLENode,
    %   bluetoothLEConnectionConfig, bluetoothLEBIGConfig.

    %   Copyright 2021-2023 The MathWorks, Inc.

    properties
        %ReceiveDelay Receive delay requested by low power node (LPN), in
        %seconds
        %   Specify the receive delay as a scalar in the range [0.01,
        %   0.255]. Units are in seconds. Set this value in the multiples
        %   of 1 millisecond. This value specifies the time interval
        %   between the LPN sending a request to and listening for a
        %   response from the Friend node. For more information about this
        %   property, see Bluetooth mesh profile v1.0.1, section 3.6.5.3.
        %   The default value is 0.01 seconds.
        ReceiveDelay (1,1) {mustBeGreaterThanOrEqual(ReceiveDelay,0.01), ...
            mustBeLessThanOrEqual(ReceiveDelay,0.255)} = 0.01

        %ReceiveWindow Receive window supported by Friend node, in
        %seconds
        %   Specify the receive window as a scalar in the range [0.001,
        %   0.255]. Units are in seconds. Set this value in the multiples
        %   of 1 millisecond. This value specifies the time for which the
        %   LPN listens for a response (data or update message) from the
        %   Friend node. For more information about this property, see
        %   Bluetooth mesh profile v1.0.1, section 3.6.5.4. The default
        %   value is 0.001 seconds.
        ReceiveWindow (1,1) {mustBeGreaterThanOrEqual(ReceiveWindow,0.001), ...
            mustBeLessThanOrEqual(ReceiveWindow,0.255)} = 0.001

        %PollTimeout Timeout to terminate friendship between LPN and Friend
        %node, in seconds
        %   Specify the poll timeout as a real value in the range [1,
        %   345599.9]. Units are in seconds. Set this value in the
        %   multiples of 100 milliseconds. This value specifies the maximum
        %   time allowed between two consecutive requests sent by the LPN
        %   to the Friend node to terminate the friendship. If the Friend
        %   node is unable to receive any request from the LPN within this
        %   value, the object terminates the friendship between the LPN and
        %   Friend node. For more information about this property, see
        %   Bluetooth mesh profile v1.0.1, section 3.6.5.3. The default
        %   value is 1 second.
        PollTimeout (1,1) {mustBeGreaterThanOrEqual(PollTimeout,1), ...
            mustBeLessThanOrEqual(PollTimeout,345599.9)} = 1
    end

    properties (Hidden)
        %FriendAddress Element address of the corresponding Friend node
        %   Specify the friend address as a 4-element character vector or a
        %   string scalar denoting 2-octet hexadecimal unicast address. At
        %   a low power node (LPN), this value specifies the element
        %   address of the friend node.
        FriendAddress = "0001"

        %LPNAddress Element address of the corresponding low power node
        %(LPN)
        %   Specify the LPN address as a 4-element character vector or a
        %   string scalar denoting 2-octet hexadecimal unicast address. At
        %   a Friend node, this value specifies the element address of the
        %   LPN.
        LPNAddress = "0002"
    end

    methods
        function obj = bluetoothMeshFriendshipConfig(varargin)
            obj@comm.internal.ConfigBase(varargin{:});
        end

        function obj = set.ReceiveDelay(obj, value)
            coder.internal.errorIf((mod(value, 1e-3) ~= 0), ...
                "bluetooth:bluetoothLENode:InvalidReceiveDelay");
            obj.ReceiveDelay = value; % in seconds
        end

        function obj = set.ReceiveWindow(obj, value)
            coder.internal.errorIf((mod(value, 1e-3) ~= 0), ...
                "bluetooth:bluetoothLENode:InvalidReceiveWindow");
            obj.ReceiveWindow = value; % in seconds
        end

        function obj = set.PollTimeout(obj, value)
            coder.internal.errorIf((mod(value, 100e-3) ~= 0), ...
                "bluetooth:bluetoothLENode:InvalidPollTimeout");
            obj.PollTimeout = value; % in seconds
        end

        function obj = configureFriendship(obj, friendNode, lowPowerNode)
            %configureFriendship Configure friendship between LPN and
            %Friend node
            %
            %   OBJ = configureFriendship(OBJ, FRIENDNODE, LOWPOWERNODE)
            %   establishes friendship between a Friend node, "friendNode"
            %   and a LPN, "lowPowerNode", by configuring the friendship
            %   parameters. At a Friend node, friendship with multiple LPNs
            %   is not supported.
            %
            %   OBJ is an object of type <a
            %   href="matlab:help('bluetoothMeshFriendshipConfig')">bluetoothMeshFriendshipConfig</a>
            %
            %   FRIENDNODE is an object of type bluetoothLENode with the
            %   Role property set as "broadcaster-observer".
            %
            %   LOWPOWERNODE is an object of type bluetoothLENode with the
            %   Role property set as "broadcaster-observer".

            % Validate node type (bluetoothLENode)
            validateattributes(friendNode, {'bluetoothLENode'}, {'scalar'}, ...
                mfilename, "friendNode", 2);
            validateattributes(lowPowerNode, {'bluetoothLENode'}, {'scalar'}, ...
                mfilename, "lowPowerNode", 3);
            % Validate node Role (broadcaster-observer)
            validatestring(friendNode.Role, {'broadcaster-observer'}, ...
                mfilename, "friendNode.Role");
            validatestring(lowPowerNode.Role, {'broadcaster-observer'}, ...
                mfilename, "lowPowerNode.Role");
            % Validate node features (Friend and LowPower)
            coder.internal.errorIf(~friendNode.MeshConfig.Friend, ...
                "bluetooth:bluetoothLENode:ConfigureFriendshipInvalidFN");
            coder.internal.errorIf(~lowPowerNode.MeshConfig.LowPower, ...
                "bluetooth:bluetoothLENode:ConfigureFriendshipInvalidLPN");
            % Validate existing friendship at node
            coder.internal.errorIf(friendNode.FriendshipEstablished, ...
                "bluetooth:bluetoothLENode:ConfigureFriendshipFailedFN");
            coder.internal.errorIf(lowPowerNode.FriendshipEstablished, ...
                "bluetooth:bluetoothLENode:ConfigureFriendshipFailedLPN");

            % Validate friendship timing parameters
            validateFriendshipParams(obj);

            % Element address of the Friend node
            obj.FriendAddress = friendNode.MeshConfig.ElementAddress;
            % Element address of the LPN
            obj.LPNAddress = lowPowerNode.MeshConfig.ElementAddress;
            % Assign friendship configuration at both nodes
            addMeshFriendship(friendNode, obj);
            addMeshFriendship(lowPowerNode, obj);
        end
    end

    methods (Access = private)
        function validateFriendshipParams(obj)
            % As per Bluetooth mesh profile v1.0.1, section 3.6.6.4.2, it
            % is recommended to resend poll message 3 times to assure a
            % good balance between reliability and power consumption. Thus,
            % the PollTimeout > (3*(ReceiveDelay + ReceiveWindow)).

            coder.internal.errorIf((obj.PollTimeout*1e3 <= (3* (obj.ReceiveDelay + obj.ReceiveWindow))), ...
                "bluetooth:bluetoothLENode:InvalidFriendshipParams");
        end
    end
end
