64Zbit.com
Tech is way, WAY interesting

How bad is the air out there? – Six Colors

Use Scriptable app to run javascript in a widget on your iOS device.

Right now, several parts of the state of California are on fire. This isn’t the usual early-fall fire season where dry offshore winds fan the flames—that’s yet to come, oh boy! This is a weirder set of fires started by lightning from a rare set of thunderstorms that passed through a few weeks ago.

In any event, when there are fires burning within a few hundred miles of where you live, the air quality can be really bad and highly variable. Just yesterday, we awoke to clean air. Then the wind shifted and the Air Quality Index (AQI) went rapidly from green to red. It was hazy and ugly outside, and smelled like a barbecue. A couple of hours later, the air was back in healthy territory and I went for a run.

Link to the original article


How Many Decimals of Pi Do We Really Need? - Edu News | NASA/JPL Edu

How Many Decimals of Pi Do We Really Need? 3.141592653589793. That’s it. For the whole visible universe!

Link to the original article


The Intel Split – Stratechery by Ben Thompson

The Intel Split

It appears that Intel's partnership with TSMC is much larger than it first seemed; the implications for Intel as whole are massive.

Link to the original article


Obsidian Community Plugins

There are several Community Plugins used to create the 64Zbit.com website. Here are a list of the ones I'm currently using.


* Obsidian Shell Command

It's not bad to open a shell command and execute the make prod command, but it's even better to hit a hotkey within Obsidian to do the same thing.

More info on GitHub

This plugin allows you to execute a shell command from within Obsidian.

Settings

It also allows you to execute that command from the Obsidian command pallet. Which allows you to execute the command from a hotkey.

Example bash script to copy all files to remote web server

If you want to manually upload the files then here is a good use of the scp command.

scp -r /Users/doug/OneDrive/www_root/pelican/projects/64zbit/output/* user@64zbit.com:/home/pi/dev_volumes/public_html/apache/new/

* Customizable Page Header

Add a button to the page header area of Obsidian to run an Obsidian command. Such as the afore mentioned Shell Command to publish the Pelican website to the production server.

Settings

More info on GitHub


* Paste URL Into Selection

A super helpful utility that detects when there is a URL in the clipboard and then pastes it in the correct format into Obsidian. Detects images too.

Settings

More info on GitHub


Google Fonts Blog: Flow and Redacted

When you need to hide something, but still want them to be able to see it later. Of course, they could just look at the source.

Pretty nice looking fonts. Check out the details here:

Google Fonts Blog: Flow and Redacted: Check out these new options for wireframes and other early-stage designs


Moxie Marlinspike 'My First Impressions of Web3'

Moxie Marlinspike 'My First Impressions of Web3'

Read the full article on moxie.org

I think these market forces will likely continue, and in my mind the question of how long it continues is a question of whether the vast amounts of accumulated cryptocurrency are ultimately inside an engine or a leaky bucket. If the money flowing through NFTs ends up channeled back into crypto space, it could continue to accelerate forever (regardless of whether or not it’s just web2x2). If it churns out, then this will be a blip. Personally, I think enough money has been made at this point that there are enough faucets to keep it going, and this won’t just be a blip. If that’s the case, it seems worth thinking about how to avoid web3 being web2x2 (web2 but with even less privacy) with some urgency.

It's worse than I thought. Web3 is already a mess.


Wordle

Wordle is a fun free word of the day game where you have six tries to find the five letter word.

It was tough today.

Wordle 204 6/6

Whew!

Whew!

Play today's Wordle


Using Pelican

site image

Publish with Obsidian

Caps-P - publish

Caps-T - select template

Pelican Site Generator

Make prod - publish to production server

start localhost:8000 dev server and reload on changes

pelican --autoreload --listen


First Robotics Rapid React

First Robotics Rapid React
https://www.firstinspires.org/robotics/frc/kickoff


pelican-plugins/jinja2content: Use Jinja2 template code within post content

This plugin allows the use of Jinja2 directives inside your Pelican articles and pages.

In this approach, your content is first rendered by the Jinja template engine. The result is then passed to the normal Pelican reader as usual. There are two consequences for usage. First, this means the Pelican context and Jinja variables usually visible to your article or page template are not available at rendering time. Second, it means that if any of your input content could be parsed as Jinja directives, they will be rendered as such. This is unlikely to happen accidentally, but it’s good to be aware of.

All input that needs Pelican variables such as article, category, etc., should be put inside your theme’s templating. As such, the main use of this plugin is to automatically generate parts of your articles or pages.

Markdown, reStructured Text, and HTML input are all supported. Note that by enabling this plugin, all input files of these file types will be pre-processed with the Jinja renderer. It is not currently supported to selectively enable or disable jinja2content for only some of these input sources.

Link to the original article


Images with Obsidian and Pelican

A short article on how to work with images so they display correctly in Obsidian and when published with Pelican.

Native

This default Obsidian format, with drag and drop into the document, works in Obsidian, but not Pelican.

Obsidian Native: (doesn't work on this site)

![Obsidian](CleanShot%202022-01-05%20at%2019.30.59@2x.png) Obsidian

Path

Obsidian knows where to find the image, whereas Pelican needs a path added to find the image. In this case /images/

Added Path:

![Added Path](/images/CleanShot%202022-01-05%20at%2019.30.59@2x.png) Added Path

Img Tag

But the images are 2x based on the image format and the Retina display it was captured from. It needs to be resized to 50% to display properly. There is not a size option available in Obsidian markdown. You can revert to a standard img html tag to make this work. However, the image will not display in Obsidian.

Use <img> tag:

<img src="/images/CleanShot%202022-01-05%20at%2019.30.59@2x.png" alt="alt text" title="image Title" width="50%"/>

alt text

1x with Path

The solution is to use images that are 1x sized. Or, set your screen capture tool to 1x, non Retina. This way the images will display correctly in Obsidian and when published with Pelican, with only the path being added manually to the file name.

1x with path added:

![](/images/CleanShot%202022-01-05%20at%2019.59.47.png)

Automation

What automation tools are available in Pelican to automatically reformat and resize the images?

To be continued....


Raspberry Pi as a Flask Server

I created an Air Quality Index gadget made from a Raspberry Pi Zero W with a tiny OLED screen from Adafruit. It shows the AQI from my local PurpleAir sensor.

I created a Flask web server on the Pi so I could remotely see the AQI and change the PurpleAir sensor ID.

print("The triple-colon syntax will *not* show line numbers.")

from flask import Flask, render_template, request, jsonify, make_response
import os
import logging
import datastore
import aqistore

# DotMap is a dot-access dictionary subclass
# https://pypi.org/project/dotmap/
# https://github.com/drgrib/dotmap
from dotmap import DotMap

# logging configuration
# debug, info, warning, error, critical
logging.basicConfig(filename='./instance/aqi.log',
                    level=logging.DEBUG, format='%(asctime)s %(message)s')
logging.info('Started')
logging.info('running server.py')

# Example ajax code from
# https://github.com/caseydunham/ajax-flask-demo

app = Flask(__name__)
app.config.from_mapping(
    SECRET_KEY='dev',
    DATABASE=os.path.join(app.instance_path, 'aqi.sqlite'),
    LOGGER=os.path.join(app.instance_path, 'aqi.log'),
)

# ensure the instance folder exists
try:
    os.makedirs(app.instance_path)
    logging.info('server - created instance folder.')
except OSError:
    pass

# default sensor_id for PurpleAir sensor Forest Park
sensor_id = 104402


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/pi')
def pi():
    return 'Raspberry Pie!'


@app.route('/sensor')
def sensor_index():
    return render_template('sensor.html')


@app.route('/aqi')
def aqi_index():
    resp = make_response(render_template('aqi.html'))
    resp.set_cookie('aqi', 'aqi')
    return resp


@app.route('/api/sensor', methods=['GET', 'POST'])
def get_sensor_post():
    logging.info('**************** starting sensor ')
    # logging.info('request user_agent: ', request.)
    out = get_sensor_proc()
    r = out.toDict()
    return jsonify(result=r, status=200)


def get_sensor_proc():
    error = None
    out = DotMap()
    sensor_id = 0
    try:
        sensor_id = datastore.get_sensor_id()
    except Exception as e:
        error = e
        logging.warning(e)
    out.sensor_id = sensor_id
    out.error = error
    logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(message)s')
    logging.info('get_sensor_proc - sensor_id from db.', out.toDict())
    return out


@app.route('/api/aqi', methods=['GET', 'POST'])
def aqi_post():
    logging.info('**************** starting aqi ')
    # logging.info('request user_agent: ', request.)
    out = aqi_proc()
    r = out.toDict()
    return jsonify(result=r, status=200)


def aqi_proc():
    error = None
    aqi = 0
    aqiColor = 0
    try:
        out = aqistore.purpleAir()
    except Exception as e:
        error = e
        logging.warning(e)
    out.error = error
    logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(message)s')
    logging.info('aqi_proc - data from purpleAir.', out.toDict())
    return out


@app.route('/api/sensor_post', methods=['POST'])
def sensor_post():
    json = request.get_json()
    msg = DotMap(json)
    out = sensor_proc(msg)
    r = out.toDict()
    return jsonify(result=r, status=200)


def sensor_proc(msg):
    sensor_id = msg.sensor_id
    logging.info('server - updating db sensor_id: ' + str(sensor_id))
    error = None

    if not sensor_id:
        error = 'Sensor_id is required.'
        logging.warning(error)

    if error is None:
        error = datastore.set_sensor_id(sensor_id)
    out = DotMap()
    out.sensor_id = sensor_id
    out.error = error
    return out


@app.route('/api/say_name', methods=['POST'])
def say_name_post():
    json = request.get_json()
    msg = DotMap(json)
    out = say_name_proc(msg)
    r = out.toDict()
    return jsonify(result=r, status=200)

# process say_name message


def say_name_proc(msg):
    datastore.get_db()
    first_name = msg.first_name
    last_name = msg.last_name
    day_week = msg.day_week

    out = DotMap()
    out.first_name = first_name
    out.last_name = last_name
    out.day_week = day_week
    datastore.close_db()
    return out


@app.route('/init')
def init():
    datastore.init_db()
    return 'Database initialized'

# dynamic route


@app.route('/<name>')
def print_name(name):
    return 'Hi, {}'.format(name)


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

New Pelican based Website

It's been in the works for awhile, but today I updated my production server settings to show the new website based on the Pelican static site generator.

I tried to follow the same look and feel of the Ghost based server but with a fully customizable template. With Ghost I was limited to using their default template and never wanted to learn how to change it. With the new Pelican based site it is super easy to make all the modifications I want.


Favicon Generator for perfect icons on all browsers

Why RealFaviconGenerator No hard decision With so many platforms and icons, it's hard to know exactly what you should do. What are the dimensions of favicon.ico? How many Touch icons do I need? RealFaviconGenerator did the reseach and testing for you.

Done in 5 minutes You spent hours on design, colors, graphics... How much time left for the favicon? Probably not much. But no worries, you only need a few minutes to tackle this task.

Compelling design, a platform at a time Each platform comes with its own design requirements. You can't just use the same picture everywhere. RealFaviconGenerator knows this and lets you craft your icons platform per platform.

Instant feedback How will Android display my icon? How will iOS round my Touch icon? No more guesswork. RealFaviconGenerator instantly shows you how your icons will look like.

Link to the original article


iPhone Device Resolutions

iphone

source:paintcodeapp.com


pelican-plugins/search: Pelican plugin that adds site search capability

This plugin generates an index for searching content on a Pelican-powered site.

Why would you want this?

Static sites are, well, static… and thus usually don’t have an application server component that could be used to power site search functionality. Rather than give up control (and privacy) to third-party search engine corporations, this plugin adds elegant and self-hosted site search capability to your site. Last but not least, searches are really fast. 🚀

Want to see just how fast? Try it out for yourself. Following are some sites that use this plugin:

Link to the original article


Publish Pelican To Remote Web server

Makefile

When you install Pelican be sure to install the Makefile too. This allows you to use the make command to build your static website. It takes a bit of configuration for your specific server details, but it's easy to setup.

All the details are handled in these three files:

pelicanconf.py
publishconf.py
Makefile

The command I ended up using is: make ssh_upload

This creates a production build and uploads all the files to the server.

I actually renamed ssh_upload in the Makefile to prod, so now I use the command: make prod

Obsidian Shell Command

It's not bad to open a shell command and execute the make prod command, but it's even better to hit a hotkey within Obsidian to do the same thing.

Install the Obsidian ShellCommands Plugin

This plugin allows you to execute a shell command from within Obsidian.

It also allows you to execute that command from the Obsidian command pallet.

Which allows you to execute the command from a hotkey.

Copy all files to remote web server

If you want to manually upload the files then here is a good use of the scp command.

scp -r /Users/doug/OneDrive/www_root/pelican/projects/64zbit/output/* user@64zbit.com:/home/pi/dev_volumes/public_html/apache/new/

Deep Thoughts

Thoughts

— 2021/12/04 We shall go into the land so our children can always hold us and will never be alone. — The wheel of time S1E4

It is like swimming. If you can’t swim, you won’t be having any fun at all. Swimming sucks if all you do is float (or even sink) and fight the water. But boy, if you figure out the technique and glide through the water, it is incredible. But you don’t learn swimming by aiming for ease and fun. You learn to swim by aiming to be fast and graceful.

  • In the end we only regret the chances we didn’t take
  • If we all do all that we can do then great things will happen
  • Quote John S. - “I’m experiencing a narrowing of the possibility space due to aging.”

School Success

I think kids’ school success comes down to this in this order:

  1. Homelife
  2. Sleep
  3. Diet
  4. Exercise
  5. Teachers
  6. Tech
  7. School Year Length
  8. Homework

What many seem to think:

  1. School Year Length
  2. Homework
  3. Teachers
  4. Tech
  5. Homelife
  6. Exercise
  7. Sleep
  8. Diet

pelican-plugins

Current list of Pelican plug-ins on GitHub

Link to the original article


European civilization is built on ham and cheese,

European civilization is built on ham and cheese, which allowed protein to be stored throughout the icy winters.

Without this, urban societies in most of central Europe would simply not have been possible.

This is also why we have hardback books. Here's why. 1/

Link to the original article


SQLite with Python - Chris Ostrouchov

SQLite is a commonly misunderstood database. I myself first heard of the database when I was experimenting with android app development. My thoughts were that since the database was a single file and its name had lite in it, that it could not be taken seriously. But I could not have been more wrong. Now I love sqlite and use it for much of my scientific research. Sqlite is everywhere. It is on every android phone, airplanes, and the storage for many computer applications. The sqlite website details when using sqlite would be appropriate to use and can be summarized with these three questions.

Link to the original article


It's going to be okay. - The Oatmeal

And if you haven't seen this, well then. Let's fix that right now. Via @Oatmeal.

Link to the original article


Install Mini PiTFT | Pi Hole Ad Blocker with Pi Zero W | Adafruit Learning System

Raspberry Pi Zero W We've updated our popular PiOLED script for use with the Mini PiTFT, a 135x240 Color TFT add-on for your Raspberry Pi. This cute little display has two tactile buttons on GPIO pins that we'll use to make a simple user-interface display for your Pi-Hole.

Link to the original article


The Expanse UI Design — HUDS+GUIS

The Expanse UI Design Here’s a look at the various FUI designs from the sci-fi series The Expanse.

Special thanks to Brian Benton who suggested this and provided some great links as well! A lot of the images have been collected from this massive image dump from drainsmith and further below we have some insights and images provided by Rhys Yorke who worked on The Expanse (Season 3 & 5) as a motion graphics designer.

Link to the original article


Ping network monitor

The ping command is a built in linux and macOS command that shows the performance of the network connection to a remote server. It can be used to log network performance issues over time. The default ping command displays the results to standard output (the shell window). Used with the following options it routes the output to a file that you can look at later.

The ping command will ping the remote server every second until you manually kill the process. This will create 86,400 pings per day in the output file. It's not something you want to forget about and let it run forever. It could create a very large file that fills up your drive space and crashes your system. I run my ping network monitor on a Raspberry Pi 4 so that it will run 24 hours per day in low power and uninterupted environment.

Ping directed to a file

You would normally just run the ping command interactivly and then stop it when you are done. But, that's not what we are doing today. We are looking for an intermident bug that may happen anytime in the future. For this we need to run the command for weeks at a time and be able to look at the results after a network error has been detected.

Here is the ping command, running in the background, with the output directed to a file called "network.log".
Copy and paste this text to your command line.

ping google.com 2>&1 | while read pong; do date "+%c: $pong"; done >network.log &

Here are the details of what this command does

  • ping // the ping command to run
  • google.com // name of the remote server
  • 2>&1 // routes stderr to stdout
  • | while read pong; do date "+%c: $pong"; done // pipe the ping results and add the current date and time
  • >network.log // routes output to file network.log
  • & // at end means to run in background

The pipe command, represented by the vertical bar | takes the output of the first command and routes it into the second command. In this case it takes the output of the ping command and routes it into a command that prepends the current date and then uses the > command to route everthing to a file instead of standard out (stdout).

The & at the end of the line makes this command run in the background. This frees up your terminal so you can run other commands. It will continue running even when you exit your terminal and logout. The commands below show you how to find the background command later and control it.

Jobs and Processes

The jobs command only works for jobs you have started in the current shell. If you exit the shell and open a new one then this command will not display your jobs. You will need to use the other commands listed below to work with system level processes.

Fun fact: jobs are started by a user, processes are started and managed by the system. A users job is also a system process.

Process Id

Every command running on the computer is assigned a unique process id (PID). You can use this PID to interact with background processes.

The terms Command, Job, and Process are basically the same thing. They are programs running on your computer.

Type top into your shell to see a list of the top processes running on your current computer. Notice the PID column listed on the far left. Type q to exit this view. For a fun day of reading type man top to read all the details of the top command.

Use the jobs command to see running background jobs, -l shows the process id (PID). (That’s a lowercase L)

jobs -l 

Viewing your ping log

Use the cat command to view contents of the output file, use the | more option to show a page at a time. This could take awhile, you are getting 86,400 lines per day and paging through them a few lines at a time will get tedious.

cat network.log 
or
cat network.log | more

Look at the output

If all goes well you should see a time= value at the end of each line. This tells you the ping completed successfully and you have a good connection to the server.

When the connection goes down you will receive error messages. These will be helpful in determining what went wrong.

Example showing a request timout error

Use grep to find interesting data

The grep command will help you find interesting data in your output file.

cat network.log | grep -v time

The -v option tells grep to "invert match", so any line that does not contain the "time" string.

This command will search the network.log for any line that does not contain the string "time". So for any ping command that returns anything other than a normal ping time will be displayed. This includes any error messages that you should look at.

Example showing an unreachable server
Example showing an unreachable server

Find your running ping command

Use the pgrep command to find running ping jobs and return the process id (PID). Pgrep is included in many Linux distributions.

pgrep ping 

Example showing pgrep ping output

pgrep returns the process id (PID) where the string matches. In this case the PID = 24895. Warning: Don't use this PID, use the PID you find on your own system.

Stopping the ping command

Use the kill command to stop a running job. Be careful, you can kill the wrong job and crash your system. Make sure you enter the correct process id (PID) you found above.

kill PID 

Here's nother command to find the running ping processes. Use ps if your distribution doesn’t include the pgrep command. The ps command displays the current process status for all running processes. It's a long list and you can use grep to show you just what you want.

ps -aux | grep ping 

Example showing ps -aux output

The process id on this distribution is in the second column from the left. In this case the PID = 24895.

Removing the network.log

When you are done with your analysis you can remove the network.log file with the rm command. Becareful not to remove the wrong file, this can crash your system.

rm network.log

References

More info about the Jobs Command
https://www.computerhope.com/unix/ujobs.htm

Date logic from
https://stackoverflow.com/questions/10679807/how-do-i-timestamp-every-ping-result

Use the linux manual pages to learn more about each command.
man kill
man ps
man grep
man pgrep
man ping
man cat
man more
man jobs
man date
man top
man rm

You can search for the linux pipe command too.