After trying to get this working for quite a while, I am under the impression that it will not work (or there is a rather obscured way of doing it). I wound up implementing my own TCP/IP client device driver (i.e. a Simulink block similar to the ones provided by the package) to do the trick and thought I'd leave my implementation here for anyone that's looking. (I think it's better that way anyway as you can really define how you want your client to work.)
To create the device driver, one would need to follow the instructions found on the MATHWORKS site here.
My C implementation for the client is as follows:
/* File: client.h */
#ifndef _CLIENT_H_
#define _CLIENT_H_
#include "rtwtypes.h"
extern int socket_desc;
void init_socket_comm(void);
void send_socket_data(void);
void close_socket(void);
#endif /* _CLIENT_H */
and
/* File: client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "client.h"
int socket_desc;
int_T init_socket_comm(void)
{
struct sockaddr_in server; /* Server socket parameters */
/* Create socket and get socket descriptor */
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0)
{
fprintf(stderr, "Could not create socket\n");
exit(EXIT_FAILURE);
}
/* Specify parameters for server socket */
server.sin_addr.s_addr = inet_addr("127.0.0.1"); /* Server TCP IP;
server.sin_family = AF_INET;
server.sin_port = htons(25000); /* TCP port */;
/* Connect socket to server */
if (connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
{
fprintf(stderr, "Could not connect to server\n");
/* Close socket */
close(socket_desc);
printf("Socket closed successfully.\n");
exit(EXIT_FAILURE);
}
return socket_desc;
}
/* Sends an array of doubles. */
void send_socket_data(void)
{
int buffer_size = 56;
real_T buffer[7] = {3.21232, 5.31453, 10.34108, 7.34652, 2.34524, 4.44432, 3.45642};
unsigned char *buffer_ptr = (unsigned char *)buffer;
int sent_size;
/* Send data to server */
while (buffer_size > 0)
{
if ((sent_size = send(socket_desc, buffer, buffer_size, 0)) < 0)
{
fprintf(stderr, "Send failed.\n");
/* Close socket */
close(socket_desc);
printf("Socket closed successfully.\n");
exit(EXIT_FAILURE);
}
buffer_ptr += sent_size;
buffer_size -= sent_size;
}
}
void close_socket(void)
{
/* Close socket */
close(socket_desc);
}
Next, you'd need you System Object (I named mine TcpClient):
% File: TcpClient.m
classdef TcpClient < matlab.System & coder.ExternalDependency
%
% System object TcpClient block.
properties
% Public, tunable properties.
end
properties (Nontunable)
% Public, non-tunable properties.
end
properties (Access = private)
% Pre-computed constants.
end
methods
% Constructor
function obj = TcpClient(varargin)
% Support name-value pair arguments when constructing the object.
setProperties(obj,nargin,varargin{:});
end
end
methods (Access=protected)
function setupImpl(obj) %#ok<MANU>
if isempty(coder.target)
% Place simulation setup code here
else
% Call C-function implementing device initialization
coder.cinclude('client.h');
coder.ceval('init_socket_comm');
end
end
function stepImpl(obj,u) %#ok<INUSD>
if isempty(coder.target)
% Place simulation output code here
else
% Call C-function implementing device output
coder.ceval('send_socket_data');
end
end
function releaseImpl(obj) %#ok<MANU>
if isempty(coder.target)
% Place simulation termination code here
else
% Call C-function implementing device termination
coder.ceval('close_socket');
end
end
end
methods (Access=protected)
%% Define input properties
function num = getNumInputsImpl(~)
num = 1;
end
function num = getNumOutputsImpl(~)
num = 0;
end
function flag = isInputSizeMutableImpl(~,~)
flag = false;
end
function flag = isInputComplexityMutableImpl(~,~)
flag = false;
end
function validateInputsImpl(~, u)
if isempty(coder.target)
% Run input validation only in Simulation
validateattributes(u,{'double'},{'scalar'},'','u');
end
end
function icon = getIconImpl(~)
% Define a string as the icon for the System block in Simulink.
icon = 'Sink';
end
end
methods (Static, Access=protected)
function simMode = getSimulateUsingImpl(~)
simMode = 'Interpreted execution';
end
function isVisible = showSimulateUsingImpl
isVisible = false;
end
end
methods (Static)
function name = getDescriptiveName()
name = 'Sink';
end
function b = isSupportedContext(context)
b = context.isCodeGenTarget('rtw');
end
function updateBuildInfo(buildInfo, context)
if context.isCodeGenTarget('rtw')
% Update buildInfo
srcDir = fullfile(fileparts(mfilename('fullpath')),'src'); %#ok<NASGU>
includeDir = fullfile(fileparts(mfilename('fullpath')),'include');
addIncludePaths(buildInfo,includeDir);
% Use the following API's to add include files, sources and
addSourceFiles(buildInfo,'client.c', srcDir);
end
end
end
end
Now you can send doubles and if you create your server correctly using the code from here which I adapted to create a function that reads the TCP buffer:
/* File: server.c */
int read_socket_data(int new_socket, void *buffer, int buffer_size)
{
int read_size;
int read_attempts;
/* Continously read TCP buffer */
while ((read_size = recv(new_socket, buffer, buffer_size, 0)) >= 0)
{
if (read_size > 0)
{
/* Print read buffer */
for (int offset = 0; offset < 7; offset++)
{
printf("%lf\n", *((double *)buffer + offset));
}
}
}
return read_size;
}
you can read and print the doubles correctly.