If you use PySide6 and have developed against PySide6 version 6.2.x, and you upgrade to 6.3 or later, you may find the following failures.
Module Import Error
ModuleNotFoundError: No module named 'PySide6.QtCore'
The Qt documentation hints at it, so if you performed just a pip install to the new version, then it is likely you’re issue. Instead uninstall and re-install.
In case you are updating your 6.2.x install, make sure the PySide6_Essentials and PySide6_Addons wheels are getting installed, otherwise, uninstall and install PySide6 to get the new structure.
After upgrading PySide6 to 6.5 on a Ubuntu 20.04, attempting to load an application functional with PySide6 6.2.4 you may find it fails on a missing plugin as follows.
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: xcb, vnc, wayland, minimalegl, vkkhrdisplay, offscreen, wayland-egl, minimal, linuxfb, eglfs.
If you enable debug by adding the environment variable …
QT_DEBUG_PLUGINS=1
… you may see later versions of PySide6 are looking for -cursor xcb library also.
libxcb-cursor.so.0: cannot open shared object file: No such file or directory
This can be installed using apt install as follows
We recommend always using a project name with the docker-compose -p argument.
# start two separate instances of the same docker-compose project
docker-compose -p dev_instance_1 up
docker-compose -p dev_instance_2 up
Docker compose nicely defines and contains your services and is pretty straight forward. It is not designed for large scale deployment though and a big gotcha is that if you run multiple instances on a single computer/server, you may destroy parts of your existing instance, so take care and ALWAYS use project names if you are using multiple instances on the one server. If you are using docker-compose for your development (as we) you will likely run into this.
Volumes across Instances
The danger of multiple instances extends further if you are defining volumes. For this reason if you are using volumes in your multi instance development, consider using extensible yaml files as detailed in Docker docs.
List the docker services, and then connect using docker exec.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dbc1effc3903 dev_project/nginx:latest "nginx -g 'daemon of…" 3 weeks ago Up Less than a second 443/tcp, 0.0.0.0:81->80/tcp, :::81->80/tcp dev_instance_1_nginx_1
# select identifier from list
docker exec -it dbc1effc3903 /bin/bash
bash-5.1# echo here you are on the docker cli
If you have worked with network capable embedded devices, you will have worked with web interfaces to control them as it is a convenient UI interface.
If you have an interface written in AngularJS, then you may be considering updating to Angular as a natural progression.
There are numerous examples on line of controlled and gradual ways to do this, and they seem very valid, but most of them require a consistent architecture on the AngularJS side.
If your main aim is to brute replace routes/pages one by one. i.e. Create a new Angular page to replace the AngularJS one, then caressing AngularJS into Angular ‘style’ is probably not good value for money.
Instead, here is a summary of some sites found which together will allow you to
upgrade your entire AngularJS site into a parent Angular site.
route/re-direct to the base page of your AngularJS site (and effectively hand over the router)
Install a event dispatcher form AngularJS to Angular for information that the new pages need from the old ones.
The relevant piece here is the ‘window:message’ where window is a system string, as shown in the reference above, and the message is what the AngularJS dispatcher (see further down) has in its CustomEvent.
On the AngularJS side, you need to dispatch the event, as follows.
angular.module('Main', ['ngTouch'])
.controller('MainController', ['$window', '$scope', '$q', '$http', '$location', '$interval') {
---snip---
$scope.someFunction = function () {
// data here is some variable/object
yourDispatcher({'your_msg_code': data});
---snip---
}
function yourDispatcher(data) {
// message and detail are part of the custom event so need to be just that.
var event = new CustomEvent('message', {
'detail' : data
});
window.dispatchEvent(event);
}
---snip---
}
When it comes to user interfaces Qt® software is good at it, and we love QtQuick and the QML language.
If you have developed UIs after the mobile boom (post 2005), you will have developed List Views. Every platform has them.
There are a fair view examples for Qt software List Views, both for PySide2/PyQt and C++, which point to using QAbstractListModel.
Many of them though point you at list views which show multiple string values. For example a list view of Users with first name and last name. The examples show how to extracts each of these strings in the QAbstractListModel using the Roles in the model.
Instead it would be nice to use a ‘variant’ to obtain a reference to your own class, which will have properties and methods which you can reference directly from your QML Qt software.
In Python this is reasonable straight forward because everything is a variant and the integration works ‘naturally’ as it were. So returning your class via the data() method of the QAbstractListModel works ‘out of the box’.
For C++ classes it is not as intuitive, primarily because to expose your class members and properties to QML, you need a QObject, as detailed in the guidelines provided in the Qt software documentation on integrating C++ with QML language. Take special note of the Q_OBJECT, Q_PROPERTY and Q_INVOKABLE macros.
Unfortunately, to return a custom class as a QVariant in the QAbstractListModel, we need it registered using meta data, which states:
Any class or struct that has a public default constructor, a public copy constructor, and a public destructor can be registered.
Which a QObject does not fulfil as it does not have a copy constructor. So, we are between a rock and a hard place.
QAbstractListView is not the only container class we can use in a list view, but it is arguably the correct one. You could use say QList<Object *>, but then adding and removing items will not be correctly reflected.
The solution in C++ is to ensure that we return a pointer via the QVariant.
Lets look at an example. Firstly, we create our class, and we provide two strings store internally as mText and mCommand, and a submit method. mText is exposed via a property we will call name, and we expose the submit method using a Q_INVOKABLE macro. To provide an example of multiple ways to expose your members and methods, we also provide a public slot alternate_submit, as they can be referenced from QML language directly. Which you will use will be a subjective choice.
#define YOURCLASS_H
#include <QObject>
#include <QMetaType>
class YourClass: public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ Text WRITE setText)
public:
YourClass();
YourClass(const QString& txt, const QString& command);
QString Text(void) const;
QString Command(void) const;
Q_INVOKABLE void submit(void);
signals:
public slots:
void alternate_submit(void);
private:
QString mText;
QString mCommand;
};
#endif // YOURCLASS_H
Next, we create our abstract list. Although we do not need to, we will create two roles, one called text, the other item, which will return the pointer to our whole class, rather than just a string. The key here is the static_cast on returning our item.
QVariant YourListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if ( role == ETEXT)
{
return QVariant::fromValue(mDatas[index.row()]->Text());
}
else if (role == EITEM)
{
return QVariant::fromValue(static_cast<QObject *> mDatas[index.row()]));
}
return QVariant();
}
With that in place, your QML language can now reference your mText, in two ways, via model.text as provided by the the abstract list ETEXT role, or model.item.name as provided by the property of the EITEM role. Useful, practically no, but as a demonstration, yes. The other duplicate we added was the submit() and alternate_submit() methods. These can both be used to call a function from your QML language. Lets exemplify with a QML language snippet.
import QtQuick 2.0
import QtQuick.Controls 2.0
Item {
width:parent.width
height: 40
clip: true
Button {
anchors.fill: parent
onClicked: model.item.alternate_submit() // or model.item.submit() or item.submit()
text: model.item.name // or model.text or item.name
}
}
A number of alternatives are given for obtaining the properties. This is because model can be implicit to the QML file, so you can drop it. Adding it is arguably an easier read.
Errors you may hit
Undefined Reference in qmetatype.h
If you hit an undefined reference in the qmetatype.h, QMetaTypeFunctionHelper, as follows
...include\QtCore\qmetatype.h:766: error: undefined reference to `YourClass::YourClass()'
Then you have forgotten your default constructor. Referring to the documentation (which of course we read very carefully).
Any class or struct that has a public default constructor, a public copy constructor, and a public destructor can be registered.
TypeError: Property ‘submit’ of object QVariant(YourClass) is not a function
To be able to execute a function in a C++ class from the QML language you need to inherit your class from QObject, assign it the QOBJECT macro. Also the ‘function’ needs to be assigned the Q_INVOKABLE macro if it is a normal C++ method, or be a public slot.
In the YourClass example above, submit() and alternate_submit() can both be used within the QML language.
error: use of deleted function ‘QObject::QObject(const QObject&)’
error: use of deleted function ‘QObject::QObject(const QObject&)’
This will occur if you are trying to return a QVariant of a class inheriting a QObject. This can not be done as QObjects do not have a copy constructor. Instead cast and return the pointer to your object.
This simply means you have not added a NOTIFY method for the QML language binding system to use. Refer The Property System | Qt Core 5.15.5, and in their example it is the priorityChanged method.
Qt is a registered trademark of The Qt Company Ltd. and its subsidiaries.
Connections will keep growing as it is all connection that have been made, and will not decrease.
Threads_connected you need to ensure goes back to a low number like one or two (for the connection you are monitoring on). If this stays high once your application ends, you are not closing connections.
Max_used_connections is interesting to see at any one time how many connections are active. This way you can increase the max_connections variable.
Acknowledgements
The following knowledge and help sites provided much of this content.
There are a lot of examples online. The following one outlines most of the possibilities you can choose from: deploy-flask-uwsgi-nginx
We recommend using the apps-available and apps-enabled as the method for starting your uwsgi server flask application. This is less intrusive and requires less custom parts like an additional system specific service.
For additional security you could install your applications somewhere other than /var/www if that is being served as your root for nginx (for example use /srv/uwsgi-apps instead).
To ensure independent application environments, us a python virtual environment for each of your applications. If you do choose to use the system libraries, we touch on some issues you may run into.
For the nginx configuration, the default uwsgi socket location for your application can be used. On Ubuntu at least it has been:
To help you trouble shoot during setup, once you have defined <yourapplication>.ini file under /etc/uwsgi/apps-available and symlinked to apps-enable, restart uwsgi and then tail the uwsgi log for your application.
If something goes wrong inside your application on (re)starting uwsgi, that log will show it.
For example
- mapped 654912 bytes (639 KB) for 8 cores
- *** Operational MODE: preforking ***
Traceback (most recent call last):
File "./wsgi.py", line 1, in <module>
from app import app as application
File "./app.py", line 1, in <module>
from flask import Flask, jsonify, request
ModuleNotFoundError: No module named 'flask'
- unable to load app 0 (mountpoint='') (callable not found or import error)
Module Not Found Error: No module name
In the example above either the system (or your virtual environment) does not have flask installed or you are using the wrong python plugin.
If your python –version is 3.6.x the python plugin in your uwsgi .ini file should be
plugin = python36
When you run uwsgi through its apps-enabled/<yourapp>.ini method, the application will not be run as your user, so even if you have installed flask and other libraries using pip(3), they are attached to your user’s local, rather than the system library.
If you install using pip a library you will see the output.
Requirement already satisfied: flask in /home/user/.local/lib/python3.6/site-packages
Note the /home/user/.local.
If you are not using a virtual environment, you need to ensure libraries are system libraries, either install them using their corresponding distribution package (e.g. in Ubuntu, sudo apt install python3-flask, or using sudo -H pip …)
No Python Application Found
If you see the error
--- no python application found, check your startup logs for errors ---
Then look earlier in the application log (/var/log/uwsgi/app/<yourapplication>.log) to see if your application was started or if their was an exception.
Unable to load app
unable to load app 0 (mountpoint='') (callable not found or import error)
*** no app loaded. going in full dynamic mode ***
To decipher this, look into <yourapplication>.ini file for the module and chdir lines
The wsgi of wsgi:myapp must correspond to the file name wsgi.py in your /srv/uwsgi-apps/yourapplication folder and the myapp must correspond to the import line in your wsgi.py file which imports your flask app as ‘myapp‘. In the example here, the flask app file was called app.py (as many tutorials tend to name their app files).
from app import app as myapp
if __name__ == '__main__':
myapp.run()
DANGER! If using touch reload, verify your .ini changes on a staging server before deploying to a production server, because your application will be down if there is an error loading it.
This means that most likely you need to echo commands to the master fifo as the www-data user (unless you specify a different user using uid in .ini file).
$ sudo -u www-data sh
[sudo] password for user:
$ echo r > /tmp/<yourapplication>-master-fifo
HUP System Signal
If you already deployed your application and you are not in a position to add touch reload or master fifo, you can use the -HUP signal to reload your application.
If you are a startup needing schematic and PCB design capabilities, or you are learning electronics, Kicad is an open source tool with everything you would need to get started. You can install it following the download instructions on the Kicad web site.
This tutorial will walk you through creating schematic design and PCB layout in Kicad to create some flashing LEDs, using an Astable Multivibrator design.
Select File->New->Project and name your project say LEDFlashAstable.
To start the schematic design double click on the LEDFlashAstable.sch file.
This will start the first schematic page, into which we will place and connect all components. The following is the final schematic we are aiming for.
To place a component click on the Opamp icon, on the right tool bar.
This will select the component tool. To actually place the component, move the mouse to where on the schematic page you want to place the component and click.
Click on the schematic page to open the component library page. You will see a window and status bar while component libraries are loaded.
If you have a lot of libraries this can take a few minutes.
The first component we will place is the BJT transistor. Choosing a component is one of the subtle skills of an electronics engineer. There as so many to choose from and the wrong choice could be costly later. In this tutorial we will use Kicad to help us choose our component.
Typing in the filter box, will filter the components to suitable ones. BUT, take care as if you have a very large library set (as below with 16427 items loaded), typing a single character will take a long time to filter.
Instead, copy the text bjt from here and paste it into the filter box.
Then add dual to further narrow down our search.
As you can see in the search window Kicad conveniently gives you the voltage and current rating. A quick scan shows that almost all the voltages are high enough. Additional for the dual devices it seems the lowest current is 100mA, so we could chose any one at which point price may become the deciding factor. Additionally because most are SOT-363 (a 2x2mm package) the choice in Kicad is somewhat irrelevant as most will be pin for pin compatible.
The MBT3904DW would suit this circuit wo we will choose it.
To select the component into Kicad select Unit A of MBT3904DW and click ok.
Place the component by clicking on the page. To place the second half of the package/chip, click on the page again, which will open the library selection to the same location you just were. Click on Unit B, and then click OK.
While the image is ‘see through’, click Y (for mirror) so that the component faces the opposite direction (as per our example circuit).
In a similar way place a resistor.
Now what we want to do is choose the package that we want, which will define our foot print.
Hover the cursor over the resistor, and press ‘e’ for edit.
Click on the Footprints text box and then click the ‘book’ in the right corner. This will open the footprint library.
On the left scroll down to Resistor_SMD (surface mount resistor), and then on the right column scroll to and double click on R_0603_1608Metric.
We chose the 0603 SMD package as its big enough to work with manually using a soldering iron.
Then click ok to close the components edit window.
Now we want to repeat/copy this resistor, to place four resistors. This ensures each resistor will have the same footprint.
Hover your cursor over the same resistor and press ‘c’ for copy. This will ‘copy’ the component and allow you to place it. Repeat another two times to get the 4 resistors.
To move the first resistor placed (as it is out of line), hover over it and press ‘m’ for move. Then move it and click once positioned.
Now we need to place two capacitors.
We still have the component symbol selected (right of screen), so click anywhere on the grid/screen (not on a symbol).
In the component library, type c for capacitor or if you have a lot of symbols/libraries, copy and past capacitor to the filter box.
Select C for Unpolarized capacitor (though you could use a polarized capacitor), and click Ok.
Whilst the component is ‘see through’ move and place it by clicking the mouse key.
Hover over the capacitor symbol and press ‘e’ for edit, as done earlier for the resistor.
Click on the Footprint text box and then click the ‘books’ to open the foot print library.
This time scroll on the left to Capacitor_SMD and then scroll to and double click C_0603_1608Metric on the right list.
Then click on the Value text box and type 10u or 10uF.
Then Click Ok to save the edit.
Hover over the capacitor symbol and press ‘c’ to copy and then place a second by moving the copy and clicking to position it.
As noticed the capacitors are a little too close to the resistors. Click and hold the mouse button, starting top left of middle resistors and move to bottom right to select two resistors.
Then drag the components by moving the mouse to the new position and click the mouse button to place.
Now we add two LEDs in series with our outer most resistors.
Click on the screen/grid. Then type LED (or copy paste if you have a large number of symbols) and select LED and click Ok.
Press ‘r’ for rotate a few times to orient the LED as shown.
Click to place the LED.
Press ‘e’ to edit the component and click on Footprint text box and then the books on the right to open the footprint library.
Scroll on the left column to LED_SMD and in right column double click on LED_1206_3216Metric.
Then click Ok to close the symbol editor.
1206 is a fairly common SMD led size and should be a decent size for our purposes.
Now duplicate this LED by hovering over it and pressing ‘c’ for copy and placing it on the opposite side by moving it and clicking once positioned.
Now we need to draw the wires to create the circuit.
Either select the wire tool on the right
or hover over the top left LED pin (circle on component pins) and press ‘w’ for wire.
Then move the mouse to the pin to connect the wire to, the opposing LED…
… and click on the pin. Note the automatic creation of the connection points (big green circle) on each pin. This means all those components are connected to the same “NET” or circuit wire.
Do the same with the rest of the connections, to create the following circuit.
Take care with the four cross over wires which should NOT have a junction circle (green dots). If you find a junction is created automatically it will be because your wire crosses a ‘pin’, so move components as needed to avoid this.
Now we have a fairly complete circuit, but we still need power and ground.
This can be done by selecting the ‘power tool’.
Then click on the screen to open the selector. Scroll down, select GND and press Ok.
Place GND near the bottom.
Repeat this except place VDD at the top.
To ensure we have an easy way to connect power and ground, we also add a connector for power and ground.
Select the component symbol and click on the grid/screen.
Type ‘conn’ and scroll down to Connector_Generic and select Conn_01x02 and press Ok.
Place the component by clicking on the screen somewhere. The location is not important as we will keep it ‘separate’.
To set a footprint, hover over the connector component and click ‘e’ for edit. Then click on the Footprints text box and then click on the ‘books’ icon to open the footprint library.
Select Connector_Wire, SolderWirePad_1x02_P3.81mm_Drill0.8mm. This footprint may be too large, but before creating the PCB we are not sure, so select it as a starting point.
Now we will connect ground to pin 1 and Vdd to pin 2 of the connector.
Hover over the GND component at the bottom of the schematic and press ‘c’ for copy. Then move it to near pin 1 of the connector.
Then Hover over VDD component at the top of the schematic and press ‘c’ for copy. Then move it to near pin 2 of the connector.
Keeping VDD at the top and GND below which is a convention in electronic circuits.
To make the wire layout clean, hover over the connector, press ‘m’ for move and then press ‘r’ twice to rotate the component ‘upside down’. Then move it to the left and click to place it.
Now move cursor to the pins and click ‘w’ for wire and connect the wires.
That completes our circuit layout. Note how it looks like we have two circuits. This is because VDD and GND are ‘invisibly’ connected.
If you click the ‘Highlight net tool’ on the right (pink and grey lines) and then click on the top green wire, which is the ‘VDD NET’, you will see the ‘invisible connection’ in the pink lines on the circuit.
It is a convenient way to visually verify your circuit connections. The safest way though is to use the Electrical Rules Checker.
Electrical Rules Checker
Now we need to check our circuit. The Rule checker helps us by finding issues with our schematic before we go to design the PCB.
Click on the lady bird (bug) icon at top right of tool bar, then click Ok.
The ‘Messages box’ has a message Item not annotated. This is because we have not given each of our components unique identifiers, which is necessary.
Press Close to close the window.
We can manually annotate if we want, but we can automate this, especially useful with larger circuits.
Click on the Annotate button
You can control what is annotated, but for our purposes default settings are fine, so press Annotate button to give each component an identifier.
Press Close to close the annotate window.
Now you will see all the components have an ID and the ? marks are gone.
Press the lady bird button at the top right again, and Press Run in the popup window.
As you can see there are three messages, and three green arrows on the schematic to show where the error is.
The first error is telling us that the connector pin for GND is not connected. If you zoom in, it certainly looks connected and no different to the VDD connector.
To work around this (which may be an issue with the component itself), we can try add a junction.
Click the junction tool on the right.
Then move the cursor to the join, and click to add the junction. Press Run on the Rule Checker window again to check. (Note, you can move the window to the right so it is always there while you fix the circuit, for convenience).
That has corrected the warning, though technically this one should not have been necessary.
The last two errors are related to Kicad noticing the circuit does not have any ‘driving’ components. This is because we have a passive circuit that will be connected to a battery or other power source, which is not defined in the schematic.
To hide these warnings we can add what Kicad calls a ‘power flag’.
Click on the power tool on the right hand tool bar, and type PWR in the popup window.
Select PWR_FLAG and press OK.
Place this component near the connector’s VDD. Then hover over it and press ‘c’ to copy it and move it near the GND.
Finally go to the pin and press ‘w’ for wire and create a wire from the PWR_FLAG to the GND and VDD NETs.
Another Run of the Electrical Rules Checker now will show no warnings or errors.
Finally lets chose the resistors to use. For the maths behind choosing resistor and capacitor values, refer to Astable Multivibrator.
We have two load resistors in series with the LEDs (on the same ‘line’). These we can make 100ohms and are responsible to ensure the current through the LEDs is not too high.
Hover over the resistor and press ‘e’ to edit. Change the Value to 100.
The remaining two resistors R2&R3 we will set to 33kOhms.
The result of this circuit is a flashing rate of just under a second.
Congratulations, one flashing LED circuit.
Exercises
Test your skills and add a second LED in parallel to each existing LED. i.e. one led to right of D2 and another LED to left of D1.
This circuit has no input protection, so if someone were to supply a high voltage, components would be damaged. Add a current limiting resistor and Zener diode to provide some simple protection to your circuit.
No one could deny open source has greatly impacted the tech industry in the last 20+ years. There is probably not a single web site you visit that does not run on open source in some way.
When it comes to code reuse, you can not beat it.
Yet its proliferation and ease of changing (forking a project) has also meant that for every solution/project there are many divergences.
Is this the open source weakness. Will consistent proprietary source win out in the end?
Technology businesses today are faced with the dilemma of open source. They can’t live with it, nor without it.
Traditionally a business needs to own its Intellectual Property to be commercially viable.
Open source contradicts this as ownership is open and shared, making the choice of using it a catch-22.
Once upon a time the businesses owned the high tech and hence in a way controlled the technology. Today, open source drives many technology sectors and is changing its landscape.
Today spending money on entirely proprietary source means you will be competing against companies who are faster to market simply because they leverage and reuse existing open source components.
Yet, even if you do not need to buy open source, it is not “free” and maintaining it for your own needs comes with its own challenges.
How your business handles this dilemma can make the difference between success and failure.
At Direkt Embedded we challenge you to embrace open source and invite you to take us with you on your journey.
Helping you create robust embedded systems and software