# **Taskbus 使用手册**
Taskbus 是一款基于C++/Qt的多进程软件合作平台。使用该平台，多个基于标准输入输出设备（Stdio）的进程能够互相交换数据，并共同完成较为复杂的功能。Taskbus 初衷是为不具备良好计算机编程背景的小型团队提供开发SDR软件无线电程序的能力增量，当然也可以用来做非SDR领域的任何事情。关于本软件的技术原理，请参考[taskbus_zh_CN.md](taskbus_zh_CN.md)。本手册主要介绍该软件的使用方法。

[TOC]

## 1. 编译
获取可执行程序的方法主要包括源码编译和直接使用发行版。鉴于TaskBus主要使用Qt C++开发，在Linux环境下，编译比较方便，因此目前[对Windows平台准备了发行版](https://gitcode.net/coloreaglestdio/taskbus/-/releases)。如果使用发行版，则无需编译taskBus项目，因此仅需要参考1.2节配置UHD即可。本节主要介绍在windows平台下的编译和安装，Linux下因为依赖性很容易通过包管理器解决，故而不作为重点。

### 1.1 获取源码
(**直接下载发行版的用户可忽略本节**)
从下列网址下载最新的代码：
[https://gitcode.net/coloreaglestdio/taskbus](https://gitcode.net/coloreaglestdio/taskbus)
也可以直接使用Git签出：
```bash
#for Qt5
git clone https://gitcode.net/coloreaglestdio/taskbus.git
#for Qt6
git clone -b qt6 https://gitcode.net/coloreaglestdio/taskbus.git
```
### 1.2 安装 libUHD 并首次驱动USRP设备
#### 1.2.1 安装libUHD库的两种方法
** 方法（1）：直接从官网下载。 **
从 [https://files.ettus.com/binaries/uhd/](https://files.ettus.com/binaries/uhd/) 下载新版的uhd，2022年后，一般可以安装4.x版本。
下载安装包，直接安装后，请配置UHD的环境变量，PATH路径。配置完毕，打开CMD，运行下面的命令，以确保已经正确设置。
```dos
C:\>echo %UHD_PKG_PATH% [回车]
D:\UHD4.1.0

C:\>PATH [回车]
C:\WINDOWS\system32;C:\WINDOWS;\...;D:\UHD4.1.0\bin;...;
```
如果不设置环境变量，编译得时候找不到头文件，运行的时候找不到libuhd.dll

** 方法（2）：从Pothos SDR下载。**
如果希望在windows下使用PothosSDR获得GNU-Radio的所有功能，可以使用软件无线电全家桶PothosSDR。从 [https://downloads.myriadrf.org/builds/PothosSDR/](https://downloads.myriadrf.org/builds/PothosSDR/) 下载最新版，直接安装。

直接安装后，请配置UHD的环境变量，PATH路径。配置完毕，打开CMD，运行下面的命令，以确保已经正确设置。
```dos
C:\>echo %UHD_PKG_PATH% [回车]
E:\PothosSDR

C:\>PATH [回车]
C:\WINDOWS\system32;C:\WINDOWS;\...;E:\PothosSDR\bin;...;
```
而后，使用脚本下载 uhd的FPGA固件。

```dos
#假设Pothos SDR 安装在 E:\，则运行
E:\> python PothosSDR\lib\uhd\utils\uhd_images_downloader.py -i E:\PothosSDR\share\uhd [回车]
```
运行后，会发现uhd文件夹下多了images文件夹。

#### 1.2.2 确认USRP设备运行正常
在命令行执行：
```dos
C:\> uhd_usrp_probe [回车]
```
不报错，并显示设备的参数了，则说明安装基本正常。**请注意上述命令返回状态中的警告** ，如网卡mtu、send_buffer_size等参数的配置警告。这些警告与正确编译taskBus无关，但与发挥设备最大的吞吐能力有关。为了保证稳定持续的吞吐，需要细致的参考以下几篇文章，解决X310万兆网、千兆网、USB等各种配置。
- [https://files.ettus.com/manual/page_transport.html](https://files.ettus.com/manual/page_transport.html)
- [https://goldenhawking.blog.csdn.net/article/details/110727815](https://goldenhawking.blog.csdn.net/article/details/110727815)

### 1.3 安装boost
(**直接下载发行版的用户可忽略本节**)

如果您已经有了boost的某个版本，可以直接使用该版本的boost。若没有安装，且仅为了编译 taskBus，则可以使用源码自带的boost.

因为taskBus使用的是libUHD的C语言接口，在C++环境下，仅需要几个boost库的头文件支持。在源码的[modules/3rdlibs/boost_headers_1075.7z](../modules/3rdlibs/boost_headers_1075.7z)中，包含了boost 1.75的头文件。把该压缩包释放到libUHD或者PothosSD的include文件夹下，使得其看起来与uhd的头文件uhd.h平级。

```txt
include-|
        |- boost
        |- uhd
        |...
        |- uhd.h
```

### 1.4 检查并配置pthread
(**直接下载发行版的用户可忽略本节**)
pthread是一个windows下仿POSIX的线程库。pthread.h被libuhd所使用，但可能会和您编译环境中的头文件冲突。该冲突发生在使用PothosSDR和MinGW64编译器的情况下。当您使用的是Mingw64编译器，请执行以下操作：

- 找到 PothosSDR\include 文件夹
- 把pthread.h重命名为pthread.hpp

### 1.5 安装Qt
(**直接下载发行版的用户可忽略本节**)
目前windows下请在线安装Qt，以及对应的编译器。

- 由于uhd库仅仅使用了C接口，故而编译taskBus的编译器与libuhd的编译器可以是不同的。
- 当编译器不同时，请不要使用uhd库中C接口的 C\+\+ 扩展，如试图直接从 rx_meta->rx_metadata_cpp.time_spec 使用C\+\+/boost的timestamp结构。C++在二进制上的ABI差异可能导致诡异的错误。

以下编译环境是经过测试的：

- MSYS2 mingw64 Qt + Pothos SDR \*
- mingw64 Qt + Pothos SDR \*
- MSVC2019 x64 Qt + Pothos SDR
- MSYS2 mingw64 Qt + libUHD
- mingw64 Qt + libUHD
- MSVC2019 x64 Qt + libUHD

（\* 表示需要进行1.4节所说的pthead替换）

### 1.6 编译
(**直接下载发行版的用户可忽略本节**)
打开 QtCreator, 载入工程。
- 若使用的是MSYS2环境，建议载入CMake工程。qmake工程在静态Qt库编译时，会遇到链接错误（2022-04-04测试），使用CMake可以避免错误。
- 请参考下表选择合适的编译配置

|系统|编译环境|编译器(Qt)|UHD安装方式|需配置boost头(1.3节）|需配置pthread.h（1.4节）|须留心libiio版本问题（2.2.2节）|优选项目类型|
|--|--|--|--|--|--|--|--|
|win|MSVC2019|MSVC2019|libUHD|Y|N|Y|qmake|
|win|MSVC2019|MSVC2019|Pothos SDR|Y|N|N|qmake|
|win|CMD|MinGW64|libUHD|Y|N|Y|cmake|
|win|CMD|MinGW64|Pothos SDR|Y|Y|N|cmake|
|win|MSYS2 bash|MinGW64|libUHD|N|N|Y|cmake|
|win|MSYS2 bash|MinGW64|Pothos SDR|N|Y|N|cmake|
|win|MSYS2 bash|MinGW64-static|libUHD|N|N|Y|cmake|
|win|MSYS2 bash|MinGW64-static|Pothos SDR|N|Y|N|cmake|
|linux|bash|gcc|apt/yum/pacman|N|N|N|cmake|

如果有真实的非虚拟机linux环境，还是建议在Linux下运行。

### 1.7 编译后的结果
一旦编译完成，在输出文件夹下会产生 bin文件夹，含有所有的可执行文件。这个文件夹应该类似：
```dos
E:\build\bin> tree /F [回车]
E:.
│  subtask_wrapper.exe
│  taskBusPlatform.exe
└─modules
        filter_fir.exe
        mod_fm.exe
        mod_fm_dem.exe
        network_p2p.exe
        resample_pqfraction.exe
        sink_file.exe
        sink_plots.exe
        sink_plutosdr.exe
        sink_soundcard.exe
        sink_SQL.exe
        source_file.exe
        source_plutosdr.exe
        source_soundcard.exe
        transform_fft.exe
        uhd_usrp_continous.exe
        uhd_usrp_io.exe
        wrapper_scripts.exe
        wrapper_stdio.exe
```

## 2 安装
taskBus由若干可执行文件（在windows下就是exe文件）共同完成任务。为脱离编译器环境运行，这些模块所需要的动态链接库都需要位于可发现的位置上。对Linux而言，由于使用的都是官方库，所以不存在安装问题。基本上双击 taskBusPlatform 就能启动。对Windows而言，需要格外注意依赖项。建议下载[https://dependencywalker.com/](https://dependencywalker.com/)以便在出问题时查看依赖。

### 2.1 执行Qt发布

打开Qt的命令行，在bin文件夹下，执行Qt发布工具。如果是静态链接，则无需本步骤。

```dos
E:\build\bin> windeployqt  --compiler-runtime taskBusPlatform.exe
E:\build\bin> windeployqt  --compiler-runtime --dir . modules/sink_sql.exe
E:\build\bin> windeployqt  --compiler-runtime --dir . modules/sink_soundcard.exe
E:\build\bin> windeployqt  --compiler-runtime modules/sink_sql.exe
E:\build\bin> windeployqt  --compiler-runtime modules/sink_soundcard.exe
```

### 2.2 确认额外的动态库

即使是静态链接到Qt，还是需要动态库的支持。
#### 2.2.1 fftw
在bin文件夹执行命令:
```dos
E:\build\bin> modules\transform_fft.exe
```
若报错，说明需要拷贝源码文件夹 taskbus\modules\3rdlibs\win32\fftw\x64\libfftw3-3.dll 到bin\modules文件夹下。

#### 2.2.2 解决libiio::libusb冲突
若使用Pluto SDR，请确保libiio不要使用旧版进行安装。旧版会在windows\system32下释放libusb-1.0.dll，与uhd的libusb-1.0.dll冲突。
解决方法：
- 把libiio的文件夹 （如taskbus\modules\3rdlibs\win32\libiio\MS64）中所有文件拷贝到一个单独的文件夹下，并把source_plutosdr,sink_plutosdr两个模块移动到本文件夹。
- 直接使用Pothos SDR全家桶，不安装libiio

#### 2.2.3 MSYS64环境额外处理
MSYS64环境依赖的开源库，请在msys64 bash下使用ldd查找缺项。
```bash
$ ldd transform_fft.exe | grep "mingw64"
        libgcc_s_seh-1.dll => /mingw64/bin/libgcc_s_seh-1.dll (0x7ffd1e7f0000)
        libwinpthread-1.dll => /mingw64/bin/libwinpthread-1.dll (0x7ffd1e110000)
        //...
```

### 2.3 加载所有的模块
打开 taskBusPlatform.exe, 点击“载入模块”，定位到modules文件夹，全选除了wrapper_scripts.exe之外的文件，可以看到加载的结果。如果如下图所示，表示加载成功。
![LoadModules](handbook/1.LoadModules.jpg)
![LoadModules](handbook/2.LoadModulesOk.jpg)

### 2.4 排查问题
如果发现缺少某个模块，请到命令行下，执行 模块名.exe --information,若能够输出json，则表示正常。否则，请对照出错提示，结合[dependencywalker](https://dependencywalker.com/)或者ldd查看依赖。
比如，对fft模块，执行:
```dos
E:\build\bin> modules\transform_fft.exe --information [回车]
{
        "transform_fft":{
                "name":"libfftw",
                "parameters":{
                         "sptype":{
                                "type":"enum",
 #...
        }
}
```
 则表示没有问题。

## 3 设计师界面
taskBus 的工作原理是使用设计师 taskBusPlatform.exe 设计工程，连接各个模块的执行文件。而后，保存工程为.tbj(json)格式，并在设计师内运行。同时，tbj文件也可以通过命令行工具subtask_wrapper.exe封装后，脱离界面运行。本节介绍设计师界面的基本情况。

###3.1 基本框架
当您下载或者编译了特定的发行版本后，会获得一个含有多个可执行文件、配置文件的文件夹。以发行版 taskbus_win64_20220419_Qt6 为例，这个文件夹的结构大致如下：
```txt
├─bin					设计师可执行文件（主程序）
├─doc					文档文件夹
├─examples				工程范例文件夹
├─modules				模块文件夹
│  ├─plutosdr			ADALM PlutoSDR模块
│  ├─usrp				Ettus USRP UHD模块
│  └─wrapper_scripts	用于脚本（python，node.js)的封装器模块
└─templates				模块模板
    ├─cpp		纯C++模板
    ├─csharp	C#模板
    ├─FMDem		C语言FM解调器（二次封装，需要wrapper_stdio）
    ├─matlab	Matlab语言
    ├─mfc    	MFC框架
    ├─nodejs	node.js+wrapper_scripts
    ├─python	python 3脚本+wrapper_scripts
    └─python2	python 2脚本+wrapper_scripts
```

####3.1.1 自带模块一览表

在模块modules文件夹里，是编译好的各个模块，以发行版 taskbus_win64_20220419_Qt6 为例，主要包括：

|模块可执行文件夹|模块功能|备注|
|--|--|--|
|filter_fir.exe|Fir滤波器|时域Fir滤波|
|mod_fm.exe|调频FM广播调制器|可产生广播|
|mod_fm_dem.exe|调频FM广播解调器|可还原音乐|
|network_p2p.exe|分布式点对点TCP模块|可以把两台计算机联动起来|
|resample_pqfraction.exe|分数倍重采样|与Matlab resample(p,q)类似|
|sink_file.exe|文件信宿|可把数据保存为文本或者二进制|
|sink_plots.exe|画图信宿|包括简单的1D,2D,时频图|
|sink_plutosdr.exe|PlutoSDR信宿|发行版中在独立的文件夹，避免libiio和usrp的冲突|
|sink_soundcard.exe|声卡信宿|可播放声音|
|sink_SQL.exe|SQL信宿|用于执行SQL，也可以用wrapper_stdio+命令行数据库客户端代替|
|source_file.exe|文件信源|可以按照灵活的方式批量读取文件|
|source_plutosdr.exe|PlutoSDR信源||
|source_soundcard.exe|声卡信源|可以进行录音并把波形带入平台|
|transform_fft.exe|FFT变换|使用libfftw|
|uhd_usrp_continous.exe|UHD连续吞吐|不带时戳的USRP吞吐|
|uhd_usrp_io.exe|UHD突发/连续吞吐|带时戳的USRP吞吐，可获取每份数据的时戳，并为每份发射数据准备预告的时戳|
|wrapper_scripts.exe|脚本包装器|用于包装python,node.js等脚本制作的模块。相关例子见templates中python文件夹|
|wrapper_stdio.exe|标准命令行包装器|用于包装简单的基本命令行程序，构成1输入（Stdin），两输出(stdout, stderr)模块。见examples里的usrp_fm_wrapper.tbj|

#### 3.1.2 模块加载历史记录
一旦模块加载成功，会记录在default_mods.text中。其可能的内容如下：
```text
../modules/sink_soundcard.exe
../modules/source_file.exe
../modules/usrp/uhd_usrp_continous.exe
../templates/python2/example_python2.exe
../templates/nodejs/example_nodejs.exe
../modules/sink_plots.exe
../modules/source_soundcard.exe
../modules/sink_SQL.exe
../modules/mod_fm_dem.exe
../modules/filter_fir.exe
../modules/plutosdr/source_plutosdr.exe
../modules/mod_fm.exe
../modules/plutosdr/sink_plutosdr.exe
../modules/network_p2p.exe
../modules/usrp/uhd_usrp_io.exe
../modules/transform_fft.exe
../modules/resample_pqfraction.exe
../templates/python/example_python.exe
../examples/voice_spec.exe
../modules/wrapper_stdio.exe
../modules/sink_file.exe
```
对封装的子项目，在对应的子项目名.text里，也会设置加载的文件名。如：

[examples/voice_spec.text](../examples/voice_spec.text)

###3.2 界面元素
双击bin/taskBusPlatform.exe 启动程序，主要界面元素如下：
![mainGUI](handbook/3.MainGUI.jpg)

####3.2.1 主工具栏按钮
各个按钮的意义如下：

|图标|文字|作用|行为|
|--|--|--|--|
|![载入模块](handbook/buttons/load_module.png)|载入模块|载入一个符合taskBus接口定义标准的模块（JSON描述）|弹出对话框，选择EXE文件后，会试图用 --information 开关启动程序。如果失败，则试图寻找 程序文件名.json文件。如果失败，则不会加载。|
|![新建工程](handbook/buttons/new_project.png)|新建工程|新建空白工程||
|![打开工程](handbook/buttons/open_project.png)|打开工程|打开存在的工程|如果工程对应的某个模块没有预先加载，则打开工程后看不到对应的模块图标。|
|![保存工程](handbook/buttons/save_project.png)|保存工程|保存目前的修改||
|![执行](handbook/buttons/start_project.png)|执行|执行工程|会依次启动各个进程，并吞吐stdio数据|
|![停止执行](handbook/buttons/ddimg_exit.png)|停止执行|中止执行当前工程|会发quit()指令到所有进程，并等待。超时后会强制终止相关进程。|
|![隐藏](handbook/buttons/ticon2.png)|隐藏|隐藏主界面|最小化到任务栏，变成图标。|

#### 3.2.2 “编辑”工具栏按钮
各个按钮的意义如下：

|图标|文字|作用|快捷键|行为|
|--|--|--|--|--|
|![放大](handbook/buttons/zoomIn.png)|放大|Ctrl+‘=’|放大视图。|点击按钮后，视图被放大。|
|![缩小](handbook/buttons/zoomOut.png)|缩小|Ctrl+‘-’|缩小视图。|点击按钮后，视图被缩小。|
|![还原](handbook/buttons/038-2.png)|还原||还原视图|点击按钮后，视图比例重新回到100%。|
|![复制](handbook/buttons/Copy.png)|复制|Ctrl+‘c’|复制元素。|点击按钮后，当前被选中模块的信息会被复制到剪贴板。|
|![剪切](handbook/buttons/Cut-2.png)|复制|Ctrl+‘x’|剪切元素。|点击按钮后，当前被选中模块被删除，信息会被复制到剪贴板。|
|![删除](handbook/buttons/delete_node.png)|删除|Del|删除元素。|点击按钮后，当前元素会被删除。|
|![粘贴](handbook/buttons/Paste.png)|粘贴|Ctrl+‘v’|粘贴元素。|点击按钮后，当前剪贴板里的元素会被插入到工程里。|
|![撤销](handbook/buttons/undo-1.png)|粘贴|Ctrl+‘z’|撤销操作。|点击按钮后，会不断撤销操作。|
|![重做](handbook/buttons/Redo.png)|重做|Ctrl+Shift+‘z’|重做操作。|点击按钮后，重做刚刚被撤销的操作。|
|![断开](handbook/buttons/D. line.png)|断开管脚|Ctrl+‘d’|断开选中的管脚。|点击按钮后，被鼠标选中的管脚会被断开。|
|![上移](handbook/buttons/up.png)|向上一格|Ctrl+‘上方向’|管脚布局向上移动一格。|点击按钮后，被选中的管脚会向上移动。但由于管脚布局的限制，当无法上移时，请下移其他管脚达到相同作用。|
|![下移](handbook/buttons/down.png)|向下一格|Ctrl+‘下方向’|管脚布局向下移动一格。|点击按钮后，被选中的管脚会向下移动。但由于管脚布局的限制，当无法下移时，请上移其他管脚达到相同作用。|
|![翻转](handbook/buttons/side.png)|翻转位置|Ctrl+‘左/右’|管脚移动到绘图块的另一边。|点击按钮后，被选中的管脚会翻转到另一边。|
|![调试启动](handbook/buttons/ddimg_debug.png)|启动调试||启动对选中模块的调试。|相应模块的输入、输出会被记录在debug文件夹中，这样允许离线调试独立的模块。|
|![调试终止](handbook/buttons/ddimg_debugoff.png)|停止调试||停止对选中模块的调试。|||
|![提高优先级](handbook/buttons/Process busy.png)|提高优先级||提高选中模块的进程优先级（nice）。|对实时性要求高的模块请使用高的优先级。在Linux下，优先级越高，数字越小。|
|![降低优先级](handbook/buttons/Process idle.png)|降低优先级||降低选中模块的进程优先级（nice）。|对实时性要求高的模块请使用高的优先级。|

### 3.3 主进程优先级

设置主进程的配置文件taskBusPlatform.exe.ini，可配置优先级。
```ini
[settings]
nice=2
```

**注意：相同的工程，切换平台（Linux<->Windows)后，要注意优先级的取值变化。**

## 4. 从范例工程开始

### 4.1 打开范例工程
点击“打开”按钮

|图标|文字|作用|行为|
|--|--|--|--|
|![打开工程](handbook/buttons/open_project.png)|打开工程|打开存在的工程|如果工程对应的某个模块没有预先加载，则打开工程后看不到对应的模块图标。|

加载现有的工程。以 [examples/soundcard.tbj](../examples/soundcard.tbj)为例，打开后，将看到如下界面：
![Example](handbook/4.Example.jpg)

### 4.2 配置范例工程

#### 4.2.1 配置优先级
可以试着使用按钮：

|图标|文字|作用|快捷键|行为|
|--|--|--|--|--|
|![提高优先级](handbook/buttons/Process busy.png)|提高优先级||提高选中模块的进程优先级（nice）。|对实时性要求高的模块请使用高的优先级。在Linux下，优先级越高，数字越小。|
|![降低优先级](handbook/buttons/Process idle.png)|降低优先级||降低选中模块的进程优先级（nice）。|对实时性要求高的模块请使用高的优先级。|

调整各个模块优先级，直到满足平台所需。Linux下，0为正常，<1为高优先级，>0为低优先级。Windows下，0为最低，5为最高。

- 调整前，要选中模块
- 这样的调整操作在切换Windows/Linux平台时尤为重要。因为这两个平台的优先级算数范围不同，且大小相反。


#### 4.2.2 配置模块参数表
可以查看，并试着修改模块参数表。
![Example](handbook/5.Props.jpg)
- 双击彩色的“实例值”，进入编辑状态
- 修改相应的数值。所有被修改的值，都会以命令行的参数方式传给进程。

### 4.3 拖入模块

双击或者拖拽模块，以便引入新的模块。我们可以加入采样率变换模块  resample_pqfraction模块。而后，配置其属性。
![6.NewMod.jpg](handbook/6.NewMod.jpg)

### 4.4 修改连线

选中管脚，右键单击弹出菜单，或者直接按工具栏按钮

|图标|文字|作用|快捷键|行为|
|--|--|--|--|--|
|![断开](handbook/buttons/D. line.png)|断开管脚|Ctrl+‘d’|断开选中的管脚。|点击按钮后，被鼠标选中的管脚会被断开。|

删除连线。

![7.DelLine.jpg](handbook/7.DelLine.jpg)

删除后，工程类似：
![8.AfterDel.jpg](handbook/8.AfterDel.jpg)
而后，分别单击下图中的管脚，完成连接，类似:
![9.AfterConn.jpg](handbook/9.AfterConn.jpg)

### 4.5 优化布局
通过拖动方块位置，并利用按钮

|图标|文字|作用|快捷键|行为|
|--|--|--|--|--|
|![上移](handbook/buttons/up.png)|向上一格|Ctrl+‘上方向’|管脚布局向上移动一格。|点击按钮后，被选中的管脚会向上移动。但由于管脚布局的限制，当无法上移时，请下移其他管脚达到相同作用。|
|![下移](handbook/buttons/down.png)|向下一格|Ctrl+‘下方向’|管脚布局向下移动一格。|点击按钮后，被选中的管脚会向下移动。但由于管脚布局的限制，当无法下移时，请上移其他管脚达到相同作用。|
|![翻转](handbook/buttons/side.png)|翻转位置|Ctrl+‘左/右’|管脚移动到绘图块的另一边。|点击按钮后，被选中的管脚会翻转到另一边。|

调整布局，调整后，布局如下：
![a.AfterFormat.jpg](handbook/a.AfterFormat.jpg)

### 4.6 运行工程
点击按钮

|图标|文字|作用|行为|
|--|--|--|--|
|![执行](handbook/buttons/start_project.png)|执行|执行工程|会依次启动各个进程，并吞吐stdio数据|

运行工程，并尝试配置声音来源，可以看到实时语音或者音乐的频谱。
![b.Run.jpg](handbook/b.Run.jpg)



