From 4dcef9f49d72316632afe1cade5cf04e6362b142 Mon Sep 17 00:00:00 2001
From: Tim Stadtmann <tim.stadtmann@rwth-aachen.de>
Date: Sat, 22 Apr 2017 16:15:29 +0200
Subject: [PATCH] Implement execute-method in EV3 & Sensor

---
 source/EV3.m    | 54 ++++++++++++++++++++---------------------------
 source/Sensor.m | 56 ++++++++++++++++++++++---------------------------
 2 files changed, 48 insertions(+), 62 deletions(-)

diff --git a/source/EV3.m b/source/EV3.m
index 7ddac27..9e8763c 100755
--- a/source/EV3.m
+++ b/source/EV3.m
@@ -166,7 +166,6 @@ classdef EV3 < MaskedHandle
             %     b.connect('usb', 'beep', 'on', ); % |br| 
             %     
             % See also ISCONNECTED / :attr:`isConnected`
-            
             if ev3.isConnected
                 if isCommInterfaceValid(ev3.commInterface)
                     error('EV3::connect: Already connected.');
@@ -294,11 +293,7 @@ classdef EV3 < MaskedHandle
                        'You have to call ev3.connect(...) first!']);
             end
             
-            ev3.commInterface.soundPlayTone(10, 1000, 100);
-            
-            if ev3.debug
-				fprintf('(DEBUG) EV3::beep: Sent ''soundPlayTone''-command\n');
-            end
+            ev3.execute(@soundPlayTone, 10, 1000, 100);
         end
         
         function playTone(ev3, volume, frequency, duration)
@@ -321,11 +316,7 @@ classdef EV3 < MaskedHandle
                        'You have to call ev3.connect(...) first!']);
             end
             
-            ev3.commInterface.soundPlayTone(volume, frequency, duration);
-            
-            if ev3.debug
-				fprintf('(DEBUG) EV3::playTone: Sent ''soundPlayTone''-command\n');
-            end
+            ev3.execute(@soundPlayTone, volume, frequency, duration);
         end
         
         function stopTone(ev3)
@@ -343,11 +334,7 @@ classdef EV3 < MaskedHandle
                        'You have to call ev3.connect(...) first!']);
             end
             
-            ev3.commInterface.soundStopTone();
-            
-            if ev3.debug
-				fprintf('(DEBUG) EV3::stopTone: Called ''soundStopTone''-command\n');
-            end
+            ev3.execute(@soundStopTone);
         end
         
         function status = tonePlayed(ev3)
@@ -369,11 +356,7 @@ classdef EV3 < MaskedHandle
                        'You have to call ev3.connect(...) first!']);
             end
             
-            status = ev3.commInterface.soundTest;
-            
-            if ev3.debug
-				fprintf('(DEBUG) EV3::tonePlayed: Called ''soundTest''-command\n');
-            end
+            status = ev3.execute(@soundTest);
         end
         
         %% Setter
@@ -487,21 +470,30 @@ classdef EV3 < MaskedHandle
     end
     
     methods (Access = private)  % Private brick functions that are wrapped by dependent params
+        function varargout = execute(ev3, commandHandle, varargin)
+            % Execute a CommunicationInterface-method given as a handle
+            %
+            % As those methods have different, fixed numbers of output arguments, this quantity
+            % has to be retrieved first.
+            
+            if ev3.debug
+                fprintf('(DEBUG) Sending %s\n', func2str(commandHandle));
+            end
+            
+            % Note: Arrg. MATLAB does not support nargout for class methods directly, so I have to
+            % do this ugly workaround using strings. See 
+            % https://de.mathworks.com/matlabcentral/answers/96617-how-can-i-use-nargin-nargout-to-determine-the-number-of-input-output-arguments-of-an-object-method
+            nOut = nargout(strcat('CommunicationInterface>CommunicationInterface.', func2str(commandHandle)));
+            [varargout{1:nOut}] = commandHandle(ev3.commInterface, varargin{:});
+        end
+        
         function bat = getBattery(ev3)
             % Retrieve batteryValue from brick in current mode. (Wrapped by EV3.batteryValue)
             
             if strcmpi(ev3.batteryMode, 'Percentage')
-                bat = ev3.commInterface.uiReadLbatt();
-                
-                if ev3.debug
-                    fprintf('(DEBUG) EV3::getBattery: Called ''uiReadLBatt''-command\n');
-                end
+                bat = ev3.execute(@uiReadLbatt);
             else
-                bat = ev3.commInterface.uiReadVbatt();
-                
-                if ev3.debug
-                    fprintf('(DEBUG) EV3::getBattery: Called ''uiReadVBatt''-command\n');
-                end
+                bat = ev3.execute(@uiReadVbatt);
             end
         end
         
diff --git a/source/Sensor.m b/source/Sensor.m
index 2cd6ec2..2cea9db 100755
--- a/source/Sensor.m
+++ b/source/Sensor.m
@@ -252,11 +252,7 @@ classdef Sensor < MaskedHandle
             
 %             warning(['Sensor::reset: Current version of reset resets ALL devices, that is, ',...
 %                      'all motor tacho counts and all other sensor counters!']);
-            if sensor.debug
-                fprintf('\n(DEBUG) Sensor::reset: Calling ''inputReadSI''-command on Port %d...\n',...
-                    sensor.port+1);
-            end
-            sensor.commInterface.inputDeviceClrAll(0);
+            sensor.execute(@inputDeviceClrAll, 0);
         end
         
         %% Setter
@@ -394,11 +390,7 @@ classdef Sensor < MaskedHandle
                        sensor.port+1);
             end
             
-            if sensor.debug
-                fprintf('\n(DEBUG) Sensor::setMode: Calling ''inputReadSI''-command on Port %d...\n',...
-                    sensor.port+1);
-            end
-            sensor.commInterface.inputReadSI(0, sensor.port, mode);  % Reading a value implicitly
+            sensor.execute(@inputReadSI, 0, sensor.port, mode);  % Reading a value implicitly
                                                              % sets the mode.
         end
         
@@ -431,11 +423,7 @@ classdef Sensor < MaskedHandle
                 mode = sensor.mode;
             end
             		
-            if sensor.debug
-                fprintf('\n(DEBUG) Sensor::getValue: Calling ''inputReadSI''-command on Port %d...\n',...
-                    sensor.port+1);
-            end
-            val = sensor.commInterface.inputReadSI(0, sensor.port, sensor.mode);
+            val = sensor.execute(@inputReadSI, 0, sensor.port, sensor.mode);
             
             
             if strcmp(class(sensor.mode), 'DeviceMode.Color')
@@ -446,11 +434,7 @@ classdef Sensor < MaskedHandle
             
             % See note
 			if isnan(val)
-                if sensor.debug
-                    fprintf('\n(DEBUG) Sensor::getValue: Calling ''inputReadSI''-command on Port %d...\n',...
-                        sensor.port+1);
-                end
-				val = sensor.commInterface.inputReadSI(0, sensor.port, sensor.mode);
+				val = sensor.execute(@inputReadSI, 0, sensor.port, sensor.mode);
             end
         end
         
@@ -459,12 +443,7 @@ classdef Sensor < MaskedHandle
                 error('Sensor::getStatus: Sensor-Object not connected to comm handle.');
            end
            
-            if sensor.debug
-                fprintf(['\n(DEBUG) Sensor::getStatus: Calling ''inputDeviceGetConnection''-command on ' ,...
-                         'Port %d...\n'], sensor.port+1);
-            end
-           
-           statusNo = sensor.commInterface.inputDeviceGetConnection(0, sensor.port);
+           statusNo = sensor.execute(@inputDeviceGetConnection, 0, sensor.port);
            status = ConnectionType(statusNo);
         end
         
@@ -475,13 +454,9 @@ classdef Sensor < MaskedHandle
            
             type = DeviceType.Error;
             
-            if sensor.debug
-                fprintf(['\n(DEBUG) Sensor::getStatus: Calling ''inputDeviceGetConnection''-command on ' ,...
-                         'Port %d...\n'], sensor.port+1);
-            end
             for i = 1:10
                 try
-                    [typeNo,modeNo] = sensor.commInterface.inputDeviceGetTypeMode(0, sensor.port);
+                    [typeNo,modeNo] = sensor.execute(@inputDeviceGetTypeMode, 0, sensor.port);
                     type = DeviceType(typeNo);
                 catch ME
                     continue;
@@ -498,6 +473,25 @@ classdef Sensor < MaskedHandle
         
     end
     
+    methods (Access = private)
+       function varargout = execute(sensor, commandHandle, varargin)
+            % Execute a CommunicationInterface-method given as a handle
+            %
+            % As those methods have different, fixed numbers of output arguments, this quantity
+            % has to be retrieved first.
+            
+            if sensor.debug
+                fprintf('(DEBUG) Sending %s\n', func2str(commandHandle));
+            end
+            
+            % Note: Arrg. MATLAB does not support nargout for class methods directly, so I have to
+            % do this ugly workaround using strings. See 
+            % https://de.mathworks.com/matlabcentral/answers/96617-how-can-i-use-nargin-nargout-to-determine-the-number-of-input-output-arguments-of-an-object-method
+            nOut = nargout(strcat('CommunicationInterface>CommunicationInterface.', func2str(commandHandle)));
+            [varargout{1:nOut}] = commandHandle(sensor.commInterface, varargin{:});
+        end 
+    end
+    
     methods (Access = ?EV3)
         function connect(sensor,commInterface)
             %connect Connects Sensor-object to physical brick
-- 
GitLab