From c4d5e944c176910fc9af68289a04b5783784f11d Mon Sep 17 00:00:00 2001 From: Sunil Shetye Date: Wed, 16 Apr 2025 15:39:33 +0530 Subject: send the cont_frm command to scilab workspace allow variable size in CLR, DLR, and REGISTER change cont_frm_write to print double values --- blocks/Xcos/blocks/CLR.py | 11 ++-- blocks/Xcos/blocks/DLR.py | 12 ++-- blocks/Xcos/blocks/REGISTER.py | 12 +--- blocks/Xcos/common/AAAAAA.py | 103 +++++++++++++++++++++++++++++++--- blocks/ajax-scilab/cont_frm_write.sci | 42 +++++++------- 5 files changed, 131 insertions(+), 49 deletions(-) diff --git a/blocks/Xcos/blocks/CLR.py b/blocks/Xcos/blocks/CLR.py index 6d84cbd1..9d101178 100644 --- a/blocks/Xcos/blocks/CLR.py +++ b/blocks/Xcos/blocks/CLR.py @@ -22,11 +22,12 @@ def CLR(outroot, attribid, ordering, geometry, parameters, parent=1, style=None, dependsOnT='1') addExprsNode(outnode, TYPE_STRING, 2, parameters) - addSciDBNode(outnode, TYPE_DOUBLE, AS_REAL_PARAM, 9, realParts=[0.0, - -100.0, - 1.0, -12.0, 0.0, 1.0, 100.0, - 0.0, 0.0] - ) + realParams = cont_frm(num_str, den_str) + if type(realParams) is not list: + realParams = [] + addSciDBNode(outnode, TYPE_DOUBLE, AS_REAL_PARAM, len(realParams), realParts=[ + format_real_number(x) for x in realParams + ]) addTypeNode(outnode, TYPE_DOUBLE, AS_INT_PARAM, 0, []) addObjNode(outnode, TYPE_ARRAY, CLASS_LIST, AS_OBJ_PARAM, parameters) array = ['0'] diff --git a/blocks/Xcos/blocks/DLR.py b/blocks/Xcos/blocks/DLR.py index 60c75054..7819d1b5 100644 --- a/blocks/Xcos/blocks/DLR.py +++ b/blocks/Xcos/blocks/DLR.py @@ -21,12 +21,12 @@ def DLR(outroot, attribid, ordering, geometry, parameters, parent=1, style=None, dependsOnU=depends_on_flag) addExprsNode(outnode, TYPE_STRING, 2, parameters) - addSciDBNode(outnode, TYPE_DOUBLE, AS_REAL_PARAM, 25, realParts=[0.0, - 0.0, 0.0, -0.0, 1.0, 0.0, 0.0, -0.0, 0.0, 1.0, 0.0, - 0.09848421882252024, 0.0, 0.0, 1.0, - 0.2812414377454626, 0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, -46.91897551521227, - 104.4178961198787, -127.69161340324949]) + realParams = cont_frm(num_str, den_str) + if type(realParams) is not list: + realParams = [] + addSciDBNode(outnode, TYPE_DOUBLE, AS_REAL_PARAM, len(realParams), realParts=[ + format_real_number(x) for x in realParams + ]) addTypeNode(outnode, TYPE_DOUBLE, AS_INT_PARAM, 0, []) addObjNode(outnode, TYPE_ARRAY, CLASS_LIST, AS_OBJ_PARAM, parameters) array = ['0'] diff --git a/blocks/Xcos/blocks/REGISTER.py b/blocks/Xcos/blocks/REGISTER.py index f28d5721..f8581e03 100644 --- a/blocks/Xcos/blocks/REGISTER.py +++ b/blocks/Xcos/blocks/REGISTER.py @@ -30,15 +30,9 @@ def REGISTER(outroot, attribid, ordering, geometry, parameters, parent=1, style= addPrecisionNode(outnode, TYPE_INTEGER, AS_NMODE, 1, array) addTypeNode(outnode, TYPE_DOUBLE, AS_STATE, 0, []) numbers = parameters[0].split(';') - formatted_numbers = [] - for num in numbers: - formatted_numbers.append(num) - addScilabDNode(outnode, AS_DSTATE, width=5, realParts=[ - format_real_number(formatted_numbers[0]), - format_real_number(formatted_numbers[1]), - format_real_number(formatted_numbers[2]), - format_real_number(formatted_numbers[3]), - format_real_number(formatted_numbers[4])]) + addScilabDNode(outnode, AS_DSTATE, width=len(numbers), realParts=[ + format_real_number(x) for x in numbers + ]) addObjNode(outnode, TYPE_ARRAY, CLASS_LIST, AS_ODSTATE, []) addObjNode(outnode, TYPE_ARRAY, CLASS_LIST, AS_EQUATIONS, []) diff --git a/blocks/Xcos/common/AAAAAA.py b/blocks/Xcos/common/AAAAAA.py index b516346b..ed66f966 100644 --- a/blocks/Xcos/common/AAAAAA.py +++ b/blocks/Xcos/common/AAAAAA.py @@ -1,6 +1,7 @@ +import ast import datetime import os -from os.path import abspath, join +from os.path import abspath, isfile, join import pexpect import re import sys @@ -82,6 +83,14 @@ SCILAB_PROMPT = re.compile(rf'{ANSI_ESCAPE_PATTERN}*--> {ANSI_ESCAPE_PATTERN}*') BACKSPACE = re.compile(r'.\x08') +# Following are system command which are not permitted in sci files +# (Reference scilab-on-cloud project) +SYSTEM_COMMANDS = ( + r'unix\(.*\)|unix_g\(.*\)|unix_w\(.*\)|unix_x\(.*\)|unix_s\(.*\)|host' + r'|newfun|execstr|ascii|mputl|dir\(\)' +) +SPECIAL_CHARACTERS = r'["\'\\]' + SCILAB_CURVE_C_SCI = "macros/Sources/CURVE_c.sci" SCILAB_EXPRESSION_SCI = "macros/Misc/EXPRESSION.sci" @@ -149,8 +158,8 @@ def load_variables(filename): def load_scripts(): # handle duplicate scriptfiles scriptfiles = set() - for script in INTERNAL.values(): - for scriptfile in script['scriptfiles']: + for internal in INTERNAL.values(): + for scriptfile in internal['scriptfiles']: scriptfiles.add(scriptfile) cmd = '' @@ -160,8 +169,13 @@ def load_scripts(): class ScilabWorkspace: - def __init__(self, workspace): - cmd = load_variables(workspace) + load_scripts() + def __init__(self, title, workspace): + self.title = title + self.workspace = workspace + + cmd = load_scripts() + if workspace is not None and workspace != '': + cmd += load_variables(workspace) scilab_cmd = [SCILAB, "-noatomsautoload", @@ -200,6 +214,19 @@ class ScilabWorkspace: return self.clean_output(output, expr) + def send_command(self, command): + """Send a line to the process and return its output""" + command = command.strip(' \t\n\r\f\v') + if command == '': + print('No command') + return '' + + self.child.sendline(command) + self.child.expect(SCILAB_PROMPT) + output = self.child.before.strip() + + return self.clean_output(output, command) + def clean(self): """Terminate the process cleanly""" self.child.sendline('exit') @@ -869,6 +896,8 @@ def convert_scientific_notation(parameter): def format_real_number(parameter): + if type(parameter) is not str: + return parameter if re.search(r'[a-zA-Z]', parameter): # Check if parameter contains alphabetic characters if WORKSPACE is None: print(f'No Scilab workspace available for {parameter} evaluation') @@ -1556,9 +1585,10 @@ def process_xcos_model(model, title, rootattribid, parentattribid, global WORKSPACE started_workspace = False - if workspace_file is not None and workspace_file != '' and WORKSPACE is None: - print('workspace_file=', workspace_file) - WORKSPACE = ScilabWorkspace(workspace_file) + if WORKSPACE is None: + if workspace_file is not None and workspace_file != '': + print('workspace_file=', workspace_file) + WORKSPACE = ScilabWorkspace(title, workspace_file) started_workspace = True checkModelTag(model) @@ -1773,3 +1803,60 @@ def process_xcos_model(model, title, rootattribid, parentattribid, started_workspace = False return outdiagram + + +def internal_fun(internal_key, **kwargs): + try: + internal = INTERNAL[internal_key] + function = internal['function'] + parameters = internal['parameters'] + cmd = "" + file_name = f"{WORKSPACE.title}-{internal_key}.txt" + if 'num' in parameters: + p = 's' + cmd += f"{p}=poly(0,'{p}');" + p = 'z' + cmd += f"{p}=poly(0,'{p}');" + cmd += f"{function}('{file_name}'" + for parameter in parameters: + value = kwargs[parameter] + try: + value.encode('ascii') + except UnicodeEncodeError: + msg = f"{parameter} parameter has non-ascii characters" + print(msg) + return {'msg': msg} + if re.search(SYSTEM_COMMANDS, value): + msg = f"{parameter} parameter has unsafe value" + print(msg) + return {'msg': msg} + if re.search(SPECIAL_CHARACTERS, value): + msg = f"{parameter} parameter has value with special characters" + print(msg) + return {'msg': msg} + cmd += f",{value}" if 'num' in parameters else f",'{value}'" + cmd += ");" + print(f"send command {cmd} to Scilab") + WORKSPACE.send_command(cmd) + if not isfile(file_name): + msg = f"output {file_name} does not exist" + print(msg) + return {'msg': msg} + with open(file_name, 'r') as f: + data = f.read() + data = ast.literal_eval(data) + # flatten only if data is a list of lists with length 1 + if type(data) is list and \ + all(type(item) is list and len(item) == 1 for item in data): + data = [item[0] for item in data] + print(f"data: {data}") + os.remove(file_name) + return data + except Exception as e: + msg = f"Error in internal function '{internal_key}': {str(e)}" + print(msg) + return {'msg': msg} + + +def cont_frm(num, den): + return internal_fun('getOutput', num=num, den=den) diff --git a/blocks/ajax-scilab/cont_frm_write.sci b/blocks/ajax-scilab/cont_frm_write.sci index a22bca54..7ee20b0c 100644 --- a/blocks/ajax-scilab/cont_frm_write.sci +++ b/blocks/ajax-scilab/cont_frm_write.sci @@ -1,28 +1,28 @@ -function calculate_cont_frm(filename,num,den) - f_temp = mopen(filename, 'wt');// Creating a text file - H=cont_frm(num,den); - [A,B,C,D]=abcd(H); - cont_frm_write(A,B,C,D,f_temp); - mclose(f_temp); +function calculate_cont_frm(filename, num, den) + f_temp = mopen(filename, 'wt'); + H = cont_frm(num, den); + [A, B, C, D] = abcd(H); + cont_frm_write(A, B, C, D, f_temp); + mclose(f_temp); endfunction function cont_frm_write(varargin) - loop = argn(2); - f_temp=varargin(loop); - mfprintf(f_temp, '[') - for k= 1:(loop-1) - variable= varargin(k) // Storing variable one at a time - [m,n] = size(variable) // reading the size of variable - for y = 1:n // no. of rows in variables - for z = 1:m //no. of columns in variabes - if (k == loop-1) & (y == n) & (z == m) then - mfprintf(f_temp, '[%d]', variable(z,y)) //Print the variable values - else - mfprintf(f_temp, '[%d],', variable(z,y)) //Print the variable values - end + loop = argn(2); + f_temp = varargin(loop); + mfprintf(f_temp, '[') + for k = 1:(loop-1) + variable = varargin(k) + [m, n] = size(variable) + for y = 1:n + for z = 1:m + if (k == loop-1) & (y == n) & (z == m) then + mfprintf(f_temp, '%f', variable(z, y)) + else + mfprintf(f_temp, '%f,', variable(z, y)) end + end end - end - mfprintf(f_temp, ']') + end + mfprintf(f_temp, ']') endfunction -- cgit