interrupt a TCP-IP callback function in matlab - matlab

Recently wrote code that establishes a connection between two instances of matlab. I can send messages through the TCP-IP connection which will execute code. Now I'm trying to setup the code to be interruptible as I would like to start/stop a function through TCP-IP. Problem though is that sending a second command does nothing until the function is completed. Is there a way to interrupt a TCP-IP callback function?
code:
classdef connectcompstogether<handle
properties
serverIP
clientIP
tcpipServer
tcpipClient
Port = 4000;
bsize = 8;
earlystop
end
methods
function gh = connectcompstogether(~)
% gh.serverIP = '127.0.0.1';
gh.serverIP = 'localhost';
gh.clientIP = '0.0.0.0';
end
function SetupServer(gh)
gh.tcpipServer = tcpip(gh.clientIP,gh.Port,'NetworkRole','Server');
set(gh.tcpipServer,'OutputBufferSize',gh.bsize);
fopen(gh.tcpipServer);
display('Established Connection')
end
function SetupClient(gh)
gh.tcpipClient = tcpip(gh.serverIP,gh.Port,'NetworkRole','Client');
set(gh.tcpipClient, 'InputBufferSize',gh.bsize);
set(gh.tcpipClient, 'BytesAvailableFcnCount',8);
set(gh.tcpipClient, 'BytesAvailableFcnMode','byte');
set(gh.tcpipClient, 'BytesAvailableFcn', #(h,e)gh.recmessage(h,e));
fopen(gh.tcpipClient);
display('Established Connection')
end
function CloseClient(gh)
fclose(gh.tcpipClient);
gh.tcpipClient = [];
end
end
methods
function sendmessage(gh,message)
fwrite(gh.tcpipServer,message,'double');
end
function recmessage(gh,h,e)
Message = fread(gh.tcpipClient,gh.bsize/8,'double');
if Message == 444
gh.Funwithnumbers();
elseif Message == 777
gh.earlystop = 1;
end
end
function Funwithnumbers(gh)
x=1;
while true
if x > 5000, break;end
if gh.earlystop == 1,break;end
x = x+1;
display(x)
end
end
end
end
for ease to understand code.
server
Ser = connectcompstogether;
ser.SetupServer();
ser.sendmessage(333);
Client
cli = connectcompstogether;
cli.SetupClient();
Update:
So after going through the web, I have found out based on this post that the tcpip callback cannot be interrupt. The post was in 2017 which means my 2016a version definitely cannot interrupt a callback.
So An update to my question, Is it possible to start a subprocess in matlab to run the function. I just want to use the callback to start code. If I can start a subprocess from the callback. Than I should be able to free up the main process and use tcpip to start/stop a function on a different computer.
Update 2:
So I tried to utilize parallel processing using the 'spmd' command but the problem still persisted.
function recmessage(gh,h,e)
Message = fread(gh.tcpipClient,gh.bsize/8,'double');
spmd
switch labindex
case 1
if Message == 444
gh.Funwithnumbers();
elseif Message == 777
gh.earlystop = 1;
end
end
end
end

You may use a timer object, which is convenient to delay the execution of some function.
t=timer('ExecutionMode','singleShot', 'StartDelay',0, 'TimerFcn',#myCallback);
start(t);
In this case, the StartDelay is 0, so myCallback will be almost immediately added to the queue of tasks to be processed by Matlab. The execution however will start only after the callback to the tcpip object has been completed. It will block the queue once started, however.
You may try something like:
properties
t=timer('ExecutionMode','singleShot', 'StartDelay',0, 'TimerFcn',#myCallback);
end
function tcpipCallback(gh,tcpObj,~)
message=fread(tcpObj,1,'double');
if message==444
if strcmp(get(t,'Running'),'on')
error('The function is running already');
else
set(gh.t,'UserData',false);
start(gh.t);
end
elseif message==777
set(gh.t,'UserData',true);
end
function myCallback(tObj,~)
ii=0;
while ii<5000
if get(tObj,'UserData'),break,end
ii=ii+1;
pause(.0001); %Pause to interrupt the callback; drawnnow might work too; or perhaps this is not needed at all.
end
end

Related

How to break a MATLAB system call after a specified number of seconds

I am using Windows MATLAB to run SSH commands, but every once in a while the SSH command hangs indefinitely, and then so does my MATLAB script (sometimes when running overnight). How can I have a command time-out after a certain amount of waiting time? For example, suppose I don't want to wait more than 3 seconds for a SSH command to finish execution before breaking it and moving on:
% placeholder for a command that sometimes hangs
[status,result] = system('ssh some-user#0.1.2.3 sleep 10')
% placeholder for something I still want to run if the above command hangs
[status,result] = system('ssh some-user#0.1.2.3 ls')
I'd like to make a function sys_with_timeout that can be used like this:
timeoutDuration = 3;
[status,result] = sys_with_timeout('ssh some-user#0.1.2.3 sleep 10', timeoutDuration)
[status,result] = sys_with_timeout('ssh some-user#0.1.2.3 ls', timeoutDuration)
I've tried the timeout function from FEX but it doesn't seem to work for a system/SSH command.
I don't think the system command is very flexible, and I don't see a way to do what you want using it.
But we can use the Java functionality built into MATLAB for this, according to this answer by André Caron.
This is how you'd wait for the process to finish with a timeout:
runtime = java.lang.Runtime.getRuntime();
process = runtime.exec('sleep 20');
process.waitFor(10, java.util.concurrent.TimeUnit.SECONDS);
if process.isAlive()
disp("Done waiting for this...")
process.destroyForcibly();
end
process.exitValue()
In the example, we run the sleep 20 shell command, then waitFor() waits until the program finishes, but for a maximum of 10 seconds. We poll to see if the process is still running, and kill it if it is. exitValue() returns the status, if you need it.
Running sleep 5 I see:
ans =
0
Running sleep 20 I see:
Done waiting for this...
ans =
137
Building on #Cris Luengo's answer, here is the sys_with_timeout() function. I didn't use the process.waitFor() function because I'd rather wait in a while loop and display output as it comes in. The while loop breaks once the command finishes or it times out, whichever comes first.
function [status,cmdout] = sys_with_timeout(command,timeoutSeconds,streamOutput,errorOnTimeout)
arguments
command char
timeoutSeconds {mustBeNonnegative} = Inf
streamOutput logical = true % display output as it comes in
errorOnTimeout logical = false % if false, display warning only
end
% launch command as java process (does not wait for output)
process = java.lang.Runtime.getRuntime().exec(command);
% start the timeout timer!
timeoutTimer = tic();
% Output reader (from https://www.mathworks.com/matlabcentral/answers/257278)
outputReader = java.io.BufferedReader(java.io.InputStreamReader(process.getInputStream()));
errorReader = java.io.BufferedReader(java.io.InputStreamReader(process.getErrorStream()));
% initialize output char array
cmdout = '';
while true
% If any lines are ready to read, append them to output
% and display them if streamOutput is true
if outputReader.ready() || errorReader.ready()
if outputReader.ready()
nextLine = char(outputReader.readLine());
elseif errorReader.ready()
nextLine = char(errorReader.readLine());
end
cmdout = [cmdout,nextLine,newline()];
if streamOutput == true
disp(nextLine);
end
continue
else
% if there are no lines ready in the reader, and the
% process is no longer running, then we are done
if ~process.isAlive()
break
end
% Check for timeout. If timeout is reached, destroy
% the process and break
if toc(timeoutTimer) > timeoutSeconds
timeoutMessage = ['sys_with_timeout(''',command, ''',', num2str(timeoutSeconds), ')',...
' failed after timeout of ',num2str(toc(timeoutTimer)),' seconds'];
if errorOnTimeout == true
error(timeoutMessage)
else
warning(timeoutMessage)
end
process.destroyForcibly();
break
end
end
end
if ~isempty(cmdout)
cmdout(end) = []; % remove trailing newline of command output
end
status = process.exitValue(); % return
end
Replacing ssh some-user#0.1.2.3 with wsl (requires WSL of course) for simplicity, here is an example of a function that times out:
>> [status,cmdout] = sys_with_timeout('wsl echo start! && sleep 2 && echo finished!',1)
start!
Warning: sys_with_timeout('wsl echo start! && sleep 2 && echo finished!',1) failed after timeout of 1.0002 seconds
> In sys_with_timeout (line 41)
status =
1
cmdout =
'start!'
and here is an example of a function that doesn't time out:
>> [status,cmdout] = sys_with_timeout('wsl echo start! && sleep 2 && echo finished!',3)
start!
finished!
status =
0
cmdout =
'start!
finished!'

Delays within tasks in system verilog

I am trying to call 4 tasks within another task as follows:
task execute();
logic [0:3] req1, port_select;
logic [0:3] req2;
logic [0:3] req3;
logic [0:3] req4;
logic [0:31] data11, data21;
logic [0:31] data12, data22;
logic [0:31] data13, data23;
logic [0:31] data14, data24;
bfm.reset_task();
//drive multiple ports
//repeat(1)
//begin: random_stimulus
port_select = generate_combination();
repeat(1)
begin: per_combination_iteration
//port1
req1 = port_select[0]? generate_command() : 0;
data11 = generate_data();
data21 = generate_data();
//bfm.drive_ip_port1(req,data1,data2);
//port2
req2 = port_select[1]? generate_command() : 0;
data12 = generate_data();
data22 = generate_data();
//bfm.drive_ip_port2(req,data1,data2);
//port3
req3 = port_select[2]? generate_command() : 0;
data13 = generate_data();
data23 = generate_data();
//bfm.drive_ip_port3(req,data1,data2);
//port4
req4 = port_select[3]? generate_command() : 0;
data14 = generate_data();
data24 = generate_data();
//bfm.drive_ip_port4(req,data1,data2);
fork
bfm.drive_ip_port1(req1,data11,data21);
bfm.drive_ip_port2(req2,data12,data22);
bfm.drive_ip_port3(req3,data13,data23);
bfm.drive_ip_port4(req4,data14,data24);
join
end: per_combination_iteration
//end: random_stimulus
$stop;
endtask: execute
And one of my drive_ip_port function is as follows:
//driving port2
task drive_ip_port2(input logic [0:3] req2, input logic [0:31] data1_port2, data2_port2);
req2_cmd_in = req2; //req2 command
req2_data_in = data1_port2; //req2 first operand
#200;
req2_cmd_in = 0;
req2_data_in = data2_port2; //req2 second operand
#1000;
endtask: drive_ip_port2
This is what I am trying to achieve:
I want the execute task to drive 4 ports randomly. On the first clock, I want them to send a command and data. And then on the next clock, the command should be 0 and only data need to be sent.
This is what I have tried:
As shown in my code, I have written the above code. The thought behind this code was that since tasks can handle time delays, I can call the task once and pass the data and the command and let task handle all the work.
The problem I have:
After the first clock period, I have a delay of #200(equal to my clock). Thereafter, the wire should become 0 and should remain 0 for #1000. However, I am never getting the value 0 on command. It looks like the command gets driven by this task again. I have tried using Local variables, using the watch feature, using breakpoint but still couldn't debug it. Can anyone suggest what's wrong?
I don't know why req2_cmd_in does not get set to zero. Maybe there is somewhere else an overriding assignment like a typo in another task. (Try call only one task and see what that does.)
I do know that if you want something to happen at or after a clock, wait for that clock, do not use a delay. Safest is also to make sure you start at a determined point from a clock edge. Therefore I prefer to use in my test-benches code like this:
task drive_ip_port2(input logic [0:3] req2,
input logic [0:31] data1_port2, data2_port2);
// Use this or make sure you call the task at a
// determined point from the clock
# (posedge clk) ;
// Signals here change as if they come from a clocked register
req2_cmd_in <= req2; //req2 command
req2_data_in <= data1_port2; //req2 first operand
# (posedge clk) ;
req2_cmd_in <= 0; // No command
req2_data_in <= data2_port2; // only req2 second operand
repeat (4) // 4 or 5 depends on if you wait for clock at top
# (posedge clk) ;
endtask: drive_ip_port2

System Verilog- How to ensure that specific code will be executed before another?

I have the following code in my monitor:
virtual task run_phase(uvm_phase phase);
fork
begin : clock_c
forever begin
wait(vif.fact_log2_samp != fact_log2_samp_init);
for(int counter = 0; counter < 46; counter++) begin
check = 1'b0;
#(posedge vif.clk);
end
**check =1'b1;**
end// forever
end// clock_c
begin : main_0
forever begin
mon_trx = tx_lin_int_transaction::type_id::create("mon_trx");
mon_trx.fact_log_2 = fact_log2_samp_init;
**wait (vif.xn_valid == 1'b1);**
#1;
mon_trx.rand_data_xi = vif.xi;
mon_trx.rand_data_xq = vif.xq;
if (check == 1'b0)
mon_trx.check = FALSE;
else
fact_log2_samp_init = vif.fact_log2_samp;
$cast(t, mon_trx.clone());
//send transaction to scoreboard via TLM write()
ap.write(t);
wait (vif.xn_valid == 1'b0);
end// forever
end// main_0
join
endtask: run_phase
The problem is that
wait(vif.xn_valid == 1'b1);
and the code after it execute just before
check =1'b1;
(same time).
How can I ensure that the
check =1'b1;
will execute before?
I would follow the named events method, as AndresM suggested, but if you need a quick sync in the very same block with the very same trigger condition, a simple #0 might solve the issue, thou it is unreliable due to the simulation time handling reasons. Might worth a try:
begin : clock_c
...
**check =1'b1;**
...
end
begin : main_0
...
#0;
**wait (vif.xn_valid == 1'b1);**
...
end
also you can use labels for the begin-end blocks to look and read better, eg.:
begin: main_0, end: main_0 instead of end // main_o
You might want to take a look at Chapter 15 of the IEEE Std 1800-2012, where they cover in great detail every aspect related to the different interprocess synchronization and communication mechanisms that the SystemVerilog language offers. Those options are listed below (follow the hyperlinks to see a few examples and how to use each one of them):
Semaphores
Mailboxes
Named Events

Uploading sketch in Arduino

I am working on making an interface between MATLAB and Arduino. In other words, I want to send some data from MATLAB to Arduino. I have written programs both in MATLAB and the Arduino IDE.
MATLAB program:
c = 1;
if (c ~= 0 )
f = 1;
else
disp('vhxhjf');
end
disp(f)
arduino=serial('COM5','BaudRate',9600); % create serial communication object on port COM4
fopen(arduino); % initiate arduino communication
while f
fprintf(arduino,'%s',char(f)); % send answer variable content to arduino
end
fclose(arduino); % end communication with arduino
Code for Arduino:
int ledPin = 13;
int matlabData ;
void setup() {
pinMode(13,OUTPUT);
Serial.begin(9600);
// turn the LED on when we're done
// digitalWrite(13, HIGH);
}
void loop() {
if(Serial.available() > 0 ) {
matlabData = Serial.read();
if ( matlabData != 0) {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13,LOW);
delay(1000);
}
else
digitalWrite(13,LOW);
}
}
The problem is whenever I am uploading the sketch , this error is being thrown regularly in arduino ide:
avrdude: ser_open(): can't open device "\\.\COM5": The system cannot find the file specified
It was works on the first try, but after that the above error is thrown continuosly .
Also in matlab, after the first try , the following error is thrown:
enter code here
Error using serial/fopen (line 72)
Open failed: Port: COM5 is not available. No ports are available.
Use INSTRFIND to determine if other instrument objects are connected to requested device.
Error in SP (line 65)
fopen(arduino); % initiate arduino communication
>> instrfind
Instrument Object Array
Index: Type: Status: Name:
1 serial open Serial-COM5
2 serial closed Serial-COM5
and also the command instrfind is showing that the com5 port is closed after the first try.
I have tried the solution given in this link but it is didn't work:
http://forum.arduino.cc/index.php?topic=48421.0
This usually happens when you don't close the port.
In your code, when do you close it? When is f changed so the loop exits?
According to these people, you can try to do
delete(instrfindall)
before trying to open the port or
fopen(arduino);
closeFID = onCleanup(#() fclose(arduino));
...
IMHO the second solution looks better (less destructive)
BTW: put a delay or a sleep (I don't know how this is done in ML) in the fprintf loop, otherwise you will send too many data to the poor Arduino...

Moai: Graphics that reacts to commands via Sockets

I need a program that can create pre-defined shapes on screen according to that commands I send to it via TCP.
I'm trying to listen to a port and so that I can use them. Before waiting of a command (via network) I have the commands required to create a square (I plan to change its attributes via network commands)
The problem is it is not creating any graphics or opening the window as it should be..
require "socket"
require "mime"
require "ltn12"
host = "localhost"
port = "8080"
server, error = socket.bind(host, port)
if not server then print("server: " .. tostring(error)) os.exit() end
screen=MOAISim.openWindow ( "test", 640, 640 )
viewport = MOAIViewport.new (screen)
viewport:setSize ( 640, 640 )
viewport:setScale ( 640, 640 )
layer = MOAILayer2D.new ()
layer:setViewport ( viewport )
MOAISim.pushRenderPass ( layer )
function fillSquare (x,y,radius,red,green,blue)
a = red/255
b = green/255
c = blue/255
MOAIGfxDevice.setPenColor ( a, b, c) -- green
MOAIGfxDevice.setPenWidth ( 2 )
MOAIDraw.fillCircle ( x, y, radius, 4 ) -- x,y,r,steps
end
function onDraw ( )
fillSquare(0,64,64, 0,0,255)
end
scriptDeck = MOAIScriptDeck.new ()
scriptDeck:setRect ( -64, -64, 64, 64 )
scriptDeck:setDrawCallback ( onDraw)
prop = MOAIProp2D.new ()
prop:setDeck ( scriptDeck )
layer:insertProp ( prop )
while 1 do
print("server: waiting for client command...")
control = server:accept()
command, error = control:receive()
print(command,error)
error = control:send("hi from Moai\n")
end
It is waiting of the command from client at control = server:accept() but it is not opening up the graphics window as it should.. Is there any command to force it to open or render
Thank you
MOAI doesn't run your scripts in a separate thread. A blocking call (server:accept) or forever loop (while true do) will block your MOAI app and it will appear to freeze while it merrily sits in your script forever.
So you have to do two things:
Use non-blocking calls. In this case, you need to set your server's timeout to 0. That makes server:accept return immediately. Check it's return value to see if you got a connection.
Put your while loop in a coroutine and yield once per iteration.
You'll need to handle the client the same way, using non-blocking calls in a coroutine loop.
function clientProc(client)
print('client connected:', client)
client:settimeout(0) -- make client socket reads non-blocking
while true do
local command, err = client:receive('*l')
if command then
print('received command:', command)
err = client:send("hi from Moai\n")
elseif err == 'closed' then
print('client disconnected:', client)
break
elseif err ~= 'timeout' then
print('error: ', err)
break
end
coroutine.yield()
end
client:close()
end
function serverProc()
print("server: waiting for client connections...")
server:settimeout(0) -- make server:accept call non-blocking
while true do
local client = server:accept()
if client then
MOAICoroutine.new():run(clientProc, client)
end
coroutine.yield()
end
end
MOAICoroutine.new():run(serverProc)
Set the timeout for the server socket, since the accept is a blocking call.
server:settimeout(1)
Thanks Mud...I found that before u replied so the following coroutine works
function threadFunc()
local action
while 1 do
stat, control = server:accept()
--print(control,stat)
while 1 do
if stat then
command, error = stat:receive()
print("Comm: ", command, error)
if command then
stat:close()
print("server: closing connection...")
break
else
break
end
--[[
error = stat:send("hi")
if error then
stat:close()
print("server: closing connection...",error)
break
end ]] --
else
break
end
end
coroutine.yield()
end
end
That was very helpful though