Full Code of JorgeMaker/SimpleFOCStudio for AI

main 6fe2896155bc cached
37 files
164.2 KB
38.9k tokens
276 symbols
1 requests
Download .txt
Repository: JorgeMaker/SimpleFOCStudio
Branch: main
Commit: 6fe2896155bc
Files: 37
Total size: 164.2 KB

Directory structure:
gitextract_ef7r4v5m/

├── .github/
│   └── workflows/
│       └── create_executables.yml
├── .gitignore
├── LICENSE
├── README.md
├── command_to_generate_spec.txt
├── device.json
├── requirements.txt
├── scriptTest.py
├── simpleFOCStudio.py
├── simpleFOCStudio.spec
└── src/
    ├── gui/
    │   ├── commandlinetool/
    │   │   ├── commandlinetool.py
    │   │   └── configureConnectionWidget.py
    │   ├── configtool/
    │   │   ├── configureConnectionDialog.py
    │   │   ├── connectionControl.py
    │   │   ├── controlLoopConfig.py
    │   │   ├── deviceConfigurationTool.py
    │   │   ├── deviceInteractionFrame.py
    │   │   ├── deviceJoggingControl.py
    │   │   ├── deviceTreeview.py
    │   │   ├── devicesInspectorTree.py
    │   │   ├── droDisplayWidget.py
    │   │   ├── generalControls.py
    │   │   ├── generalSettingsWidget.py
    │   │   ├── generatedCodeDisplay.py
    │   │   ├── graphicWidget.py
    │   │   ├── pidConfiguration.py
    │   │   ├── torqueConfig.py
    │   │   └── treeViewConfigTool.py
    │   ├── mainWindow.py
    │   ├── resources/
    │   │   ├── add_motor.psd
    │   │   ├── motor.psd
    │   │   └── studioicon.icns
    │   ├── sharedcomnponets/
    │   │   ├── commandLineInterface.py
    │   │   └── sharedcomponets.py
    │   ├── toolbar.py
    │   └── workAreaTabbedWidget.py
    └── simpleFOCConnector.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/create_executables.yml
================================================
name: Package Application with Pyinstaller

on:
  push:
    tags:
      - "v*.*.*"

jobs:

  build_windows:
    runs-on: windows-latest
    steps:
      - name: Create Executable
        uses: sayyid5416/pyinstaller@v1
        with:
          spec: 'simpleFOCStudio.spec'
          requirements: 'requirements.txt'
          python_ver: '3.9'
          python_arch: 'x64'
          exe_path: './dist/windows'

      - name: Rename file with details
        run: mv dist/windows/simpleFOCStudio.exe dist/windows/simpleFOCStudio-windows-x86_64-${{ github.ref_name }}.exe
      
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          files: |
            dist/windows/**

  build_linux:
    runs-on: ubuntu-latest
    steps:
      - name: Install pyqt5 dependencies
        run: sudo apt install -y qtbase5-dev
      - name: Create Executable
        uses: sayyid5416/pyinstaller@v1
        with:
          spec: 'simpleFOCStudio.spec'
          requirements: 'requirements.txt'
          python_ver: '3.9'
          python_arch: 'x64'
          exe_path: './dist/linux'

      - name: Rename file with details
        run: mv dist/linux/simpleFOCStudio dist/linux/simpleFOCStudio-linux-x86_64-${{ github.ref_name }}
      
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          files: |
            dist/linux/**


================================================
FILE: .gitignore
================================================
/venv
/.idea
**/*.log
**/__pycache__

build/
dist/

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 JorgeMaker

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
## *Simple**FOC**Studio*

Graphical user interface for the [*Simple**FOC**library*](https://github.com/simplefoc). This application allows to tune and configure any BLDC/Stepper *Simple**FOC**library* controlled device, using serial port communications and the [Commander](https://docs.simplefoc.com/commander_interface) interface.
#### The main features are:

- Plug and play with the *Simple**FOC**library* version 2.1
- Real-time tuning and configuration of the motors
- Real-time plotting and monitoring of motor variables
- Code generation for easier integration of the tuned parameters in your code
- Built on PyQt5 and a standardized `SimpleFOCConnector` interface that can be used as a gateway form python to the *Simple**FOC**library* device.

<p align="center">
  <img  src="./DOC/new_gif.gif">
</p>

### Installation
Don't worry, *Simple**FOC**Studio* is easy to install even if you have never used the terminal before! 😃
There are just couple of steps to take:
1. Install Python if you don't have it installed yet
    - We suggest to use Anaconda. [Here is how to install it.](https://docs.anaconda.com/anaconda/install/)
    - Once you have your Anaconda running open your terminal (on windows anaconda prompt) and run:
    ```sh
    conda create -n simplefoc python=3.9.0
    ```
    - Once this is done you will never have to run that command again, from now on you will just need:
    ```sh
    conda activate simplefoc
    ```
2. Clone this repository or download the zip file
3. Enter the folder containing the repository using the terminal
    -  the command will be something like this:
    ```sh
    cd  some_path_on_disk/SimpleFOCStudio
    ```
4. Final step of the installation is installing all the necessary libraries for the *Simple**FOC**Studio* :
    ```sh
    pip install -r "requirements.txt"
    ```

Once you have done all the steps above you do not need to repeat them any more. All you need to do the next time is open your terminal in the *Simple**FOC**Studio* directory and run the command:
```sh
python simpleFOCStudio.py
```
Or if using Anaconda:
```sh   
conda activate simplefoc
python simpleFOCStudio.py
```


### Usage
*Simple**FOC**Studio* has several useful features:
- A simple approach to tuning your motor setup
  - Form view for fast motion control PID/LPF tuning
  - TreeView for more in depth tunning and experimenting
- Code generation for transferring the found parameters into your arduino code
- Serial terminal integrated with various commander features
#### Motion control tunning windows


Once you have your application running add a device by clicking the  <img src="./src/gui/resources/add_motor.png" height="18"> motor button in the toolbar. You can choose either the <img src="./src/gui/resources/tree.png" height="18"> TreeView or the <img src="./src/gui/resources/form.png" height="18">FormView.
- To connect to your device first configure the serial port by clicking on <img src="./src/gui/resources/configure.png" height="18">Configure button
- Add your com port info and click OK
- Then add the device command ID that you've added to the commander usually its `M`
   - Command `M` , Arduino code : `command.add('M',doMotor,"my motor")`
   - Command `A` , Arduino code : `command.add('A',doMotor,"my motor")`
- Then click to the <img src="./src/gui/resources/connect.png" height="18">Connect button and you should be ready to go!

<p align="center">
  <img src="./DOC/treeview.png" width="400px">
  <img src="./DOC/formview.png" width="400px">
</p>

#### Code generation

*Simple**FOC**Studio* helps you to easier transfer your carefully tuned parameters to the Arduino code. Once you are happy with the performance of your system you can automatically generate the arduino code of the parameters you have tuned. To generate the code :
- Click on the <img src="./src/gui/resources/gen.png" height="18"> Arudino button in the toolbar.
- Choose which sets of parameters you wish to generate the code for and click OK
- In the new tab you will have a code of your tuned parameters.

The generated code you can just copy/paste in your <code>setup()</code> function, just before calling the <code>motor.init()</code>

<p align="center">
  <img src="./DOC/gen.gif" width="700px">
</p>

#### Custom Commands

You can create your own custom commands if you [extend the Commnader interface](https://docs.simplefoc.com/commander_interface) in your sketch. This can be used for example to do things like change register settings for SPI devicesor any oyher functionality. Each custom command has a name and a value as you can see at the below image.

<p align="center">
  <img src="./DOC/customCommands.png">
</p>
Once you have added each custom command in order to execute it you just need to select it and once selected press the space key (⎵) or right arrow key (→).

#### Jogging panel
<p align="center">
  <img src="./DOC/JoggingPanel.png">
</p>
This panel is used to actuate with yor motor without having to write comands, is like using a joystick but pressing buttons. Each buton performas an action:

- Fast Reverse button: reduces the current target by 2 times the specified increment.
- Reverse button: reduces the current target by the specified increment.
- Fordward button: Increase the current target by the specified increment.
- Fast Fordward button: Increase the current target by 2 times the specified increment.
- Stop button: in angle control mode, sets the current angle as target angle and in velocity control sets the target to zero.


#### Integrated serial terminal

*Simple**FOC**Studio* also has integrated serial terminal for easier debugging and monitoring.

<p align="center">
  <img src="./DOC/term.png" width="700px">
</p>

### Arduino code

Basically there are two things you need to do:
1. Use the commander interface and add the motor to the commander
2. Use the monitoring and add the `motor.monitor()` in the loop

Here is a mockup of the code:

```cpp
#include <SimpleFOC.h>

....

// include commander interface
Commander command = Commander(Serial);
void doMotor(char* cmd) { command.motor(&motor, cmd); }

void setup(){
  ....
  // add the motor to the commander interface
  // The letter (here 'M') you will provide to the SimpleFOCStudio
  command.add('M',doMotor,"motor");
  // tell the motor to use the monitoring
  motor.useMonitoring(Serial);
  motor.monitor_downsample = 0; // disable monitor at first - optional
  ...

}
void loop(){
  ....

  ....
  // real-time monitoring calls
  motor.monitor();
  // real-time commander calls
  command.run();
}
```


================================================
FILE: command_to_generate_spec.txt
================================================
pyi-makespec --onefile --noconsole --icon src/gui/resources/studioicon.icns --add-data src:src simpleFOCStudio.py


================================================
FILE: device.json
================================================
{
    "LPFAngle": 0.0,
    "LPFCurrentD": 0.005,
    "LPFCurrentQ": 0.005,
    "LPFVelocity": 0.2,
    "PIDAngle": {
        "D": 0.0,
        "I": 0.0,
        "P": 20.0,
        "outputLimit": 10.0,
        "outputRamp": 0.0
    },
    "PIDCurrentD": {
        "D": 0.0,
        "I": 300.0,
        "P": 3.0,
        "outputLimit": 12.0,
        "outputRamp": 0.0
    },
    "PIDCurrentQ": {
        "D": 0.0,
        "I": 300.0,
        "P": 3.0,
        "outputLimit": 12.0,
        "outputRamp": 0.0
    },
    "PIDVelocity": {
        "D": 0.0,
        "I": 20.0,
        "P": 0.2,
        "outputLimit": 11.0,
        "outputRamp": 1000.0
    },
    "connectionID": "",
    "controlType": 2,
    "currentLimit": 0.2,
    "customCommands": [
        {
            "commandName": "Command1",
            "commandValue": "D100"
        }
    ],
    "devCommandID": "M",
    "initialTarget": 0,
    "motionDownsample": 0.0,
    "phaseResistance": 0.0,
    "sensorElectricalZero": 2.676,
    "sensorZeroOffset": 0.0,
    "serialByteSize": 8,
    "serialParity": "N",
    "serialPortName": "/dev/cu.usbserial-14140",
    "serialRate": "115200",
    "stopBits": 1,
    "torqueType": 0,
    "velocityLimit": 10.0,
    "voltageLimit": 11.0
}

================================================
FILE: requirements.txt
================================================
# Requirements for SimpleFOCStudio
PyQt5==5.15.9
pyqtgraph==0.13.1
pyserial==3.5
numpy==1.24.0
# Requirements for Pyinstaller packaging process:
pyinstaller
Pillow

================================================
FILE: scriptTest.py
================================================
from src.simpleFOCConnector import SimpleFOCDevice
import time
if __name__ == '__main__':
    deviceConnector = SimpleFOCDevice.getInstance()
    deviceConnector.serialPortName = 'COM32'
    deviceConnector.serialRate = 115200
    deviceConnector.devCommandID = 'M'

    if deviceConnector.connect(SimpleFOCDevice.ONLY_CONNECT):
        while True:
            deviceConnector.sendControlType(SimpleFOCDevice.ANGLE_CONTROL)
            deviceConnector.sendTargetValue(0)
            time.sleep(2.0)
            deviceConnector.sendTargetValue(3)
            time.sleep(2)
            deviceConnector.sendTargetValue(6)
            time.sleep(2)
            deviceConnector.sendTargetValue(-6)
            time.sleep(2)
            deviceConnector.sendControlType(SimpleFOCDevice.VELOCITY_CONTROL)
            deviceConnector.sendTargetValue(30)
            time.sleep(2)
            deviceConnector.sendTargetValue(-30)
            time.sleep(2)


================================================
FILE: simpleFOCStudio.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" This module contains ans script to start the SimpleFOC ConfigTool, a GIU
    application ta monitor, tune and configure BLDC motor controllers based on
    SimpleFOC library.
"""
from PyQt5 import QtWidgets, QtCore
from src.gui.mainWindow import UserInteractionMainWindow
import sys
import logging

if __name__ == '__main__':
    try:
        QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) 
        QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
        logging.basicConfig(filename='.SimpleFOCConfigTool.log', filemode='w',
                         format='%(name)s - %(levelname)s - %(message)s')
        app = QtWidgets.QApplication(sys.argv)
        mainWindow = QtWidgets.QMainWindow()
        userInteractionMainWindow = UserInteractionMainWindow()
        userInteractionMainWindow.setupUi(mainWindow)
        mainWindow.show()
        sys.exit(app.exec_())
    except Exception as exception:\
    logging.error(exception, exc_info=True)


================================================
FILE: simpleFOCStudio.spec
================================================
# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
    ['simpleFOCStudio.py'],
    pathex=[],
    binaries=[],
    datas=[('src', 'src')],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='simpleFOCStudio',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=['src\\gui\\resources\\studioicon.icns'],
)


================================================
FILE: src/gui/commandlinetool/commandlinetool.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets

from src.gui.commandlinetool.configureConnectionWidget import \
    ConfigureConnection
from src.gui.sharedcomnponets.commandLineInterface import CommandLineWidget
from src.gui.sharedcomnponets.sharedcomponets import (WorkAreaTabWidget,
                                                      GUIToolKit)
from src.simpleFOCConnector import SimpleFOCDevice


class CommandLineConsoleTool(WorkAreaTabWidget):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.verticalLayout = QtWidgets.QVBoxLayout(self)
        self.verticalLayout.setObjectName('verticalLayout')

        self.configureConnection = ConfigureConnection()
        self.verticalLayout.addWidget(self.configureConnection)

        self.commandLineInterface = CommandLineWidget()
        self.verticalLayout.addWidget(self.commandLineInterface)

        self.device.commProvider.rawDataReceived.connect(self.commandLineInterface.publishCommandResponseData)

    def getTabIcon(self):
        return GUIToolKit.getIconByName('consoletool')

    def getTabName(self):
        return self.device.connectionID


================================================
FILE: src/gui/commandlinetool/configureConnectionWidget.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import serial
from PyQt5 import (QtGui, QtCore, QtWidgets)

from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit
from src.gui.sharedcomnponets.sharedcomponets import SerialPortComboBox
from src.simpleFOCConnector import SimpleFOCDevice


class ConfigureConnection(QtWidgets.QGroupBox):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.setTitle('Configure serial connection')
        self.setObjectName('configureConnection')

        self.configCoonLayout = QtWidgets.QHBoxLayout(self)
        self.configCoonLayout.setObjectName(
            'configureConnectionorizontalLayout')

        self.portNameLabel = QtWidgets.QLabel(self)
        self.portNameLabel.setObjectName('portNameLabel')
        self.configCoonLayout.addWidget(self.portNameLabel)

        self.portNameComboBox = SerialPortComboBox(self)
        self.portNameComboBox.setObjectName('portNameComboBox')
        self.portNameComboBox.setMinimumWidth(250)
        self.configCoonLayout.addWidget(self.portNameComboBox)

        self.bitRateLabel = QtWidgets.QLabel(self)
        self.bitRateLabel.setObjectName('bitRateLabel')
        self.configCoonLayout.addWidget(self.bitRateLabel)

        self.bitRatelineEdit = QtWidgets.QLineEdit(self)
        self.bitRatelineEdit.setObjectName('bitRatelineEdit')
        self.bitRatelineEdit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp("^[0-9]*$")))
        self.bitRatelineEdit.setText('115200')
        self.configCoonLayout.addWidget(self.bitRatelineEdit)

        self.parityLabel = QtWidgets.QLabel(self)
        self.parityLabel.setObjectName('parityLabel')
        self.configCoonLayout.addWidget(self.parityLabel)

        self.parityComboBox = QtWidgets.QComboBox(self)
        self.parityComboBox.setObjectName('parityComboBox')
        self.parityComboBox.addItems(serial.PARITY_NAMES.values())
        self.configCoonLayout.addWidget(self.parityComboBox)

        serial.PARITY_NAMES.values()

        self.byteSizeLabel = QtWidgets.QLabel(self)
        self.byteSizeLabel.setObjectName('byteSizeLabel')
        self.configCoonLayout.addWidget(self.byteSizeLabel)

        self.byteSizeComboBox = QtWidgets.QComboBox(self)
        self.byteSizeComboBox.setObjectName('byteSizeComboBox')
        byteSizeList = [str(serial.EIGHTBITS), str(serial.FIVEBITS),
                        str(serial.SIXBITS),
                        str(serial.SEVENBITS)]
        self.byteSizeComboBox.addItems(byteSizeList)
        self.configCoonLayout.addWidget(self.byteSizeComboBox)

        self.stopBitsLabel = QtWidgets.QLabel(self)
        self.stopBitsLabel.setObjectName('stopBitsLabel')
        self.configCoonLayout.addWidget(self.stopBitsLabel)

        self.stopBitsComboBox = QtWidgets.QComboBox(self)
        byteStopBitsList = [str(serial.STOPBITS_ONE),
                            str(serial.STOPBITS_ONE_POINT_FIVE),
                            str(serial.STOPBITS_TWO)]
        self.stopBitsComboBox.addItems(byteStopBitsList)
        self.stopBitsComboBox.setObjectName('stopBitsComboBox')
        self.configCoonLayout.addWidget(self.stopBitsComboBox)

        self.connectDisconnectButton = QtWidgets.QPushButton(self)
        self.connectDisconnectButton.setIcon(
            GUIToolKit.getIconByName('connect'))
        self.connectDisconnectButton.setObjectName('connectDeviceButton')
        self.connectDisconnectButton.setText('Connect')
        self.connectDisconnectButton.clicked.connect(
            self.connectDisconnectDeviceAction)

        self.configCoonLayout.addWidget(self.connectDisconnectButton)

        self.portNameLabel.setText('Port Name')
        self.bitRateLabel.setText('Bit rate')
        self.parityLabel.setText('Parity')
        self.byteSizeLabel.setText('Byte size')
        self.stopBitsLabel.setText('Stop bits')

        self.device.addConnectionStateListener(self)
        self.connectionStateChanged(self.device.isConnected)

    def getConfigValues(self):
        values = {
            'connectionID': '',
            'serialPortName': self.portNameComboBox.currentText(),
            'serialRate': self.bitRatelineEdit.text(),
            'stopBits': self.stopBitsExtractor(self.stopBitsComboBox.currentText()),
            'serialByteSize': int(str(self.byteSizeComboBox.currentText())),
            'serialParity':  list(serial.PARITY_NAMES.keys())[list(serial.PARITY_NAMES.values()).index(self.parityComboBox.currentText())][0]
        }
        return values

    def stopBitsExtractor(self, value):
        if value == '1.5':
            return float(self.stopBitsComboBox.currentText())
        else:
            return int(self.stopBitsComboBox.currentText())

    def connectionStateChanged(self, isConnectedFlag):
        if isConnectedFlag:
            self.connectDisconnectButton.setText('Disconnect')
            self.connectDisconnectButton.setIcon(
                GUIToolKit.getIconByName('disconnect'))
        else:
            self.connectDisconnectButton.setText('Connect')
            self.connectDisconnectButton.setIcon(
                GUIToolKit.getIconByName('connect'))

        self.portNameLabel.setEnabled(not isConnectedFlag)
        self.portNameComboBox.setEnabled(not isConnectedFlag)
        self.bitRateLabel.setEnabled(not isConnectedFlag)
        self.bitRatelineEdit.setEnabled(not isConnectedFlag)
        self.parityLabel.setEnabled(not isConnectedFlag)
        self.parityComboBox.setEnabled(not isConnectedFlag)
        self.byteSizeLabel.setEnabled(not isConnectedFlag)
        self.byteSizeComboBox.setEnabled(not isConnectedFlag)
        self.stopBitsLabel.setEnabled(not isConnectedFlag)
        self.stopBitsComboBox.setEnabled(not isConnectedFlag)

    def connectDisconnectDeviceAction(self):
        if self.device.isConnected:
            self.disConnectAction()
        else:
            self.connectAction()

    def connectAction(self):
        deviceConfig = self.getConfigValues()
        self.device.configureConnection(deviceConfig)
        self.device.connect(SimpleFOCDevice.ONLY_CONNECT)

    def disConnectAction(self):
        self.device.disConnect()

================================================
FILE: src/gui/configtool/configureConnectionDialog.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import serial
from PyQt5 import (QtCore, QtGui, QtWidgets)

from src.gui.sharedcomnponets.sharedcomponets import SerialPortComboBox
from src.simpleFOCConnector import SimpleFOCDevice


class ConfigureSerailConnectionDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setupUi(SimpleFOCDevice.getInstance())

    def setupUi(self, device=None):
        self.setObjectName('Dialog')
        self.resize(700, 188)

        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName('gridLayout')

        self.portNameLabel = QtWidgets.QLabel(self)
        self.portNameLabel.setObjectName('portNameLabel')
        self.gridLayout.addWidget(self.portNameLabel, 0, 0, 1, 1)

        self.portNameComboBox = SerialPortComboBox(self)
        self.portNameComboBox.setObjectName('portNameComboBox')
        self.portNameComboBox.setMinimumWidth(250)
        self.gridLayout.addWidget(self.portNameComboBox, 0, 1, 1, 1)

        self.bitRateLabel = QtWidgets.QLabel(self)
        self.bitRateLabel.setObjectName('bitRateLabel')
        self.gridLayout.addWidget(self.bitRateLabel, 0, 2, 1, 1)



        self.bitRatelineEdit = QtWidgets.QLineEdit(self)
        self.bitRatelineEdit.setObjectName('bitRatelineEdit')
        self.bitRatelineEdit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp("^[0-9]*$")))
        self.gridLayout.addWidget(self.bitRatelineEdit, 0, 3, 1, 1)

        self.parityLabel = QtWidgets.QLabel(self)
        self.parityLabel.setObjectName('parityLabel')
        self.gridLayout.addWidget(self.parityLabel, 1, 0, 1, 1)

        self.parityComboBox = QtWidgets.QComboBox(self)
        self.parityComboBox.setObjectName('parityComboBox')
        self.parityComboBox.addItems(serial.PARITY_NAMES.values())
        self.gridLayout.addWidget(self.parityComboBox, 1, 1, 1, 1)

        serial.PARITY_NAMES.values()

        self.byteSizeLabel = QtWidgets.QLabel(self)
        self.byteSizeLabel.setObjectName('byteSizeLabel')
        self.gridLayout.addWidget(self.byteSizeLabel, 1, 2, 1, 1)

        self.byteSizeComboBox = QtWidgets.QComboBox(self)
        self.byteSizeComboBox.setObjectName('byteSizeComboBox')
        byteSizeList = [str(serial.EIGHTBITS), str(serial.FIVEBITS), str(serial.SIXBITS),
                        str(serial.SEVENBITS)]
        self.byteSizeComboBox.addItems(byteSizeList)
        self.gridLayout.addWidget(self.byteSizeComboBox, 1, 3, 1, 1)

        self.stopBitsLabel = QtWidgets.QLabel(self)
        self.stopBitsLabel.setObjectName('stopBitsLabel')
        self.gridLayout.addWidget(self.stopBitsLabel, 2, 0, 1, 1)

        self.stopBitsComboBox = QtWidgets.QComboBox(self)
        byteStopBitsList = [str(serial.STOPBITS_ONE),
                            str(serial.STOPBITS_ONE_POINT_FIVE),
                            str(serial.STOPBITS_TWO)]
        self.stopBitsComboBox.addItems(byteStopBitsList)
        self.stopBitsComboBox.setObjectName('stopBitsComboBox')
        self.gridLayout.addWidget(self.stopBitsComboBox, 2, 1, 1, 1)

        self.connectionIDLabel = QtWidgets.QLabel(self)
        self.connectionIDLabel.setObjectName('connectionNameLabel')
        self.gridLayout.addWidget(self.connectionIDLabel, 2, 2, 1, 1)

        self.connectionIDlineEdit = QtWidgets.QLineEdit(self)
        self.connectionIDlineEdit.setMaxLength(10)
        self.connectionIDlineEdit.setObjectName('connectionNameEdit')
        self.gridLayout.addWidget(self.connectionIDlineEdit, 2, 3, 1, 1)

        self.buttonBox = QtWidgets.QDialogButtonBox(self)
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')

        self.gridLayout.addWidget(self.buttonBox, 3, 0, 1, 4)

        self.setWindowTitle('Configure serial connection')
        self.portNameLabel.setText('Port Name')
        self.bitRateLabel.setText('Bit rate')
        self.parityLabel.setText('Parity')
        self.byteSizeLabel.setText('Byte size')
        self.stopBitsLabel.setText('Stop bits')
        self.connectionIDLabel.setText('Conn ID')

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        QtCore.QMetaObject.connectSlotsByName(self)

        if device is not None:
            self.fillForm(device)

    def fillForm(self, deviceConnector):
        self.connectionIDlineEdit.setText(deviceConnector.connectionID)
        self.portNameComboBox.setCurrentText(deviceConnector.serialPortName)
        self.bitRatelineEdit.setText(str(deviceConnector.serialRate))
        self.stopBitsComboBox.setCurrentText(str(deviceConnector.stopBits))
        self.byteSizeComboBox.setCurrentText(str(deviceConnector.serialByteSize))
        self.parityComboBox.setCurrentText(str(deviceConnector.serialParity))

    def getConfigValues(self):
        values = {
            'connectionID': self.connectionIDlineEdit.text(),
            'serialPortName': self.portNameComboBox.currentText(),
            'serialRate': self.bitRatelineEdit.text(),
            'stopBits': self.stopBitsExtractor(self.stopBitsComboBox.currentText()),
            'serialByteSize': int(str(self.byteSizeComboBox.currentText())),
            'serialParity':  list(serial.PARITY_NAMES.keys())[list(serial.PARITY_NAMES.values()).index(self.parityComboBox.currentText())][0]
        }
        return values

    def stopBitsExtractor(self, value):
        if value == '1.5':
            return float(self.stopBitsComboBox.currentText())
        else:
            return int(self.stopBitsComboBox.currentText())

================================================
FILE: src/gui/configtool/connectionControl.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets

from src.gui.configtool.configureConnectionDialog import \
    ConfigureSerailConnectionDialog
from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit
from src.simpleFOCConnector import SimpleFOCDevice


class ConnectionControlGroupBox(QtWidgets.QGroupBox):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.setObjectName('connectionControl')
        self.setTitle('Connection control')

        self.horizontalLayout = QtWidgets.QHBoxLayout(self)
        self.horizontalLayout.setObjectName('generalControlHL')

        self.devCommandIDLabel = QtWidgets.QLabel("Command:")
        self.horizontalLayout.addWidget(self.devCommandIDLabel)

        self.devCommandIDLetter = QtWidgets.QLineEdit()
        self.devCommandIDLetter.setObjectName('devCommandIDLetter')
        self.devCommandIDLetter.editingFinished.connect(self.changeDevicedevCommandID)
        self.horizontalLayout.addWidget(self.devCommandIDLetter)
        self.devCommandIDLetter.setText(self.device.devCommandID)

        self.pullConfig = QtWidgets.QPushButton()
        self.pullConfig.setObjectName('pullConfig')
        self.pullConfig.setIcon(GUIToolKit.getIconByName('pull'))
        self.pullConfig.setText(' Pull Params')
        self.pullConfig.clicked.connect(self.device.pullConfiguration)
        
        self.horizontalLayout.addWidget(self.pullConfig)

        self.connectDisconnectButton = QtWidgets.QPushButton(self)
        self.connectDisconnectButton.setIcon(GUIToolKit.getIconByName('connect'))
        self.connectDisconnectButton.setObjectName('connectDeviceButton')
        self.connectDisconnectButton.setText('Connect')
        self.connectDisconnectButton.clicked.connect(self.connectDisconnectDeviceAction)

        self.horizontalLayout.addWidget(self.connectDisconnectButton)

        self.configureDeviceButton = QtWidgets.QPushButton(self)
        self.configureDeviceButton.setIcon(GUIToolKit.getIconByName('configure'))
        self.configureDeviceButton.setObjectName('configureDeviceButton')
        self.configureDeviceButton.setText('Configure')
        self.configureDeviceButton.clicked.connect(self.configureDeviceAction)
        self.horizontalLayout.addWidget(self.configureDeviceButton)

        self.device.addConnectionStateListener(self)
        self.connectionStateChanged(self.device.isConnected)
    
    def changeDevicedevCommandID(self):
        self.device.devCommandID = self.devCommandIDLetter.text()

    def connectDisconnectDeviceAction(self):
        if self.device.isConnected:
            self.device.disConnect()
        else:
            connectionMode  = SimpleFOCDevice.PULL_CONFIG_ON_CONNECT
            self.device.connect(connectionMode)

    def connectionStateChanged(self, isConnected):
        if isConnected:
            self.connectDisconnectButton.setIcon(
                GUIToolKit.getIconByName('disconnect'))
            self.connectDisconnectButton.setText('Disconnect')
        else:
            self.connectDisconnectButton.setIcon(
                GUIToolKit.getIconByName('connect'))
            self.connectDisconnectButton.setText('Connect')

    def configureDeviceAction(self):
        dialog = ConfigureSerailConnectionDialog()
        result = dialog.exec_()
        if result:
            deviceConfig = dialog.getConfigValues()
            self.device.configureConnection(deviceConfig)


================================================
FILE: src/gui/configtool/controlLoopConfig.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets

from src.simpleFOCConnector import SimpleFOCDevice


class ControlLoopGroupBox(QtWidgets.QGroupBox):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.setObjectName('controlLoop')
        self.setTitle('Control Loop Mode')

        self.controlLoopHorizontalLayout = QtWidgets.QHBoxLayout(self)
        self.controlLoopHorizontalLayout.setObjectName('controlLoopHorizontalLayout')

        
        self.selectorControlLoop = QtWidgets.QComboBox(self)
        self.selectorControlLoop.setObjectName('selectorControlLoop')
        self.selectorControlLoop.addItems(['Torque', 'Velocity', 'Angle', 'Velocity openloop', 'Angle openloop'])
        self.selectorControlLoop.currentIndexChanged.connect(self.changeControlLoop)
        self.controlLoopHorizontalLayout.addWidget(self.selectorControlLoop)

        self.setControlLopMode(self.device.controlType)

        self.disableUI()
        self.device.addConnectionStateListener(self)
        self.device.commProvider.commandDataReceived.connect(
            self.commandResponseReceived)

        self.connectionStateChanged(self.device.isConnected)

    def connectionStateChanged(self, deviceConnected):
        if deviceConnected is True:
            self.enabeUI()
        else:
            self.disableUI()

    def enabeUI(self):
        self.setEnabled(True)

    def disableUI(self):
        self.setEnabled(False)

    def setControlLopMode(self, value):
        if value == SimpleFOCDevice.TORQUE_CONTROL:
            self.selectorControlLoop.setCurrentIndex(0)
        elif value == SimpleFOCDevice.VELOCITY_CONTROL:
            self.selectorControlLoop.setCurrentIndex(1)
        elif value == SimpleFOCDevice.ANGLE_CONTROL:
            self.selectorControlLoop.setCurrentIndex(2)
        elif value == SimpleFOCDevice.VELOCITY_OPENLOOP_CONTROL:
            self.selectorControlLoop.setCurrentIndex(3)
        elif value == SimpleFOCDevice.ANGLE_OPENLOOP_CONTROL:
            self.selectorControlLoop.setCurrentIndex(4)

    def changeControlLoop(self):
        index = self.selectorControlLoop.currentIndex()
        if index == 0:
            self.device.sendControlType(SimpleFOCDevice.TORQUE_CONTROL)
        elif index == 1:
            self.device.sendControlType(SimpleFOCDevice.VELOCITY_CONTROL)
        elif index == 2:
            self.device.sendControlType(SimpleFOCDevice.ANGLE_CONTROL)
        elif index == 3:
            self.device.sendControlType(SimpleFOCDevice.VELOCITY_OPENLOOP_CONTROL)
        elif index == 4:
            self.device.sendControlType(SimpleFOCDevice.ANGLE_OPENLOOP_CONTROL)

    def commandResponseReceived(self, cmdRespose):
        self.setControlLopMode(self.device.controlType)

================================================
FILE: src/gui/configtool/deviceConfigurationTool.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets

from src.gui.configtool.connectionControl import ConnectionControlGroupBox
from src.gui.configtool.controlLoopConfig import ControlLoopGroupBox
from src.gui.configtool.deviceJoggingControl import DeviceJoggingControl
from src.gui.configtool.droDisplayWidget import DROGroupBox
from src.gui.configtool.generalControls import GeneralControls
from src.gui.configtool.generalSettingsWidget import GeneralSettingsGroupBox
from src.gui.configtool.graphicWidget import SimpleFOCGraphicWidget
from src.gui.configtool.pidConfiguration import PidGroupBox
from src.gui.configtool.torqueConfig import TorqueGroupBox
from src.gui.sharedcomnponets.commandLineInterface import CommandLineWidget
from src.gui.sharedcomnponets.sharedcomponets import (WorkAreaTabWidget,
                                                      GUIToolKit)
from src.simpleFOCConnector import SimpleFOCDevice


class DeviceConfigurationTool(WorkAreaTabWidget):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.setObjectName('DeviceConfigurationTool')

        self.verticalLayout = QtWidgets.QVBoxLayout(self)
        self.verticalLayout.setObjectName('verticalLayout')

        self.counterWidget = QtWidgets.QWidget(self)
        self.counterWidget.setObjectName('counterWidget')
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.counterWidget)
        self.horizontalLayout.setObjectName('horizontalLayout')
        self.digitalReadOut = DROGroupBox(self.counterWidget)
        self.horizontalLayout.addWidget(self.digitalReadOut)
        
        self.controlLoop = ControlLoopGroupBox(self.counterWidget)
        self.horizontalLayout.addWidget(self.controlLoop)

        self.torqueConfig = TorqueGroupBox(self.counterWidget)
        self.horizontalLayout.addWidget(self.torqueConfig)

        self.connectionControl = ConnectionControlGroupBox(self.counterWidget)
        self.horizontalLayout.addWidget(self.connectionControl)
        self.verticalLayout.addWidget(self.counterWidget)

        self.graphicWidget = SimpleFOCGraphicWidget()
        self.verticalLayout.addWidget(self.graphicWidget)

        self.bottomWidget = QtWidgets.QWidget(self)
        self.bottomWidget.setObjectName('bottomWidget')

        self.bottomHorizontalLayout = QtWidgets.QHBoxLayout(self.bottomWidget)
        self.bottomHorizontalLayout.setObjectName('configureHorizontalLayout')

        self.pidConfigurator = PidGroupBox(self.bottomWidget)
        self.bottomHorizontalLayout.addWidget(self.pidConfigurator)

        self.generalLayout = QtWidgets.QVBoxLayout()
        self.generalDeviceSettings = GeneralSettingsGroupBox(self.bottomWidget)

        self.generalControls = GeneralControls(self.bottomWidget)
        self.generalLayout.addWidget(self.generalControls)
        self.generalLayout.addWidget(self.generalDeviceSettings)
        self.bottomHorizontalLayout.addLayout(self.generalLayout)

        self.lasWidget = QtWidgets.QWidget(self)
        self.lastVerticalLayout = QtWidgets.QVBoxLayout(self.lasWidget)

        self.commandLine = CommandLineWidget(self)
        self.lastVerticalLayout.addWidget(self.commandLine)

        self.joggingControl = DeviceJoggingControl(self)
        self.lastVerticalLayout.addWidget(self.joggingControl)

        self.bottomHorizontalLayout.addWidget(self.lasWidget)
        self.verticalLayout.addWidget(self.bottomWidget)

        self.device.commProvider.commandDataReceived.connect(self.commandLine.publishCommandResponseData)

    def getTabIcon(self):
        return GUIToolKit.getIconByName('motor')

    def getTabName(self):
        return self.device.connectionID

    def configureConnection(self, configvalues):
        self.device.serialPortName = configvalues['serialPortName']
        self.device.serialRate = configvalues['serialRate']
        self.device.stopBits = configvalues['stopBits']
        self.device.serialByteSize = configvalues['serialByteSize']
        self.device.serialParity = configvalues['serialParity']


================================================
FILE: src/gui/configtool/deviceInteractionFrame.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QVBoxLayout, QFrame, QSplitter)

from src.gui.configtool.graphicWidget import SimpleFOCGraphicWidget
from src.gui.sharedcomnponets.commandLineInterface import CommandLineWidget
from src.simpleFOCConnector import SimpleFOCDevice


class DeviceInteractionFrame(QFrame):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.layout = QVBoxLayout(self)
        self.setLayout(self.layout)
        self.device = SimpleFOCDevice.getInstance()

        self.graphicWidget = SimpleFOCGraphicWidget(self)
        self.cmdLineTollWidget = CommandLineWidget(self)

        self.cmdLineTollWidget.setMaximumHeight(150)

        self.verticalSplitter = QSplitter(Qt.Vertical)
        self.verticalSplitter.addWidget(self.graphicWidget)
        self.verticalSplitter.addWidget(self.cmdLineTollWidget)
        self.device.commProvider.commandDataReceived.connect(
            self.cmdLineTollWidget.publishCommandResponseData)
        self.layout.addWidget(self.verticalSplitter)

        self.setLayout(self.layout)


================================================
FILE: src/gui/configtool/deviceJoggingControl.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PyQt5 import (QtGui, QtWidgets, QtCore)

from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit
from src.simpleFOCConnector import SimpleFOCDevice


class DeviceJoggingControl(QtWidgets.QGroupBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.device = SimpleFOCDevice.getInstance()

        self.setObjectName('joggingControl')
        self.setTitle('Jogging control')

        self.horizontalLayout = QtWidgets.QHBoxLayout(self)
        self.horizontalLayout.setObjectName('generalControlHL')

        self.fastFordwardButton = QtWidgets.QPushButton()
        self.fastFordwardButton.setObjectName('fastbackward')
        self.fastFordwardButton.setIcon(GUIToolKit.getIconByName('fastbackward'))
        self.fastFordwardButton.clicked.connect(self.joggingFastBackward)
        self.horizontalLayout.addWidget(self.fastFordwardButton)

        self.backwardButton = QtWidgets.QPushButton()
        self.backwardButton.setObjectName('backward')
        self.backwardButton.setIcon(GUIToolKit.getIconByName('backward'))
        self.backwardButton.clicked.connect(self.joggingBackward)
        self.horizontalLayout.addWidget(self.backwardButton)

        self.stopButton = QtWidgets.QPushButton()
        self.stopButton.setObjectName('stopbutton')
        self.stopButton.setIcon(GUIToolKit.getIconByName('stopjogging'))
        self.stopButton.clicked.connect(self.joggingStop)
        self.horizontalLayout.addWidget(self.stopButton)

        self.fordwardButton = QtWidgets.QPushButton()
        self.fordwardButton.setObjectName('fordward')
        self.fordwardButton.setIcon(GUIToolKit.getIconByName('fordward'))
        self.fordwardButton.clicked.connect(self.joggingFordward)
        self.horizontalLayout.addWidget(self.fordwardButton)

        self.fastBackwardButton = QtWidgets.QPushButton()
        self.fastBackwardButton.setObjectName('fastfordward')
        self.fastBackwardButton.setIcon(GUIToolKit.getIconByName('fastfordward'))
        self.fastBackwardButton.clicked.connect(self.joggingfastFordward)
        self.horizontalLayout.addWidget(self.fastBackwardButton)

        self.incrementLabel = QtWidgets.QLabel("Increment:")
        self.horizontalLayout.addWidget(self.incrementLabel)

        onlyFloat = QtGui.QRegExpValidator(
            QtCore.QRegExp("[+-]?([0-9]*[.])?[0-9]+"))
        self.incrementEdit = QtWidgets.QLineEdit()
        self.incrementEdit.setValidator(onlyFloat)
        self.incrementEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.incrementEdit.setText('1.0')
        self.incrementEdit.setObjectName('incrementEdit')
        self.horizontalLayout.addWidget(self.incrementEdit)

        self.disableUI()
        self.device.addConnectionStateListener(self)

    def connectionStateChanged(self, isConnectedFlag):
        if isConnectedFlag is True:
            self.enabeUI()
        else:
            self.disableUI()
    def enabeUI(self):
        self.setEnabled(True)

    def disableUI(self):
        self.setEnabled(False)

    def joggingFastBackward(self):
        currenttarget = self.device.targetNow
        increment = self.incrementEdit.text()
        newTarget = float(currenttarget) - 2 * float(increment)
        self.device.sendTargetValue(str(newTarget))
    def joggingBackward(self):
        increment = self.incrementEdit.text()
        currenttarget = self.device.targetNow
        newTarget = float(currenttarget) - float(increment)
        self.device.sendTargetValue(str(newTarget))
    def joggingStop(self):
        controltType = self.device.controlType
        if (controltType == SimpleFOCDevice.ANGLE_CONTROL or
                controltType == SimpleFOCDevice.ANGLE_OPENLOOP_CONTROL):
            self.device.sendTargetValue(self.device.angleNow)
        if (controltType == SimpleFOCDevice.VELOCITY_CONTROL or
                controltType == SimpleFOCDevice.VELOCITY_OPENLOOP_CONTROL):
            self.device.sendTargetValue('0')
    def joggingFordward(self):
        increment = self.incrementEdit.text()
        currenttarget = self.device.targetNow
        newTarget = float(currenttarget) + float(increment)
        self.device.sendTargetValue(str(newTarget))
    def joggingfastFordward(self):
        increment = self.incrementEdit.text()
        currenttarget = self.device.targetNow
        newTarget = float(currenttarget) + 2 * float(increment)
        self.device.sendTargetValue(str(newTarget))

================================================
FILE: src/gui/configtool/deviceTreeview.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import (QtWidgets,QtCore)
from PyQt5.Qt import QTreeWidget
from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit
from src.simpleFOCConnector import SimpleFOCDevice
from src.simpleFOCConnector import Command

class DeviceTreeView(QTreeWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.sFOCDevice = QtWidgets.QTreeWidgetItem(self)
        self.sFOCDevice.setText(0, 'sFOC Device')
        self.sFOCDevice.setIcon(0, GUIToolKit.getIconByName('motor'))

        self.setColumnCount(2)

        self.motionControl = QtWidgets.QTreeWidgetItem(self.sFOCDevice)
        self.motionControl.setText(0, 'Motion config')
        self.motionControl.setIcon(0, GUIToolKit.getIconByName('pidconfig'))
        self.sFOCDevice.addChild(self.motionControl)
        
        self.controller = QtWidgets.QTreeWidgetItem(self.motionControl)
        self.controller.setText(0, 'Motion Control Type')
        self.controller.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.selectorControlLoop = QtWidgets.QComboBox(self)
        self.selectorControlLoop.addItems(['Torque', 'Velocity', 'Angle', 'Velocity openloop', 'Angle openloop'])
        self.selectorControlLoop.currentIndexChanged.connect(self.changeControlLoop)
        self.setItemWidget(self.controller,1,self.selectorControlLoop)

        self.torque = QtWidgets.QTreeWidgetItem(self.motionControl)
        self.torque.setText(0, 'Torque Control Type')
        self.torque.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.selectorTorque = QtWidgets.QComboBox(self)
        self.selectorTorque.addItems(['Voltage', 'DC Curret', 'FOC Current'])
        self.selectorTorque.currentIndexChanged.connect(self.changeTorque)
        self.setItemWidget(self.torque,1,self.selectorTorque)
        
        self.motionDownsample = QtWidgets.QTreeWidgetItem(self.motionControl)
        self.motionDownsample.setText(0, 'Motion Downsample')
        self.motionDownsample.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.motionDownsample.setText(1, '')
        self.motionDownsample.setFlags(
            self.motionDownsample.flags() | QtCore.Qt.ItemIsEditable)
        
        self.PIDVelocityConfig = self.addPIDSubtree(self.motionControl,'Velocity PID')
        self.PIDAngleConfig = self.addPIDSubtree(self.motionControl,'Angle PID')
        self.PIDCurrentQConfig = self.addPIDSubtree(self.motionControl,'Current q PID')
        self.PIDCurrentDConfig = self.addPIDSubtree(self.motionControl,'Current d PID')

        self.limitsConfig = QtWidgets.QTreeWidgetItem(self.sFOCDevice)
        self.limitsConfig.setText(0, 'Limits')
        self.limitsConfig.setIcon(0, GUIToolKit.getIconByName('statistics'))
        self.sFOCDevice.addChild(self.limitsConfig)

        self.velocityLimit = QtWidgets.QTreeWidgetItem(self.limitsConfig)
        self.velocityLimit.setText(0, 'Velocity limit')
        self.velocityLimit.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.velocityLimit.setText(1, '')
        self.velocityLimit.setFlags(
            self.velocityLimit.flags() | QtCore.Qt.ItemIsEditable)

        self.voltageLimit = QtWidgets.QTreeWidgetItem(self.limitsConfig)
        self.voltageLimit.setText(0, 'Voltage limit')
        self.voltageLimit.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.voltageLimit.setText(1, '')
        self.voltageLimit.setFlags(
            self.voltageLimit.flags() | QtCore.Qt.ItemIsEditable)

        self.currentLimit = QtWidgets.QTreeWidgetItem(self.limitsConfig)
        self.currentLimit.setText(0, 'Current limit')
        self.currentLimit.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.currentLimit.setText(1, '')
        self.currentLimit.setFlags(
            self.currentLimit.flags() | QtCore.Qt.ItemIsEditable)

        self.statesConfig = QtWidgets.QTreeWidgetItem(self.sFOCDevice)
        self.statesConfig.setText(0, 'States')
        self.statesConfig.setIcon(0, GUIToolKit.getIconByName('statistics'))
        self.sFOCDevice.addChild(self.statesConfig)

        self.satateTarget = QtWidgets.QTreeWidgetItem(self.statesConfig)
        self.satateTarget.setText(0, 'Target')
        self.satateTarget.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.satateTarget.setText(1, '')

        self.stateVq = QtWidgets.QTreeWidgetItem(self.statesConfig)
        self.stateVq.setText(0, 'Voltage q')
        self.stateVq.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.stateVd = QtWidgets.QTreeWidgetItem(self.statesConfig)
        self.stateVd.setText(0, 'Voltage d')
        self.stateVd.setIcon(0, GUIToolKit.getIconByName('gear'))

        self.stateCq = QtWidgets.QTreeWidgetItem(self.statesConfig)
        self.stateCq.setText(0, 'Current q')
        self.stateCq.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.stateCd = QtWidgets.QTreeWidgetItem(self.statesConfig)
        self.stateCd.setText(0, 'Current d')
        self.stateCd.setIcon(0, GUIToolKit.getIconByName('gear'))

        self.stateVel = QtWidgets.QTreeWidgetItem(self.statesConfig)
        self.stateVel.setText(0, 'Velocity')
        self.stateVel.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.stateVel.setText(1, '')

        self.stateAngle = QtWidgets.QTreeWidgetItem(self.statesConfig)
        self.stateAngle.setText(0, 'Angle')
        self.stateAngle.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.stateAngle.setText(1, '')

        self.sensorConfig = QtWidgets.QTreeWidgetItem(self.sFOCDevice)
        self.sensorConfig.setText(0, 'Sensor config')
        self.sensorConfig.setIcon(0, GUIToolKit.getIconByName('sensor'))
        self.sFOCDevice.addChild(self.sensorConfig)

        self.sensorZeroOffset = QtWidgets.QTreeWidgetItem(self.sensorConfig)
        self.sensorZeroOffset.setText(0, 'Zero Angle Offset')
        self.sensorZeroOffset.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.sensorZeroOffset.setText(1, '')
        self.sensorZeroOffset.setFlags(
            self.sensorZeroOffset.flags() | QtCore.Qt.ItemIsEditable)

        self.sensorZeroElecOffset = QtWidgets.QTreeWidgetItem(self.sensorConfig)
        self.sensorZeroElecOffset.setText(0, 'Electrical Zero Offset')
        self.sensorZeroElecOffset.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.sensorZeroElecOffset.setText(1, '')
        self.sensorZeroElecOffset.setFlags(
            self.sensorZeroElecOffset.flags() | QtCore.Qt.ItemIsEditable)

        self.generalSettings = QtWidgets.QTreeWidgetItem(self.sFOCDevice)
        self.generalSettings.setText(0, 'General settings')
        self.generalSettings.setIcon(0, GUIToolKit.getIconByName('generalsettings'))
        self.sFOCDevice.addChild(self.generalSettings)

        self.phaseRes = QtWidgets.QTreeWidgetItem(self.generalSettings)
        self.phaseRes.setText(0, 'Phase Resistance')
        self.phaseRes.setIcon(0, GUIToolKit.getIconByName('res'))
        self.phaseRes.setText(1, '')
        self.phaseRes.setFlags(
            self.phaseRes.flags() | QtCore.Qt.ItemIsEditable)

        self.deviceStatus = QtWidgets.QTreeWidgetItem(self.generalSettings)
        self.deviceStatus.setText(0, 'Motor Status')
        self.deviceStatus.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.selectStatus = QtWidgets.QComboBox(self)
        self.selectStatus.addItems(['Disabled', 'Enabled'])
        self.selectStatus.currentIndexChanged.connect(self.changeStatus)
        self.setItemWidget(self.deviceStatus,1,self.selectStatus)

        self.modulationType = QtWidgets.QTreeWidgetItem(self.generalSettings)
        self.modulationType.setText(0, 'PWM modulation')
        self.modulationType.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.selectModulation = QtWidgets.QComboBox(self)
        self.selectModulation.addItems(['Sine PWM', 'Space Vector PWM', 'Trapezoidal 120', 'Trapezoidal 150'])
        self.selectModulation.currentIndexChanged.connect(self.changeModType)
        self.setItemWidget(self.modulationType,1,self.selectModulation)

        self.modulationCenter = QtWidgets.QTreeWidgetItem(self.generalSettings)
        self.modulationCenter.setText(0, 'Modulation center')
        self.modulationCenter.setIcon(0, GUIToolKit.getIconByName('gear'))
        self.selectModCenter = QtWidgets.QComboBox(self)
        self.selectModCenter.addItems(['Disabled', 'Enabled'])
        self.selectModCenter.currentIndexChanged.connect(self.changeModCenter)
        self.setItemWidget(self.modulationCenter,1,self.selectModCenter)

        self.customComands = QtWidgets.QTreeWidgetItem(self.sFOCDevice)
        self.customComands.setText(0, 'Custom commands')
        self.customComands.setIcon(0, GUIToolKit.getIconByName('customcommands'))
        self.sFOCDevice.addChild(self.customComands)

        for customCommand in self.device.customCommands.customCommandsList:
            self.initCustomCommand(customCommand)

        self.installEventFilter(self)
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.customCommandsMenu)

        self.header().resizeSection(0,230)

        self.setAlternatingRowColors(True)
        self.header().hide()
        self.expandItem(self.sFOCDevice)
        self.expandItem(self.motionControl)

        self.device.addConnectionStateListener(self)
        self.device.commProvider.commandDataReceived.connect(self.commandResponseReceived)
        self.device.commProvider.stateMonitorReceived.connect(self.stateResponseReceived)

        self.itemChanged.connect(self.treeItemEdited)

        self.setEnabled(self.device.isConnected)

    def customCommandsMenu(self, position):
        indexes = self.selectedIndexes()
        if len(indexes) > 0:
            level = 0
            index = indexes[0]
            while index.parent().isValid():
                index = index.parent()
                level += 1
        selectedItem = self.selectedItems()[0]
        menu = QtWidgets.QMenu()
        if selectedItem.text(0) == 'Custom commands':
            addComand = QtWidgets.QAction("Add command", self)
            addComand.triggered.connect(self.addCommandAction)
            menu.addAction(addComand)
        elif hasattr(selectedItem, 'isCustomCommand'):
            executeCommand = QtWidgets.QAction("Execute", self)
            executeCommand.triggered.connect(self.executeCustomCommandAction)
            menu.addAction(executeCommand)
            deleteCommand = QtWidgets.QAction("Remove", self)
            deleteCommand.triggered.connect(self.deleteCustomCommand)
            menu.addAction(deleteCommand)

        menu.exec_(self.viewport().mapToGlobal(position))

    def addCommandAction(self):
        selectedItem = self.selectedItems()[0]
        self.addCustomCommand(selectedItem)

    def executeCustomCommandAction(self):
        selectedItem = self.selectedItems()[0]
        selectedCustomCommand = selectedItem.text(1)
        self.device.sendCommand(selectedCustomCommand)

    def deleteCustomCommand(self):
        root = self.invisibleRootItem()
        deletedIndex = self.customComands.indexOfChild(self.selectedItems()[0])
        self.device.customCommands.customCommandsList.pop(deletedIndex)
        for item in self.selectedItems():
            (item.parent() or root).removeChild(item)

    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.KeyPress:
            if event.key() == QtCore.Qt.Key_Return:
                selectedItem = self.selectedItems()[0]
                if selectedItem.text(0) == 'Custom commands':
                    self.addCustomCommand(selectedItem)
            if event.key() == QtCore.Qt.Key_Space or event.key() == QtCore.Qt.Key_Right:
                selectedItem = self.selectedItems()[0]
                if selectedItem.parent().text(0) == 'Custom commands':
                    self.executeCustomCommandAction()
            if event.key() == QtCore.Qt.Key_Delete or event.key() == QtCore.Qt.Key_Backspace:
                selectedItem = self.selectedItems()[0]
                if selectedItem.parent().text(0) == 'Custom commands':
                    self.deleteCustomCommand()
        return super(DeviceTreeView, self).eventFilter(obj, event)

    def addCustomCommand(sefl,selectedItem):
        customCommand = QtWidgets.QTreeWidgetItem()
        customCommand.isCustomCommand = True
        customCommand.setText(0, 'Command')
        customCommand.setIcon(0, GUIToolKit.getIconByName('gear'))

        customCommand.setFlags(
            customCommand.flags() | QtCore.Qt.ItemIsEditable)
        selectedItem.addChild(customCommand)
        sefl.device.customCommands.customCommandsList.append(Command('Command',''))

    def initCustomCommand(sefl, command):
        customCommand = QtWidgets.QTreeWidgetItem()
        customCommand.isCustomCommand = True
        customCommand.setText(0, command.cmdName)
        customCommand.setText(1, command.cmd)
        customCommand.setIcon(0, GUIToolKit.getIconByName('gear'))
        customCommand.setFlags(
            customCommand.flags() | QtCore.Qt.ItemIsEditable)
        sefl.customComands.addChild(customCommand)

    def addPIDSubtree(self, parent,  label):
        pidConfiguration = QtWidgets.QTreeWidgetItem()
        pidConfiguration.setText(0, label)
        pidConfiguration.setIcon(0, GUIToolKit.getIconByName('pidconfig'))
        parent.addChild(pidConfiguration)

        proportionalGain = QtWidgets.QTreeWidgetItem(pidConfiguration)
        proportionalGain.setText(0, 'Proportional gain')
        proportionalGain.setIcon(0, GUIToolKit.getIconByName('gear'))
        proportionalGain.setText(1, '')
        proportionalGain.setFlags(
            proportionalGain.flags() | QtCore.Qt.ItemIsEditable)

        integralGain = QtWidgets.QTreeWidgetItem(pidConfiguration)
        integralGain.setText(0, 'Integral gain')
        integralGain.setIcon(0, GUIToolKit.getIconByName('gear'))
        integralGain.setText(1, '')
        integralGain.setFlags(
            integralGain.flags() | QtCore.Qt.ItemIsEditable)

        derivativeGain = QtWidgets.QTreeWidgetItem(pidConfiguration)
        derivativeGain.setText(0, 'Derivative gain')
        derivativeGain.setIcon(0, GUIToolKit.getIconByName('gear'))
        derivativeGain.setText(1, '')
        derivativeGain.setFlags(
            derivativeGain.flags() | QtCore.Qt.ItemIsEditable)

        voltageRamp = QtWidgets.QTreeWidgetItem(pidConfiguration)
        voltageRamp.setText(0, 'Output Ramp')
        voltageRamp.setIcon(0, GUIToolKit.getIconByName('gear'))
        voltageRamp.setText(1, '')
        voltageRamp.setFlags(
            voltageRamp.flags() | QtCore.Qt.ItemIsEditable)
        
        limit = QtWidgets.QTreeWidgetItem(pidConfiguration)
        limit.setText(0, 'Output Limit')
        limit.setIcon(0, GUIToolKit.getIconByName('gear'))
        limit.setText(1, '')
        limit.setFlags(
            limit.flags() | QtCore.Qt.ItemIsEditable)

        lpfTf = QtWidgets.QTreeWidgetItem(pidConfiguration)
        lpfTf.setText(0, 'Low pass filter')
        lpfTf.setIcon(0, GUIToolKit.getIconByName('gear'))
        lpfTf.setText(1, '')
        lpfTf.setFlags(
            lpfTf.flags() | QtCore.Qt.ItemIsEditable)

        return pidConfiguration

    def treeItemEdited(self, item, column):
        if item.parent().text(0) == 'Custom commands':
            updatedIndex = self.customComands.indexOfChild(item)
            updatedValue = item.text(column)
            if column == 0:
                self.device.customCommands.customCommandsList[
                    updatedIndex].cmdName = updatedValue
            else:
                self.device.customCommands.customCommandsList[
                    updatedIndex].cmd = updatedValue
        else:
            self.sendCommand(item, column)

    def sendCommand(self, item, column):
        value = item.text(1)
        fieldName = item.text(0)
        pidLabel = item.parent().text(0)
        pid = {}
        lpf = {}
        if 'Velocity PID' in pidLabel:
            pid = self.device.PIDVelocity
            lpf = self.device.LPFVelocity
        elif 'Angle PID' in pidLabel:
            pid = self.device.PIDAngle
            lpf = self.device.LPFAngle
        elif 'Current q PID' in pidLabel:
            pid = self.device.PIDCurrentQ
            lpf = self.device.LPFCurrentQ
        elif 'Current d PID' in pidLabel:
            pid = self.device.PIDCurrentD
            lpf = self.device.LPFCurrentD

        if 'Proportional gain' in fieldName:
            self.device.sendProportionalGain(pid, value)
        elif 'Integral gain' in fieldName:
            self.device.sendIntegralGain(pid, value)
        elif 'Derivative gain' in fieldName:
            self.device.sendDerivativeGain(pid, value)
        elif 'Output Ramp' in fieldName:
            self.device.sendOutputRamp(pid, value)
        elif 'Low pass filter' in fieldName:
            self.device.sendLowPassFilter(lpf, value)
        elif 'Output Limit' in fieldName:
            self.device.sendOutputLimit(pid,value)
        elif 'Voltage limit' in fieldName:
            self.device.sendVoltageLimit(value)
        elif 'Velocity limit' in fieldName:
            self.device.sendVelocityLimit(value)
        elif 'Current limit' in fieldName:
            self.device.sendCurrentLimit(value)
        elif 'Phase Resistance' in fieldName:
            self.device.sendPhaseResistance(value)
        elif 'Zero Angle Offset' in fieldName:
            self.device.sendSensorZeroOffset(value)
        elif 'Electrical Zero Offset' in fieldName:
            self.device.sendSensorZeroElectrical(value)
        elif 'Motion Downsample' in fieldName:
            self.device.sendMotionDownsample(value)

    def refreshPIDSubtree(self, pidDisp, pidVal, lpfVal):
        pidDisp.child(0).setText(1,str(pidVal.P))
        pidDisp.child(1).setText(1,str(pidVal.I))
        pidDisp.child(2).setText(1,str(pidVal.D))
        pidDisp.child(3).setText(1,str(pidVal.outputRamp))
        pidDisp.child(4).setText(1,str(pidVal.outputLimit))
        pidDisp.child(5).setText(1,str(lpfVal.Tf))

    def commandResponseReceived(self, comandResponse):
        self.refreshDeviceTree()
        self.setTorqueMode(self.device.torqueType)
        self.setControlLopMode(self.device.controlType)
        self.setEnabledDisabled(self.device.deviceStatus)
        self.setModCenter(self.device.modulationCentered)
        self.setModType(self.device.modulationType)

    def stateResponseReceived(self, comandResponse):
        self.blockSignals(True)
        self.stateVel.setText(1,str(self.device.velocityNow))
        self.stateAngle.setText(1,str(self.device.angleNow))
        self.stateVd.setText(1,str(self.device.voltageDNow))
        self.stateVq.setText(1,str(self.device.voltageQNow))
        self.stateCq.setText(1,str(self.device.currentQNow))
        self.stateCd.setText(1,str(self.device.currentDNow))
        self.satateTarget.setText(1,str(self.device.targetNow))
        self.update()
        self.blockSignals(False)

    def refreshDeviceTree(self):
        self.blockSignals(True)

        self.refreshPIDSubtree( self.PIDVelocityConfig, self.device.PIDVelocity, self.device.LPFVelocity)
        self.refreshPIDSubtree( self.PIDAngleConfig, self.device.PIDAngle, self.device.LPFAngle)
        self.refreshPIDSubtree( self.PIDCurrentQConfig, self.device.PIDCurrentQ, self.device.LPFCurrentQ)
        self.refreshPIDSubtree( self.PIDCurrentDConfig, self.device.PIDCurrentD, self.device.LPFCurrentD)

        self.voltageLimit.setText(1,str(self.device.voltageLimit))
        self.velocityLimit.setText(1,str(self.device.velocityLimit))
        self.currentLimit.setText(1,str(self.device.currentLimit))

        self.sensorZeroOffset.setText(1,str(self.device.sensorZeroOffset))
        self.sensorZeroElecOffset.setText(1,str(self.device.sensorElectricalZero))
        
        self.phaseRes.setText(1,str(self.device.phaseResistance))
        # self.deviceStatus.setText(1,str(self.device.deviceStatus))

        self.motionDownsample.setText(1,str(self.device.motionDownsample))
        # self.torque.setText(1,str(self.device.torqueType))
        # self.controller.setText(1,str(self.device.controlType))
        self.update()
        self.blockSignals(False)

    def setTorqueMode(self, value):
        self.blockSignals(True)
        if value == SimpleFOCDevice.VOLTAGE_TORQUE:
            self.selectorTorque.setCurrentIndex(0)
        elif value == SimpleFOCDevice.DC_CURRENT_TORQUE:
            self.selectorTorque.setCurrentIndex(1)
        elif value == SimpleFOCDevice.FOC_CURRENT_TORQUE:
            self.selectorTorque.setCurrentIndex(2)
        self.blockSignals(False)

    def changeTorque(self):
        index = self.selectorTorque.currentIndex()
        if index == 0:
            self.device.sendTorqueType(SimpleFOCDevice.VOLTAGE_TORQUE)
        elif index == 1:
            self.device.sendTorqueType(SimpleFOCDevice.DC_CURRENT_TORQUE)
        elif index == 2:
            self.device.sendTorqueType(SimpleFOCDevice.FOC_CURRENT_TORQUE)

    def setEnabledDisabled(self, value):
        self.blockSignals(True)
        if value == 0:
            self.selectStatus.setCurrentIndex(0)
        elif value == 1:
            self.selectStatus.setCurrentIndex(1)
        self.blockSignals(False)

    def changeStatus(self):
        index = self.selectStatus.currentIndex()
        if index == 0:
            self.device.sendDeviceStatus(0)
        elif index == 1:
            self.device.sendDeviceStatus(1)
        
    def setModCenter(self,value):
        self.blockSignals(True)
        self.selectModCenter.setCurrentIndex(int(value))
        self.blockSignals(False)
        
    def changeModCenter(self):
        index = self.selectModCenter.currentIndex()
        if index == 0:
            self.device.sendModulationCentered(0)
        elif index == 1:
            self.device.sendModulationCentered(1)

    def setModType(self, value):
        self.blockSignals(True)
        if value == SimpleFOCDevice.SINE_PWM:
            self.selectModulation.setCurrentIndex(0)
        elif value == SimpleFOCDevice.SPACE_VECTOR_PWM:
            self.selectModulation.setCurrentIndex(1)
        elif value == SimpleFOCDevice.TRAPEZOIDAL_120:
            self.selectModulation.setCurrentIndex(2)
        elif value == SimpleFOCDevice.TRAPEZOIDAL_150:
            self.selectModulation.setCurrentIndex(3)
        self.blockSignals(False)

    def changeModType(self):
        index = self.selectModulation.currentIndex()
        if index == 0:
            self.device.sendModulationType(SimpleFOCDevice.SINE_PWM)
        elif index == 1:
            self.device.sendModulationType(SimpleFOCDevice.SPACE_VECTOR_PWM)
        elif index == 2:
            self.device.sendModulationType(SimpleFOCDevice.TRAPEZOIDAL_120)
        elif index == 3:
            self.device.sendModulationType(SimpleFOCDevice.TRAPEZOIDAL_150)

    def setControlLopMode(self, value):
        self.blockSignals(True)
        if value == SimpleFOCDevice.TORQUE_CONTROL:
            self.selectorControlLoop.setCurrentIndex(0)
        elif value == SimpleFOCDevice.VELOCITY_CONTROL:
            self.selectorControlLoop.setCurrentIndex(1)
        elif value == SimpleFOCDevice.ANGLE_CONTROL:
            self.selectorControlLoop.setCurrentIndex(2)
        elif value == SimpleFOCDevice.VELOCITY_OPENLOOP_CONTROL:
            self.selectorControlLoop.setCurrentIndex(3)
        elif value == SimpleFOCDevice.ANGLE_OPENLOOP_CONTROL:
            self.selectorControlLoop.setCurrentIndex(4)
        self.blockSignals(False)

    def changeControlLoop(self):
        index = self.selectorControlLoop.currentIndex()
        if index == 0:
            self.device.sendControlType(SimpleFOCDevice.TORQUE_CONTROL)
        elif index == 1:
            self.device.sendControlType(SimpleFOCDevice.VELOCITY_CONTROL)
        elif index == 2:
            self.device.sendControlType(SimpleFOCDevice.ANGLE_CONTROL)
        elif index == 3:
            self.device.sendControlType(SimpleFOCDevice.VELOCITY_OPENLOOP_CONTROL)
        elif index == 4:
            self.device.sendControlType(SimpleFOCDevice.ANGLE_OPENLOOP_CONTROL)
    
    def connectionStateChanged(self, connectionFlag):
        if connectionFlag is True:
            self.setEnabled(True)
        else:
            self.setEnabled(False)


================================================
FILE: src/gui/configtool/devicesInspectorTree.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import (QVBoxLayout, QFrame)

from src.gui.configtool.connectionControl import ConnectionControlGroupBox
from src.gui.configtool.deviceJoggingControl import DeviceJoggingControl
from src.gui.configtool.deviceTreeview import DeviceTreeView
from src.gui.configtool.droDisplayWidget import DROGroupBox
from src.gui.configtool.generalControls import GeneralControls
from src.simpleFOCConnector import SimpleFOCDevice


class DevicesInspectorTree(QFrame):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.device = SimpleFOCDevice.getInstance()

        self.layout = QVBoxLayout(self)
        self.setLayout(self.layout)

        self.droWidget = DROGroupBox(self)
        self.layout.addWidget(self.droWidget)

        self.generalControls = GeneralControls(self)
        self.layout.addWidget(self.generalControls)

        self.treeView = DeviceTreeView(self)
        self.layout.addWidget(self.treeView)

        self.joggingControl = DeviceJoggingControl(self)
        self.layout.addWidget(self.joggingControl)

        self.connectionControl = ConnectionControlGroupBox(self)
        self.layout.addWidget(self.connectionControl)

        self.setMaximumWidth(500)


================================================
FILE: src/gui/configtool/droDisplayWidget.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PyQt5 import (QtGui,QtWidgets)

from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit
from src.simpleFOCConnector import SimpleFOCDevice


class DROGroupBox(QtWidgets.QGroupBox):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.setTitle('Simple FOC Digital Read Out')
        self.setObjectName('digitalReadOut')

        self.droHorizontalLayout = QtWidgets.QHBoxLayout(self)
        self.droHorizontalLayout.setObjectName('droHorizontalLayout')

        self.signal0Label = QtWidgets.QLabel(self)
        self.signal0Label.setObjectName('angleLabel')
        self.signal0Label.setText('Angle')
        self.droHorizontalLayout.addWidget(self.signal0Label)

        self.signal0LCDNumber = QtWidgets.QLCDNumber(self)
        self.putStyleToLCDNumber(self.signal0LCDNumber)
        self.signal0LCDNumber.setObjectName('signal0LCDNumber')
        self.droHorizontalLayout.addWidget(self.signal0LCDNumber)

        self.signal1Label = QtWidgets.QLabel(self)
        self.signal1Label.setObjectName('velLabel')
        self.signal1Label.setText('Velocity')
        self.droHorizontalLayout.addWidget(self.signal1Label)

        self.signal1LCDNumber = QtWidgets.QLCDNumber(self)
        self.putStyleToLCDNumber(self.signal1LCDNumber)
        self.signal1LCDNumber.setObjectName('signal1LCDNumber')
        self.droHorizontalLayout.addWidget(self.signal1LCDNumber)

        self.signal2Label = QtWidgets.QLabel(self)
        self.signal2Label.setObjectName('torqueLabel')
        self.signal2Label.setText('Target')
        self.droHorizontalLayout.addWidget(self.signal2Label)

        self.signal2LCDNumber = QtWidgets.QLCDNumber(self)
        self.putStyleToLCDNumber(self.signal2LCDNumber)
        self.signal2LCDNumber.setObjectName('signal2LCDNumber')
        self.droHorizontalLayout.addWidget(self.signal2LCDNumber)

        self.signal3Label = QtWidgets.QLabel(self)
        self.signal3Label.setObjectName('targetLabel')
        self.signal3Label.setText('Target')
        self.droHorizontalLayout.addWidget(self.signal3Label)

        self.signal3LCDNumber = QtWidgets.QLCDNumber(self)
        self.putStyleToLCDNumber(self.signal3LCDNumber)
        self.signal3LCDNumber.setObjectName('signal3LCDNumber')
        self.droHorizontalLayout.addWidget(self.signal3LCDNumber)

        self.commandResponseReceived('init')

        self.initDiplay()
        self.disableUI()

        self.device.addConnectionStateListener(self)
        self.device.commProvider.stateMonitorReceived.connect(self.commandResponseReceived)

        self.connectionStateChanged(self.device.isConnected)

    def connectionStateChanged(self, isConnectedFlag):
        if isConnectedFlag is True:
            self.enabeUI()
            self.initDiplay()
        else:
            self.initDiplay()
            self.disableUI()

    def enabeUI(self):
        self.setEnabled(True)

    def disableUI(self):
        self.setEnabled(False)

    def initDiplay(self):
        self.signal0LCDNumber.display(0.0)
        self.signal1LCDNumber.display(0.0)
        self.signal2LCDNumber.display(0.0)
        self.signal3LCDNumber.display(0.0)

    def putStyleToLCDNumber(self, lcdNumber):
        lcdNumber.setStyleSheet('''QLCDNumber {background-color: white;}''')
        palette = self.setColor(lcdNumber.palette(), GUIToolKit.RED_COLOR)
        lcdNumber.setPalette(palette)

    def setColor(self, palette, colorTouple):
        R = colorTouple[0]
        G = colorTouple[1]
        B = colorTouple[2]
        # foreground color
        palette.setColor(palette.WindowText, QtGui.QColor(R, G, B))
        # background color
        palette.setColor(palette.Background, QtGui.QColor(R, G, B))
        # 'light' border
        palette.setColor(palette.Light, QtGui.QColor(R, G, B))
        # 'dark' border
        palette.setColor(palette.Dark, QtGui.QColor(R, G, B))
        return palette

    def commandResponseReceived(self, cmdRespose):        
        if self.device.torqueType ==  SimpleFOCDevice.VOLTAGE_TORQUE:
            self.signal2Label.setText("Voltage")
            self.signal2LCDNumber.display(self.device.voltageQNow)
        else: # dc current or FOC current
            self.signal2Label.setText("Current")
            self.signal2LCDNumber.display(self.device.currentQNow)

        self.signal3LCDNumber.display(self.device.targetNow)
        self.signal1LCDNumber.display(self.device.velocityNow)
        self.signal0LCDNumber.display(self.device.angleNow)


================================================
FILE: src/gui/configtool/generalControls.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import (QtGui, QtWidgets, QtCore)

from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit
from src.simpleFOCConnector import SimpleFOCDevice


class GeneralControls(QtWidgets.QGroupBox):

    def __init__(self, parent=None):

        super().__init__(parent)

        # self.setMaximumWidth(300)

        onlyFloat = QtGui.QRegExpValidator(
            QtCore.QRegExp("[+-]?([0-9]*[.])?[0-9]+"))

        self.device = SimpleFOCDevice.getInstance()

        self.setTitle('General Controls')

        self.setObjectName('generalControls')

        self.gcGridLayout = QtWidgets.QGridLayout(self)
        self.gcGridLayout.setObjectName('gcGridLayout')


        self.enableDeviceButton = QtWidgets.QPushButton(self)
        self.enableDeviceButton.setObjectName('enButton')
        self.enableDeviceButton.setText('Enable Device')
        self.enableDeviceButton.setIcon(GUIToolKit.getIconByName('greendot'))
        self.enableDeviceButton.clicked.connect(self.toggleEnable)
        self.gcGridLayout.addWidget(self.enableDeviceButton, 1, 0, 1, 1)

        self.sensorZeroButton = QtWidgets.QPushButton(self)
        self.sensorZeroButton.setObjectName('homeButton')
        self.sensorZeroButton.setText('Sensor Zero')
        self.sensorZeroButton.setIcon(GUIToolKit.getIconByName('home'))
        self.sensorZeroButton.clicked.connect(self.setSensorZero)
        self.gcGridLayout.addWidget(self.sensorZeroButton, 1, 1, 1, 1)

        self.setZeroTarget = QtWidgets.QPushButton(self)
        self.setZeroTarget.setObjectName('zeroButton')
        self.setZeroTarget.setText('Zero Target')
        self.setZeroTarget.setIcon(GUIToolKit.getIconByName('stop'))
        self.setZeroTarget.clicked.connect(self.setTargetZero)
        self.gcGridLayout.addWidget(self.setZeroTarget, 1, 2, 1, 1)
        self.reloadValues()

        self.device.addConnectionStateListener(self)
        self.device.commProvider.commandDataReceived.connect(self.commandResponseReceived)

        self.connectionStateChanged(self.device.isConnected)

    def connectionStateChanged(self, deviceConnected):
        if deviceConnected is True:
            self.enabeUI()
        else:
            self.disableUI()

    def enabeUI(self):
        self.setEnabled(True)

    def disableUI(self):
        self.setEnabled(False)

    def setSensorZero(self):
        val = self.device.angleNow + self.device.sensorZeroOffset
        self.device.sendSensorZeroOffset(val)

    def setTargetZero(self):
        self.device.sendTargetValue(0)
    
    def toggleEnable(self):
        val = int( not self.device.deviceStatus)
        self.device.sendDeviceStatus(val)

    def commandResponseReceived(self, comandResponse):
        self.reloadValues()
        
    def reloadValues(self):
        if self.device.deviceStatus:
            self.enableDeviceButton.setText('Disable Device')
            self.enableDeviceButton.setIcon(GUIToolKit.getIconByName('reddot'))
        else:
            self.enableDeviceButton.setText('Enable Device')
            self.enableDeviceButton.setIcon(GUIToolKit.getIconByName('greendot'))

================================================
FILE: src/gui/configtool/generalSettingsWidget.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import (QtGui, QtWidgets, QtCore)

from src.gui.sharedcomnponets.sharedcomponets import ConfigQLineEdit
from src.simpleFOCConnector import SimpleFOCDevice


class GeneralSettingsGroupBox(QtWidgets.QGroupBox):

    def __init__(self, parent=None):

        super().__init__(parent)

        self.setMaximumWidth(300)

        onlyFloat = QtGui.QRegExpValidator(
            QtCore.QRegExp("[+-]?([0-9]*[.])?[0-9]+"))

        self.device = SimpleFOCDevice.getInstance()

        self.setTitle('General device settings')

        self.setObjectName('generalDeviceSettings')

        self.gcGridLayout = QtWidgets.QGridLayout(self)
        self.gcGridLayout.setObjectName('gcGridLayout')

        self.motionDownsample = QtWidgets.QLabel(self)
        self.motionDownsample.setObjectName('motionDownsample')
        self.motionDownsample.setText('Motion Downsample')
        self.gcGridLayout.addWidget(self.motionDownsample, 2, 0, 1, 1)

        self.motionDownsampleEdit = ConfigQLineEdit(self)
        self.motionDownsampleEdit.setObjectName('motionDownsampleEdit')
        self.motionDownsampleEdit.setValidator(onlyFloat)
        self.motionDownsampleEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.motionDownsampleEdit.updateValue.connect(self.sendMotionDownsampleAction)
        self.gcGridLayout.addWidget(self.motionDownsampleEdit, 2, 1, 1, 1)

        self.curLimitLabel = QtWidgets.QLabel(self)
        self.curLimitLabel.setObjectName('curLimitLabel')
        self.curLimitLabel.setText('Current Limit')
        self.gcGridLayout.addWidget(self.curLimitLabel, 3, 0, 1, 1)

        self.velLimitlabel = QtWidgets.QLabel(self)
        self.velLimitlabel.setObjectName('velLimitlabel')
        self.velLimitlabel.setText('Velocity limit')
        self.gcGridLayout.addWidget(self.velLimitlabel, 4, 0, 1, 1)

        self.volLimitLabel = QtWidgets.QLabel(self)
        self.volLimitLabel.setObjectName('volLimitLabel')
        self.volLimitLabel.setText('Voltage limit')
        self.gcGridLayout.addWidget(self.volLimitLabel, 6, 0, 1, 1)

        self.clLineEdit = ConfigQLineEdit(self)
        self.clLineEdit.setObjectName('clLineEdit')
        self.clLineEdit.setValidator(onlyFloat)
        self.clLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.clLineEdit.updateValue.connect(self.sendCurrentLimitAction)
        self.gcGridLayout.addWidget(self.clLineEdit, 3, 1, 1, 1)

        self.vlLineEdit = ConfigQLineEdit(self)
        self.vlLineEdit.setObjectName('vlLineEdit')
        self.vlLineEdit.setValidator(onlyFloat)
        self.vlLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.vlLineEdit.updateValue.connect(self.sendVelLimitAction)
        self.gcGridLayout.addWidget(self.vlLineEdit, 4, 1, 1, 1)

        self.volLLineEdit = ConfigQLineEdit(self)
        self.volLLineEdit.setObjectName('volLLineEdit')
        self.volLLineEdit.setValidator(onlyFloat)
        self.volLLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.volLLineEdit.updateValue.connect(self.sendVoltageLimitAction)
        self.gcGridLayout.addWidget(self.volLLineEdit, 6, 1, 1, 1)

        self.reloadValues()

        self.device.addConnectionStateListener(self)
        self.device.commProvider.commandDataReceived.connect(self.commandResponseReceived)

        self.connectionStateChanged(self.device.isConnected)

    def connectionStateChanged(self, deviceConnected):
        if deviceConnected is True:
            self.enabeUI()
        else:
            self.disableUI()

    def enabeUI(self):
        self.setEnabled(True)

    def disableUI(self):
        self.setEnabled(False)

    def sendMotionDownsampleAction(self):
        value = self.motionDownsampleEdit.text()
        value = value.replace(',', '.')
        self.motionDownsampleEdit.setText(value)
        self.device.sendMotionDownsample(value)

    def sendCurrentLimitAction(self):
        value = self.clLineEdit.text()
        value = value.replace(',', '.')
        self.clLineEdit.setText(value)
        self.device.sendCurrentLimit(self.clLineEdit.text())

    def sendVelLimitAction(self):
        value = self.vlLineEdit.text()
        value = value.replace(',', '.')
        self.vlLineEdit.setText(value)
        self.device.sendVelocityLimit(self.vlLineEdit.text())

    def sendVoltageLimitAction(self):
        value = self.volLLineEdit.text()
        value = value.replace(',', '.')
        self.volLLineEdit.setText(value)
        self.device.sendVoltageLimit(self.volLLineEdit.text())

    def commandResponseReceived(self, comandResponse):
        self.reloadValues()
        
    def reloadValues(self):
        self.motionDownsampleEdit.setText(str(self.device.motionDownsample))
        self.clLineEdit.setText(str(self.device.currentLimit))
        self.vlLineEdit.setText(str(self.device.velocityLimit))
        self.volLLineEdit.setText(str(self.device.voltageLimit))

================================================
FILE: src/gui/configtool/generatedCodeDisplay.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
from PyQt5.QtCore import QRegExp
from PyQt5.QtCore import Qt
from PyQt5.QtGui import (QSyntaxHighlighter,QTextCharFormat,QBrush,QColor)
from PyQt5.QtWidgets import (QVBoxLayout)

from src.gui.sharedcomnponets.sharedcomponets import (WorkAreaTabWidget,
                                                      GUIToolKit)
from src.simpleFOCConnector import SimpleFOCDevice


class GenerateCodeDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setWindowTitle("Generate Code")
        self.setWindowIcon(GUIToolKit.getIconByName('gen'))

        self.checkBoxMotionControl = QtWidgets.QCheckBox(self)
        self.checkBoxMotionControl.setObjectName('motion')
        self.checkBoxMotionControl.setText("Torque/Motion control")
        self.checkBoxMotionControl.setIcon(GUIToolKit.getIconByName('motor'))
        self.checkBoxMotionControl.setChecked(True)

        self.checkBoxPidVel = QtWidgets.QCheckBox(self)
        self.checkBoxPidVel.setObjectName('pidVel')
        self.checkBoxPidVel.setText("PID velocity")
        self.checkBoxPidVel.setIcon(GUIToolKit.getIconByName('pidconfig'))
        self.checkBoxPidVel.setChecked(True)
        
        self.checkBoxPidAngle = QtWidgets.QCheckBox(self)
        self.checkBoxPidAngle.setObjectName('pidAngle')
        self.checkBoxPidAngle.setText("PID angle")
        self.checkBoxPidAngle.setIcon(GUIToolKit.getIconByName('pidconfig'))
        self.checkBoxPidAngle.setChecked(True)
        
        self.checkBoxPidCq = QtWidgets.QCheckBox(self)
        self.checkBoxPidCq.setObjectName('pidCq')
        self.checkBoxPidCq.setText("PID current q")
        self.checkBoxPidCq.setIcon(GUIToolKit.getIconByName('pidconfig'))
        self.checkBoxPidCq.setChecked(True)
        
        self.checkBoxPidCd = QtWidgets.QCheckBox(self)
        self.checkBoxPidCd.setObjectName('pidCq')
        self.checkBoxPidCd.setText("PID current d")
        self.checkBoxPidCd.setIcon(GUIToolKit.getIconByName('pidconfig'))
        self.checkBoxPidCd.setChecked(True)
        
        self.checkBoxLimits = QtWidgets.QCheckBox(self)
        self.checkBoxLimits.setObjectName('limits')
        self.checkBoxLimits.setText("Limits")
        self.checkBoxLimits.setIcon(GUIToolKit.getIconByName('statistics'))
        self.checkBoxLimits.setChecked(True)
        
        self.checkBoxPhaseRes = QtWidgets.QCheckBox(self)
        self.checkBoxPhaseRes.setObjectName('phaseRes')
        self.checkBoxPhaseRes.setText("Phase Resistance")
        self.checkBoxPhaseRes.setIcon(GUIToolKit.getIconByName('res'))
        self.checkBoxPhaseRes.setChecked(True)
        
        self.checkBoxModulation = QtWidgets.QCheckBox(self)
        self.checkBoxModulation.setObjectName('modulation')
        self.checkBoxModulation.setText("PWM Modulation")
        self.checkBoxModulation.setIcon(GUIToolKit.getIconByName('gear'))
        self.checkBoxModulation.setChecked(True)
        
        self.sensorOffset = QtWidgets.QCheckBox(self)
        self.sensorOffset.setObjectName('sensorOffset')
        self.sensorOffset.setText("Sensor Offset")
        self.sensorOffset.setIcon(GUIToolKit.getIconByName('gear'))
        self.sensorOffset.setChecked(True)

        self.sensorElOffset = QtWidgets.QCheckBox(self)
        self.sensorElOffset.setObjectName('sensorOffset')
        self.sensorElOffset.setToolTip('Be careful!<br> Only for absolute sensors')
        self.sensorElOffset.setText("Sensor Electrical Offset")
        self.sensorElOffset.setIcon(GUIToolKit.getIconByName('gear'))
        self.sensorElOffset.setChecked(False)

        QBtn = QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel

        self.buttonBox = QtWidgets.QDialogButtonBox(QBtn)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        text = "<h1>Arduino Code Generation</h1>"
        text += "Arduino code generation for the motor parameters currently used in the <i>Simple<b>FOC</b>Studio</i> <br>"
        text += "Once you are happy with the performance of your system you can generate the arduino code of the parameters you have tuned.<br>"
        text += "The generated code you can just copy/paste in your <code>setup()</code> function, just before calling the <code>motor.init()</code><br>"
        text += "<h4>Choose the parameter sets to be generated:</h4>"

        self.layout = QtWidgets.QVBoxLayout()
        message1 = QtWidgets.QLabel(text)
        self.layout.addWidget(message1)
        self.layout.addWidget(self.checkBoxMotionControl)
        self.layout.addWidget(self.checkBoxPidVel)
        self.layout.addWidget(self.checkBoxPidAngle)
        self.layout.addWidget(self.checkBoxPidCq)
        self.layout.addWidget(self.checkBoxPidCd)
        self.layout.addWidget(self.checkBoxLimits)
        self.layout.addWidget(self.checkBoxPhaseRes)
        self.layout.addWidget(self.checkBoxModulation)
        self.layout.addWidget(self.sensorOffset)
        self.layout.addWidget(self.sensorElOffset)
        self.layout.addWidget(self.buttonBox)
        self.setLayout(self.layout)

class GeneratedCodeDisplay(WorkAreaTabWidget):

    def __init__(self, parent=None ):
        super().__init__(parent)
        
        self.device = SimpleFOCDevice.getInstance()
        dlg = GenerateCodeDialog()  # If you pass self, the dialog will be centered over the main window as before.
        if dlg.exec_():
            toGenerate=[
                dlg.checkBoxMotionControl.isChecked(),
                dlg.checkBoxPidVel.isChecked(),
                dlg.checkBoxPidAngle.isChecked(),
                dlg.checkBoxPidCq.isChecked(),
                dlg.checkBoxPidCd.isChecked(),
                dlg.checkBoxLimits.isChecked(),
                dlg.sensorOffset.isChecked(),
                dlg.sensorElOffset.isChecked(),
                dlg.checkBoxPhaseRes.isChecked(),
                dlg.checkBoxModulation.isChecked(),
            ]
            code = self.device.toArduinoCode(toGenerate)

        self.layout = QVBoxLayout(self)

        text = "<h1>Generated Arduino Code</h1>"
        text += "This generated code you can just copy/paste into your <code>setup()</code> function, it is important that you place it before calling the <code>motor.init()</code><br>"

        message1 = QtWidgets.QLabel(text)
        self.layout.addWidget(message1)

        self.codeDisplayBefore = QtWidgets.QLabel(self)
        self.layout.addWidget(self.codeDisplayBefore)
        code0 = '<font color="#5e6d03">#include</font> <font color="#434f54">&lt;</font><b><font color="#d35400">SimpleFOC</font></b><font color="#434f54">.</font><font color="#000000">h</font><font color="#434f54">&gt;</font>'
        code0 +="<br>...<br>"
        code0 += '<font color="#00979c">void</font> <font color="#5e6d03">setup</font><font color="#000000">(</font><font color="#000000">)</font> <font color="#000000">{</font><br>'
        code0 += "  ...."
        self.codeDisplayBefore.setText(code0)
        self.codeDisplayBefore.setTextFormat(Qt.TextFormat.RichText)

        self.codeDisplay = QtWidgets.QTextEdit(self)
        self.codeDisplay.setObjectName('codeDisplay')
        self.codeDisplay.setText(code)

        highlighter = MyHighlighter( self.codeDisplay, "Classic" )
        self.layout.addWidget(self.codeDisplay)

        self.codeDisplayAfter = QtWidgets.QLabel(self)
        self.layout.addWidget(self.codeDisplayAfter)
        code1 = '<font color="#434f54">&#47;&#47; initialize motor</font><br>'
        code1 += '<font color="#d35400">motor</font><font color="#434f54">.</font><font color="#d35400">init</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font><br>'
        code1 += '<font color="#434f54">&#47;&#47; align sensor and start FOC</font><br>'
        code1 += '<font color="#d35400">motor</font><font color="#434f54">.</font><font color="#d35400">initFOC</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font><br> ...<br> }'
        code1 += '<br><font color="#00979c">void</font> <font color="#5e6d03">loop</font><font color="#000000">(</font><font color="#000000">)</font> <font color="#000000">{</font>'
        code1 += '<br> .... <br>'
        code1 += '<font color="#d35400">motor</font><font color="#434f54">.</font><font color="#d35400">move</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font><br>'
        code1 += '<font color="#d35400">motor</font><font color="#434f54">.</font><font color="#d35400">loopFOC</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font><br>'
        code1 += '.... <br>}'
        # MyHighlighter( self.codeDisplayAfter, "Classic" )
        self.codeDisplayAfter.setText(code1)
        self.codeDisplayAfter.setTextFormat(Qt.TextFormat.RichText)

        self.setLayout(self.layout)

    def getTabIcon(self):
        return GUIToolKit.getIconByName('gen')

    def getTabName(self):
        return 'Generated Code'


class MyHighlighter( QSyntaxHighlighter ):

    def __init__( self, parent, theme ):
      QSyntaxHighlighter.__init__( self, parent )
      self.parent = parent
      keyword = QTextCharFormat()
      comment = QTextCharFormat()

      self.highlightingRules = []

      # keyword
      brush = QBrush(QColor(211,84,0), Qt.SolidPattern )
      keyword.setForeground( brush )
      keywords = list( [ "motor",'FOCModulationType','MotionControlType','TorqueControlType'] )
      for word in keywords:
        pattern = QRegExp("\\b" + word + "\\b")
        rule = HighlightingRule( pattern, keyword )
        self.highlightingRules.append( rule )

      # comment
      brush = QBrush( Qt.gray, Qt.SolidPattern )
      pattern = QRegExp( "\/\/.*[^\n]" )
      comment.setForeground( brush )
      comment.setFontItalic( True )
      rule = HighlightingRule( pattern, comment )
      self.highlightingRules.append( rule )


    def highlightBlock( self, text ):
      for rule in self.highlightingRules:
        expression = QRegExp( rule.pattern )
        index = expression.indexIn( text )
        while index >= 0:
          length = expression.matchedLength()
          self.setFormat( index, length, rule.format )
          index = expression.indexIn( text, index + length )
      self.setCurrentBlockState( 0 )

class HighlightingRule():
  def __init__( self, pattern, format ):
    self.pattern = pattern
    self.format = format


================================================
FILE: src/gui/configtool/graphicWidget.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging

import numpy as np
import pyqtgraph as pg
from PyQt5 import QtWidgets

from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit
from src.simpleFOCConnector import SimpleFOCDevice

class SimpleFOCGraphicWidget(QtWidgets.QGroupBox):

    disconnectedState = 0
    initialConnectedState = 1
    connectedPausedState = 2
    connectedPlottingStartedState = 3

    signals = ['Target', 'Vq','Vd','Cq','Cd','Vel','Angle']
    signal_tooltip = ['Target', 'Voltage Q [Volts]','Voltage D [Volts]','Current Q [miliAmps]','Current D [miliAmps]','Velocity [rad/sec]','Angle [rad]']
    signalColors = [GUIToolKit.RED_COLOR, GUIToolKit.BLUE_COLOR, GUIToolKit.PURPLE_COLOR,GUIToolKit.YELLOW_COLOR, GUIToolKit.MAROON_COLOR, GUIToolKit.ORANGE_COLOR, GUIToolKit.GREEN_COLOR]
    signalIcons = ['reddot', 'bluedot','purpledot', 'yellowdot', 'maroondot', 'orangedot', 'greendot']

    def __init__(self, parent=None):

        super().__init__(parent)

        self.setObjectName('plotWidget')
        self.setTitle('Real time motor variables: ')
        self.horizontalLayout = QtWidgets.QVBoxLayout(self)
        self.device = SimpleFOCDevice.getInstance()

        self.numberOfSamples = 300

        pg.setConfigOptions(antialias=True)
        self.plotWidget = pg.PlotWidget()
        self.plotWidget.showGrid(x=True, y=True, alpha=0.5)
        self.plotWidget.addLegend()

        # self.legend = pg.LegendItem()
        # self.legend.setParentItem(self.plotWidget)

        self.timeArray = np.arange(-self.numberOfSamples, 0, 1)
        
        self.controlPlotWidget = ControlPlotPanel(controllerPlotWidget=self)

        self.signalDataArrays = []
        self.signalPlots = []
        self.signalPlotFlags = []
        for (sig, sigColor, checkBox, tooltip) in zip(self.signals, self.signalColors,self.controlPlotWidget.signalCheckBox, self.signal_tooltip):
            # define signal plot data array
            self.signalDataArrays.append(np.zeros(self.numberOfSamples))
            # configure signal plot parameters
            signalPen = pg.mkPen(color=sigColor, width=1.5)
            self.signalPlots.append(pg.PlotDataItem(self.timeArray,
                                            self.signalDataArrays[-1],
                                            pen=signalPen, name=tooltip))
            self.plotWidget.addItem(self.signalPlots[-1])

            # is plotted flag
            self.signalPlotFlags.append(True)
            # add callback
            checkBox.stateChanged.connect(self.signalPlotFlagUpdate)

        self.horizontalLayout.addWidget(self.plotWidget)
        self.horizontalLayout.addWidget(self.controlPlotWidget)
        
        self.device.commProvider.monitoringDataReceived.connect(
            self.upDateGraphic)

        self.currentStatus = self.disconnectedState
        self.controlPlotWidget.pauseContinueButton.setDisabled(True)

        self.device.addConnectionStateListener(self)

        self.connectionStateChanged(self.device.isConnected)

    def connectionStateChanged(self, deviceConnected):
        if deviceConnected is True:
            self.currentStatus = self.initialConnectedState
            self.enabeUI()
        else:
            self.controlPlotWidget.startStoPlotAction()
            self.controlPlotWidget.stopAndResetPlot()
            self.currentStatus = self.disconnectedState
            self.disableUI()

    def enabeUI(self):
        self.setEnabled(True)

    def disableUI(self):
        self.setEnabled(False)

    def signalPlotFlagUpdate(self):
        self.controlPlotWidget.updateMonitorVariables()
        for i, (checkBox, plotFlag) in enumerate(zip(self.controlPlotWidget.signalCheckBox, self.signalPlotFlags)):
            if checkBox.isChecked() and (not plotFlag):
                self.signalPlotFlags[i] = True
                self.plotWidget.addItem( self.signalPlots[i] )
            elif (not checkBox.isChecked()) and plotFlag:
                self.signalPlotFlags[i]  = False
                self.plotWidget.removeItem( self.signalPlots[i] )

    def connectioStatusUpdate(self, connectedFlag):
        if connectedFlag:
            self.currentStatus = self.initialConnectedState
        else:
            self.currentStatus = self.disconnectedState

    def upDateGraphic(self, signalList):
        if self.currentStatus is self.connectedPlottingStartedState or \
                self.currentStatus is self.connectedPausedState:

            signals = np.array(signalList, dtype=float)
            signalIndex = 0

            enabled = np.where(np.array(self.signalPlotFlags) == True)[0]

            if(len(enabled) != len(signals)):
                logging.warning('Arrived corrupted data')
                return
            else:
                for i, ind in enumerate(enabled):
                    self.signalDataArrays[ind] = np.roll(self.signalDataArrays[ind], -1)
                    self.signalDataArrays[ind][-1] = signals[i]

            if self.currentStatus is self.connectedPlottingStartedState:
                self.updatePlot()


    def computeStatic(self, array):
        mean = np.mean(array)
        std = np.std(array)
        max = np.max(array)
        min = np.min(array)
        meadian = np.median(array)

    def updatePlot(self):
        for i, plotFlag in enumerate(self.signalPlotFlags):
            if plotFlag:
                self.signalPlots[i].setData(self.timeArray, self.signalDataArrays[i])
                self.signalPlots[i].updateItems()
                self.signalPlots[i].sigPlotChanged.emit(self.signalPlots[i])


class ControlPlotPanel(QtWidgets.QWidget):

    def __init__(self, parent=None, controllerPlotWidget=None):
        '''Constructor for ToolsWidget'''
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()
        self.controlledPlot = controllerPlotWidget
        
        self.verticalLayout = QtWidgets.QVBoxLayout(self)
        self.setLayout(self.verticalLayout)

        self.horizontalLayout1 = QtWidgets.QHBoxLayout()
        self.horizontalLayout1.setObjectName('horizontalLayout')

        self.startStopButton = QtWidgets.QPushButton(self)
        self.startStopButton.setText('Start')
        self.startStopButton.setObjectName('Start')
        self.startStopButton.clicked.connect(self.startStoPlotAction)
        self.startStopButton.setIcon(GUIToolKit.getIconByName('start'))
        self.horizontalLayout1.addWidget(self.startStopButton)

        self.pauseContinueButton = QtWidgets.QPushButton(self)
        self.pauseContinueButton.setObjectName('pauseButton')
        self.pauseContinueButton.setText('Pause')
        self.pauseContinueButton.setIcon(GUIToolKit.getIconByName('pause'))
        self.pauseContinueButton.clicked.connect(self.pauseContinuePlotAction)
        self.horizontalLayout1.addWidget(self.pauseContinueButton)

        self.zoomAllButton = QtWidgets.QPushButton(self)
        self.zoomAllButton.setObjectName('zoomAllButton')
        self.zoomAllButton.setText('View all')
        self.zoomAllButton.setIcon(GUIToolKit.getIconByName('zoomall'))
        self.zoomAllButton.clicked.connect(self.zoomAllPlot)
        self.horizontalLayout1.addWidget(self.zoomAllButton)

        self.signalCheckBox = []
        for i in range(len(self.controlledPlot.signals)):
            checkBox = QtWidgets.QCheckBox(self)
            checkBox.setObjectName('signalCheckBox'+str(i))
            checkBox.setToolTip(self.controlledPlot.signal_tooltip[i])
            checkBox.setText(self.controlledPlot.signals[i])
            checkBox.setIcon(GUIToolKit.getIconByName(self.controlledPlot.signalIcons[i]))
            checkBox.setChecked(True)
            self.signalCheckBox.append(checkBox)
            self.horizontalLayout1.addWidget(checkBox)


        spacerItem = QtWidgets.QSpacerItem(100, 20,
                                           QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Maximum)

        self.horizontalLayout1.addItem(spacerItem)
        self.horizontalLayout1.addItem(spacerItem)

        self.downsampleLabel = QtWidgets.QLabel(self)
        self.downsampleLabel.setText('Downsample')
        self.downampleValue = QtWidgets.QLineEdit(self.downsampleLabel)
        self.downampleValue.setText("100")
        self.downampleValue.editingFinished.connect(self.changeDownsampling)
        self.horizontalLayout1.addWidget(self.downsampleLabel)
        self.horizontalLayout1.addWidget(self.downampleValue)

        self.verticalLayout.addLayout(self.horizontalLayout1)

    def startStoPlotAction(self):
        if self.controlledPlot.currentStatus is self.controlledPlot.initialConnectedState:
            # Start pressed
            self.startStopButton.setText('Stop')
            self.startStopButton.setIcon(GUIToolKit.getIconByName('stop'))
            self.controlledPlot.currentStatus = \
                self.controlledPlot.connectedPlottingStartedState
            self.pauseContinueButton.setEnabled(True)
            self.device.sendMonitorDownsample(int(self.downampleValue.text()))
            self.updateMonitorVariables()
        else:
            # Stop pressed
            self.startStopButton.setText('Start')
            self.startStopButton.setIcon(GUIToolKit.getIconByName('start'))
            self.pauseContinueButton.setText('Pause')
            self.pauseContinueButton.setIcon(GUIToolKit.getIconByName('pause'))
            self.pauseContinueButton.setEnabled(False)
            self.stopAndResetPlot()
            self.device.sendMonitorDownsample(0)
            self.device.sendMonitorClearVariables()

    def pauseContinuePlotAction(self):
        if self.controlledPlot.currentStatus is self.controlledPlot.connectedPausedState:
            # Continue pressed
            self.pauseContinueButton.setText('Pause')
            self.pauseContinueButton.setIcon(GUIToolKit.getIconByName('pause'))
            self.controlledPlot.currentStatus = self.controlledPlot.connectedPlottingStartedState
        else:
            # Pause pressed
            self.pauseContinueButton.setText('Continue')
            self.pauseContinueButton.setIcon(
                GUIToolKit.getIconByName('continue'))
            self.controlledPlot.currentStatus = self.controlledPlot.connectedPausedState

    def stopAndResetPlot(self):
        self.controlledPlot.currentStatus = self.controlledPlot.initialConnectedState
        for dataArray in self.controlledPlot.signalDataArrays:
            dataArray = np.zeros(self.controlledPlot.numberOfSamples)

    def zoomAllPlot(self):
        self.controlledPlot.plotWidget.enableAutoRange()

    def changeDownsampling(self):
        if  self.controlledPlot.currentStatus == self.controlledPlot.connectedPlottingStartedState:
            self.device.sendMonitorDownsample(int(self.downampleValue.text()))

    def updateMonitorVariables(self):
        self.device.sendMonitorVariables([self.signalCheckBox[0].isChecked(), 
                                                self.signalCheckBox[1].isChecked(),
                                                 self.signalCheckBox[2].isChecked(), 
                                                 self.signalCheckBox[3].isChecked(), 
                                                 self.signalCheckBox[4].isChecked(), 
                                                 self.signalCheckBox[5].isChecked(), 
                                                 self.signalCheckBox[6].isChecked()])


================================================
FILE: src/gui/configtool/pidConfiguration.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import (QtGui, QtWidgets, QtCore)
from src.gui.sharedcomnponets.sharedcomponets import ConfigQLineEdit
from src.simpleFOCConnector import SimpleFOCDevice


class PidGroupBox(QtWidgets.QGroupBox):

    def __init__(self, parent=None):

        super().__init__(parent)
        self.setMaximumWidth(300)

        onlyFloatInputValidator = QtGui.QRegExpValidator(
            QtCore.QRegExp("[+-]?([0-9]*[.])?[0-9]+"))

        self.device = SimpleFOCDevice.getInstance()

            
        self.activePID = self.device.PIDVelocity
        self.activeLPF = self.device.LPFVelocity

        self.setObjectName('pidConfigurator')
        self.setTitle('PID Controller configuration')

        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName('gridLayout')
        
        self.sPidLabel = QtWidgets.QLabel(self)
        self.sPidLabel.setObjectName('pgLabel')
        self.sPidLabel.setText('Select PID')
        self.gridLayout.addWidget(self.sPidLabel, 0, 1, 1, 1)

        self.selectorPIDF = QtWidgets.QComboBox(self)
        self.selectorPIDF.setObjectName('selectPIDF')
        self.selectorPIDF.addItems(['Velocity', 'Angle', 'Current Q', 'Current D'])
        self.selectorPIDF.currentIndexChanged.connect(self.changePIDF)
        self.gridLayout.addWidget(self.selectorPIDF, 0, 2, 1, 1)

        self.pgLabel = QtWidgets.QLabel(self)
        self.pgLabel.setObjectName('pgLabel')
        self.pgLabel.setText('Proportional gain')
        self.gridLayout.addWidget(self.pgLabel, 1, 1, 1, 1)

        self.iglabel = QtWidgets.QLabel(self)
        self.iglabel.setObjectName('iglabel')
        self.iglabel.setText('Integral gain')
        self.gridLayout.addWidget(self.iglabel, 2, 1, 1, 1)

        self.dgLabel = QtWidgets.QLabel(self)
        self.dgLabel.setObjectName('dgLabel')
        self.dgLabel.setText('Derivative gain')
        self.gridLayout.addWidget(self.dgLabel, 3, 1, 1, 1)

        self.vrLabel = QtWidgets.QLabel(self)
        self.vrLabel.setObjectName('vrLabel')
        self.vrLabel.setText('Output ramp')
        self.gridLayout.addWidget(self.vrLabel, 4, 1, 1, 1)

        self.vrLabel = QtWidgets.QLabel(self)
        self.vrLabel.setObjectName('lpfLabel')
        self.vrLabel.setText('Low pass filter')
        self.gridLayout.addWidget(self.vrLabel, 5, 1, 1, 1)

        self.pgLineEdit = ConfigQLineEdit(self)
        self.pgLineEdit.setObjectName('pgLineEdit')
        self.pgLineEdit.setValidator(onlyFloatInputValidator)
        self.pgLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.pgLineEdit.editingFinished.connect(self.sendProportionalGainAction)
        self.gridLayout.addWidget(self.pgLineEdit, 1, 2, 1, 1)

        self.igLineEdit = ConfigQLineEdit(self)
        self.igLineEdit.setObjectName('igLineEdit')
        self.igLineEdit.setValidator(onlyFloatInputValidator)
        self.igLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.igLineEdit.editingFinished.connect(self.sendIntegralGainAction)
        self.gridLayout.addWidget(self.igLineEdit, 2, 2, 1, 1)

        self.dgLineEdit = ConfigQLineEdit(self)
        self.dgLineEdit.setObjectName('dgLineEdit')
        self.dgLineEdit.setValidator(onlyFloatInputValidator)
        self.dgLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.dgLineEdit.editingFinished.connect(self.sendDerivativeGainAction)
        self.gridLayout.addWidget(self.dgLineEdit, 3, 2, 1, 1)
        
        self.vrLineEdit = ConfigQLineEdit(self)
        self.vrLineEdit.setObjectName('vrLineEdit')
        self.vrLineEdit.setValidator(onlyFloatInputValidator)
        self.vrLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.vrLineEdit.editingFinished.connect(self.sendRampAction)
        self.gridLayout.addWidget(self.vrLineEdit, 4, 2, 1, 1)

        self.lpfLineEdit = ConfigQLineEdit(self)
        self.lpfLineEdit.setObjectName('lpfLineEdit')
        self.lpfLineEdit.setValidator(onlyFloatInputValidator)
        self.lpfLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.lpfLineEdit.editingFinished.connect(self.sendLPFAction)
        self.gridLayout.addWidget(self.lpfLineEdit, 5, 2, 1, 1)

        self.reloadPIDValues()

        # self.setDerivativeGainAction(self.device.derivativeGainPID)
        # self.setProportionalGainAction(self.device.proportionalGainPID)
        # self.setIntegralGainAction(self.device.integralGainPID)
        # self.setVoltageRampAction(self.device.voltageRampPID)

        self.connectionStateChanged(self.device.isConnected)
        self.device.addConnectionStateListener(self)
        self.device.commProvider.commandDataReceived.connect(self.commandResponseReceived)

    def connectionStateChanged(self, deviceConnected):
        if deviceConnected is True:
            self.enabeUI()
        else:
            self.disableUI()

    def enabeUI(self):
        self.setEnabled(True)

    def disableUI(self):
        self.setEnabled(False)

    def sendDerivativeGainAction(self):
        value = self.dgLineEdit.text()
        value = value.replace(',', '.')
        self.dgLineEdit.setText(value)
        self.device.sendDerivativeGain(self.activePID, value)

    def sendProportionalGainAction(self):
        value = self.pgLineEdit.text()
        value = value.replace(',', '.')
        self.pgLineEdit.setText(value)
        self.device.sendProportionalGain(self.activePID, self.pgLineEdit.text())

    def sendIntegralGainAction(self):
        value = self.igLineEdit.text()
        value = value.replace(',', '.')
        self.igLineEdit.setText(value)
        self.device.sendIntegralGain(self.activePID, self.igLineEdit.text())

    def sendRampAction(self):
        value = self.vrLineEdit.text()
        value = value.replace(',', '.')
        self.vrLineEdit.setText(value)
        self.device.sendOutputRamp(self.activePID, self.vrLineEdit.text())

    def sendLPFAction(self):
        value = self.lpfLineEdit.text()
        value = value.replace(',', '.')
        self.lpfLineEdit.setText(value)
        self.device.sendLowPassFilter(self.activeLPF, self.lpfLineEdit.text())

    def reloadPIDValues(self):
        self.pgLineEdit.setText(str(self.activePID.P))
        self.dgLineEdit.setText(str(self.activePID.D))
        self.igLineEdit.setText(str(self.activePID.I))
        self.vrLineEdit.setText(str(self.activePID.outputRamp))
        self.lpfLineEdit.setText(str(self.activeLPF.Tf))

    def changePIDF(self):
        index = self.selectorPIDF.currentIndex()
        if index == 0:
            self.activePID = self.device.PIDVelocity
            self.activeLPF = self.device.LPFVelocity
        elif index == 1:
            self.activePID = self.device.PIDAngle
            self.activeLPF = self.device.LPFAngle
        elif index == 2:
            self.activePID = self.device.PIDCurrentQ
            self.activeLPF = self.device.LPFCurrentQ
        elif index == 3:
            self.activePID = self.device.PIDCurrentD
            self.activeLPF = self.device.LPFCurrentD

        self.device.pullPIDConf(self.activePID, self.activeLPF)
        self.reloadPIDValues()

    def commandResponseReceived(self, commandDataReceived):
        self.pgLineEdit.setText(str(self.activePID.P))
        self.dgLineEdit.setText(str(self.activePID.D))
        self.igLineEdit.setText(str(self.activePID.I))
        self.vrLineEdit.setText(str(self.activePID.outputRamp))
        self.lpfLineEdit.setText(str(self.activeLPF.Tf))



================================================
FILE: src/gui/configtool/torqueConfig.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets

from src.simpleFOCConnector import SimpleFOCDevice


class TorqueGroupBox(QtWidgets.QGroupBox):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.setObjectName('torqueMode')
        self.setTitle('Torque Mode')
        
        self.torqueTypeHorizontalLayout = QtWidgets.QHBoxLayout(self)
        self.torqueTypeHorizontalLayout.setObjectName('torqueHorizontalLayout')


        
        self.selectorTorque = QtWidgets.QComboBox(self)
        self.selectorTorque.setObjectName('selectorControlLoop')
        self.selectorTorque.addItems(['Voltage', 'DC Current', 'FOC Current'])
        self.selectorTorque.currentIndexChanged.connect(self.changeTorque)
        self.torqueTypeHorizontalLayout.addWidget(self.selectorTorque)

        self.setTorqueMode(self.device.torqueType)

        self.disableUI()
        self.device.addConnectionStateListener(self)
        self.device.commProvider.commandDataReceived.connect(
            self.commandResponseReceived)

        self.connectionStateChanged(self.device.isConnected)

    def connectionStateChanged(self, deviceConnected):
        if deviceConnected is True:
            self.enabeUI()
        else:
            self.disableUI()

    def enabeUI(self):
        self.setEnabled(True)

    def disableUI(self):
        self.setEnabled(False)

    def setTorqueMode(self, value):
        if value == SimpleFOCDevice.VOLTAGE_TORQUE:
            self.selectorTorque.setCurrentIndex(0)
        elif value == SimpleFOCDevice.DC_CURRENT_TORQUE:
            self.selectorTorque.setCurrentIndex(1)
        elif value == SimpleFOCDevice.FOC_CURRENT_TORQUE:
            self.selectorTorque.setCurrentIndex(2)

    def changeTorque(self):
        index = self.selectorTorque.currentIndex()
        if index == 0:
            self.device.sendTorqueType(SimpleFOCDevice.VOLTAGE_TORQUE)
        elif index == 1:
            self.device.sendTorqueType(SimpleFOCDevice.DC_CURRENT_TORQUE)
        elif index == 2:
            self.device.sendTorqueType(SimpleFOCDevice.FOC_CURRENT_TORQUE)

    def commandResponseReceived(self, cmdRespose):
        self.setTorqueMode(self.device.torqueType)

================================================
FILE: src/gui/configtool/treeViewConfigTool.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QVBoxLayout, QSplitter)

from src.gui.configtool.deviceInteractionFrame import DeviceInteractionFrame
from src.gui.configtool.devicesInspectorTree import DevicesInspectorTree
from src.gui.sharedcomnponets.sharedcomponets import (WorkAreaTabWidget,
                                                      GUIToolKit)
from src.simpleFOCConnector import SimpleFOCDevice


class TreeViewConfigTool(WorkAreaTabWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.device = SimpleFOCDevice.getInstance()

        self.layout = QVBoxLayout(self)

        self.treeViewWidget = DevicesInspectorTree(self)
        self.leftWidget = DeviceInteractionFrame(self)

        self.verticalSplitter = QSplitter(Qt.Horizontal)
        self.verticalSplitter.addWidget(self.treeViewWidget)
        self.verticalSplitter.addWidget(self.leftWidget)

        self.layout.addWidget(self.verticalSplitter)

        self.setLayout(self.layout)

    def getTabIcon(self):
        return GUIToolKit.getIconByName('motor')

    def getTabName(self):
        return self.device.connectionID

================================================
FILE: src/gui/mainWindow.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import (QtCore, QtWidgets)

from src.gui.toolbar import SimpleFOCConfigToolBar
from src.gui.workAreaTabbedWidget import WorkAreaTabbedWidget


class UserInteractionMainWindow(object):

    def setupUi(self, main_window):

        main_window.setObjectName('MainWindow')
        main_window.resize(1300, 900)
        main_window.setWindowTitle('SimpleFOC Configuration Tool ')

        self.centralwidget = QtWidgets.QWidget(main_window)
        self.centralwidget.setObjectName('centralwidget')

        # Add layout de to the main window
        self.horizontalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName('verticalLayout')

        # Add tabebd tools widget to the main  window
        self.tabbedToolsWidget = WorkAreaTabbedWidget(self.centralwidget)
        self.horizontalLayout.addWidget(self.tabbedToolsWidget)

        # Add toolbar to the main window
        self.toolBar = SimpleFOCConfigToolBar(main_window,self.tabbedToolsWidget, main_window)
        main_window.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)

        # Add status bar to the main window
        self.statusbar = QtWidgets.QStatusBar(main_window)
        self.statusbar.setObjectName('statusbar')
        main_window.setStatusBar(self.statusbar)

        # Add central Widget to the main window
        main_window.setCentralWidget(self.centralwidget)



================================================
FILE: src/gui/sharedcomnponets/commandLineInterface.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import (QtGui, QtWidgets)

from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit
from src.simpleFOCConnector import SimpleFOCDevice


class CommandLineWidget(QtWidgets.QGroupBox):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.device = SimpleFOCDevice.getInstance()

        self.setObjectName('groupBox')
        self.setTitle('Command Line interface')

        self.cmlVerticalLayout = QtWidgets.QVBoxLayout(self)
        self.cmlVerticalLayout.setObjectName('cmlVerticalLayout')

        self.commandLineDisplay = QtWidgets.QTextEdit(self)
        self.commandLineDisplay.setObjectName('commandLineDisplay')
        self.cmlVerticalLayout.addWidget(self.commandLineDisplay)

        self.commandLineDisplay.setReadOnly(True)
        self.commandLineDisplay.setTextColor(QtGui.QColor(68, 117, 68, 255))

        self.cmlWidget = QtWidgets.QWidget(self)
        self.cmlWidget.setObjectName('cmlWidget')
        self.cmlHorizontalLayout = QtWidgets.QHBoxLayout(self.cmlWidget)
        self.cmlHorizontalLayout.setObjectName('cmlHorizontalLayout')

        self.commandLineEdit = QtWidgets.QLineEdit(self.cmlWidget)
        self.commandLineEdit.setObjectName('commandLineEdit')
        self.cmlHorizontalLayout.addWidget(self.commandLineEdit)

        self.commandLineEdit.returnPressed.connect(self.sendAction)

        self.sendButton = QtWidgets.QPushButton(self.cmlWidget)
        self.sendButton.setObjectName('sendButton')
        self.sendButton.setText('Send')
        self.sendButton.setIcon(GUIToolKit.getIconByName('send'))
        self.sendButton.clicked.connect(self.sendAction)

        self.cmlHorizontalLayout.addWidget(self.sendButton)

        self.clearButton = QtWidgets.QPushButton(self.cmlWidget)
        self.clearButton.setObjectName('clearButton')
        self.cmlHorizontalLayout.addWidget(self.clearButton)
        self.clearButton.setIcon(GUIToolKit.getIconByName('delete'))
        self.clearButton.clicked.connect(self.clearAction)
        self.clearButton.setText('Clear')
        
        self.listDevices = QtWidgets.QPushButton(self.cmlWidget)
        self.listDevices.setObjectName('listDevices')
        self.cmlHorizontalLayout.addWidget(self.listDevices)
        self.listDevices.setIcon(GUIToolKit.getIconByName('list'))
        self.listDevices.clicked.connect(self.sendListDevices)
        self.listDevices.setText('List Devices')

        self.cmlVerticalLayout.addWidget(self.cmlWidget)
        self.device.addConnectionStateListener(self)
        self.setEnabled(False)

    def connectionStateChanged(self, deviceConnected):
        if deviceConnected is True:
            self.enabeUI()
            self.publishCommandResponseData('Connected ...')
        else:
            self.disableUI()
            self.publishCommandResponseData('Disconnected ...')

    def enabeUI(self):

        self.commandLineDisplay.setEnabled(True)
        self.cmlWidget.setEnabled(True)
        self.commandLineEdit.setEnabled(True)
        self.sendButton.setEnabled(True)

        self.setEnabled(True)

    def disableUI(self):
        # self.commandLineDisplay.setEnabled(False)
        self.commandLineEdit.setEnabled(False)
        self.sendButton.setEnabled(False)

    def publishCommandResponseData(self, data):
        self.commandLineDisplay.append(data)
        self.commandLineDisplay.moveCursor(QtGui.QTextCursor.End)

    def clearAction(self):
        self.commandLineDisplay.setPlainText('')

    def sendAction(self):
        self.device.sendCommand(self.commandLineEdit.text())
        self.commandLineEdit.setText('')
        
    def sendListDevices(self):
        self.device.sendCommand('?')


================================================
FILE: src/gui/sharedcomnponets/sharedcomponets.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from PyQt5 import (QtGui, QtWidgets,QtCore)
from serial.tools import list_ports


class GUIToolKit(object):
    ''' This class is used to provide icons for the rest of the application
        hiding the location of the resources
    '''
    RED_COLOR = (255, 92, 92)
    GREEN_COLOR = (57, 217, 138)
    BLUE_COLOR = (91, 141, 236)
    ORANGE_COLOR = (253, 172, 66)
    YELLOW_COLOR = (255,255,51)
    PURPLE_COLOR = (75,0,130)
    MAROON_COLOR = (222,184,135)

    @staticmethod
    def getIconByName(icoName):

        file_index = {
            'add': 'add.png',
            'add_motor': 'add_motor.png',
            'tree': 'tree.png',
            'gen': 'gen.png',
            'home': 'home.png',
            'form': 'form.png',
            'edit': 'edit.png',
            'delete': 'delete.png',
            'statistics': 'statistics.png',
            'reddot': 'reddot.png',
            'orangedot': 'orangedot.png',
            'greendot': 'greendot.png',
            'bluedot': 'bluedot.png',
            'purpledot': 'purpledot.png',
            'yellowdot': 'yellowdot.png',
            'maroondot': 'maroondot.png',
            'send': 'send.png',
            'zoomall': 'zoomall.png',
            'connect': 'connect.png',
            'continue': 'continue.png',
            'alert': 'alert.png',
            'gear': 'gear.png',
            'generalsettings': 'generalsettings.png',
            'open': 'open.png',
            'loop': 'loop.png',
            'save': 'save.png',
            'stop': 'stop.png',
            'restart': 'continue.png',
            'res': 'res.png',
            'sensor': 'sensor.png',
            'start': 'start.png',
            'motor': 'motor.png',
            'pause': 'pause.png',
            'pull': 'pull.png',
            'push': 'push.png',
            'list': 'list.png',
            'disconnect': 'disconnect.png',
            'configure': 'configure.png',
            'pidconfig': 'pidconfig.png',
            'consoletool': 'consoletool.png',
            'fordward': 'fordward.png',
            'fastbackward': 'fastbackward.png',
            'backward': 'backward.png',
            'stopjogging': 'stopjogging.png',
            'fastfordward': 'fastfordward.png',
            'customcommands':'customcommands.png'
        }
        currentDir = os.path.dirname(__file__)
        icon_path = os.path.join(currentDir, '../resources', file_index[icoName])
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(icon_path), QtGui.QIcon.Normal,
                      QtGui.QIcon.Off)
        return icon


class ConfigQLineEdit(QtWidgets.QLineEdit):
    return_key = 16777220
    updateValue = QtCore.pyqtSignal()
    def __init__(self, parent=None):
        '''Constructor for ToolsWidget'''
        super().__init__(parent)

    def keyPressEvent(self, event):
        if event.key() == self.return_key:
            self.updateValue.emit()
        else:
            super().keyPressEvent(event)

class WorkAreaTabWidget(QtWidgets.QTabWidget):
    def __init__(self, parent=None):
        '''Constructor for ToolsWidget'''
        super().__init__(parent)

    def getTabIcon(self):
        raise NotImplemented

    def getTabName(self):
        raise NotImplemented

class SerialPortComboBox(QtWidgets.QComboBox):
    def __init__(self, parent=None, snifer=None):
        super().__init__(parent)
        self.addItems(self.getAvailableSerialPortNames())

    def getAvailableSerialPortNames(self):
        portNames = []
        for port in list_ports.comports():
            if port[2] != 'n/a':
                portNames.append(port[0])

        return portNames

    def showPopup(self):
        selectedItem = self.currentText()
        super().clear()
        availableSerialPortNames = self.getAvailableSerialPortNames()
        self.addItems(availableSerialPortNames)
        if selectedItem in availableSerialPortNames:
            self.setCurrentText(selectedItem)
        super().showPopup()


================================================
FILE: src/gui/toolbar.py
================================================
# !/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
from src.gui.sharedcomnponets.sharedcomponets import GUIToolKit


class SimpleFOCConfigToolBar(QtWidgets.QToolBar):

    def __init__(self,main_window, devicesTabedWidget,  parent=None):
        super().__init__(parent)
        
        self.addDeviceAction = QtWidgets.QToolButton(main_window)
        self.addDeviceAction.setIcon(GUIToolKit.getIconByName('add_motor'))
        self.addDeviceAction.setObjectName('addDeviceAction')
        self.addDeviceAction.setPopupMode(QtWidgets.QToolButton.InstantPopup)

        self.addDeviceMenu = QtWidgets.QMenu(self.addDeviceAction)
        self.addDeviceTreeView  = QtWidgets.QAction("Tree View",self.addDeviceMenu)
        self.addDeviceTreeView.setIcon(GUIToolKit.getIconByName('tree'))
        self.addDeviceTreeView.triggered.connect(devicesTabedWidget.addDeviceTree)
        self.addDeviceFormView  = QtWidgets.QAction("Form View",self.addDeviceMenu)
        self.addDeviceFormView.setIcon(GUIToolKit.getIconByName('form'))
        self.addDeviceFormView.triggered.connect(devicesTabedWidget.addDeviceForm)
        
        self.addDeviceMenu.addAction(self.addDeviceTreeView)
        self.addDeviceMenu.addAction(self.addDeviceFormView)
        self.addDeviceAction.setMenu(self.addDeviceMenu)
        self.addWidget(self.addDeviceAction)

        self.openDeviceAction = QtWidgets.QAction(main_window)
        self.openDeviceAction.setIcon(GUIToolKit.getIconByName('open'))
        self.openDeviceAction.setObjectName('openDeviceAction')
        self.openDeviceAction.triggered.connect(devicesTabedWidget.openDevice)

        self.addAction(self.openDeviceAction)

        self.saveDeviceAction = QtWidgets.QAction(main_window)
        self.saveDeviceAction.setIcon(GUIToolKit.getIconByName('save'))
        self.saveDeviceAction.setObjectName('saveDeviceAction')
        self.saveDeviceAction.triggered.connect(devicesTabedWidget.saveDevice)

        self.addAction(self.saveDeviceAction)

        self.generateCodeAction = QtWidgets.QAction(main_window)
        self.generateCodeAction.setIcon(GUIToolKit.getIconByName('gen'))
        self.generateCodeAction.setObjectName('genertecode')
        self.generateCodeAction.triggered.connect(devicesTabedWidget.generateCode)

        self.addAction(self.generateCodeAction)
        self.addSeparator()

        self.openConsoleToolAction = QtWidgets.QAction(main_window)
        self.openConsoleToolAction.setIcon(GUIToolKit.getIconByName('consoletool'))
        self.openConsoleToolAction.setToolTip('Open Serial Cosole tool')
        self.openConsoleToolAction.setObjectName('openconsoletool')
        self.openConsoleToolAction.triggered.connect(devicesTabedWidget.openConsoleTool)

        self.addAction(self.openConsoleToolAction)

        self.addSeparator()


================================================
FILE: src/gui/workAreaTabbedWidget.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
from PyQt5 import QtWidgets
from src.gui.commandlinetool.commandlinetool import CommandLineConsoleTool
from src.gui.configtool.deviceConfigurationTool import DeviceConfigurationTool
from src.gui.configtool.generatedCodeDisplay import GeneratedCodeDisplay
from src.gui.configtool.treeViewConfigTool import TreeViewConfigTool
from src.simpleFOCConnector import SimpleFOCDevice


class WorkAreaTabbedWidget(QtWidgets.QTabWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setTabsClosable(True)
        self.setMovable(True)
        self.setObjectName('devicesTabWidget')

        self.device = SimpleFOCDevice.getInstance()

        self.cmdLineTool = None
        self.configDeviceTool = None
        self.generatedCodeTab = None
        self.activeToolsList = []

        self.tabCloseRequested.connect(self.removeTabHandler)

        self.setStyleSheet(
            'QTabBar::close - button { image: url(close.png) subcontrol - position: left; }')
        self.setStyleSheet('QTabBar::tab { height: 30px; width: 150px;}')

    def removeTabHandler(self, index):
        if type(self.currentWidget()) == CommandLineConsoleTool:
            self.cmdLineTool = None
        if type(self.currentWidget()) == DeviceConfigurationTool or type(
                self.currentWidget()) == TreeViewConfigTool:
            self.configDeviceTool = None
        if type(self.currentWidget()) == GeneratedCodeDisplay:
            self.generatedCodeTab = None
        if self.configDeviceTool == None and self.cmdLineTool == None:
            if self.device.isConnected:
                self.device.disConnect()

        self.activeToolsList.pop(index)
        self.removeTab(index)

    def addDeviceForm(self):
        if self.configDeviceTool is None:
            self.configDeviceTool = DeviceConfigurationTool()
            self.activeToolsList.append(self.configDeviceTool)
            self.addTab(self.configDeviceTool,
                        self.configDeviceTool.getTabIcon(), 'Device')
            self.setCurrentIndex(self.currentIndex() + 1)
            
    def addDeviceTree(self):
        if self.configDeviceTool is None:
            self.configDeviceTool = TreeViewConfigTool()
            self.activeToolsList.append(self.configDeviceTool)
            self.addTab(self.configDeviceTool,
                        self.configDeviceTool.getTabIcon(), 'Device')
            self.setCurrentIndex(self.currentIndex() + 1)

    def openDevice(self):
        if self.configDeviceTool is None:
            dlg = QtWidgets.QFileDialog()
            dlg.setFileMode(QtWidgets.QFileDialog.AnyFile)
            filenames = None
            if dlg.exec_():
                filenames = dlg.selectedFiles()
                try:
                    with open(filenames[0]) as json_file:
                        configurationInfo = json.load(json_file)
                        sfd = SimpleFOCDevice.getInstance()
                        sfd.configureDevice(configurationInfo)
                        self.configDeviceTool = TreeViewConfigTool()
                        sfd.openedFile = filenames
                        self.activeToolsList.append(self.configDeviceTool)
                        tabName = self.configDeviceTool.getTabName()
                        if tabName == '':
                            tabName = 'Device'
                        self.addTab(self.configDeviceTool,
                                    self.configDeviceTool.getTabIcon(), tabName)
                        self.setCurrentIndex(self.currentIndex() + 1)

                except Exception as exception:
                    msgBox = QtWidgets.QMessageBox()
                    msgBox.setIcon(QtWidgets.QMessageBox.Warning)
                    msgBox.setText('Error while opening selected file')
                    msgBox.setWindowTitle('SimpleFOC configDeviceTool')
                    msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
                    msgBox.exec()

    def saveDevice(self):
        if len(self.activeToolsList) > 0:
            currentconfigDeviceTool = self.activeToolsList[self.currentIndex()]
            if currentconfigDeviceTool.device.openedFile is None:
                options = QtWidgets.QFileDialog.Options()
                options |= QtWidgets.QFileDialog.DontUseNativeDialog
                fileName, _ = QtWidgets.QFileDialog.getSaveFileName(self,
                                                                    'Save device configuration',
                                                                    '',
                                                                    'JSON configuration file (*.json)',
                                                                    options=options)
                if fileName:
                    self.saveToFile(currentconfigDeviceTool.device, fileName)
            else:
                self.saveToFile(currentconfigDeviceTool.device,
                                currentconfigDeviceTool.device.openedFile)
                                
    def generateCode(self):
        if len(self.activeToolsList) > 0:
            currentconfigDeviceTool = self.activeToolsList[self.currentIndex()]
            self.generatedCodeTab = GeneratedCodeDisplay()
            self.activeToolsList.append(self.generatedCodeTab)
            self.addTab(self.generatedCodeTab,
                        self.generatedCodeTab.getTabIcon(), self.generatedCodeTab.getTabName())
            self.setCurrentIndex(self.currentIndex() + 1)


    def saveToFile(self, deviceToSave, file):
        if type(file) is list:
            with open(file[0], 'w', encoding='utf-8') as f:
                f.write(json.dumps(deviceToSave.toJSON(), indent=4, sort_keys=True))
        else:
            with open(file, 'w', encoding='utf-8') as f:
                f.write(json.dumps(deviceToSave.toJSON(), indent=4, sort_keys=True))

    def openConsoleTool(self):
        if self.cmdLineTool is None:
            self.cmdLineTool = CommandLineConsoleTool()
            self.activeToolsList.append(self.cmdLineTool)
            self.addTab(self.cmdLineTool,
                        self.cmdLineTool.getTabIcon(), 'Cmd Line')
            self.setCurrentIndex(self.currentIndex() + 1)


================================================
FILE: src/simpleFOCConnector.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
import threading
import time

import serial
from PyQt5 import QtCore, QtWidgets
from serial import SerialException
from collections import defaultdict

class PIDController:
    P = 0
    D = 0
    I = 0
    outputRamp = 0
    outputLimit = 0
    cmd =''

    def __init__(self, cmd):
        self.cmd = cmd
    
    def load(self, jsonValues):
        self.P = jsonValues['P']
        self.I = jsonValues['I']
        self.D = jsonValues['D']
        self.outputRamp = jsonValues['outputRamp']
        self.outputLimit = jsonValues['outputLimit']

    def serialize(self):
        return {
            'P': self.P,
            'I': self.I,
            'D': self.D,
            'outputRamp':self.outputRamp,
            'outputLimit':self.outputLimit
        }


class LowPassFilter:
    Tf = 0
    cmd =''
    cmdTf = 'F'

    def __init__(self, cmd):
        self.cmd = cmd


class Command:
    cmdName = ''
    cmd = ''

    def __init__(self,cmdname='Command', cmd=''):
        self.cmdName = cmdname
        self.cmd = cmd

    def load(self, jsonValues):
        self.cmdName = jsonValues['commandName']
        self.cmd = jsonValues['commandValue']

    def serialize(self):
        return {
            'commandName': self.cmdName,
            'commandValue': self.cmd
        }


class CustomCommands:
    customCommandsList = []

    def __init__(self,commandsLis=[]):
        for command in  commandsLis:
            self.customCommandsList.append(command)
    def load(self, jsonValues):
        for commandInJson in jsonValues:
            command = Command()
            command.load(commandInJson)
            self.customCommandsList.append(command)

    def serialize(self):
        serializedCustomCommands = defaultdict(list)
        for command in self.customCommandsList:
            serializedCommand = command.serialize()
            serializedCustomCommands['customCommands'].append(serializedCommand)
        return serializedCustomCommands

class SimpleFOCDevice:
    __instance = None

    TORQUE_CONTROL  = 0
    VELOCITY_CONTROL = 1
    ANGLE_CONTROL = 2
    VELOCITY_OPENLOOP_CONTROL = 3
    ANGLE_OPENLOOP_CONTROL = 4

    SINE_PWM  = 0
    SPACE_VECTOR_PWM = 1
    TRAPEZOIDAL_120 = 2
    TRAPEZOIDAL_150 = 3

    VOLTAGE_TORQUE = 0
    DC_CURRENT_TORQUE  = 1
    FOC_CURRENT_TORQUE = 2

    VELOCITY_PID = 'V'
    ANGLE_PID = 'A'
    CURRENT_Q_PID = 'Q'
    CURRENT_D_PID = 'D'

    PULL_CONFIG_ON_CONNECT = 'Pull config'
    PUSH_CONFG_ON_CONNECT = 'Push config'
    ONLY_CONNECT = 'Only connect'

    @staticmethod
    def getInstance():
        """ Static access method. """
        if SimpleFOCDevice.__instance == None:
            SimpleFOCDevice()
        return SimpleFOCDevice.__instance

    def __init__(self):
        """ Virtually private constructor. """
        if SimpleFOCDevice.__instance != None:
            raise Exception("This class is a singleton!")
        else:
            # serial connection variables
            self.serialPort = None
            self.responseThread = None
            self.isConnected = False
            self.openedFile = None

            self.connectionStateListenerList = []

            self.serialPortName = ""
            self.serialRate = 115200
            self.serialByteSize = serial.EIGHTBITS
            self.serialParity = serial.PARITY_NONE
            self.stopBits = serial.STOPBITS_ONE
            self.commProvider = SerialPortReceiveHandler()
            self.commProvider.commandDataReceived.connect(self.parseResponses)
            self.commProvider.stateMonitorReceived.connect(self.parseStateResponses)
            self.connectionID = ""

            # command id of the device
            self.devCommandID = ''

            # motion control paramters
            self.PIDVelocity = PIDController(self.VELOCITY_PID)
            self.PIDAngle = PIDController(self.ANGLE_PID)
            self.PIDCurrentQ = PIDController(self.CURRENT_Q_PID)
            self.PIDCurrentD = PIDController(self.CURRENT_D_PID)
            self.LPFVelocity = LowPassFilter(self.VELOCITY_PID)
            self.LPFAngle = LowPassFilter(self.ANGLE_PID)
            self.LPFCurrentQ = LowPassFilter(self.CURRENT_Q_PID)
            self.LPFCurrentD = LowPassFilter(self.CURRENT_D_PID)
            self.velocityLimit = 0
            self.voltageLimit = 0
            self.currentLimit = 0
            self.controlType =  SimpleFOCDevice.ANGLE_CONTROL
            self.torqueType =  SimpleFOCDevice.VOLTAGE_TORQUE
            self.initialTarget = 0
            self.motionDownsample = 0

            # monitor variables
            self.monitorDownsample = 0
            self.monitorVariables = 0

            # state variables
            self.target = 0
            self.stateUpdater = StateUpdateRunner(self)
            self.targetNow = 0
            self.angleNow = 0
            self.velocityNow = 0
            self.voltageQNow = 0
            self.voltageDNow = 0
            self.currentQNow = 0
            self.currentDNow = 0

            # general variables
            self.phaseResistance = 0
            self.deviceStatus = 0
            self.modulationType = 0
            self.modulationCentered = 1

            # sensor variables
            self.sensorElectricalZero = 0
            self.sensorZeroOffset = 0

            # list of custom commands
            self.customCommands = CustomCommands()

            # return the class instance
            SimpleFOCDevice.__instance = self


    def configureDevice(self, jsonValue):
        # motion control parameters
        self.PIDVelocity.load(jsonValue['PIDVelocity'])
        self.PIDAngle.load(jsonValue['PIDAngle'])
        self.PIDCurrentD.load(jsonValue['PIDCurrentD'])
        self.PIDCurrentQ.load(jsonValue['PIDCurrentQ'])
        
        # low pass filters
        self.LPFVelocity.Tf = jsonValue['LPFVelocity']
        self.LPFAngle.Tf = jsonValue['LPFAngle']
        self.LPFCurrentQ.Tf = jsonValue['LPFCurrentQ']
        self.LPFCurrentD.Tf = jsonValue['LPFCurrentD']
        # limit variables
        self.velocityLimit = jsonValue['velocityLimit']
        self.voltageLimit = jsonValue['voltageLimit']
        self.currentLimit = jsonValue['currentLimit']
        # motion control types
        self.controlType = jsonValue['controlType']
        self.torqueType = jsonValue['torqueType']
        self.motionDownsample = jsonValue['motionDownsample']

        # sensor zero offset and electrical zero offset
        self.sensorElectricalZero = jsonValue['sensorElectricalZero']
        self.sensorZeroOffset = jsonValue['sensorZeroOffset']

        # motor phase resistance
        self.phaseResistance = jsonValue['phaseResistance']

        # initial target
        self.initialTarget = jsonValue['initialTarget']
    
        # serial communication variables
        self.connectionID = jsonValue['connectionID']
        self.serialPortName = jsonValue['serialPortName']
        self.serialRate = jsonValue['serialRate']
        self.serialByteSize = jsonValue['serialByteSize']
        self.serialParity = jsonValue['serialParity']
        self.stopBits = jsonValue['stopBits']
        try:
            self.customCommands.customCommandsList = []
            self.customCommands.load(jsonValue['customCommands'])
        except KeyError:
            pass
        try:
            self.devCommandID = jsonValue['devCommandID']
        except KeyError:
            pass

    def configureConnection(self, configDict):
        self.connectionID = configDict['connectionID']
        self.serialPortName = configDict['serialPortName']
        self.serialRate = configDict['serialRate']
        self.serialByteSize = configDict['serialByteSize']
        self.serialParity = configDict['serialParity']
        self.stopBits = configDict['stopBits']

    def toJSON(self):
        valuesToSave = {
            'PIDVelocity': self.PIDVelocity.serialize(),
            'PIDAngle': self.PIDAngle.serialize(),
            'PIDCurrentD': self.PIDCurrentD.serialize(),
            'PIDCurrentQ': self.PIDCurrentQ.serialize(),
            'LPFVelocity':self.LPFVelocity.Tf,
            'LPFAngle':self.LPFAngle.Tf,
            'LPFCurrentD':self.LPFCurrentD.Tf,
            'LPFCurrentQ':self.LPFCurrentQ.Tf,
            'velocityLimit': self.velocityLimit,
            'voltageLimit': self.voltageLimit,
            'currentLimit': self.currentLimit,
            'controlType': self.controlType,
            'motionDownsample':self.motionDownsample,
            'torqueType': self.torqueType,
            'phaseResistance': self.phaseResistance,
            'sensorZeroOffset': self.sensorZeroOffset,
            'sensorElectricalZero': self.sensorElectricalZero,
            'initialTarget': self.initialTarget,
            'connectionID': self.connectionID,
            'serialPortName': self.serialPortName,
            'serialRate': self.serialRate,
            'serialByteSize': self.serialByteSize,
            'serialParity': self.serialParity,
            'stopBits': self.stopBits,
            'devCommandID': self.devCommandID,

        }
        valuesToSave.update(self.customCommands.serialize())
        return valuesToSave

        
    def toArduinoCode(self, generateParams = []):

        # code = "#include <SimpleFOC.h>\n\n"
        # code += "void setup(){\n\n"
        # code += "....\n\n"
        code = "\n"
        if generateParams[0] or generateParams==[]:
            code += "// control loop type and torque mode \n"
            code += "motor.torque_controller = TorqueControlType::"
            if self.torqueType == self.VOLTAGE_TORQUE:
                code += "voltage"
            elif self.torqueType == self.DC_CURRENT_TORQUE:
                code += "dc_current"
            elif self.torqueType == self.FOC_CURRENT_TORQUE:
                code += "foc_current"
            code += ";\n"
            code += "motor.controller = MotionControlType::"
            if self.controlType == self.TORQUE_CONTROL:
                code += "torque"
            elif self.controlType == self.VELOCITY_CONTROL:
                code += "velocity"
            elif self.controlType == self.ANGLE_CONTROL:
                code += "angle"
            elif self.controlType == self.VELOCITY_CONTROL:
                code += "velocity_openloop"
            elif self.controlType == self.ANGLE_CONTROL:
                code += "angle_openloop"
            code += ";\n"
            code += "motor.motion_downsample = " + str(self.motionDownsample) +";\n" 
            code += "\n"

        if generateParams[1] or generateParams==[]:
            code += "// velocity loop PID\n"  
            code += "motor.PID_velocity.P = " + str(self.PIDVelocity.P) +";\n"  
            code += "motor.PID_velocity.I = " + str(self.PIDVelocity.I) +";\n"  
            code += "motor.PID_velocity.D = " + str(self.PIDVelocity.D) +";\n"  
            code += "motor.PID_velocity.output_ramp = " + str(self.PIDVelocity.outputRamp) +";\n"  
            code += "motor.PID_velocity.limit = " + str(self.PIDVelocity.outputLimit) +";\n"  
            code += "// Low pass filtering time constant \n"  
            code += "motor.LPF_velocity.Tf = " + str(self.LPFVelocity.Tf) +";\n"  
        if generateParams[2] or generateParams==[]:
            code += "// angle loop PID\n"
            code += "motor.P_angle.P = " + str(self.PIDAngle.P) +";\n"  
            code += "motor.P_angle.I = " + str(self.PIDAngle.I) +";\n"   
            code += "motor.P_angle.D = " + str(self.PIDAngle.D) +";\n"    
            code += "motor.P_angle.output_ramp = " + str(self.PIDAngle.outputRamp) +";\n"   
            code += "motor.P_angle.limit = " + str(self.PIDAngle.outputLimit) +";\n"  
            code += "// Low pass filtering time constant \n" 
            code += "motor.LPF_angle.Tf = " + str(self.LPFAngle.Tf) +";\n"  
        if generateParams[3] or generateParams==[]: 
            code += "// current q loop PID \n"
            code += "motor.PID_current_q.P = " + str(self.PIDCurrentQ.P) +";\n"  
            code += "motor.PID_current_q.I = " + str(self.PIDCurrentQ.I) +";\n"   
            code += "motor.PID_current_q.D = " + str(self.PIDCurrentQ.D) +";\n"   
            code += "motor.PID_current_q.output_ramp = " + str(self.PIDCurrentQ.outputRamp) +";\n"  
            code += "motor.PID_current_q.limit = " + str(self.PIDCurrentQ.outputLimit) +";\n"  
            code += "// Low pass filtering time constant \n" 
            code += "motor.LPF_current_q.Tf = " + str(self.LPFCurrentQ.Tf) +";\n"  
        if generateParams[4] or generateParams==[]:
            code += "// current d loop PID\n"
            code += "motor.PID_current_d.P = " + str(self.PIDCurrentD.P) +";\n"   
            code += "motor.PID_current_d.I = " + str(self.PIDCurrentD.I) +";\n"  
            code += "motor.PID_current_d.D = " + str(self.PIDCurrentD.D) +";\n"  
            code += "motor.PID_current_d.output_ramp = " + str(self.PIDCurrentD.outputRamp) +";\n"   
            code += "motor.PID_current_d.limit = " + str(self.PIDCurrentD.outputLimit) +";\n"  
            code += "// Low pass filtering time constant \n" 
            code += "motor.LPF_current_d.Tf = " + str(self.LPFCurrentD.Tf) +";\n" 
 
        if generateParams[5] or generateParams==[]:
            code += "// Limits \n"
            code += "motor.velocity_limit = " + str(self.velocityLimit) +";\n" 
            code += "motor.voltage_limit = " + str(self.voltageLimit) +";\n" 
            code += "motor.current_limit = " + str(self.currentLimit) +";\n" 

        if generateParams[6] or generateParams==[]:
            code += "// sensor zero offset - home position \n"
            code += "motor.sensor_offset = " + str(self.sensorZeroOffset) +";\n" 

        if generateParams[7] or generateParams==[]:
            code += "// sensor zero electrical angle \n"
            code += "// this parameter enables skipping a part of initFOC \n"
            code += "motor.sensor_electrical_offset = " + str(self.sensorElectricalZero) +";\n" 

        if generateParams[8] or generateParams==[]:
            code += "// general settings \n"
            code += "// motor phase resistance \n"
            code += "motor.phase_resistance = " + str(self.sensorElectricalZero) +";\n" 
            
        if generateParams[9] or generateParams==[]:
            code += "// pwm modulation settings \n"
            code += "motor.foc_modulation = FOCModulationType::"
            if self.modulationType == self.SINE_PWM:
                code += "SinePWM"
            elif self.modulationType == self.SPACE_VECTOR_PWM:
                code += "SpaceVectorPWM"
            elif self.modulationType == self.TRAPEZOIDAL_120:
                code += "Trapezoid_120"
            elif self.modulationType == self.TRAPEZOIDAL_150:
                code += "Trapezoid_150"
            code += ";\n"
            code += "motor.modulation_centered = " + str(self.modulationCentered) +";\n" 

        # code += "\n\nmotor.init();\nmotor.initFOC();\n\n...\n\n }"
        # code += "\n\nvoid loop() {\n\n....\n\n}"
        
        return code

    def __initCommunications(self):
        self.serialPort = serial.Serial(self.serialPortName,
                                        self.serialRate,
                                        self.serialByteSize,
                                        self.serialParity,
                                        self.stopBits)

        self.commProvider.serialComm = self.serialPort
        self.commProvider.start()

    def __closeCommunication(self):
        self.serialPort.close()

    def connect(self, connectionMode):
        try:
            self.__initCommunications()
        except SerialException as serEx:
            logging.warning('Is not possible to open serial port')
            logging.warning('Port =' + self.serialPortName)
            logging.warning('Rate =' + str(self.serialRate))
            logging.warning('parity =' + str(self.serialParity))
            logging.warning('Byte size =' + str(self.serialByteSize))
            logging.warning('Stop bits=' + str(self.stopBits))

            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Warning)
            msgBox.setText('Error while trying to open serial port')
            msgBox.setWindowTitle('SimpleFOC ConfigTool')
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec()
            return False
        else:
            self.isConnected = True
            for listener in self.connectionStateListenerList:
                listener.connectionStateChanged(True)
            if connectionMode == SimpleFOCDevice.PULL_CONFIG_ON_CONNECT:
                self.pullConfiguration()
                if self.stateUpdater.stopped():
                    self.stateUpdater = StateUpdateRunner(self)
                self.stateUpdater.start()
            elif connectionMode == SimpleFOCDevice.PUSH_CONFG_ON_CONNECT:
                self.pushConfiguration()
                if self.stateUpdater.stopped():
                    self.stateUpdater = StateUpdateRunner(self)
                self.stateUpdater.start()
                pass
            return True

    def disConnect(self):
        self.isConnected = False
        self.__closeCommunication()
        self.stateUpdater.stop()
        for listener in self.connectionStateListenerList:
            listener.connectionStateChanged(False)

    def addConnectionStateListener(self, listener):
        self.connectionStateListenerList.append(listener)

    def sendCommand(self, command):
        if self.isConnected:
            self.serialPort.write((str(command) + '\n').encode('utf-8'))

    def setCommand(self, command, value):
        if self.isConnected:
           self.sendCommand(str(self.devCommandID) + str(command) + str(value))

    def getCommand(self, command):
        if self.isConnected:
           self.sendCommand(str(self.devCommandID) + str(command) )

    def sendControlType(self, loop_control_type):
        if self.isConnected:
            if loop_control_type  != '':
                self.controlType = loop_control_type    
            self.setCommand('C', str(loop_control_type))
            
    def sendTorqueType(self, torque_type):
        if self.isConnected:
            if torque_type  != '':
                self.torqueType = torque_type    
            self.setCommand('T', str(torque_type))
            
    def sendMotionDownsample(self, value):
        if self.isConnected:
            if value  != '':
                self.motionDownsample = value    
            self.setCommand('CD', str(value))

    def sendProportionalGain(self, pid, value ):
        if self.isConnected:
            if value  != '':
                pid.P = value
            self.setCommand(str(pid.cmd)+'P',  str(value))

    def sendIntegralGain(self, pid, value):
        if self.isConnected:
            if value  != '':
                pid.I = value
            self.setCommand(str(pid.cmd)+'I', str(value))

    def sendDerivativeGain(self, pid,  value):
        if self.isConnected:
            if value  != '':
                pid.D = value
            self.setCommand(str(pid.cmd)+'D', str(value))

    def sendOutputRamp(self, pid, value):
        if self.isConnected:
            if value  != '':
                pid.outputRamp = value
            self.setCommand(str(pid.cmd)+'R', str(value))

    def sendOutputLimit(self, pid, value):
        if self.isConnected:
            if value  != '':
                pid.outputLimit = value
            self.setCommand(str(pid.cmd)+'L', str(value))

    def sendLowPassFilter(self, lpf, value):
        if self.isConnected:
            if value  != '':
                lpf.Tf = value
            self.setCommand(str(lpf.cmd)+'F', str(value))

    def sendVelocityLimit(self, value):
        if self.isConnected:
            if value  != '':
                self.velocityLimit = value
            self.setCommand('LV', str(value))

    def sendVoltageLimit(self, value):
        if self.isConnected:
            if value  != '':
                self.voltageLimit = value
            self.setCommand('LU', str(value))

    def sendCurrentLimit(self, value):
        if self.isConnected:
            if value  != '':
                self.currentLimit = value
            self.setCommand('LC', str(value))

    def sendPhaseResistance(self, value):
        if self.isConnected:
            if value  != '':
                self.phaseResistance = value
            self.setCommand('R', str(value))

    def sendTargetValue(self, targetvalue):
        if self.isConnected:
            if targetvalue  != '':
                self.target = targetvalue
            self.setCommand('',self.target)

    def sendSensorZeroOffset(self, targetvalue):
        if self.isConnected:
            if targetvalue  != '':
                self.sensorZeroOffset = targetvalue
            self.setCommand('SM', str(targetvalue))

    def sendSensorZeroElectrical(self, targetvalue):
        if self.isConnected:
            if targetvalue  != '':
                self.sensorElectricalZero = targetvalue
            self.setCommand('SE', str(targetvalue))

    def sendDeviceStatus(self, targetvalue):
        if self.isConnected:
            if targetvalue != '':
                self.deviceStatus = targetvalue
            self.setCommand('E', str(targetvalue))

            
    def sendModulationCentered(self, targetvalue):
        if self.isConnected:
            if targetvalue != '':
                self.modulationCentered = targetvalue
            self.setCommand('WC', str(targetvalue))
            
    def sendModulationType(self, targetvalue):
        if self.isConnected:
            if targetvalue != '':
                self.modulationType = targetvalue
            self.setCommand('WT', str(targetvalue))
            
    def sendDeviceStatus(self, targetvalue):
        if self.isConnected:
            if targetvalue != '':
                self.deviceStatus = targetvalue
            self.setCommand('E', str(targetvalue))

    def sendMonitorDownsample(self, targetvalue):
        if self.isConnected:
            if targetvalue != '':
                self.monitorDownsample = targetvalue
            self.setCommand('MD', str(targetvalue))

    def sendMonitorClearVariables(self):
        if self.isConnected:
            self.monitorVariables = 0
            self.getCommand('MC')

    def sendMonitorVariables(self, vararray):
        if self.isConnected:
            if vararray != '':
                val = 0
                m  = 10**6
                for var in vararray:
                    val = val+ int(var)*m
                    m = m/10
                self.monitorVariables = vararray
                self.setCommand('MS', "{:07d}".format(int(val)))
            else:
                self.getCommand('MS')


    def updateStates(self):
        if self.isConnected:
            self.getCommand('MG0')
            time.sleep(100 / 1000)
            self.getCommand('MG1')
            time.sleep(100 / 1000)
            self.getCommand('MG2')
            time.sleep(100 / 1000)
            self.getCommand('MG3')
            time.sleep(100 / 1000)
            self.getCommand('MG4')
            time.sleep(100 / 1000)
            self.getCommand('MG5')
            time.sleep(100 / 1000)
            self.getCommand('MG6')
            time.sleep(100 / 1000)


    def pushConfiguration(self):
        print("push")
        # self.sendControlType(self.controlType)
        # self.sendProportionalGain(self.PIDVelocity, self.self)
        # self.sendIntegralGain(self.PIDVelocity, self.integralGainPID)
        # self.sendDerivativeGain(self.PIDVelocity, self.derivativeGainPID)
        # self.sendOutputRamp(self.PIDVelocity, self.voltageRampPID)
        # self.sendLowPassFilter(self.LPFVelocity,self.lowPassFilter)
        # self.sendPGain(self.anglePGain)
        # self.sendVelocityLimit(self.velocityLimit)
        # self.sendVoltageLimit(self.voltageLimit)
        # self.sendTargetValue(self.initialTarget)

    def pullPIDConf(self, pid, lpf):
        self.sendProportionalGain(pid,'')
        time.sleep(5 / 1000)
        self.sendIntegralGain(pid,'')
        time.sleep(5 / 1000)
        self.sendDerivativeGain(pid,'')
        time.sleep(5 / 1000)
        self.sendOutputRamp(pid,'')
        time.sleep(5 / 1000)
        self.sendOutputLimit(pid,'')
        time.sleep(5 / 1000)
        self.sendLowPassFilter(lpf,'')

    def pullConfiguration(self):
        time.sleep(5 / 1000)
        self.sendControlType('')
        time.sleep(5 / 1000)
        self.sendTorqueType('')
        time.sleep(5 / 1000)
        self.pullPIDConf( self.PIDVelocity, self.LPFVelocity)
        time.sleep(5 / 1000)
        self.pullPIDConf( self.PIDAngle, self.LPFAngle)
        time.sleep(5 / 1000)
        self.pullPIDConf( self.PIDCurrentD, self.LPFCurrentD)
        time.sleep(5 / 1000)
        self.pullPIDConf( self.PIDCurrentQ, self.LPFCurrentQ)
        time.sleep(5 / 1000)
        self.sendVelocityLimit('')
        time.sleep(5 / 1000)
        self.sendVoltageLimit('')
        time.sleep(5 / 1000)
        self.sendCurrentLimit('')
        time.sleep(5 / 1000)
        self.sendSensorZeroElectrical('')
        time.sleep(5 / 1000)
        self.sendSensorZeroOffset('')
        time.sleep(5 / 1000)
        self.sendMotionDownsample('')
        time.sleep(5 / 1000)
        self.sendPhaseResistance('')
        time.sleep(5 / 1000)
        self.sendModulationCentered('')
        time.sleep(5 / 1000)
        self.sendModulationCentered('')
        time.sleep(5 / 1000)
        self.sendDeviceStatus('')

    def parsePIDFResponse(self, pid, lpf, comandResponse):
        if 'P' in comandResponse:
            pid.P = float(comandResponse.replace('P: ', ''))
        if 'I' in comandResponse:
            pid.I = float(comandResponse.replace('I: ', ''))
        if 'D' in comandResponse:
            pid.D = float(comandResponse.replace('D: ', ''))
        if 'ramp' in comandResponse:
            val = comandResponse.replace('ramp:', '')
            if 'ovf' in val:
                pid.outputRamp = 0
            else:
                pid.outputRamp = float(comandResponse.replace('ramp:', ''))
        if 'limit' in comandResponse:
            pid.outputLimit = float(comandResponse.replace('limit:', ''))
        if 'Tf' in comandResponse:
            lpf.Tf = float(comandResponse.replace('Tf: ', ''))

    def parseLimitsResponse(self, comandResponse):
        if 'vel:' in comandResponse:
            self.velocityLimit = float(comandResponse.replace('vel:', ''))
        elif 'volt:' in comandResponse:
            self.voltageLimit = float(comandResponse.replace('volt:', ''))
        elif 'curr:' in comandResponse:
            self.currentLimit = float(comandResponse.replace('curr:', ''))

    def parseMotionResponse(self, comandResponse):
        if 'downsample' in comandResponse:
            self.motionDownsample = float(comandResponse.replace('downsample:', ''))
        elif 'torque' in comandResponse:
            self.controlType = 0
        elif 'angle open' in comandResponse:
            self.controlType = 4
        elif 'angle' in comandResponse:
            self.controlType = 2
        elif 'vel open' in comandResponse:
            self.controlType = 3
        elif 'vel' in comandResponse:
            self.controlType = 1
            
    def parsePWMModResponse(self, comandResponse):
        if 'center' in comandResponse:
            self.modulationCentered = float(comandResponse.replace('center:', ''))
        elif 'type' in comandResponse:
            comandResponse = comandResponse.replace('type:', '')
            if 'Sine' in comandResponse:
                self.modulationType = self.SINE_PWM
            elif 'SVPWM' in comandResponse:
                self.modulationType = self.SPACE_VECTOR_PWM
            elif 'Trap 120' in comandResponse:
                self.modulationType = self.TRAPEZOIDAL_120
            elif 'Trap 150' in comandResponse:
                self.modulationType = self.TRAPEZOIDAL_150
            
    def parseTorqueResponse(self, comandResponse):
        if 'volt' in comandResponse:
            self.torqueType = 0
        elif 'dc curr' in comandResponse:
            self.torqueType = 1
        elif 'foc curr' in comandResponse:
            self.torqueType = 2

    def parseSensorResponse(self, comandResponse):
        if 'el. offset' in comandResponse:
            self.sensorElectricalZero = float(comandResponse.replace('el. offset:', ''))
        elif 'offset' in comandResponse:
            self.sensorZeroOffset = float(comandResponse.replace('offset:', ''))

    def parseMonitorResponse(self, comandResponse):
        if 'all' in comandResponse:
            varStr = comandResponse.replace('all:', '')
            states = varStr.rstrip().split('\t', 7)
            self.targetNow = states[0]
            self.voltageQNow = states[1]
            self.voltageDNow = states[2]
            self.currentQNow = states[3]
            self.currentDNow = states[4]
            self.velocityNow = states[5]
            self.angleNow = states[6]
        if 'target' in comandResponse:
            self.targetNow = float(comandResponse.replace('target:', ''))
        elif 'Vq' in comandResponse:
            self.voltageQNow = float(comandResponse.replace('Vq:', ''))
        elif 'Vd' in comandResponse:
            self.voltageDNow = float(comandResponse.replace('Vd:', ''))
        elif 'Cq' in comandResponse:
            self.currentQNow = float(comandResponse.replace('Cq:', ''))
        elif 'Cd' in comandResponse:
            self.currentDNow = float(comandResponse.replace('Cd:', ''))
        elif 'vel' in comandResponse:
            self.velocityNow = float(comandResponse.replace('vel:', ''))
        elif 'angle' in comandResponse:
            self.angleNow = float(comandResponse.replace('angle:', ''))

    def parseResponses(self, comandResponse):
        if 'PID vel' in comandResponse:
            comandResponse = comandResponse.replace('PID vel|', '')
            self.parsePIDFResponse(self.PIDVelocity, self.LPFVelocity, comandResponse)
        elif 'PID angle' in comandResponse:
            comandResponse = comandResponse.replace('PID angle|', '')
            self.parsePIDFResponse(self.PIDAngle, self.LPFAngle, comandResponse)
        elif 'PID curr q' in comandResponse:
            comandResponse = comandResponse.replace('PID curr q|', '')
            self.parsePIDFResponse(self.PIDCurrentQ, self.LPFCurrentQ, comandResponse)
        elif 'PID curr d' in comandResponse:
            comandResponse = comandResponse.replace('PID curr d|', '')
            self.parsePIDFResponse(self.PIDCurrentD, self.LPFCurrentD, comandResponse)
        elif 'Limits' in comandResponse:
            comandResponse = comandResponse.replace('Limits|', '')
            self.parseLimitsResponse(comandResponse)
        elif 'Motion' in comandResponse:
            comandResponse = comandResponse.replace('Motion:', '')
            self.parseMotionResponse(comandResponse)
        elif 'Torque' in comandResponse:
            comandResponse = comandResponse.replace('Torque:', '')
            self.parseTorqueResponse(comandResponse)
        elif 'Sensor' in comandResponse:
            comandResponse = comandResponse.replace('Sensor |', '')
            self.parseSensorResponse(comandResponse)
        elif 'Monitor' in comandResponse:
            comandResponse = comandResponse.replace('Monitor |', '')
            self.parseMonitorResponse(comandResponse)
        elif 'Status' in comandResponse:
            self.deviceStatus = float(comandResponse.replace('Status:', ''))
        elif 'R phase' in comandResponse:
            self.phaseResistance = float(comandResponse.replace('R phase:', ''))
        elif 'PWM Mod' in comandResponse:
            comandResponse = comandResponse.replace('PWM Mod | ', '')
            self.parsePWMModResponse(comandResponse)

    def parseStateResponses(self, comandResponse):
        if 'Monitor' in comandResponse:
            comandResponse = comandResponse.replace('Monitor |', '')
            self.parseMonitorResponse(comandResponse)


class SerialPortReceiveHandler(QtCore.QThread):
    monitoringDataReceived = QtCore.pyqtSignal(list)
    commandDataReceived = QtCore.pyqtSignal(str)
    stateMonitorReceived = QtCore.pyqtSignal(str)
    rawDataReceived = QtCore.pyqtSignal(str)

    def __init__(self, serial_port=None, *args,**kwargs):
        super(SerialPortReceiveHandler, self).__init__(*args, **kwargs)
        self._stop_event = threading.Event()
        self.serialComm = serial_port

    def handle_received_data(self, data):
        if not data:
            return
            
        if self.isDataReceivedMonitoring(data):
            try:
                v = data.rstrip().split('\t')
                self.monitoringDataReceived.emit(v)
            except ValueError as error:
                logging.error(error, exc_info=True)
                logging.error('data =' + str(data), exc_info=True)
            except IndexError as error:
                logging.error(error, exc_info=True)
                logging.error('data =' + str(data), exc_info=True)
        elif self.isDataReceivedStates(data):
            self.stateMonitorReceived.emit(data.rstrip())
        else:
            self.commandDataReceived.emit(data.rstrip())
        self.rawDataReceived.emit(data.rstrip())

    def isDataReceivedMonitoring(self, data):
        if data[0].isdigit() or data[0] == '-':
            return True
        else:
            return False
            
    def isDataReceivedStates(self, data):
        if 'Monitor' in data:
            return True
        else:
            return False

    def run(self):
        try:
            while not self.stopped():
                if self.serialComm is not None:
                    if self.serialComm.isOpen():
                        reading = self.serialComm.readline()
                        if reading:
                            self.handle_received_data(reading.decode())
        except SerialException as serialException:
            logging.error(serialException, exc_info=True)
        except TypeError as typeError:
            logging.error(typeError, exc_info=True)
        except AttributeError as ae:
            logging.error(ae, exc_info=True)            

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()


class StateUpdateRunner(QtCore.QThread):

    def __init__(self, connector=None, *args,**kwargs):
        super(StateUpdateRunner, self).__init__(*args, **kwargs)
        self._stop_event = threading.Event()
        self.deviceConnector = connector
    def run(self):
        try:
            while not self.stopped():
                if self.deviceConnector is not None:
                    if self.deviceConnector.commProvider.serialComm.isOpen():
                        self.deviceConnector.updateStates()
                        time.sleep(1)
        except SerialException as serialException:
            logging.error(serialException, exc_info=True)

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()
Download .txt
gitextract_ef7r4v5m/

├── .github/
│   └── workflows/
│       └── create_executables.yml
├── .gitignore
├── LICENSE
├── README.md
├── command_to_generate_spec.txt
├── device.json
├── requirements.txt
├── scriptTest.py
├── simpleFOCStudio.py
├── simpleFOCStudio.spec
└── src/
    ├── gui/
    │   ├── commandlinetool/
    │   │   ├── commandlinetool.py
    │   │   └── configureConnectionWidget.py
    │   ├── configtool/
    │   │   ├── configureConnectionDialog.py
    │   │   ├── connectionControl.py
    │   │   ├── controlLoopConfig.py
    │   │   ├── deviceConfigurationTool.py
    │   │   ├── deviceInteractionFrame.py
    │   │   ├── deviceJoggingControl.py
    │   │   ├── deviceTreeview.py
    │   │   ├── devicesInspectorTree.py
    │   │   ├── droDisplayWidget.py
    │   │   ├── generalControls.py
    │   │   ├── generalSettingsWidget.py
    │   │   ├── generatedCodeDisplay.py
    │   │   ├── graphicWidget.py
    │   │   ├── pidConfiguration.py
    │   │   ├── torqueConfig.py
    │   │   └── treeViewConfigTool.py
    │   ├── mainWindow.py
    │   ├── resources/
    │   │   ├── add_motor.psd
    │   │   ├── motor.psd
    │   │   └── studioicon.icns
    │   ├── sharedcomnponets/
    │   │   ├── commandLineInterface.py
    │   │   └── sharedcomponets.py
    │   ├── toolbar.py
    │   └── workAreaTabbedWidget.py
    └── simpleFOCConnector.py
Download .txt
SYMBOL INDEX (276 symbols across 24 files)

FILE: src/gui/commandlinetool/commandlinetool.py
  class CommandLineConsoleTool (line 13) | class CommandLineConsoleTool(WorkAreaTabWidget):
    method __init__ (line 15) | def __init__(self, parent=None):
    method getTabIcon (line 31) | def getTabIcon(self):
    method getTabName (line 34) | def getTabName(self):

FILE: src/gui/commandlinetool/configureConnectionWidget.py
  class ConfigureConnection (line 11) | class ConfigureConnection(QtWidgets.QGroupBox):
    method __init__ (line 13) | def __init__(self, parent=None):
    method getConfigValues (line 98) | def getConfigValues(self):
    method stopBitsExtractor (line 109) | def stopBitsExtractor(self, value):
    method connectionStateChanged (line 115) | def connectionStateChanged(self, isConnectedFlag):
    method connectDisconnectDeviceAction (line 136) | def connectDisconnectDeviceAction(self):
    method connectAction (line 142) | def connectAction(self):
    method disConnectAction (line 147) | def disConnectAction(self):

FILE: src/gui/configtool/configureConnectionDialog.py
  class ConfigureSerailConnectionDialog (line 10) | class ConfigureSerailConnectionDialog(QtWidgets.QDialog):
    method __init__ (line 11) | def __init__(self, parent=None):
    method setupUi (line 16) | def setupUi(self, device=None):
    method fillForm (line 110) | def fillForm(self, deviceConnector):
    method getConfigValues (line 118) | def getConfigValues(self):
    method stopBitsExtractor (line 129) | def stopBitsExtractor(self, value):

FILE: src/gui/configtool/connectionControl.py
  class ConnectionControlGroupBox (line 11) | class ConnectionControlGroupBox(QtWidgets.QGroupBox):
    method __init__ (line 13) | def __init__(self, parent=None):
    method changeDevicedevCommandID (line 59) | def changeDevicedevCommandID(self):
    method connectDisconnectDeviceAction (line 62) | def connectDisconnectDeviceAction(self):
    method connectionStateChanged (line 69) | def connectionStateChanged(self, isConnected):
    method configureDeviceAction (line 79) | def configureDeviceAction(self):

FILE: src/gui/configtool/controlLoopConfig.py
  class ControlLoopGroupBox (line 8) | class ControlLoopGroupBox(QtWidgets.QGroupBox):
    method __init__ (line 9) | def __init__(self, parent=None):
    method connectionStateChanged (line 36) | def connectionStateChanged(self, deviceConnected):
    method enabeUI (line 42) | def enabeUI(self):
    method disableUI (line 45) | def disableUI(self):
    method setControlLopMode (line 48) | def setControlLopMode(self, value):
    method changeControlLoop (line 60) | def changeControlLoop(self):
    method commandResponseReceived (line 73) | def commandResponseReceived(self, cmdRespose):

FILE: src/gui/configtool/deviceConfigurationTool.py
  class DeviceConfigurationTool (line 20) | class DeviceConfigurationTool(WorkAreaTabWidget):
    method __init__ (line 22) | def __init__(self, parent=None):
    method getTabIcon (line 83) | def getTabIcon(self):
    method getTabName (line 86) | def getTabName(self):
    method configureConnection (line 89) | def configureConnection(self, configvalues):

FILE: src/gui/configtool/deviceInteractionFrame.py
  class DeviceInteractionFrame (line 11) | class DeviceInteractionFrame(QFrame):
    method __init__ (line 12) | def __init__(self, parent=None):

FILE: src/gui/configtool/deviceJoggingControl.py
  class DeviceJoggingControl (line 10) | class DeviceJoggingControl(QtWidgets.QGroupBox):
    method __init__ (line 11) | def __init__(self, parent=None):
    method connectionStateChanged (line 66) | def connectionStateChanged(self, isConnectedFlag):
    method enabeUI (line 71) | def enabeUI(self):
    method disableUI (line 74) | def disableUI(self):
    method joggingFastBackward (line 77) | def joggingFastBackward(self):
    method joggingBackward (line 82) | def joggingBackward(self):
    method joggingStop (line 87) | def joggingStop(self):
    method joggingFordward (line 95) | def joggingFordward(self):
    method joggingfastFordward (line 100) | def joggingfastFordward(self):

FILE: src/gui/configtool/deviceTreeview.py
  class DeviceTreeView (line 9) | class DeviceTreeView(QTreeWidget):
    method __init__ (line 10) | def __init__(self, parent=None):
    method customCommandsMenu (line 196) | def customCommandsMenu(self, position):
    method addCommandAction (line 220) | def addCommandAction(self):
    method executeCustomCommandAction (line 224) | def executeCustomCommandAction(self):
    method deleteCustomCommand (line 229) | def deleteCustomCommand(self):
    method eventFilter (line 236) | def eventFilter(self, obj, event):
    method addCustomCommand (line 252) | def addCustomCommand(sefl,selectedItem):
    method initCustomCommand (line 263) | def initCustomCommand(sefl, command):
    method addPIDSubtree (line 273) | def addPIDSubtree(self, parent,  label):
    method treeItemEdited (line 323) | def treeItemEdited(self, item, column):
    method sendCommand (line 336) | def sendCommand(self, item, column):
    method refreshPIDSubtree (line 382) | def refreshPIDSubtree(self, pidDisp, pidVal, lpfVal):
    method commandResponseReceived (line 390) | def commandResponseReceived(self, comandResponse):
    method stateResponseReceived (line 398) | def stateResponseReceived(self, comandResponse):
    method refreshDeviceTree (line 410) | def refreshDeviceTree(self):
    method setTorqueMode (line 434) | def setTorqueMode(self, value):
    method changeTorque (line 444) | def changeTorque(self):
    method setEnabledDisabled (line 453) | def setEnabledDisabled(self, value):
    method changeStatus (line 461) | def changeStatus(self):
    method setModCenter (line 468) | def setModCenter(self,value):
    method changeModCenter (line 473) | def changeModCenter(self):
    method setModType (line 480) | def setModType(self, value):
    method changeModType (line 492) | def changeModType(self):
    method setControlLopMode (line 503) | def setControlLopMode(self, value):
    method changeControlLoop (line 517) | def changeControlLoop(self):
    method connectionStateChanged (line 530) | def connectionStateChanged(self, connectionFlag):

FILE: src/gui/configtool/devicesInspectorTree.py
  class DevicesInspectorTree (line 13) | class DevicesInspectorTree(QFrame):
    method __init__ (line 14) | def __init__(self, parent=None):

FILE: src/gui/configtool/droDisplayWidget.py
  class DROGroupBox (line 10) | class DROGroupBox(QtWidgets.QGroupBox):
    method __init__ (line 12) | def __init__(self, parent=None):
    method connectionStateChanged (line 73) | def connectionStateChanged(self, isConnectedFlag):
    method enabeUI (line 81) | def enabeUI(self):
    method disableUI (line 84) | def disableUI(self):
    method initDiplay (line 87) | def initDiplay(self):
    method putStyleToLCDNumber (line 93) | def putStyleToLCDNumber(self, lcdNumber):
    method setColor (line 98) | def setColor(self, palette, colorTouple):
    method commandResponseReceived (line 112) | def commandResponseReceived(self, cmdRespose):

FILE: src/gui/configtool/generalControls.py
  class GeneralControls (line 9) | class GeneralControls(QtWidgets.QGroupBox):
    method __init__ (line 11) | def __init__(self, parent=None):
    method connectionStateChanged (line 57) | def connectionStateChanged(self, deviceConnected):
    method enabeUI (line 63) | def enabeUI(self):
    method disableUI (line 66) | def disableUI(self):
    method setSensorZero (line 69) | def setSensorZero(self):
    method setTargetZero (line 73) | def setTargetZero(self):
    method toggleEnable (line 76) | def toggleEnable(self):
    method commandResponseReceived (line 80) | def commandResponseReceived(self, comandResponse):
    method reloadValues (line 83) | def reloadValues(self):

FILE: src/gui/configtool/generalSettingsWidget.py
  class GeneralSettingsGroupBox (line 9) | class GeneralSettingsGroupBox(QtWidgets.QGroupBox):
    method __init__ (line 11) | def __init__(self, parent=None):
    method connectionStateChanged (line 84) | def connectionStateChanged(self, deviceConnected):
    method enabeUI (line 90) | def enabeUI(self):
    method disableUI (line 93) | def disableUI(self):
    method sendMotionDownsampleAction (line 96) | def sendMotionDownsampleAction(self):
    method sendCurrentLimitAction (line 102) | def sendCurrentLimitAction(self):
    method sendVelLimitAction (line 108) | def sendVelLimitAction(self):
    method sendVoltageLimitAction (line 114) | def sendVoltageLimitAction(self):
    method commandResponseReceived (line 120) | def commandResponseReceived(self, comandResponse):
    method reloadValues (line 123) | def reloadValues(self):

FILE: src/gui/configtool/generatedCodeDisplay.py
  class GenerateCodeDialog (line 14) | class GenerateCodeDialog(QtWidgets.QDialog):
    method __init__ (line 15) | def __init__(self, parent=None):
  class GeneratedCodeDisplay (line 109) | class GeneratedCodeDisplay(WorkAreaTabWidget):
    method __init__ (line 111) | def __init__(self, parent=None ):
    method getTabIcon (line 172) | def getTabIcon(self):
    method getTabName (line 175) | def getTabName(self):
  class MyHighlighter (line 179) | class MyHighlighter( QSyntaxHighlighter ):
    method __init__ (line 181) | def __init__( self, parent, theme ):
    method highlightBlock (line 207) | def highlightBlock( self, text ):
  class HighlightingRule (line 217) | class HighlightingRule():
    method __init__ (line 218) | def __init__( self, pattern, format ):

FILE: src/gui/configtool/graphicWidget.py
  class SimpleFOCGraphicWidget (line 12) | class SimpleFOCGraphicWidget(QtWidgets.QGroupBox):
    method __init__ (line 24) | def __init__(self, parent=None):
    method connectionStateChanged (line 78) | def connectionStateChanged(self, deviceConnected):
    method enabeUI (line 88) | def enabeUI(self):
    method disableUI (line 91) | def disableUI(self):
    method signalPlotFlagUpdate (line 94) | def signalPlotFlagUpdate(self):
    method connectioStatusUpdate (line 104) | def connectioStatusUpdate(self, connectedFlag):
    method upDateGraphic (line 110) | def upDateGraphic(self, signalList):
    method computeStatic (line 131) | def computeStatic(self, array):
    method updatePlot (line 138) | def updatePlot(self):
  class ControlPlotPanel (line 146) | class ControlPlotPanel(QtWidgets.QWidget):
    method __init__ (line 148) | def __init__(self, parent=None, controllerPlotWidget=None):
    method startStoPlotAction (line 211) | def startStoPlotAction(self):
    method pauseContinuePlotAction (line 232) | def pauseContinuePlotAction(self):
    method stopAndResetPlot (line 245) | def stopAndResetPlot(self):
    method zoomAllPlot (line 250) | def zoomAllPlot(self):
    method changeDownsampling (line 253) | def changeDownsampling(self):
    method updateMonitorVariables (line 257) | def updateMonitorVariables(self):

FILE: src/gui/configtool/pidConfiguration.py
  class PidGroupBox (line 8) | class PidGroupBox(QtWidgets.QGroupBox):
    method __init__ (line 10) | def __init__(self, parent=None):
    method connectionStateChanged (line 112) | def connectionStateChanged(self, deviceConnected):
    method enabeUI (line 118) | def enabeUI(self):
    method disableUI (line 121) | def disableUI(self):
    method sendDerivativeGainAction (line 124) | def sendDerivativeGainAction(self):
    method sendProportionalGainAction (line 130) | def sendProportionalGainAction(self):
    method sendIntegralGainAction (line 136) | def sendIntegralGainAction(self):
    method sendRampAction (line 142) | def sendRampAction(self):
    method sendLPFAction (line 148) | def sendLPFAction(self):
    method reloadPIDValues (line 154) | def reloadPIDValues(self):
    method changePIDF (line 161) | def changePIDF(self):
    method commandResponseReceived (line 179) | def commandResponseReceived(self, commandDataReceived):

FILE: src/gui/configtool/torqueConfig.py
  class TorqueGroupBox (line 8) | class TorqueGroupBox(QtWidgets.QGroupBox):
    method __init__ (line 9) | def __init__(self, parent=None):
    method connectionStateChanged (line 37) | def connectionStateChanged(self, deviceConnected):
    method enabeUI (line 43) | def enabeUI(self):
    method disableUI (line 46) | def disableUI(self):
    method setTorqueMode (line 49) | def setTorqueMode(self, value):
    method changeTorque (line 57) | def changeTorque(self):
    method commandResponseReceived (line 66) | def commandResponseReceived(self, cmdRespose):

FILE: src/gui/configtool/treeViewConfigTool.py
  class TreeViewConfigTool (line 13) | class TreeViewConfigTool(WorkAreaTabWidget):
    method __init__ (line 15) | def __init__(self, parent=None):
    method getTabIcon (line 32) | def getTabIcon(self):
    method getTabName (line 35) | def getTabName(self):

FILE: src/gui/mainWindow.py
  class UserInteractionMainWindow (line 9) | class UserInteractionMainWindow(object):
    method setupUi (line 11) | def setupUi(self, main_window):

FILE: src/gui/sharedcomnponets/commandLineInterface.py
  class CommandLineWidget (line 9) | class CommandLineWidget(QtWidgets.QGroupBox):
    method __init__ (line 11) | def __init__(self, parent=None):
    method connectionStateChanged (line 66) | def connectionStateChanged(self, deviceConnected):
    method enabeUI (line 74) | def enabeUI(self):
    method disableUI (line 83) | def disableUI(self):
    method publishCommandResponseData (line 88) | def publishCommandResponseData(self, data):
    method clearAction (line 92) | def clearAction(self):
    method sendAction (line 95) | def sendAction(self):
    method sendListDevices (line 99) | def sendListDevices(self):

FILE: src/gui/sharedcomnponets/sharedcomponets.py
  class GUIToolKit (line 8) | class GUIToolKit(object):
    method getIconByName (line 21) | def getIconByName(icoName):
  class ConfigQLineEdit (line 79) | class ConfigQLineEdit(QtWidgets.QLineEdit):
    method __init__ (line 82) | def __init__(self, parent=None):
    method keyPressEvent (line 86) | def keyPressEvent(self, event):
  class WorkAreaTabWidget (line 92) | class WorkAreaTabWidget(QtWidgets.QTabWidget):
    method __init__ (line 93) | def __init__(self, parent=None):
    method getTabIcon (line 97) | def getTabIcon(self):
    method getTabName (line 100) | def getTabName(self):
  class SerialPortComboBox (line 103) | class SerialPortComboBox(QtWidgets.QComboBox):
    method __init__ (line 104) | def __init__(self, parent=None, snifer=None):
    method getAvailableSerialPortNames (line 108) | def getAvailableSerialPortNames(self):
    method showPopup (line 116) | def showPopup(self):

FILE: src/gui/toolbar.py
  class SimpleFOCConfigToolBar (line 7) | class SimpleFOCConfigToolBar(QtWidgets.QToolBar):
    method __init__ (line 9) | def __init__(self,main_window, devicesTabedWidget,  parent=None):

FILE: src/gui/workAreaTabbedWidget.py
  class WorkAreaTabbedWidget (line 12) | class WorkAreaTabbedWidget(QtWidgets.QTabWidget):
    method __init__ (line 14) | def __init__(self, parent=None):
    method removeTabHandler (line 33) | def removeTabHandler(self, index):
    method addDeviceForm (line 48) | def addDeviceForm(self):
    method addDeviceTree (line 56) | def addDeviceTree(self):
    method openDevice (line 64) | def openDevice(self):
    method saveDevice (line 94) | def saveDevice(self):
    method generateCode (line 111) | def generateCode(self):
    method saveToFile (line 121) | def saveToFile(self, deviceToSave, file):
    method openConsoleTool (line 129) | def openConsoleTool(self):

FILE: src/simpleFOCConnector.py
  class PIDController (line 12) | class PIDController:
    method __init__ (line 20) | def __init__(self, cmd):
    method load (line 23) | def load(self, jsonValues):
    method serialize (line 30) | def serialize(self):
  class LowPassFilter (line 40) | class LowPassFilter:
    method __init__ (line 45) | def __init__(self, cmd):
  class Command (line 49) | class Command:
    method __init__ (line 53) | def __init__(self,cmdname='Command', cmd=''):
    method load (line 57) | def load(self, jsonValues):
    method serialize (line 61) | def serialize(self):
  class CustomCommands (line 68) | class CustomCommands:
    method __init__ (line 71) | def __init__(self,commandsLis=[]):
    method load (line 74) | def load(self, jsonValues):
    method serialize (line 80) | def serialize(self):
  class SimpleFOCDevice (line 87) | class SimpleFOCDevice:
    method getInstance (line 115) | def getInstance():
    method __init__ (line 121) | def __init__(self):
    method configureDevice (line 196) | def configureDevice(self, jsonValue):
    method configureConnection (line 244) | def configureConnection(self, configDict):
    method toJSON (line 252) | def toJSON(self):
    method toArduinoCode (line 285) | def toArduinoCode(self, generateParams = []):
    method __initCommunications (line 392) | def __initCommunications(self):
    method __closeCommunication (line 402) | def __closeCommunication(self):
    method connect (line 405) | def connect(self, connectionMode):
    method disConnect (line 440) | def disConnect(self):
    method addConnectionStateListener (line 447) | def addConnectionStateListener(self, listener):
    method sendCommand (line 450) | def sendCommand(self, command):
    method setCommand (line 454) | def setCommand(self, command, value):
    method getCommand (line 458) | def getCommand(self, command):
    method sendControlType (line 462) | def sendControlType(self, loop_control_type):
    method sendTorqueType (line 468) | def sendTorqueType(self, torque_type):
    method sendMotionDownsample (line 474) | def sendMotionDownsample(self, value):
    method sendProportionalGain (line 480) | def sendProportionalGain(self, pid, value ):
    method sendIntegralGain (line 486) | def sendIntegralGain(self, pid, value):
    method sendDerivativeGain (line 492) | def sendDerivativeGain(self, pid,  value):
    method sendOutputRamp (line 498) | def sendOutputRamp(self, pid, value):
    method sendOutputLimit (line 504) | def sendOutputLimit(self, pid, value):
    method sendLowPassFilter (line 510) | def sendLowPassFilter(self, lpf, value):
    method sendVelocityLimit (line 516) | def sendVelocityLimit(self, value):
    method sendVoltageLimit (line 522) | def sendVoltageLimit(self, value):
    method sendCurrentLimit (line 528) | def sendCurrentLimit(self, value):
    method sendPhaseResistance (line 534) | def sendPhaseResistance(self, value):
    method sendTargetValue (line 540) | def sendTargetValue(self, targetvalue):
    method sendSensorZeroOffset (line 546) | def sendSensorZeroOffset(self, targetvalue):
    method sendSensorZeroElectrical (line 552) | def sendSensorZeroElectrical(self, targetvalue):
    method sendDeviceStatus (line 558) | def sendDeviceStatus(self, targetvalue):
    method sendModulationCentered (line 565) | def sendModulationCentered(self, targetvalue):
    method sendModulationType (line 571) | def sendModulationType(self, targetvalue):
    method sendDeviceStatus (line 577) | def sendDeviceStatus(self, targetvalue):
    method sendMonitorDownsample (line 583) | def sendMonitorDownsample(self, targetvalue):
    method sendMonitorClearVariables (line 589) | def sendMonitorClearVariables(self):
    method sendMonitorVariables (line 594) | def sendMonitorVariables(self, vararray):
    method updateStates (line 608) | def updateStates(self):
    method pushConfiguration (line 626) | def pushConfiguration(self):
    method pullPIDConf (line 639) | def pullPIDConf(self, pid, lpf):
    method pullConfiguration (line 652) | def pullConfiguration(self):
    method parsePIDFResponse (line 686) | def parsePIDFResponse(self, pid, lpf, comandResponse):
    method parseLimitsResponse (line 704) | def parseLimitsResponse(self, comandResponse):
    method parseMotionResponse (line 712) | def parseMotionResponse(self, comandResponse):
    method parsePWMModResponse (line 726) | def parsePWMModResponse(self, comandResponse):
    method parseTorqueResponse (line 740) | def parseTorqueResponse(self, comandResponse):
    method parseSensorResponse (line 748) | def parseSensorResponse(self, comandResponse):
    method parseMonitorResponse (line 754) | def parseMonitorResponse(self, comandResponse):
    method parseResponses (line 780) | def parseResponses(self, comandResponse):
    method parseStateResponses (line 816) | def parseStateResponses(self, comandResponse):
  class SerialPortReceiveHandler (line 822) | class SerialPortReceiveHandler(QtCore.QThread):
    method __init__ (line 828) | def __init__(self, serial_port=None, *args,**kwargs):
    method handle_received_data (line 833) | def handle_received_data(self, data):
    method isDataReceivedMonitoring (line 853) | def isDataReceivedMonitoring(self, data):
    method isDataReceivedStates (line 859) | def isDataReceivedStates(self, data):
    method run (line 865) | def run(self):
    method stop (line 880) | def stop(self):
    method stopped (line 883) | def stopped(self):
  class StateUpdateRunner (line 887) | class StateUpdateRunner(QtCore.QThread):
    method __init__ (line 889) | def __init__(self, connector=None, *args,**kwargs):
    method run (line 893) | def run(self):
    method stop (line 903) | def stop(self):
    method stopped (line 906) | def stopped(self):
Condensed preview — 37 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (175K chars).
[
  {
    "path": ".github/workflows/create_executables.yml",
    "chars": 1383,
    "preview": "name: Package Application with Pyinstaller\n\non:\n  push:\n    tags:\n      - \"v*.*.*\"\n\njobs:\n\n  build_windows:\n    runs-on:"
  },
  {
    "path": ".gitignore",
    "chars": 50,
    "preview": "/venv\n/.idea\n**/*.log\n**/__pycache__\n\nbuild/\ndist/"
  },
  {
    "path": "LICENSE",
    "chars": 1067,
    "preview": "MIT License\n\nCopyright (c) 2021 JorgeMaker\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
  },
  {
    "path": "README.md",
    "chars": 6558,
    "preview": "## *Simple**FOC**Studio*\n\nGraphical user interface for the [*Simple**FOC**library*](https://github.com/simplefoc). This "
  },
  {
    "path": "command_to_generate_spec.txt",
    "chars": 114,
    "preview": "pyi-makespec --onefile --noconsole --icon src/gui/resources/studioicon.icns --add-data src:src simpleFOCStudio.py\n"
  },
  {
    "path": "device.json",
    "chars": 1239,
    "preview": "{\n    \"LPFAngle\": 0.0,\n    \"LPFCurrentD\": 0.005,\n    \"LPFCurrentQ\": 0.005,\n    \"LPFVelocity\": 0.2,\n    \"PIDAngle\": {\n   "
  },
  {
    "path": "requirements.txt",
    "chars": 163,
    "preview": "# Requirements for SimpleFOCStudio\nPyQt5==5.15.9\npyqtgraph==0.13.1\npyserial==3.5\nnumpy==1.24.0\n# Requirements for Pyinst"
  },
  {
    "path": "scriptTest.py",
    "chars": 946,
    "preview": "from src.simpleFOCConnector import SimpleFOCDevice\nimport time\nif __name__ == '__main__':\n    deviceConnector = SimpleFO"
  },
  {
    "path": "simpleFOCStudio.py",
    "chars": 1052,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\" This module contains ans script to start the SimpleFOC ConfigTool, a G"
  },
  {
    "path": "simpleFOCStudio.spec",
    "chars": 728,
    "preview": "# -*- mode: python ; coding: utf-8 -*-\n\n\na = Analysis(\n    ['simpleFOCStudio.py'],\n    pathex=[],\n    binaries=[],\n    d"
  },
  {
    "path": "src/gui/commandlinetool/commandlinetool.py",
    "chars": 1228,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import QtWidgets\n\nfrom src.gui.commandlinetool.configureConnect"
  },
  {
    "path": "src/gui/commandlinetool/configureConnectionWidget.py",
    "chars": 6236,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport serial\nfrom PyQt5 import (QtGui, QtCore, QtWidgets)\n\nfrom src.gui.s"
  },
  {
    "path": "src/gui/configtool/configureConnectionDialog.py",
    "chars": 5761,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport serial\nfrom PyQt5 import (QtCore, QtGui, QtWidgets)\n\nfrom src.gui.s"
  },
  {
    "path": "src/gui/configtool/connectionControl.py",
    "chars": 3520,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import QtWidgets\n\nfrom src.gui.configtool.configureConnectionDi"
  },
  {
    "path": "src/gui/configtool/controlLoopConfig.py",
    "chars": 2844,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import QtWidgets\n\nfrom src.simpleFOCConnector import SimpleFOCD"
  },
  {
    "path": "src/gui/configtool/deviceConfigurationTool.py",
    "chars": 4121,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import QtWidgets\n\nfrom src.gui.configtool.connectionControl imp"
  },
  {
    "path": "src/gui/configtool/deviceInteractionFrame.py",
    "chars": 1135,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5.QtCore import Qt\nfrom PyQt5.QtWidgets import (QVBoxLayout, QFra"
  },
  {
    "path": "src/gui/configtool/deviceJoggingControl.py",
    "chars": 4498,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom PyQt5 import (QtGui, QtWidgets, QtCore)\n\nfrom src.gui.sharedcomnpone"
  },
  {
    "path": "src/gui/configtool/deviceTreeview.py",
    "chars": 24568,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import (QtWidgets,QtCore)\nfrom PyQt5.Qt import QTreeWidget\nfrom"
  },
  {
    "path": "src/gui/configtool/devicesInspectorTree.py",
    "chars": 1268,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5.QtWidgets import (QVBoxLayout, QFrame)\n\nfrom src.gui.configtool"
  },
  {
    "path": "src/gui/configtool/droDisplayWidget.py",
    "chars": 4610,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom PyQt5 import (QtGui,QtWidgets)\n\nfrom src.gui.sharedcomnponets.shared"
  },
  {
    "path": "src/gui/configtool/generalControls.py",
    "chars": 3158,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import (QtGui, QtWidgets, QtCore)\n\nfrom src.gui.sharedcomnponet"
  },
  {
    "path": "src/gui/configtool/generalSettingsWidget.py",
    "chars": 4942,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import (QtGui, QtWidgets, QtCore)\n\nfrom src.gui.sharedcomnponet"
  },
  {
    "path": "src/gui/configtool/generatedCodeDisplay.py",
    "chars": 10604,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import QtWidgets\nfrom PyQt5.QtCore import QRegExp\nfrom PyQt5.Qt"
  },
  {
    "path": "src/gui/configtool/graphicWidget.py",
    "chars": 11545,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport logging\n\nimport numpy as np\nimport pyqtgraph as pg\nfrom PyQt5 impor"
  },
  {
    "path": "src/gui/configtool/pidConfiguration.py",
    "chars": 7498,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import (QtGui, QtWidgets, QtCore)\nfrom src.gui.sharedcomnponets"
  },
  {
    "path": "src/gui/configtool/torqueConfig.py",
    "chars": 2291,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import QtWidgets\n\nfrom src.simpleFOCConnector import SimpleFOCD"
  },
  {
    "path": "src/gui/configtool/treeViewConfigTool.py",
    "chars": 1201,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5.QtCore import Qt\nfrom PyQt5.QtWidgets import (QVBoxLayout, QSpl"
  },
  {
    "path": "src/gui/mainWindow.py",
    "chars": 1443,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import (QtCore, QtWidgets)\n\nfrom src.gui.toolbar import SimpleF"
  },
  {
    "path": "src/gui/sharedcomnponets/commandLineInterface.py",
    "chars": 3748,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import (QtGui, QtWidgets)\n\nfrom src.gui.sharedcomnponets.shared"
  },
  {
    "path": "src/gui/sharedcomnponets/sharedcomponets.py",
    "chars": 4027,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport os\nfrom PyQt5 import (QtGui, QtWidgets,QtCore)\nfrom serial.tools im"
  },
  {
    "path": "src/gui/toolbar.py",
    "chars": 2843,
    "preview": "# !/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom PyQt5 import QtWidgets\nfrom src.gui.sharedcomnponets.sharedcomponets"
  },
  {
    "path": "src/gui/workAreaTabbedWidget.py",
    "chars": 6313,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport json\nfrom PyQt5 import QtWidgets\nfrom src.gui.commandlinetool.comma"
  },
  {
    "path": "src/simpleFOCConnector.py",
    "chars": 35438,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport logging\nimport threading\nimport time\n\nimport serial\nfrom PyQt5 impo"
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the JorgeMaker/SimpleFOCStudio GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 37 files (164.2 KB), approximately 38.9k tokens, and a symbol index with 276 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!