Programming languages

How to install .NET Core SDK on Ubuntu 22.04

wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
sudo apt-get update && sudo apt-get install -y dotnet-sdk-7.0

Source for these commands: Microsoft documentation

Posted by Uli Köhler in C#, Linux

How to download forum pages to HTML using Python & requests

This will download page 1000 … page 1 in descending order and save the HTML to 1000.html up to 1.html

import requests
for i in range(1000, 0, -1):
    with open(f"{i}.html", "w") as outfile:
        outfile.write(requests.get(f"https://forum.my-domain.com/showthread.php?123456-my-thread/page{i}").text)

With progress bar

import requests
from tqdm import tqdm
for i in tqdm(range(1000, 0, -1)):
    with open(f"{i}.html", "w") as outfile:
        outfile.write(requests.get(f"https://forum.my-domain.com/showthread.php?123456-my-thread/page{i}").text)

 

Posted by Uli Köhler in Python

How I fixed PlatformIO Arduino portGET_ARGUMENT_COUNT() result does not match for 0 arguments

Problem:

When trying to compile your Arduino PlatformIO project, you see multiple error messages like the following.

In file included from /home/uli/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/sys-include/stdlib.h:19,
                 from /home/uli/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include/c++/8.4.0/cstdlib:75,
                 from /home/uli/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include/c++/8.4.0/stdlib.h:36,
                 from /home/uli/.platformio/packages/framework-arduinoespressif32/cores/esp32/WString.h:26,
                 from /home/uli/.platformio/packages/framework-arduinoespressif32/cores/esp32/Print.h:26,
                 from /home/uli/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src/WiFi.h:27,
                 from /home/uli/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src/WiFi.cpp:24:
/home/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/port/xtensa/include/freertos/portmacro.h:717:41: error: static assertion failed: portGET_ARGUMENT_COUNT() result does not match for 0 arguments
 _Static_assert(portGET_ARGUMENT_COUNT() == 0, "portGET_ARGUMENT_COUNT() result does not match for 0 arguments");

Solution:

For me, the solution was as follows. I had

build_flags = --std=c++17

in my platformio.ini. Replacing it by

build_flags = --std=gnu++17

fixed the issue for me.

Posted by Uli Köhler in Arduino, C/C++, PlatformIO

How to setup & use WordPress REST API authentication using Python

WordPress authentication plugin setup

First, install the WordPress REST API Authentication wordpress plugin, which you can find by searching for WordPress REST API Authentication:

Then you need to open the plugin configuration page. Open Plugins in the WordPress admin panel, locate the  WordPress REST API Authentication plugin and click Configure

Select Basic Authentication:

Then click Next on the top right:

and click Finish on the next page:

Setup in Python

Assuming you have a WordPress user admin with password abc123 we can modify our code from How to get WordPress posts as JSON using Python & the WordPress REST API in order to query a non-public endpoint:

import requests
import base64

# Compute basic authentication header
auth_header = b"Basic " + base64.b64encode(b"admin:abc123")

# posts is a list of JSON objects, each representing a post
posts = requests.get("https://mydomain.com/wp-json/wp/v2/posts",
                     params={"context": "edit"},
                     headers={"Authorization": auth_header}).json()

 

Posted by Uli Köhler in Python, Wordpress

How to get all WordPress posts as JSON using Python & the WordPress REST API

In our previous post How to get WordPress posts as JSON using Python & the WordPress REST API we showed how to fetch a single page of 10 posts using the WordPress REST API in Python.

In this post, we’ll use the pagination in order to fetch a list of all the posts.

Firstly, we observe that once we query an invalid page such as ?page=1000000, the returned JSON will be

{'code': 'rest_post_invalid_page_number',
 'message': 'The page number requested is larger than the number of pages available.',
 'data': {'status': 400}}

instead of the JSON array representing the list of posts.

Using this information, we can write a fetcher that fetches pages of 100 posts each until this error message is encountered:

from tqdm import tqdm
import requests

def page_numbers():
    """Infinite generate of page numbers"""
    num = 1
    while True:
        yield num
        num += 1

posts = []
for page in tqdm(page_numbers()):
    # Fetch the next [pagesize=10] posts
    posts_page = requests.get("https://mydomain.com/wp-json/wp/v2/posts", params={"page": page, "per_page": 100}).json()
    # Check for "last page" error code
    if isinstance(posts_page, dict) and posts_page["code"] == "rest_post_invalid_page_number": # Found last page
        break
    # No error code -> add posts
    posts += posts_page

 

 

Posted by Uli Köhler in Python, Wordpress

How to get WordPress posts as JSON using Python & the WordPress REST API

You can use the requests library to fetch the posts as JSON from /wp-json/wp/v2/posts

On the wordpress site, you typically don’t need to configure this – the JSON API is enabled by default and accessing publically available info can be done without authentication.

import requests

# posts is a list of JSON objects, each representing a post
posts = requests.get("https://mydomain.com/wp-json/wp/v2/posts").json()

This will, by default, fetch the most recent 10 posts. See TODO for more info on how to fetch all posts using pagination

Posted by Uli Köhler in Python, Wordpress

How to escape double quotes (“) in stirng

Note: This solution does not deal with double quotes which are escaped already correctly, plus it does not correctly escape backslashes. However it can still serve as a starting point for doing customized escaping.

'foo"bar"gas'.replace(/"/g, "\\\"") # Results in foo\"bar\"gas

 

Posted by Uli Köhler in Javascript

Remove all slashes from string using pure Javascript

"foo/bar/gas".replace(/\//g, "") # foobargas

 

Posted by Uli Köhler in Javascript

How to fix Ubuntu PHP Call to undefined function mb_internal_encoding()

Problem:

When you see the following error message in your PHP log:

2022/12/22 12:57:20 [error] 1908680#1908680: *9092980 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught Error: Call to undefined function mb_internal_encoding() in /var/www/snappymail/v/0.0.0/include.php:90
Stack trace:
#0 /var/www/index.php(11): include()
#1 {main}
  thrown in /var/www/snappymail/v/0.0.0/include.php on line 90" while reading response header from upstream, client: ::ffff:77.7.108.195, server: mydomain.com, request: "GET /?admin HTTP/2.0", upstream: "fastcgi://unix:/var/run/php/php8.2-fpm.sock:", host: "mydomain.com"

Solution:

The missing function mb_internal_encoding() is from the PHP mbstring module.

In order to install it, first you need to identify the PHP version running the given script. This can be done either by looking at the webserver config files for the given domain, or by looking in the error log. In this case, we can identify that the PHP version is 8.2 from upstream: "fastcgi://unix:/var/run/php/php8.2-fpm.sock:"

In case you can’t identify the correct version, I recommend installing mbstring for every installed PHP version, which you can see by using sudo dpkg --get-selections | grep php.

Given the version number, we can install the mbstring extension from the Ubuntu/Debian package sources:

sudo apt -y install php8.2-mbstring

Depending on your configuration you might also need to restart the webserver and/or PHP-FPM service. I recommend to try it out without restart, then restart the webserver and (if you are using PHP-FPM) restart the PHP-FPM for your PHP version. In case that doesn’t help, you can always reboot.

After that, the error message should have disappeared – sometimes you need to install additional PHP modules and it’s best to just watch the error log for more missing functions or other errors related to missing extension.

Posted by Uli Köhler in PHP

Simple tsconfig.json template for NodeJS

Use this tsconfig.json as a starting point to setup your NodeJS TypeScript project:

{
  "compilerOptions": {
    "strict": false,
    "target": "es2020",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "sourceMap": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "skipLibCheck": true,
    "outDir": "./build",
    "rootDir": "./",
    "lib": [
      "esnext"
    ],
    "forceConsistentCasingInFileNames": true
  },
  "include": [
    "**/*.ts",
    "types/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

 

Posted by Uli Köhler in NodeJS, Typescript

How to import @koa/router in Typescript

import Router from '@koa/router';
import Koa from 'koa';

const app = new Koa();
const router = new Router();

 

Posted by Uli Köhler in NodeJS, Typescript

How to import Koa in Typescript

import Koa from 'koa';

const app = new Koa();

/* TODO your code goes here */

 

Posted by Uli Köhler in NodeJS, Typescript

Minimal Koa Typescript example using @koa/router and koa-body

This example showcases how to make a simple Hello World server using Koa in Typescript.

import Router from '@koa/router';
import koaBody from 'koa-body';
import Koa from 'koa';

const router = new Router();
const app = new Koa();

app.use(koaBody());

router.get('/', (ctx)  => {
    ctx.body = "Hello world";
});

app
    .use(router.routes())
    .use(router.allowedMethods());

if (!module.parent) app.listen(3000);
{
  "compilerOptions": {
    "strict": true,
    "target": "es2020",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "sourceMap": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "skipLibCheck": true,
    "outDir": "./build",
    "rootDir": "./",
    "lib": [
      "esnext"
    ],
    "forceConsistentCasingInFileNames": true
  },
  "include": [
    "**/*.ts",
    "types/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}
{
  "name": "KoaTypescriptTest",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "./node_modules/.bin/tsnd --respawn server.ts",
    "build": "./node_modules/.bin/tsc -b tsconfig.json"
  },
  "dependencies": {
    "@koa/router": "^12.0.0",
    "koa": "^2.14.1",
    "koa-body": "^6.0.1"
  },
  "devDependencies": {
    "@types/koa": "^2.13.5",
    "@types/koa__router": "^12.0.0",
    "@types/node": "^18.11.17",
    "ts-node-dev": "^1.1.8",
    "typescript": "^4.9.4"
  }
}

 

Posted by Uli Köhler in NodeJS, Typescript

ESP32 minimal httpd_uri_t example (ESP-IDF)

This httpd_uri_t handler just answers Hello World!:

static const httpd_uri_t rootHandler = {
    .uri       = "/",
    .method    = HTTP_GET,
    .handler   = [](httpd_req_t *req) {
        httpd_resp_set_type(req, "text/html");
        httpd_resp_send(req, "<h1>Hello World!</h1>", HTTPD_RESP_USE_STRLEN);

        return ESP_OK;
    }
};

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32

How to fix Arduino error: ‘class HardwareSerial’ has no member named ‘prinln’; did you mean ‘println’?

When you see the following error message:

error: 'class HardwareSerial' has no member named 'prinln'; did you mean 'println'?

You have a typo in your code: You are trying to call prinln() but you’re missing the t in println(). Add the t so you’re calling println() and retry compiling your project.

Posted by Uli Köhler in Arduino, C/C++

How to fix Arduino [WiFiUdp.cpp:183] endPacket(): could not send data: 118

When you see a log message like

[ 13701][E][WiFiUdp.cpp:183] endPacket(): could not send data: 118

on your microcontroller, you can use Serial.println(strerror(118)); to find out what the error code 118 means.

In the case of 118 (tested with arduino-espressif32 v2.0.5) the error means

Host unreachable

Typically, this error means that you are not connected to the internet / network but it might also mean that the

Note that the error message by itself does not give any indication what part of your code tried to send the UDP packet – hence, it’s not immediately clear what host specifically can’t be reached. However, this message specifically happens with code that sends UDP packets. In almost all cases, the error won’t happen when the microcontroller responds to UDP packets from another host (such as ArduinoOTA) but when the microcontroller tries to send packets to the network initiated by the microcontroller itself (such as NTP).

Posted by Uli Köhler in Arduino, C/C++, Embedded

Netmiko MikroTik RouterOS minimal example

This example prints the identity (i.e. user-defined name) of the switch/router at IP address 10.0.0.1 with password abc123abc.

from netmiko import ConnectHandler
mikrotik = {
    'device_type': 'mikrotik_routeros',
    'host':   '10.0.0.1',
    'username': 'admin',
    'password': 'abc123abc'
}

mikrotik_connection = ConnectHandler(**mikrotik)
print(mikrotik_connection.send_command(f'/system/identity/print', cmd_verify=False))

Example output:

name: MySwitch01

 

Posted by Uli Köhler in MikroTik, Networking, Python

How to find first element in sorted numpy array that is larger than a given scalar

Also see How to find first element in sorted numpy array that is smaller than a given scalar

You can use np.searchsorted() like this:

idx = np.searchsorted(arr, scalar, side='right') + 1

Full example:

import numpy as np

# Example array
arr = np.array([1, 2, 3, 4, 5])

# We'll search for this value
scalar = 3.5

# Use numpy.searchsorted() to find the first element in the array that is larger than the scalar
# We need to use + 1 since searchsorted() returns the first element that is smaller than the scalar
idx = np.searchsorted(arr, scalar, side='right') + 1

# Print the resulting index
print(idx)

 

Posted by Uli Köhler in Python

How to find first element in sorted numpy array that is smaller than a given scalar

Also see How to find first element in sorted numpy array that is larger than a given scalar

You can use np.searchsorted() like this:

idx = np.searchsorted(arr, scalar, side='left')

Full example:

import numpy as np

# Example array
arr = np.array([1, 2, 3, 4, 5])

# We'll search for this value
scalar = 3.5

# Use numpy.searchsorted() to find the first element in the array that is smaller than the scalar
idx = np.searchsorted(arr, scalar, side='left')

# Print the resulting index
print(idx)

 

Posted by Uli Köhler in Python

How to add progress bar to “for i in range(…)” loop in Python

You can use the tqdm library to easily add a progress bar to your Python for i in range(...) loop:

Just

from tqdm import tqdm

at the top of your script and then surround range(...) with tqdm(...). For example,

mysum = 0
for i in range(50):
    sum += i

becomes

mysum = 0
for i in tqdm(range(50)):
    mysum += i

 

Posted by Uli Köhler in Python