Always Set Zoom Level for a Webcam

# /etc/udev/rules.d/99-local-webcam.rules
# Logitech C925e webcam zoom
SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="085b", PROGRAM="/usr/bin/v4l2-ctl --set-ctrl zoom_absolute=150 --device /dev/%k"
Posted in General | Tagged | Leave a comment

XDG Base Directory Compliant ~/.python_history

# Store interactive Python shell history in ~/.cache/python_history
# instead of ~/.python_history.
#
# Create the following .config/pythonstartup.py file
# and export its path using PYTHONSTARTUP environment variable:
#
# export PYTHONSTARTUP="${XDG_CONFIG_HOME:-$HOME/.config}/pythonstartup.py"
import atexit
import os
import readline
histfile = os.path.join(os.getenv("XDG_CACHE_HOME", os.path.expanduser("~/.cache")), "python_history")
try:
readline.read_history_file(histfile)
# default history len is -1 (infinite), which may grow unruly
readline.set_history_length(1000)
except FileNotFoundError:
pass
atexit.register(readline.write_history_file, histfile)
Posted in General | Tagged | Leave a comment

ZTE Speedport Entry 2i Key Generator

#!/usr/bin/env python
#
# ZTE Speedport Entry 2i Key Generator
#
# The script generates the key for decryption and encryption
# of ZTE Speedport Entry 2i configuration file using
# https://github.com/mkst/zte-config-utility
#
# Usage:
#
# ./zte-speedport-entry-2i-key-generator.py
# MAC address: c85a9fa21821
# Serial: 268EG8JL4M16271
# Factory SSID: ZTE-ABCDEF
# Factory WLAN Key: zxcvbnmasdfg
# Factory Username: admin
# Factory Password: qwertyui
# Hardware Version: V1.0.1
# ade8b5e3e9c57a5f
#
# Configuration decryption:
#
# PYTHONPATH=./zte-config-utility
# python ./zte-config-utility/examples/decode.py config.bin config.xml --key ade8b5e3e9c57a5f
#
# Configuration encryption:
#
# PYTHONPATH=./zte-config-utility
# python ./zte-config-utility/examples/encode.py config.xml config.bin --key ade8b5e3e9c57a5f --signature "Speedport Entry 2i"
from hashlib import md5
l = lambda s: len(s).to_bytes(3, "little")
a = lambda s: s.encode("ascii")
mac = int(input("MAC address: "), 16)
serial = a(input("Serial: "))
ssid = a(input("Factory SSID: "))
wlan_key = a(input("Factory WLAN Key: "))
username = a(input("Factory Username: "))
password = a(input("Factory Password: "))
mac_zte = a("54BE53")
version = a(input("Hardware Version: "))
zero = a("0")
print(md5(
b"\x01\x00\x00\x06\x00\x00" + (mac).to_bytes(6, "big") + \
b"\x01\x01\x00\x06\x00\x00" + (mac + 1).to_bytes(6, "big") + \
b"\x01\x02\x00\x06\x00\x00" + (mac + 2).to_bytes(6, "big") + \
b"\x01\x03\x00\x06\x00\x00" + (mac + 3).to_bytes(6, "big") + \
b"\x02\x00\x00" + l(serial) + serial + \
b"\x04\x00\x00" + l(ssid) + ssid + \
b"\x05\x10\x00" + l(wlan_key) + wlan_key + \
b"\x06\x01\x00" + l(username) + username + \
b"\x07\x01\x00" + l(password) + password + \
b"\x03\x00\x00" + l(mac_zte) + mac_zte + \
b"\x08\x06\x00" + l(version) + version + \
b"\x08\x07\x00" + l(zero) + zero
).hexdigest()[:16])

Posted in General | Leave a comment

GPT Backup and Restore

# GPT Backup
sudo sgdisk --backup=nvme0n1.gpt /dev/nvme0n1
# GPT Restore
sudo sgdisk --load-backup=nvme0n1.gpt /dev/nvme0n1
Posted in General | Leave a comment

Python’s math.prod vs functools.reduce(operator.mul)

Simple Python code performance measurement of math.prod and functools.reduce with operator.mul using timeit module.

#!/usr/bin/env python
# An example of Python code benchmarking.
# In this case math.prod vs functools.reduce(operator.mul).
# As can be seen, math.prod is almost twice as fast as the other option:
#
# ./timeit-test.py
# 4.723656065994874
# 7.586232994995953
# 18.008398708996538
# 31.734708059004333
from operator import mul
from functools import reduce
from math import prod
from itertools import combinations
from random import shuffle
from timeit import timeit
def msolve(numbers, length):
for c in combinations(numbers, length):
prod(c)
def rsolve(numbers, length):
for c in combinations(numbers, length):
reduce(mul, c)
x = list(range(1000))
shuffle(x)
print(timeit(lambda: msolve(x, 2), number=100))
print(timeit(lambda: rsolve(x, 2), number=100))
print(timeit(lambda: msolve(x, 3), number=1))
print(timeit(lambda: rsolve(x, 3), number=1))
view raw timeit-test.py hosted with ❤ by GitHub
Posted in General | Tagged | Leave a comment

Proxy ARP

Enable cross connection between two segments inside the same LAN without NAT. For example an access point connected to a laptop via Wi-Fi and a Raspberry Pi connected to the same laptop via Ethernet.

#!/bin/sh
# Enable connection between AP and RPi without NAT
# AP --- wifi --- laptop --- ethernet --- RPi
# Reference: https://wiki.debian.org/BridgeNetworkConnectionsProxyArp
# 0. Assign static IP to RPi
# 1. Enable Proxy ARP and routing on the laptop
echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp
echo 1 > /proc/sys/net/ipv4/ip_forward
# 2. Add static route for RPi on the laptop
ip route add 192.168.1.254/32 dev eth0
view raw proxy-arp.sh hosted with ❤ by GitHub

Posted in General | Tagged | Leave a comment

Disk Backup and Restore

An example how to backup and restore an SD card containing Raspberry Pi OS.

# Backup
sudo dd if=/dev/mmcblk0 count=1 bs=512 of=mmcblk0.mbr
sudo fsarchiver savefs mmcblk0.fsa /dev/mmcblk0p1 /dev/mmcblk0p2 -v -j 4
# Info
fsarchiver archinfo mmcblk0.fsa
# Restore
sudo dd if=mmcblk0.mbr count=1 bs=512 of=/dev/mmcblk0
sudo partprobe /dev/mmcblk0
sudo fsarchiver restfs mmcblk0.fsa id=0,dest=/dev/mmcblk0p1 id=1,dest=/dev/mmcblk0p2 -v
view raw fsarchiver.sh hosted with ❤ by GitHub

Posted in General | Tagged , | Leave a comment

Enable TCP BBR

Speed up TCP connections be enabling TCP BBR on Arch Linux:

# Enable TCP BBR module
echo tcp_bbr | sudo tee /etc/modules-load.d/tcp-bbr.conf
# Set TCP to use BBR
sudo tee /etc/sysctl.d/99-tcp-bbr.conf > /dev/null <<'EOF'
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
EOF
# Apply the changes
sudo modprobe tcp_bbr
sudo sysctl --system
view raw tcp-bbr.sh hosted with ❤ by GitHub

Posted in General | Tagged | Leave a comment

Turn Python into HTTP server serving local directory

# Python 3
sudo python -m http.server 80
# Python 2
sudo python2 -m SimpleHTTPServer 80

Posted in General | Tagged | Leave a comment

System Benchmarking

Using OpenBenchmarking.org and Phoronix Test Suite for system benchmarking and online result comparison.

  • Registering an account on OpenBenchmarking.org
  • Download and install the latest Phoronix Test Suite:
    wget https://github.com/phoronix-test-suite/phoronix-test-suite/archive/v9.6.0m3.tar.gz
    tar xvf v9.6.0m3.tar.gz
    cd phoronix-test-suite-9.6.0m3/
    sudo ./install-sh
    

    In case of Raspbian or Ubuntu running on Raspberry Pi, install also additional packages:

    sudo apt install php-cli php-xml php-curl php-zip
    
  • Pair your (future) benchmarks with your OpenBenchmarking.org account:
    phoronix-test-suite openbenchmarking-login
    
  • Useful commands to list available test suites, test profiles, search tests and estimate test runtime:
    phoronix-test-suite list-available-suites
    phoronix-test-suite list-available-tests
    phoronix-test-suite search mp3
    phoronix-test-suite estimate-run-time pts/video-encoding
    
  • Run a single or multiple benchmarks in interactive mode:
    phoronix-test-suite benchmark pts/smallpt
    phoronix-test-suite benchmark pts/encode-flac pts/encode-mp3 pts/vpxenc pts/x264 pts/x265
    
  • Run a benchmark in non-interactive mode against a previously uploaded test result. Useful for running the same test on a new system to compare the results:
    phoronix-test-suite batch-setup
    phoronix-test-suite batch-benchmark 2004190-V110-RPIENCO26
    
Posted in General | Leave a comment