Category: Coding / Operating Systems

ESP32: how to read and write the partition table of an ESP device?

To communicate with an ESP32 the ESP-IDF (Espressif IoT Development Framework) can be used. This framework provides a collection of useful scripts to communicate with your ESP device. The framework is supported on Windows, Linux and macOS.

You can download the ESP-IDF repository and extract the contents into a folder.

Note that you need to have python 3 installed. For example by using brew install python on macOS. In addition, the esptool library is required by running pip install esptool in your terminal.

Reading the Partition Table

The partition table is located at 0x8000 (32768) on older, and on 0x9000 (36384) on newer systems. Its length is always 0xc00 (3072) bytes.

With the esptool.py, this can be read out, for example by the command

python $(IDF_PATH)/components/esptool_py/esptool/esptool.py read_flash 0x9000 0xc00 ptable.img

To create a “human” readable csv file, you can use the gen_esp32part.py tool:

python $(IDF_PATH)/components/partition_table/gen_esp32part.py ptable.img > ptable.csv

In my case, the partition table looks as follows:

Foto von Vishnu Mohanan auf Unsplash

 

How to use your Mac for time-lapse like webcam shots

When searching for a script that captures images from my Macs internal camera, I found a small tool called ImageSnap. This small tool is very simple in its usage, but it’s one of the key tools when you want to use your Mac as a webcam.

ImageSnap is a Public Domain command-line tool that lets you capture still images from an iSight or other video source.

Installation

ImageSnap can be conveniently installed through package managers like Homebrew and MacPorts. One of the simplest methods to install ImageSnap is by executing the following command:

brew install imagesnap

Usage

To use ImageSnap, open the macOS terminal and navigate to the folder where all your images should be stored. In my case, I used a folder located in iCloud Drive so that I can access those files from any other device that uses the same iCloud account.

Then I just provided the time interval between the images by using the -t parameter:

imagesnap -t 60

A value of 60 will result in a picture every minute (= 60 seconds).

There are several other options for ImageSnap to fine tune your image capturing. The help output gives you all the details:

imagesnap -h
USAGE: imagesnap [options] [filename-or-dir]
Version: 0.2.16
Captures an image from a video device and saves it in a file.
If no device is specified, the system default will be used.
If no filename is specfied, snapshot.jpg will be used.
If timelapse is used, the filename argument can be a directory where files will be saved.
JPEG is the only supported output type.
  -h          This help message
  -v          Verbose mode
  -l          List available video devices
  -t x.xx     Take a picture every x.xx seconds
  -n num      Limit to <num> snapshots in -t timelapse mode
  -q          Quiet mode. Do not output any text
  -w x.xx     Warmup. Delay snapshot x.xx seconds after turning on camera (default 3sec)
  -d device   Use named video device

Foto von Adrian Schwarz auf Unsplash.

 

Why does the iOS App Store show more languages than my app supports?

By default, the languages of an app are listed in info.plist by setting the values for the properties list key CFBundleLocalizations. A definition as shown below should result in supported languages English and German.

	<key>CFBundleLocalizations</key>
	<array>
		<string>en</string>
		<string>de</string>
	</array>

But when looking at the AppStore, the languages shown there do not always correlated with this setting. The reason is that the languages shown on the AppStore are generated automatically based on the localized *.lproj folders found in your app.

Normally those folders should be in sync with your properties list setting. But when you use third party libraries (e.g. with CocoaPods) additional localizations might be loaded into your app. In this case, all *.lproj folders found in your app and in the pods are used for language determination.

How to correct the languages?

There is a plugin for that: cocoapods-prune-localizations, which can be simply added to your Podfile. When running pod install, this script will remove all localized files from pods or just keep the specified languages. To install the script, run:

gem install cocoapods-prune-localizations

Then add the following lines to your Podfile:

plugin 'cocoapods-prune-localizations'

Localizations will be inferred from your project.

or if you would prefer to specify the localizations:

plugin 'cocoapods-prune-localizations', {:localizations => ["en", "es"]}

This will keep the English and Spanish localizations in the Pods. Modify the localizations to your needs.

Photo by Etienne Girardet on Unsplash

Build and Release a Flutter App

Updating the app’s version number

To update the version number, navigate to the pubspec.yaml file and update the following line with the current version string:

version: 1.0.0+1

After the change, run:

flutter pub get

Build and release the iOS app

A detailled description of the whole process is described at docs.flutter.dev.

To release the iOS app, you use Flutter to build a xcarchive file. This build archive can be published the same way you would do it with Xcode by using the archive manager and one of the different Distribution options.

Build the iOS app:

flutter build ipa

The generated xcarchive file is saved to your app directory under:

/build/ios/archive/MyApp.xcarchive

Build and release the Android app

A detailled description of the whole process is described at docs.flutter.dev.

To release the Android app, you use Flutter to build a app bundle aab file. This file can be distributed by using Google Play Console or any other store.

Build the Android app:

flutter build appbundle

The generated aab app bundle file is saved to your app directory under:

/build/app/outputs/bundle/release/MyApp.aab

Photo by Artur Shamsutdinov on Unsplash

Ping server on a specific port

Terminal

You can’t ping ports, as Ping is using ICMP which doesn’t have the concept of ports. Ports belong to the transport layer protocols like TCP and UDP. However, you could use nmap to see whether ports are open or not:

nmap -p 80 example.com

The output will look like this:

nmap -p 80 google.de
Starting Nmap 7.92 ( https://nmap.org ) at 2021-12-08 10:59 CET
Nmap scan report for google.de (142.250.185.131)
Host is up (0.017s latency).
rDNS record for 142.250.185.131: fra16s50-in-f3.1e100.net

PORT   STATE SERVICE
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 0.09 seconds

Source: https://serverfault.com/questions/309357/ping-a-specific-port

CUDART Error in Singularity Container Workaround

Singularity is a Linux container system similar (and compatible to) Docker. It’s advantage over Docker is that is was designed to allow users without superuser privileges to run containers within their environment. I recently encountered the following error when running a Nvidia CUDA application within a Singularity container using “singularity run -nv <container>:

CUDART: cudaGetDeviceCount(&deviceCount); = 999 (unknown error)

Workaround: After running /usr/local/cuda/samples/1_Utilities/deviceQuery/deviceQuery outside of the container, the CUDA application within the container ran without any problem.

Fix/Solution: TODO

brew: install Java on macOS

The following steps will guide you through the installation of Java on macOS.

First, check the available Java related formulas:

% brew search java

==> Formulae
app-engine-java              java                         javacc                       jslint4java                  pdftk-java
google-java-format           java11                       javarepl                     libreadline-java

Currently, there are two different version of Java: java and java11. To check the version of both, you can use the following commands:

% brew info java

openjdk: stable 16.0.1 (bottled) [keg-only]
Development kit for the Java programming language
https://openjdk.java.net/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openjdk.rb
License: GPL-2.0-only with Classpath-exception-2.0
% brew info java11

openjdk@11: stable 11.0.10 (bottled) [keg-only]
Development kit for the Java programming language
https://openjdk.java.net/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openjdk@11.rb
License: GPL-2.0-only

Depending on your requirements, you can install one of the above. For me, some of the libraries I use in Dart are currently not compatible with the latest Java version (16.0.1), so I decided to install Java 11 with LTS (long term support).

% brew install java11

This will install Java version 11.0.10 as listed in the output above. The output also shows the following hints:

For the system Java wrappers to find this JDK, symlink it with
  sudo ln -sfn /usr/local/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk

openjdk@11 is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have openjdk@11 first in your PATH, run:
  echo 'export PATH="/usr/local/opt/openjdk@11/bin:$PATH"' >> ~/.zshrc

For compilers to find openjdk@11 you may need to set:
  export CPPFLAGS="-I/usr/local/opt/openjdk@11/include"

For me it was necessary to called the specified command, so that the system finds the java binary:

sudo ln -sfn /usr/local/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk

To see if Java was installed correctly, you can check the version of Java:

 % java --version

openjdk 11.0.10 2021-01-19
OpenJDK Runtime Environment (build 11.0.10+9)
OpenJDK 64-Bit Server VM (build 11.0.10+9, mixed mode)

That’s it!

Photo by Adam Wilson on Unsplash

Finding the NUMA Node of a Nvidia CUDA GPU in Linux

For some applications it might be useful to pin their CPU processes to the NUMA node which is connected to the GPU. To find out which GPU is located at which NUMA node one can use the following script:

for i in $(nvidia-smi -x -q | grep "gpu id" | awk -F "\"" '{print $2}' | awk -F ":" '{print "0000:"  $2 ":"  $3}' | tr '[:upper:]' '[:lower:]'); do echo $i; cat "/sys/bus/pci/devices/$i/numa_node"; done

Pinning the CPU process to the right NUMA node can speed up your application significantly on all Nvidia GPUs like the double precision HPC GPUs Tesla V100, A100 and A10, the professional Quadro RTX GPUs as well as all CUDA capable GeForce GPUs.