From 2b285db0e4464c3e2daff1990df2b8c885ffea61 Mon Sep 17 00:00:00 2001
From: Dominik Mehlem <mehlem@ient.rwth-aachen.de>
Date: Fri, 9 Dec 2022 15:20:08 +0100
Subject: [PATCH] switch from MATLAB serial to MATLAB serialport

---
 source/EV3.m        |  3 ++-
 source/Motor.m      | 18 ++++++++---------
 source/btBrickIO.m  | 48 +++++++++++++++++++++++++++++++++------------
 tools/connect.py    | 22 ++++++++++++---------
 tools/disconnect.py |  2 +-
 tools/rc.local.sh   |  1 +
 6 files changed, 62 insertions(+), 32 deletions(-)

diff --git a/source/EV3.m b/source/EV3.m
index a261347..4d94f08 100644
--- a/source/EV3.m
+++ b/source/EV3.m
@@ -268,9 +268,10 @@ classdef EV3 < MaskedHandle
             end
 
             % Delete handle to comm-interface
-            if isCommInterfaceValid(ev3.commInterface) && ev3.commInterface ~= 0
+            if isCommInterfaceValid(ev3.commInterface)
                 ev3.commInterface.delete();
             end
+            pause(5);
             ev3.commInterface = 0;
 
             ev3.isConnected = false;
diff --git a/source/Motor.m b/source/Motor.m
index 950202d..a6d7cb8 100644
--- a/source/Motor.m
+++ b/source/Motor.m
@@ -769,14 +769,14 @@ classdef Motor < MaskedHandle & dynamicprops
             p.parse(varargin{:});
             
             if ~isempty(fieldnames(p.Unmatched))
-		A = fieldnames(p.Unmatched);
-		warn = 'The following input parameters were invalid: ';
-		warn = [warn A{1}];
-		for i = 2:length(A)
-		    warn = [warn ', ' A{i}];
-		end
-		warning(warn)
-	    end
+                A = fieldnames(p.Unmatched);
+                warn = 'The following input parameters were invalid: ';
+                warn = [warn A{1}];
+                for i = 2:length(A)
+                    warn = [warn ', ' A{i}];
+                end
+                warning(warn)
+            end
             
             % Set properties
             if motor.init
@@ -926,7 +926,7 @@ classdef Motor < MaskedHandle & dynamicprops
             if ~motor.ev3Handle.isConnected || ~motor.physicalMotorConnected
                 success = false;
                 return;
-            end;
+            end
             
             if motor.currentSpeedRegulation
                 motor.handleCommand(@outputSpeed, true, 0, motor.port, power);
diff --git a/source/btBrickIO.m b/source/btBrickIO.m
index 161924b..bf275af 100644
--- a/source/btBrickIO.m
+++ b/source/btBrickIO.m
@@ -94,7 +94,8 @@ classdef btBrickIO < BrickIO
             % Set the connection handle
             try
                 if strcmp(brickIO.backend, 'serial')
-                   brickIO.handle = serial(brickIO.serialPort);
+                   brickIO.handle = serialport(brickIO.serialPort, 9600);
+                   pause(3);
                 else
                    brickIO.handle = Bluetooth(brickIO.deviceName,brickIO.channel);
                 end
@@ -115,7 +116,10 @@ classdef btBrickIO < BrickIO
             end
             
             % Open the connection
-            brickIO.open;
+            if ~strcmp(brickIO.backend, 'serial')
+                   brickIO.open;
+            end
+            
         end
         
         function delete(brickIO)
@@ -142,7 +146,9 @@ classdef btBrickIO < BrickIO
             
             % Open the bt handle
             try
-                fopen(brickIO.handle);
+                if ~strcmp(brickIO.backend, 'serial')
+                   fopen(brickIO.handle);
+                end
             catch ME 
                 if strcmp(ME.identifier, 'MATLAB:serial:fopen:opfailed')
                     % Throw only clean CommError to avoid confusion in upper layers
@@ -170,7 +176,9 @@ classdef btBrickIO < BrickIO
             
             try
                 % Close the close handle
-                fclose(brickIO.handle);
+                if ~strcmp(brickIO.backend, 'serial')
+                    fclose(brickIO.handle);
+                end
             catch ME
                 % Throw combined error because error did not happen due to communication
                 % failure
@@ -183,7 +191,7 @@ classdef btBrickIO < BrickIO
         end
         
         function rmsg = read(brickIO)
-            % Reads data from the brick through bluetooth via fread and returns the data in uint8 format.
+            % Reads data from the brick through bluetooth via read and returns the data in uint8 format.
             
             if brickIO.debug > 0
                 fprintf('\t(DEBUG) (BT read) \n');
@@ -191,12 +199,20 @@ classdef btBrickIO < BrickIO
             
             try
                 % Get the number of bytes to be read from the bt handle
-                nLength = fread(brickIO.handle,2);
+                if strcmp(brickIO.backend, 'serial')
+                    nLength = read(brickIO.handle,2,'uint8');
+                else
+                    nLength = fread(brickIO.handle,2);
+                end
 
                 % Read the remaining bytes
-                rmsg = fread(brickIO.handle,double(typecast(uint8(nLength),'uint16')));
+                if strcmp(brickIO.backend, 'serial')
+                    rmsg = read(brickIO.handle,double(typecast(uint8(nLength),'uint16')),'uint8');
+                else
+                    rmsg = fread(brickIO.handle,double(typecast(uint8(nLength),'uint16')));
+                end                
             catch ME
-                if strcmp(ME.identifier, 'MATLAB:serial:fread:opfailed')
+                if strcmp(ME.identifier, 'MATLAB:serialport:read:opfailed') || strcmp(ME.identifier, 'MATLAB:serial:fread:opfailed')
                     % Throw only clean CommError to avoid confusion in upper layers
                     msg = 'Failed to read data from Brick via Bluetooth.';
                     id = [ID(), ':', 'CommError'];
@@ -212,11 +228,15 @@ classdef btBrickIO < BrickIO
             end
             
             % Append the reply size to the return message
-            rmsg = uint8([nLength' rmsg']);
+            if strcmp(brickIO.backend, 'serial')
+                rmsg = uint8([nLength rmsg]);
+            else
+                rmsg = uint8([nLength' rmsg']);
+            end            
         end
         
         function write(brickIO,wmsg)
-            % Writes data to the brick through bluetooth via fwrite.
+            % Writes data to the brick through bluetooth via write.
             %
             % Arguments:
             %     wmsg (uint8 array): Data to be written to the brick via bluetooth
@@ -227,9 +247,13 @@ classdef btBrickIO < BrickIO
             
             try
                 % Write to the bluetooth handle
-                fwrite(brickIO.handle,wmsg);
+                if strcmp(brickIO.backend, 'serial')                    
+                    write(brickIO.handle,wmsg, class(wmsg));
+                else
+                    fwrite(brickIO.handle,wmsg);
+                end                
             catch ME
-                if strcmp(ME.identifier, 'MATLAB:serial:fwrite:opfailed')
+                if strcmp(ME.identifier, 'MATLAB:serialport:write:opfailed') || strcmp(ME.identifier, 'MATLAB:serial:fwrite:opfailed')
                     % Throw only clean CommError to avoid confusion in upper layers
                     msg = 'Failed to send data to Brick via Bluetooth.';
                     id = [ID(), ':', 'CommError'];
diff --git a/tools/connect.py b/tools/connect.py
index f0e0d99..1edfd50 100755
--- a/tools/connect.py
+++ b/tools/connect.py
@@ -204,11 +204,11 @@ def print_success(brick, device):
 
     # we can now use our bluetooth-EV3 with matlab
     print(f'''
-################ USE WITH MATLAB ################
-## 1. b=EV3                                    ##
-## 2. b.connect('bt','serPort','{device}') ##
-## 3. use b                                    ##
-#################################################
+################ USE WITH MATLAB ############
+1. b=EV3();
+2. b.connect('bt','serPort','{device}');
+3. b.beep();
+#############################################
 ''')
 
 
@@ -258,13 +258,17 @@ def pair(brick, PIN, device, channel=1):
                 # the purpose of doing this here is to do it in a controlled manner so it can be semi-automatic,
                 # since the daemon does not automatically pop up a PIN request form upon receiving from the device.
                 write(btctl, f'pair {MAC}')
+                print('Connecting...')
+                sleep(3)
+                write(btctl, f'{PIN}') # "enter" pin
 
-                print(f'Pairing {name}: accept at the device (PIN {PIN})')
+                print(f'Pairing {name}: accept at the device AND confirm PIN. (PIN {PIN})')
                 sleep(1)
-                print('then press Enter to continue...')
-                input('If the prompt does not appear in a few seconds, abort and restart this script.')
-
+                print('THEN press Enter to continue...')
+                input('If the prompt does not appear in a few seconds, press Enter to retry pairing.')
+                
                 write(btctl, f'{PIN}') # "enter" pin
+
                 for c in range(5):
                     print('.', end='', flush=True)
                     sleep(1)
diff --git a/tools/disconnect.py b/tools/disconnect.py
index 46e1225..af596b1 100755
--- a/tools/disconnect.py
+++ b/tools/disconnect.py
@@ -78,7 +78,7 @@ def print_dc_menu():
 
     try:
         print(f'\nClose matlab or make sure you disconnect /dev/{b.device} inside matlab,')
-        print('for example using "b.disconnect()".\n')
+        print('for example by using "b.disconnect()".\n')
         input('Then press Enter to continue.')
     except:
         print()
diff --git a/tools/rc.local.sh b/tools/rc.local.sh
index de41686..ac25f11 100755
--- a/tools/rc.local.sh
+++ b/tools/rc.local.sh
@@ -6,6 +6,7 @@ for i in /opt/mindstorms/tools/*; do
 	ln -s $i /usr/local/bin/
 done
 
+apt-get -y update
 
 # copy laboratory documentation
 echo "Copying documentation ..."
-- 
GitLab