| @@ -82,9 +82,10 @@ classdef Equipment < handle | |||||
| function output = read(ecq) | function output = read(ecq) | ||||
| %READ Extracts recieved data from the TCP-buffer. | %READ Extracts recieved data from the TCP-buffer. | ||||
| %This | |||||
| %This function sends the '++read'-command to the Prologix if | |||||
| %needed. Will always read the TCP-buffer in matlab. | |||||
| if ecq.channel >= 0 | if ecq.channel >= 0 | ||||
| fprintf(ecq.tcp,'++read'); | |||||
| write_unsafe('++read'); | |||||
| end | end | ||||
| output = fscanf(ecq.tcp); | output = fscanf(ecq.tcp); | ||||
| end | end | ||||
| @@ -92,7 +93,9 @@ classdef Equipment < handle | |||||
| function output = query(ecq,message) | function output = query(ecq,message) | ||||
| %QUERY Sends command to the device and read the respond. | %QUERY Sends command to the device and read the respond. | ||||
| %The command is send via the WRITE and the respond is collected | %The command is send via the WRITE and the respond is collected | ||||
| %from the device. | |||||
| % | % | ||||
| %See also WRITE, READ | |||||
| ecq.opc; | ecq.opc; | ||||
| output = ecq.query_unsafe(message); | output = ecq.query_unsafe(message); | ||||
| ecq.error; | ecq.error; | ||||
| @@ -131,7 +134,7 @@ classdef Equipment < handle | |||||
| %error occured after writing. If possible one should always use | %error occured after writing. If possible one should always use | ||||
| %the WRITE function. | %the WRITE function. | ||||
| % | % | ||||
| %See also WRITE | |||||
| %See also WRITE, QUERY | |||||
| if ecq.channel >= 0 | if ecq.channel >= 0 | ||||
| fprintf(ecq.tcp,['++addr ', num2str(ecq.channel)]); | fprintf(ecq.tcp,['++addr ', num2str(ecq.channel)]); | ||||
| end | end | ||||
| @@ -139,6 +142,12 @@ classdef Equipment < handle | |||||
| end | end | ||||
| function output = query_unsafe(ecq,message) | function output = query_unsafe(ecq,message) | ||||
| %QUERY_UNSAFE Sends command to device and reads device output. | |||||
| %This function does not check if device is ready or check if an | |||||
| %error occured after writing. If possible one should always use | |||||
| %the QUERY function. | |||||
| % | |||||
| %See also QUERY, WRITE, READ | |||||
| ecq.write_unsafe(message); | ecq.write_unsafe(message); | ||||
| output = read(ecq); | output = read(ecq); | ||||
| end | end | ||||
| @@ -155,25 +164,41 @@ classdef Equipment < handle | |||||
| methods (Static) | methods (Static) | ||||
| function tcpobject = getTCP(ipAddress,port) | function tcpobject = getTCP(ipAddress,port) | ||||
| persistent tcpconnection; | |||||
| [ipname,ipAddress] = Equipment.ip2structname(ipAddress,abs(port)); | |||||
| if port > 0 | |||||
| %GETTCP Returns TCP-object for TCP-connection. | |||||
| %Function makes a TCP-connection for specific ipAddress and | |||||
| %port. If TCP-connection already exist no new connection is | |||||
| %made and only existing handle is returned. | |||||
| %For existing connections the function will store the amount of | |||||
| %handles in use. Via the DELETE function the connection will be | |||||
| %closed if the connection is not in use anymore. | |||||
| %The connection will be removed if the port is negative number. | |||||
| persistent tcpconnection; %make variable persistent to share tcp-handles across multiple function calls. | |||||
| [ipname,ipAddress] = Equipment.ip2structname(ipAddress,abs(port)); %Get a structname and a cleaned ipaddress. | |||||
| if port > 0 %if port number is positive a connection is made. | |||||
| if isempty(tcpconnection) | if isempty(tcpconnection) | ||||
| tcpconnection = struct; | |||||
| %if the tcpconnection is empty (first time function | |||||
| %call) make a struct in the variable. | |||||
| tcpconnection = struct; | |||||
| end | end | ||||
| if ~isfield(tcpconnection, ipname) | |||||
| tcpconnection.(ipname).tcp = tcpip(ipAddress,port); | |||||
| tcpconnection.(ipname).nopen = 1; | |||||
| fopen(tcpconnection.(ipname).tcp); | |||||
| else | |||||
| if ~isfield(tcpconnection, ipname) %check if the handle is already made before. | |||||
| tcpconnection.(ipname).tcp = tcpip(ipAddress,port); %Make TCP-connection | |||||
| tcpconnection.(ipname).nopen = 1; %Set number of connections in use to 1 | |||||
| fopen(tcpconnection.(ipname).tcp); %Open the TCP-connection | |||||
| else %If connection already exist. Increase number of connections in use by 1. | |||||
| tcpconnection.(ipname).nopen = tcpconnection.(ipname).nopen + 1; | tcpconnection.(ipname).nopen = tcpconnection.(ipname).nopen + 1; | ||||
| end | end | ||||
| tcpobject = tcpconnection.(ipname).tcp; | |||||
| elseif port < 0 | |||||
| if tcpconnection.(ipname).nopen > 1 | |||||
| tcpconnection.(ipname).nopen = tcpconnection.(ipname).nopen - 1; | |||||
| tcpobject = tcpconnection.(ipname).tcp; %return the TCP-connection handle. | |||||
| elseif port < 0 %If the portnumber is negative the connection is removed. | |||||
| if tcpconnection.(ipname).nopen > 1 | |||||
| %If more than one object uses this tcp-handle. Decrease | |||||
| %the number of connections in use by 1. | |||||
| tcpconnection.(ipname).nopen = tcpconnection.(ipname).nopen - 1; %Decrease the number by 1. | |||||
| else | else | ||||
| %If only one handle uses this connection. The | |||||
| %connection is closed and the field is removed from the | |||||
| %tcpconnection struct. | |||||
| fclose(tcpconnection.(ipname).tcp); | fclose(tcpconnection.(ipname).tcp); | ||||
| tcpconnection = rmfield(tcpconnection,ipname); | tcpconnection = rmfield(tcpconnection,ipname); | ||||
| end | end | ||||
| @@ -183,10 +208,12 @@ classdef Equipment < handle | |||||
| end | end | ||||
| function bool = isnum(input) | function bool = isnum(input) | ||||
| %ISNUM Tests if the input is numeric scalar | |||||
| bool = isnumeric(input)&&isscalar(input); | bool = isnumeric(input)&&isscalar(input); | ||||
| end | end | ||||
| function num = forceNum(input) | function num = forceNum(input) | ||||
| %FORCENUM Throws an error if the input is not numeric. | |||||
| if ~isnumeric(input) | if ~isnumeric(input) | ||||
| error('Input should be a (single) number.'); | error('Input should be a (single) number.'); | ||||
| end | end | ||||
| @@ -194,15 +221,20 @@ classdef Equipment < handle | |||||
| end | end | ||||
| function iptest(ipAddress) | function iptest(ipAddress) | ||||
| %IPTEST Checks if the given IPv4-address is valid. | |||||
| validip = regexp(ipAddress,'^(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9]))$', 'once'); | validip = regexp(ipAddress,'^(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9]))$', 'once'); | ||||
| if isempty(validip) | if isempty(validip) | ||||
| error('Invalid IP-address'); | error('Invalid IP-address'); | ||||
| end | end | ||||
| end | end | ||||
| function [structname,cleanIP] = ip2structname(ipAddress,port) | |||||
| cleanIP = regexprep(ipAddress,'(?:(?<=\.)|^)(?:0+)(?=\d)',''); | |||||
| Equipment.iptest(cleanIP); | |||||
| structname = matlab.lang.makeValidName(['ip',cleanIP,'_',num2str(port)]); | |||||
| function [structname,cleanip] = ip2structname(ipAddress,port) | |||||
| %IP2STRUCTNAME Returns a structname and ip w/out leading zeros. | |||||
| %structname to store stuff in struct (especially for GETTCP). | |||||
| %cleanip is a shortened ip without leading zeros. | |||||
| cleanip = regexprep(ipAddress,'(?:(?<=\.)|^)(?:0+)(?=\d)',''); | |||||
| Equipment.iptest(cleanip); | |||||
| structname = matlab.lang.makeValidName(['ip',cleanip,'_',num2str(port)]); | |||||
| end | end | ||||
| end | end | ||||
| end | end | ||||