From 8ed5338479fb95480bae2e550e258817ceae6f34 Mon Sep 17 00:00:00 2001
From: Tim Stadtmann <tim.stadtmann@rwth-aachen.de>
Date: Thu, 27 Apr 2017 17:34:03 +0200
Subject: [PATCH] Include instrBrickIO into btBrickIO for Win (WIP)

instrBrickIO is now deprecated and will be deleted in a future commit.
This is a WIP-version and Bluetooth has not been tested yet.
---
 source/CommunicationInterface.m | 96 +++++++++------------------------
 source/btBrickIO.m              | 87 ++++++++++++++++++++++++------
 2 files changed, 98 insertions(+), 85 deletions(-)

diff --git a/source/CommunicationInterface.m b/source/CommunicationInterface.m
index 858e6d6..07fe1ad 100755
--- a/source/CommunicationInterface.m
+++ b/source/CommunicationInterface.m
@@ -113,18 +113,6 @@ classdef CommunicationInterface < handle
     properties (SetAccess = private)
         % IO connection type
         ioType;
-        % Bluetooth brick device name
-        btDevice = '';
-        % Bluetooth brick communication channel
-        btChannel = 0;
-        % Wifi brick IP address
-        wfAddr = '';
-        % Wifi brick TCP port
-        wfPort = ''; 
-        % Brick serial number
-        wfSN = ''; 
-        % Bluetooth serial port
-        serPort;
     end
     
     properties (Hidden, Access = private)
@@ -141,65 +129,32 @@ classdef CommunicationInterface < handle
              % interface to a Lego Mindstorms EV3 brick.
              %
              % Options::
-             %  'debug',D       Debug level, show communications packet
-             %  'ioType',P      IO connection type, either usb, wifi or bt
-             %  'btDevice',bt   Bluetooth brick device name
-             %  'btChannel',cl  Bluetooth connection channel
-             %  'wfAddr',wa     Wifi brick IP address
-             %  'wfPort',pr     Wifi brick TCP port, default 5555
-             %  'wfSN',sn       Wifi brick serial number (found under Brick info on the brick OR through sniffing the UDP packets the brick emits on port 3015)
-             %  'serPort',SP    Serial port connection
+             %  'debug'       Debug level, show communications packet
+             %  'ioType'      IO connection type, either usb, wifi or bt
+             %  'deviceName'   Bluetooth brick device name
+             %  'channel'  Bluetooth connection channel
+             %  'serPort'    Serial port connection
              %
              % Notes::
-             % - Can connect through: usbBrickIO, wfBrickIO, btBrickIO or
-             % instrBrickIO.
+             % - Can connect through: usbBrickIO, btBrickIO
              % - For usbBrickIO:
              %      b = Brick('ioType','usb')
-             % - For wfBrickIO:
-             %      b = Brick('ioType','wifi','wfAddr','192.168.1.104','wfPort',5555,'wfSN','0016533dbaf5')
              % - For btBrickIO:
              %      b = Brick('ioType','bt','serPort','/dev/rfcomm0')
-             % - For instrBrickIO (wifi)
-             %      b = Brick('ioType','instrwifi','wfAddr','192.168.1.104','wfPort',5555,'wfSN','0016533dbaf5')
-             % - For instrBrickIO (bluetooth)
-             %      b = Brick('ioType','instrbt','btDevice','EV3','btChannel',1)
              
-             commInterface.setProperties(varargin{:});
-%              % Init the properties
-%              opt.debug = 0;
-%              opt.btDevice = 'EV3';
-%              opt.btChannel = 1;
-%              opt.wfAddr = '192.168.1.104';
-%              opt.wfPort = 5555;
-%              opt.wfSN = '0016533dbaf5';
-%              opt.ioType = 'usb';
-%              opt.serPort = '/dev/rfcomm0';
-%              
-%              % Read in the options
-%              opt = tb_optparse(opt, varargin);
-%              commInterface.debug = opt.debug;
-%              commInterface.ioType = opt.ioType;
-
+             props = commInterface.evaluateProperties(varargin{:});
+             commInterface.ioType = props.ioType;
+             commInterface.debug = props.debug;
+             
              try
                  if(strcmp(commInterface.ioType,'usb')) % USB
-                    commInterface.conn = usbBrickIO(commInterface.debug);
-                 elseif(strcmp(commInterface.ioType,'wifi')) % WiFi
-                    commInterface.wfAddr = opt.wfAddr;
-                    commInterface.wfPort = opt.wfPort;
-                    commInterface.wfSN = opt.wfSN;
-                    commInterface.conn = wfBrickIO(commInterface.debug,commInterface.wfAddr,commInterface.wfPort,commInterface.wfSN);
+                    commInterface.conn = usbBrickIO(props.debug);
                  elseif(strcmp(commInterface.ioType,'bt')) % Bluetooth
-%                     commInterface.serPort = opt.serPort;
-                    commInterface.conn = btBrickIO(commInterface.debug,commInterface.serPort);
-                 elseif(strcmp(commInterface.ioType,'instrwifi')) % Instrumentation and Control: WiFi 
-                    commInterface.wfAddr = opt.wfAddr;
-                    commInterface.wfPort = opt.wfPort;
-                    commInterface.wfSN = opt.wfSN;
-                    commInterface.conn = instrBrickIO(commInterface.debug,'wf',commInterface.wfAddr,commInterface.wfPort,commInterface.wfSN);
-                 elseif(strcmp(commInterface.ioType,'instrbt')) % Instrumentation and Control: Bluetooth 
-                    commInterface.btDevice = opt.btDevice;
-                    commInterface.btChannel = opt.btChannel;
-                    commInterface.conn = instrBrickIO(commInterface.debug,'bt',commInterface.btDevice,commInterface.btChannel);
+                    if(strcmp(props.backend, 'serial'))
+                       commInterface.conn = btBrickIO('debug', props.debug, 'serPort', props.serPort);
+                    else
+                       commInterface.conn = btBrickIO('debug', props.debug, 'channel', props.channel, 'deviceName', props.deviceName);
+                    end
                  end
              catch ME
                  commInterface.conn = [];
@@ -222,7 +177,6 @@ classdef CommunicationInterface < handle
             brick.debug = debug;
             brick.conn.debug = debug;
         end
-        
         function set.timeOut(brick, timeOut)
             if ~isnumeric(timeOut) || timeOut < 0
                 error(ID(), 'timeOut-period of USB-handle can only be set to positive numerical values.'); 
@@ -230,37 +184,39 @@ classdef CommunicationInterface < handle
             
             brick.conn.timeOut = timeOut;
         end
-        
         function timeOut = get.timeOut(brick)
             timeOut = brick.conn.timeOut; 
         end
         
-        function setProperties(brick, varargin)
+        function props = evaluateProperties(brick, varargin)
             p = inputParser();
             p.KeepUnmatched = true;
             
             % Set default values
             defaultIOType = 'usb';
             defaultSerPort = '/dev/rfcomm0';
+            defaultBTDevice = 'EV3';
+            defaultBTChannel = 1;
+            defaultBackend = 'serial';
             defaultDebug = false;
             
-            % Define anonymous function that will return whether given value in varargin is valid
-            %validTypes = ;
+            % Define anonymous functions that will return whether given value in varargin is valid
             checkIOType = @(x) ismember(x, {'usb', 'bt'});
             checkDebug = @(x) isBool(x);
+            checkBackend = @(x) ismember(x, {'serial', 'instrumentControl'});
             
             % Add parameters
             p.addRequired('ioType', checkIOType);
             p.addOptional('serPort', defaultSerPort);
             p.addOptional('debug', defaultDebug, checkDebug);
+            p.addOptional('deviceName', defaultBTDevice);
+            p.addOptional('channel', defaultBTChannel);
+            p.addOptional('backend', defaultBackend, checkBackend);
             
             % Parse input...
             p.parse(varargin{:});
             
-            % Set properties
-            brick.ioType = p.Results.ioType;
-            brick.serPort = p.Results.serPort;
-            brick.debug = p.Results.debug;
+            props = p.Results;
         end
         
         %% Commands
diff --git a/source/btBrickIO.m b/source/btBrickIO.m
index e5a5bfb..ede4c66 100755
--- a/source/btBrickIO.m
+++ b/source/btBrickIO.m
@@ -27,11 +27,19 @@
 classdef btBrickIO < BrickIO
     properties
         % debug input
-        debug = 0;
-        % bluetooth serial port
-        serialPort = '/dev/rfcomm0'
+        debug;
+        % bluetooth serial port (used if backend == 'serial')
+        serialPort;
+        % bluetooth brick device name (used if backend == 'instrumentControl')
+        btDevice;
+        % bluetooth connection channel (used if backend == 'instrumentControl')
+        btChannel;
         % time-out period in seconds (if 0, no time-out)
-        timeOut = 10;
+        timeOut;
+        % use implementation based on the serial-connection implementation by MATLAB (should 
+        % work on mac & linux) or based on the Instrumentation & Control Toolbox 
+        % (should work on windows) (-> 'serial'|'instrumentControl')
+        backend;
     end
     
     properties (Access = 'protected')
@@ -40,20 +48,50 @@ classdef btBrickIO < BrickIO
     end 
     
     methods
-        function brickIO = btBrickIO(debug,serialPort)
+        %function brickIO = btBrickIO(debug,serialPort,backend)
+        function brickIO = btBrickIO(brickIO, varargin)
             %btBrickIO.btBrickIO Create a btBrickIO object
             %
             % btbrick = btBrickIO(debug,serialPort) is an object which
             % initialises and opens a bluetooth connection between MATLAB
-            % and the brick using serial functions.
-            %
-            % Notes::
-            % - debug is a flag specifying output printing (0 or 1).
+            % and the brick.
             
-            if nargin > 1
-                brickIO.debug = debug;
-                brickIO.serialPort = serialPort;
-            end
+            p = inputParser();
+            p.KeepUnmatched = 1;
+            
+            p.addOptional('debug', 0);
+            p.addOptional('serPort', '/dev/rfcomm0');
+            p.addOptional('btDevice', 'EV3');
+            p.addOptional('btChannel', 1);
+            p.addOptional('timeOut', 10);
+            p.addOptional('backend', 'serial');
+            
+            p.parse(varargin{:});
+            
+            brickIO.debug = p.Results.debug;
+            brickIO.serialPort = p.Results.serPort;
+            brickIO.btDevice = p.Results.btDevice;
+            brickIO.btChannel = p.Results.btChannel;
+            brickIO.timeOut = p.Results.timeOut;
+            brickIO.backend = p.Results.backend;
+            
+%             if nargin > 1
+%                 brickIO.debug = debug;
+%                 brickIO.serialPort = serialPort;
+%                 if nargin >= 3
+%                     if ~strcmp(backend, 'serial') && ~strcmp(backend, 'instrumentControl')
+%                         msg = 'btBrickIO''s backend-parameter has to be either ''serial'' or ''instrumentControl''.';
+%                         id = [ID(), ':', 'InvalidParameter'];
+%                         throw(MException(id, msg));
+%                     elseif ~license('test', 'instr_control_toolbox')
+%                         msg = 'Cannot use Instrument-Control-Toolbox for Bluetooth: Toolbox not installed.';
+%                         id = [ID(), ':', 'AssetNotAvailable'];
+%                         throw(MException(id, msg));
+%                     end
+%                     
+%                     brickIO.backend = backend;
+%                 end
+%             end
             
             if brickIO.debug > 0
                 fprintf('btBrickIO init\n');
@@ -61,7 +99,11 @@ classdef btBrickIO < BrickIO
             
             % Set the connection handle
             try
-                brickIO.handle = serial(brickIO.serialPort);
+                if strcmp(brickIO.backend, 'serial')
+                   brickIO.handle = serial(brickIO.serialPort);
+                else
+                   brickIO.handle = Bluetooth(brickIO.btDevice,brickIO.btChannel);
+                end
             catch ME
                 if ~isempty(strfind(ME.identifier, 'invalidPORT'))
                     % Throw a clean InvalidSerialPort to avoid confusion in upper layers
@@ -234,6 +276,21 @@ classdef btBrickIO < BrickIO
             if timeOut == 0
                brickIO.handle.Timeout = 9999999; % MATLAB.serial seems to have no option to disable timeout
             end
-        end 
+        end
+        function set.backend(brickIO, backend)
+            if ~strcmp(backend, 'serial')
+                if ~strcmp(backend, 'instrumentControl')
+                    msg = 'btBrickIO''s backend-parameter has to be either ''serial'' or ''instrumentControl''.';
+                    id = [ID(), ':', 'InvalidParameter'];
+                    throw(MException(id, msg));
+                elseif ~license('test', 'instr_control_toolbox')
+                    msg = 'Cannot use Instrument-Control-Toolbox for Bluetooth: Toolbox not installed.';
+                    id = [ID(), ':', 'AssetNotAvailable'];
+                    throw(MException(id, msg));
+                end
+            end
+            
+            brickIO.backend = backend;
+        end
     end 
 end
-- 
GitLab