В LabVIEW уже много лет существует возможность «прикрутить» Web к VI приборам без каких-либо сложных настроек публикации и серверов со стороны LabVIEW, используя только втроенный сервер ActiveX. Не является исключением и LabVIEW 2020 Community edition.
Для LabVIEW на данный момент момент существует несколько способов публикации виртуальных приборов в Web, требующих разного уровня знаний и предоставляющих разные возможности. В этой статье я не собираюсь их описывать, но хочу познакомить вас с нестандартным использованием встроенного в LabVIEW сервера ActiveX/COM для организации Web доступа к VI, а также управления самой средой LabVIEW. Хотя ActiveX/COM уже старая, но еще продолжающая жить в Windows технология, но именно через встроенный ActiveX сервер можно легко организовать управление LabVIEW и VI приборами, в том числе через Web.
Первое что нужно сделать, это включить в LabVIEW этот самый ActiveX сервер, делается это в настройках среды: Tools->Options->VI Server, флажок ActiveX.
Проверить, что сервер включен и к нему есть доступ, можно простым скриптом на VBScript. Нужно создать на рабочем столе текстовой файл labview_test.vbs и наполнить его следующим содержимым:
Перед выполнением скрипта запустите среду LabVIEW. Впрочем, будет работать и без предварительного запуска среды. На время выполнения скрипта будет запущен экземпляр LabVIEW как ActiveX/COM сервер, а по завершении скрипта экземпляр будет закрыт, так что придется подождать, пока все это «загрузится и выгрузится». В выводе labview_test.vbs будет имя корневого приложения и его версия.
Далее я создал простой VI прибор «ActiveX Server.vi». В нем содержится несколько контролов и вспомогательных функций. Этот VI мы будем загружать и управлять им.
От LabVIEW нам больше ничего не потребуется. Теперь можно приступать к слоям Web.
Сначала я немного поэкспериментировал с штатным Windows Web-сервером Microsoft IIS. Пробовал создавать страницы ASP на VBScript приблизительно следующего содержания:
Метод GetVIReference() загружает VI в память и устанавливает с ним связь. Основной параметр: абсолютный путь к выбранному VI.
Вывод скрипта в браузер:
Правда, пришлось немного повозиться с настройками пула приложений IIS и анонимной проверки пользователей, которые я настроил на текущего пользователя Windows.
Я решил не углублятся в ASP и переключился на PHP. Для IIS настроил PHP FastCGI демон. Настройки не привожу, они не важны для основной части этой статьи. В PHP также удалось получить доступ к COM объекту LabVIEW, по типу:
В обоих случаях при запущенной среде LabVIEW и открытом в ней VI (ActiveX Server.vi). При запросе PHP (ASP) скрипта параллельно запускался (и значительное время) новый экземпляр LabVIEW.exe, далее в нем c помощью метода GetVIReference() загружался свой экземпляр «ActiveX Server.vi». По завершении работы PHP скрипта экземпляр LabVIEW закрывался. Т.е. тут не было никакого пересечения с уже запущенным экземпляром среды LabVIEW. С помощью известной утилиты Process Explorer это хорошо наблюдается. «Игра» с настройками пула приложений IIS тоже не дала особого результата. Для себя я сделал вывод, что IIS работает как системный демон от имени system, и поэтому создается отдельный экземпляр LabVIEW.exe, привязанный к контексту system, и переиспользование уже открытого экземпляра от имени пользователя Windows мне не удастся получить.
Тогда возникла мысль попробовать сторонний web-сервер, запущенный в простом режиме приложения от имени текущего пользователя. Выбор пал на NGINX, притом я его уже использовал в качестве обратного proxy для LabVIEW WebServices.
Берем доступную текущую версию nginx под Windows. На данный момент nginx-1.17.10. Для связи PHP с NGINX я использовал следующее описание.
Несложная минимальная настройка NGINX. У меня файл: c:\nginx-1.17.10\conf\nginx.conf
Добавление листинга корневого каталога в браузер:
nginx.conf:
Включение PHP через FastCGI в корневом каталоге сервера:
Берем актуальную версию PHP для Windows. Я использовал php-7.4.5-nts-Win32-vc15-x64.zip, располагаться она у меня будет в c:\php-7.4.5-nts-Win32-vc15-x64
Переименовываем и настраиваем php.ini (который php.ini-development из архива). Вносим следующие изменения:
php.ini:
Тут подключается библиотека GD для работы с изображениями (если нужно получать какие-то изображения из LabVIEW) и модуль php_com_dotnet.dll для работы с ActiveX/COM объектами в PHP.
В процессе работы с COM в PHP обнаружился неприятный баг при работе со строками (VT_BSTR), содержащими в теле 0x0 символы. Решается он заменой php_com_dotnet.dll на перекомпилированный с исправлением. Описание бага и патч с исправлением можно найти тут. К сожалению, он до сих пор официально не исправлен в PHP. Я пересобрал php_com_dotnet.dll (для php-7.4.5-nts-Win32-vc15-x64), исправленный php_com_dotnet.dll можно найти по ссылке. Руководство для самостоятельной сборки PHP и расширений можно найти тут.
По умолчанию NGINX будет запущен на 80 TCP порту, PHP FastCGI демон на порту 9000, проверьте, что нет других работающий приложений, использующих эти порты.
Запуск и остановку NGINX и PHP FastCGI демона можно организовать разными способами. У меня для нужд отладки оформились вот такие cmd скрипты: запускающий/перезапускающий в фоне (без открытых окон демонов) start-restart-all.cmd и останавливающий kill-all.cmd, которые я положил в каталог NGINX. Используется Run Hidden Console утилита, взятая из описания.
start-restart-all.cmd:
kill-all.cmd:
Хочу обратить внимание на переменную окружения PHP_FCGI_MAX_REQUESTS. По умолчанию она равна 500. И через 500 запросов демон PHP FastCGI завершит свою работу, поэтому у себя для отладки я отключил этот счетчик. Вот цитата из документации для размышления:
This PHP behavior can be disabled by setting PHP_FCGI_MAX_REQUESTS to 0, but that can be a problem if the PHP application leaks resources. Alternatively, PHP_FCGI_MAX_REQUESTS can be set to a much higher value than the default to reduce the frequency of this problem.
Я написал 2 тестовых скрипта PHP labview.php, labview_png.php, которые необходимо разместить в корне web-сервера C:\nginx-1.17.10\html
labview.php — это основной скрипт примера
labview_png.php — возвращает изображение PNG из читаемой из LabVIEW ActiveX сервера строки типа VT_BSTR.
Выполнять скрипты лучше при запущенной среде LabVIEW, в этом случае скрипты будут переиспользовать уже открытый экземпляр LabVIEW. А не создаваться и закрывать COM экземпляр при каждом вызове скрипта. В моем скрипте используется немного AJAX и «перезапуск», а не переиспользование LabVIEW выльется в «черепаший марафон» последовательный запусков и завершений labview.exe.
Видеообзор:
Некоторое время назад я немного экспериментировал с WebServices LabVIEW (по правде сказать на довольно старой версии LabVIEW). Тогда обнаружил, что у страниц (ресурсов WebServices) нет никакого простого разграничения доступа. Предлагалось настраивать пользователей в Application Server и использовать «мертвый» Microsoft Silverlight. А мне нужен был какой-нибудь простой вариант, типа проверки пароля HTTP Basic access authentication.
Я воспользовался NGINX и настроил его в качестве обратного web proxy c включенной проверкой auth_basic. Используя приведенные ниже настройки, при обращении на адрес http://server_name:5500 после ввода пароля пользователь получает доступ к WebService приложению, работающему по адресу http://127.0.0.1:8001/webservice1/.
Защищаются все ресурсы приложения webservice1.
nginx.conf:
и файл htpasswd с паролями пользователей:
Развивая эту мысль дальше, можно включить доступ к proxy NGINX по HTTPS, а от NGINX к LabVIEW оставить HTTP.
Для LabVIEW на данный момент момент существует несколько способов публикации виртуальных приборов в Web, требующих разного уровня знаний и предоставляющих разные возможности. В этой статье я не собираюсь их описывать, но хочу познакомить вас с нестандартным использованием встроенного в LabVIEW сервера ActiveX/COM для организации Web доступа к VI, а также управления самой средой LabVIEW. Хотя ActiveX/COM уже старая, но еще продолжающая жить в Windows технология, но именно через встроенный ActiveX сервер можно легко организовать управление LabVIEW и VI приборами, в том числе через Web.
Первое что нужно сделать, это включить в LabVIEW этот самый ActiveX сервер, делается это в настройках среды: Tools->Options->VI Server, флажок ActiveX.
Проверить, что сервер включен и к нему есть доступ, можно простым скриптом на VBScript. Нужно создать на рабочем столе текстовой файл labview_test.vbs и наполнить его следующим содержимым:
Dim obj
Set obj = CreateObject("LabVIEW.Application")
'Dim vi
'Set vi = obj.GetVIReference("C:\Users\Dell\Desktop\LabVIEW Web ActiveX\ActiveX Server Executable _LV2012_NI Verified\Executable as ActiveX Server\ActiveX Server.vi")
WScript.Echo(obj.AppName & " ver: " & obj.Version)
'WScript.Echo(vi.GetControlValue("Count"))
'Set vi = Nothing
Set obj = Nothing
Перед выполнением скрипта запустите среду LabVIEW. Впрочем, будет работать и без предварительного запуска среды. На время выполнения скрипта будет запущен экземпляр LabVIEW как ActiveX/COM сервер, а по завершении скрипта экземпляр будет закрыт, так что придется подождать, пока все это «загрузится и выгрузится». В выводе labview_test.vbs будет имя корневого приложения и его версия.
Далее я создал простой VI прибор «ActiveX Server.vi». В нем содержится несколько контролов и вспомогательных функций. Этот VI мы будем загружать и управлять им.
От LabVIEW нам больше ничего не потребуется. Теперь можно приступать к слоям Web.
Тернистый путь
Сначала я немного поэкспериментировал с штатным Windows Web-сервером Microsoft IIS. Пробовал создавать страницы ASP на VBScript приблизительно следующего содержания:
<% @language = "vbscript" %>
<html><body>
<p>ASP can output HTML tags as well as plain text</p>
<%
Dim obj
Set obj = CreateObject("LabVIEW.Application")
response.write(obj.AppName & " ver: " & obj.Version & "<br>" & vbCr)
Dim vi
Set vi = obj.GetVIReference("C:\Users\Dell\Desktop\LabVIEW Web ActiveX\ActiveX Server Executable _LV2012_NI Verified\Executable as ActiveX Server\ActiveX Server.vi")
response.write(vi.GetControlValue("Count") & vbCr)
set vi = Nothing
set obj = Nothing
%>
</body></html>
Метод GetVIReference() загружает VI в память и устанавливает с ним связь. Основной параметр: абсолютный путь к выбранному VI.
Вывод скрипта в браузер:
LabVIEW.exe ver: 20.0
123
Правда, пришлось немного повозиться с настройками пула приложений IIS и анонимной проверки пользователей, которые я настроил на текущего пользователя Windows.
Я решил не углублятся в ASP и переключился на PHP. Для IIS настроил PHP FastCGI демон. Настройки не привожу, они не важны для основной части этой статьи. В PHP также удалось получить доступ к COM объекту LabVIEW, по типу:
$obj = new COM('LabVIEW.Application');
В обоих случаях при запущенной среде LabVIEW и открытом в ней VI (ActiveX Server.vi). При запросе PHP (ASP) скрипта параллельно запускался (и значительное время) новый экземпляр LabVIEW.exe, далее в нем c помощью метода GetVIReference() загружался свой экземпляр «ActiveX Server.vi». По завершении работы PHP скрипта экземпляр LabVIEW закрывался. Т.е. тут не было никакого пересечения с уже запущенным экземпляром среды LabVIEW. С помощью известной утилиты Process Explorer это хорошо наблюдается. «Игра» с настройками пула приложений IIS тоже не дала особого результата. Для себя я сделал вывод, что IIS работает как системный демон от имени system, и поэтому создается отдельный экземпляр LabVIEW.exe, привязанный к контексту system, и переиспользование уже открытого экземпляра от имени пользователя Windows мне не удастся получить.
Тогда возникла мысль попробовать сторонний web-сервер, запущенный в простом режиме приложения от имени текущего пользователя. Выбор пал на NGINX, притом я его уже использовал в качестве обратного proxy для LabVIEW WebServices.
NGINX
Берем доступную текущую версию nginx под Windows. На данный момент nginx-1.17.10. Для связи PHP с NGINX я использовал следующее описание.
Несложная минимальная настройка NGINX. У меня файл: c:\nginx-1.17.10\conf\nginx.conf
Добавление листинга корневого каталога в браузер:
nginx.conf:
location / {
root html;
index index.html index.htm;
autoindex on;
}
Включение PHP через FastCGI в корневом каталоге сервера:
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
PHP
Берем актуальную версию PHP для Windows. Я использовал php-7.4.5-nts-Win32-vc15-x64.zip, располагаться она у меня будет в c:\php-7.4.5-nts-Win32-vc15-x64
Переименовываем и настраиваем php.ini (который php.ini-development из архива). Вносим следующие изменения:
php.ini:
short_open_tag = On
html_errors = On
error_reporting = E_ALL & ~E_NOTICE
extension_dir = "ext"
extension=gd2
extension=php_com_dotnet.dll
Тут подключается библиотека GD для работы с изображениями (если нужно получать какие-то изображения из LabVIEW) и модуль php_com_dotnet.dll для работы с ActiveX/COM объектами в PHP.
В процессе работы с COM в PHP обнаружился неприятный баг при работе со строками (VT_BSTR), содержащими в теле 0x0 символы. Решается он заменой php_com_dotnet.dll на перекомпилированный с исправлением. Описание бага и патч с исправлением можно найти тут. К сожалению, он до сих пор официально не исправлен в PHP. Я пересобрал php_com_dotnet.dll (для php-7.4.5-nts-Win32-vc15-x64), исправленный php_com_dotnet.dll можно найти по ссылке. Руководство для самостоятельной сборки PHP и расширений можно найти тут.
По умолчанию NGINX будет запущен на 80 TCP порту, PHP FastCGI демон на порту 9000, проверьте, что нет других работающий приложений, использующих эти порты.
Запуск и остановку NGINX и PHP FastCGI демона можно организовать разными способами. У меня для нужд отладки оформились вот такие cmd скрипты: запускающий/перезапускающий в фоне (без открытых окон демонов) start-restart-all.cmd и останавливающий kill-all.cmd, которые я положил в каталог NGINX. Используется Run Hidden Console утилита, взятая из описания.
start-restart-all.cmd:
rem @echo off
set PHP_FCGI_MAX_REQUESTS=0
@echo Shutting down servers...
taskkill /f /IM nginx.exe
taskkill /f /IM php-cgi.exe
@timeout 1
@echo Starting servers...
@rem start /b /D "C:\php-7.4.5-nts-Win32-vc15-x64" php-cgi.exe -b 127.0.0.1:9000
RunHiddenConsole.exe "C:\php-7.4.5-nts-Win32-vc15-x64\php-cgi.exe" -b 127.0.0.1:9000
start /b /D "c:\nginx-1.17.10\" nginx.exe
@timeout 3
kill-all.cmd:
taskkill /f /IM nginx.exe
taskkill /f /IM php-cgi.exe
pause
Хочу обратить внимание на переменную окружения PHP_FCGI_MAX_REQUESTS. По умолчанию она равна 500. И через 500 запросов демон PHP FastCGI завершит свою работу, поэтому у себя для отладки я отключил этот счетчик. Вот цитата из документации для размышления:
This PHP behavior can be disabled by setting PHP_FCGI_MAX_REQUESTS to 0, but that can be a problem if the PHP application leaks resources. Alternatively, PHP_FCGI_MAX_REQUESTS can be set to a much higher value than the default to reduce the frequency of this problem.
Я написал 2 тестовых скрипта PHP labview.php, labview_png.php, которые необходимо разместить в корне web-сервера C:\nginx-1.17.10\html
labview.php — это основной скрипт примера
labview_png.php — возвращает изображение PNG из читаемой из LabVIEW ActiveX сервера строки типа VT_BSTR.
labview.php
<?php
if(strpos(exec('tasklist /FI "IMAGENAME eq LabVIEW.exe" /NH'), 'LabVIEW.exe') === false)
exit("Не запущен LabVIEW.exe");?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>LabVIEW PHP COM example</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
// setTimeout(function(){
// window.location.reload(1);
// }, 3000);
// setInterval(function() {
// var myImageElement = document.getElementById('myImage');
// myImageElement.src = 'labview_png.php?rand=' + Math.random();
//}, 200);
$(document).ready(function(){
setInterval(function(){
$("#png").attr('src', 'labview_png.php?rand=' + Math.random());
$("#auto").load(location.href + " #auto");
}, 1000);
});
</script>
</head>
<body>
<?php
//phpinfo();
echo '_GET val: ';
foreach ($_GET as $key => $value)
echo "$key=$value, ";
echo '<br>', PHP_EOL;
echo '_POST val: ';
foreach ($_POST as $key => $value)
echo "$key=$value, ";
echo '<br>', PHP_EOL;
define('FPStateInfo', ['Invalid', 'Standard', 'Closed', 'Hidden', 'Minimized', 'Maximized']);
define('ExecStateInfo', ['eBad 0 VI has errors; it cannot run', 'eIdle 1 VI is not running, but the VI is in memory.', 'eRunTopLevel 2 VI is running as a top-level VI', 'eRunning 3 VI is running as a subV']);
$obj = new COM('LabVIEW.Application');
//com_print_typeinfo($obj);
$vi = $obj->GetVIReference('C:\Users\Dell\Desktop\LabVIEW Web ActiveX\ActiveX Server Executable _LV2012_NI Verified\Executable as ActiveX Server\ActiveX Server.vi');
//$vi->OpenFrontPanel();
echo '<form action="" method="post">';
echo '<input type="button" value="Refresh page" onClick=\'window.location.href=window.location.href\'>', PHP_EOL;
$fpstate = $vi->FPState();
$vistate = $vi->ExecState();
if ($_POST['action']==='run_vi' && $vistate <= 1) {
$vi->Run(true); // async Boolean If TRUE, you do not need to wait for the VI to finish running. The default is FALSE.
} elseif ($_POST['action']==='stop_vi' && $vistate > 1) {
//$vi->SetControlValue('stop', true);
//sleep(1);
$vi->Abort();
} elseif ($_POST['action']==='open_fp' && $fpstate==2) {
$vi->OpenFrontPanel();
} elseif ($_POST['action']==='close_fp' && $fpstate!=2) {
$vi->CloseFrontPanel();
}
if ($_POST['Count2']) {
$vi->SetControlValue('Count2', $_POST['Count2']);
}
echo '<h3>SetControlValue(\'Count2\'):</h3>', PHP_EOL;
echo '<input onchange="this.form.submit()" type="number" name="Count2" value="', $vi->GetControlValue('Count2'), '">', PHP_EOL;
echo '<div id="auto">';
echo '<h3>AppName / Version:</h3>', PHP_EOL;
echo $obj->AppName(), ' / ', $obj->Version(), '<br>', PHP_EOL;
echo '<h3>ExportedVIs:</h3>', PHP_EOL;
foreach ($obj->ExportedVIs() as $value)
echo $value, '<br>', PHP_EOL;
echo '<h3>FPState:</h3>', PHP_EOL;
$fpstate = $vi->FPState();
echo $fpstate, ', ', FPStateInfo[$fpstate], PHP_EOL;
echo '<button name="action" type="submit" value="open_fp">OpenFrontPanel</button>', PHP_EOL;
echo '<button name="action" type="submit" value="close_fp">CloseFrontPanel</button>', PHP_EOL;
echo '<h3>ExecState:</h3>', PHP_EOL;
$vistate = $vi->ExecState();
if ($vistate > 1) {
echo '<font color="blue">', $vistate, ', ', ExecStateInfo[$vistate], '</font>', PHP_EOL;
} else {
echo $vistate, ', ', ExecStateInfo[$vistate], PHP_EOL;
}
echo '<button name="action" type="submit" value="run_vi">Run VI</button>', PHP_EOL;
echo '<button name="action" type="submit" value="stop_vi">Abort VI</button>', PHP_EOL;
echo '</form>', PHP_EOL;
echo '<h3>GetControlValue(\'Count\') / GetControlValue(\'Count2\'):</h3>', PHP_EOL;
echo $vi->GetControlValue('Count'), ' / ', $vi->GetControlValue('Count2'), PHP_EOL;
//echo $vi->SetControlValue('Count2', $vi->GetControlValue('Count')+1), PHP_EOL;
echo '<h3>Array1:</h3>', PHP_EOL;
foreach ($vi->GetControlValue('Array1') as $value)
echo $value, '<br>', PHP_EOL;
//$png_data = new variant(null, VT_UI1);
//$png_data = variant_set_type($vi->GetControlValue('png data'), VT_UI1);
//echo variant_cast($vi->GetControlValue('png1'), VT_BSTR), PHP_EOL;
//echo mb_strlen($vi->GetControlValue('String1')), PHP_EOL;
//echo variant_get_type($vi->GetControlValue('png1')), PHP_EOL;
echo '<h3>PNG data:</h3>', PHP_EOL;
$png_data = $vi->GetControlValue('PNG data');
echo 'PNG size:' , strlen($png_data), '<br>', PHP_EOL;
echo '</div>';
if ($vistate > 1 && $fpstate!=2) {
echo '<img src="labview_png.php" id="png">';
}
// variant_set_type($variant, VT_BSTR)
//$png_data = variant_cast($vi->GetControlValue('png data'), VT_U1);
//echo variant_get_type($png_data), PHP_EOL;
echo $vi->SetControlValue('String1', "123\x00555321");
//com_print_typeinfo($vi);
$obj = null;
?>
</body>
</html>
labview_png.php
<?php
if(strpos(exec('tasklist /FI "IMAGENAME eq LabVIEW.exe" /NH'), 'LabVIEW.exe') === false)
exit("Не запущен LabVIEW.exe");
$obj = new COM('LabVIEW.Application');
$vi = $obj->GetVIReference('C:\Users\Dell\Desktop\LabVIEW Web ActiveX\ActiveX Server Executable _LV2012_NI Verified\Executable as ActiveX Server\ActiveX Server.vi');
$data = $vi->GetControlValue('PNG data');
$im = imagecreatefromstring($data);
if ($im !== false) {
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
}
else {
echo 'Произошла ошибка.';
}
$obj = null;
?>
Выполнять скрипты лучше при запущенной среде LabVIEW, в этом случае скрипты будут переиспользовать уже открытый экземпляр LabVIEW. А не создаваться и закрывать COM экземпляр при каждом вызове скрипта. В моем скрипте используется немного AJAX и «перезапуск», а не переиспользование LabVIEW выльется в «черепаший марафон» последовательный запусков и завершений labview.exe.
Видеообзор:
Appendix. Конфигурация NGINX в качестве обратного proxy с HTTP Basic access authentication для работы с WebServices LabVIEW
Некоторое время назад я немного экспериментировал с WebServices LabVIEW (по правде сказать на довольно старой версии LabVIEW). Тогда обнаружил, что у страниц (ресурсов WebServices) нет никакого простого разграничения доступа. Предлагалось настраивать пользователей в Application Server и использовать «мертвый» Microsoft Silverlight. А мне нужен был какой-нибудь простой вариант, типа проверки пароля HTTP Basic access authentication.
Я воспользовался NGINX и настроил его в качестве обратного web proxy c включенной проверкой auth_basic. Используя приведенные ниже настройки, при обращении на адрес http://server_name:5500 после ввода пароля пользователь получает доступ к WebService приложению, работающему по адресу http://127.0.0.1:8001/webservice1/.
Защищаются все ресурсы приложения webservice1.
nginx.conf:
server {
listen 5500;
server_name localhost;
location / {
auth_basic "Unauthorized";
auth_basic_user_file htpasswd;
root html;
#autoindex on;
#index index.html index.htm;
proxy_pass http://127.0.0.1:8001/webservice1/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
и файл htpasswd с паролями пользователей:
admin:{PLAIN}1
Развивая эту мысль дальше, можно включить доступ к proxy NGINX по HTTPS, а от NGINX к LabVIEW оставить HTTP.
b_t
Спасибо!