# Taskbus 使用手册

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

- - 1. 编译
    - 1.1 获取源码
    - 1.2 安装 libUHD 并首次驱动USRP设备
      - 1.2.1 安装libUHD库的两种方法
      - 1.2.2 确认USRP设备运行正常
    - 1.3 安装boost
    - 1.4 检查并配置pthread
    - 1.5 安装Qt
    - 1.6 编译
    - 1.7 编译后的结果
  - 2 安装
    - 2.1 执行Qt发布
    - 2.2 确认额外的动态库
      - 2.2.1 fftw
      - 2.2.2 解决libiio::libusb冲突
      - 2.2.3 MSYS64环境额外处理
    - 2.3 加载所有的模块
    - 2.4 排查问题
  - 3 设计师界面
    - 3.1 基本框架
      - 3.1.1 自带模块一览表
      - 3.1.2 模块加载历史记录
    - 3.2 界面元素
      - 3.2.1 主工具栏按钮
      - 3.2.2 “编辑”工具栏按钮
    - 3.3 主进程优先级
  - 4. 从范例工程开始
    - 4.1 打开范例工程
    - 4.2 配置范例工程
      - 4.2.1 配置优先级
      - 4.2.2 配置模块参数表
    - 4.3 拖入模块
    - 4.4 修改连线
    - 4.5 优化布局
    - 4.6 运行工程

## 1. 编译

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

### 1.1 获取源码

(直接下载发行版的用户可忽略本节)
从下列网址下载最新的代码：
https://gitcode.net/coloreaglestdio/taskbus
也可以直接使用Git签出：

    #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/ 下载新版的uhd，2022年后，一般可以安装4.x版本。
下载安装包，直接安装后，请配置UHD的环境变量，PATH路径。配置完毕，打开CMD，运行下面的命令，以确保已经正确设置。

    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/ 下载最新版，直接安装。

直接安装后，请配置UHD的环境变量，PATH路径。配置完毕，打开CMD，运行下面的命令，以确保已经正确设置。

    C:\>echo %UHD_PKG_PATH% [回车]
    E:\PothosSDR

    C:\>PATH [回车]
    C:\WINDOWS\system32;C:\WINDOWS;\...;E:\PothosSDR\bin;...;

而后，使用脚本下载 uhd的FPGA固件。

    #假设Pothos SDR 安装在 E:\，则运行
    E:\> python PothosSDR\lib\uhd\utils\uhd_images_downloader.py -i E:\PothosSDR\share\uhd [回车]

运行后，会发现uhd文件夹下多了images文件夹。

#### 1.2.2 确认USRP设备运行正常

在命令行执行：

    C:\> uhd_usrp_probe [回车]

不报错，并显示设备的参数了，则说明安装基本正常。请注意上述命令返回状态中的警告 ，如网卡mtu、send_buffer_size等参数的配置警告。这些警告与正确编译taskBus无关，但与发挥设备最大的吞吐能力有关。为了保证稳定持续的吞吐，需要细致的参考以下几篇文章，解决X310万兆网、千兆网、USB等各种配置。

- https://files.ettus.com/manual/page_transport.html
- 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中，包含了boost 1.75的头文件。把该压缩包释放到libUHD或者PothosSD的include文件夹下，使得其看起来与uhd的头文件uhd.h平级。

    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文件夹，含有所有的可执行文件。这个文件夹应该类似：

    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/以便在出问题时查看依赖。

### 2.1 执行Qt发布

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

    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文件夹执行命令:

    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查找缺项。

    $ 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之外的文件，可以看到加载的结果。如果如下图所示，表示加载成功。

### 2.4 排查问题

如果发现缺少某个模块，请到命令行下，执行 模块名.exe —information,若能够输出json，则表示正常。否则，请对照出错提示，结合dependencywalker或者ldd查看依赖。
比如，对fft模块，执行:

    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 为例，这个文件夹的结构大致如下：

    ├─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中。其可能的内容如下：

    ../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

### 3.2 界面元素

双击bin/taskBusPlatform.exe 启动程序，主要界面元素如下：

#### 3.2.1 主工具栏按钮

各个按钮的意义如下：

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

#### 3.2.2 “编辑”工具栏按钮

各个按钮的意义如下：

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

### 3.3 主进程优先级

设置主进程的配置文件taskBusPlatform.exe.ini，可配置优先级。

    [settings]
    nice=2

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

## 4. 从范例工程开始

### 4.1 打开范例工程

点击“打开”按钮

图标 | 文字 | 作用 | 行为
--- | --- | --- | ---
| 打开工程 | 打开存在的工程 | 如果工程对应的某个模块没有预先加载，则打开工程后看不到对应的模块图标。

加载现有的工程。以 examples/soundcard.tbj为例，打开后，将看到如下界面：

### 4.2 配置范例工程

#### 4.2.1 配置优先级

可以试着使用按钮：

图标 | 文字 | 作用 | 快捷键 | 行为
--- | --- | --- | --- | ---
| 提高优先级 |  | 提高选中模块的进程优先级（nice）。 | 对实时性要求高的模块请使用高的优先级。在Linux下，优先级越高，数字越小。
| 降低优先级 |  | 降低选中模块的进程优先级（nice）。 | 对实时性要求高的模块请使用高的优先级。

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

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

#### 4.2.2 配置模块参数表

可以查看，并试着修改模块参数表。

- 双击彩色的“实例值”，进入编辑状态
- 修改相应的数值。所有被修改的值，都会以命令行的参数方式传给进程。

### 4.3 拖入模块

双击或者拖拽模块，以便引入新的模块。我们可以加入采样率变换模块 resample_pqfraction模块。而后，配置其属性。

### 4.4 修改连线

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

图标 | 文字 | 作用 | 快捷键 | 行为
--- | --- | --- | --- | ---
| 断开管脚 | Ctrl+‘d’ | 断开选中的管脚。 | 点击按钮后，被鼠标选中的管脚会被断开。

删除连线。

删除后，工程类似：
而后，分别单击下图中的管脚，完成连接，类似:

### 4.5 优化布局

通过拖动方块位置，并利用按钮

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

调整布局，调整后，布局如下：

### 4.6 运行工程

点击按钮

图标 | 文字 | 作用 | 行为
--- | --- | --- | ---
| 执行 | 执行工程 | 会依次启动各个进程，并吞吐stdio数据

运行工程，并尝试配置声音来源，可以看到实时语音或者音乐的频谱。