64Zbit.com
Tech is way, WAY interesting

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.


Save Text Snippets to DayOne using Better Touch Tool

For a long time I've wanted a quick way to save text snippets in a timestamped, quickly searchabe form. Today I created a Better Touch Tool keyboad shortcut to save text snippets to a specific DayOne journal.

Here are the details on github so that you too can enjoy this amazing automation feature.

dougpark/dayone

Better Touch Tool create a DayOne journal entry. Contribute to dougpark/dayone development by creating an account on GitHub.

dougparkGitHub


How-build-computer-controlled-robot

Read the full article at www.amazon.com

The book that started it all for me. Sometime around 1979 #kim1 #6502 #robot #diy #developer


Raspberry Pi USB boot

How to install Ubuntu Desktop on Raspberry Pi 4 | Ubuntu

Ubuntu is an open source software operating system that runs from the desktop, to the cloud, to all your internet connected things.

Install Ubuntu Desktop on Raspberry Pi 4

Covers the basics of updating your Pi 4 to USB boot.


Pluto Attacks

Html5, Phaser 2, Action packed arcade game

Pluto Attacks was previously hosted at povingames.com

Play Now

"The Plutonians are not happy with us calling their home a 'dwarf' planet. So when they discovered a trick in the space time continuum they sent an infinite number of drones to attack Earth. We created an energy weapon that can siphon off the energy from the drones weapons. This powers the Earths vessel and creates a powerful energy shield. Remember, don't let even one alien escape!"

Poving Games released this intense shooter based on the classic Phaser Invaders example and then taken it into complete overdrive! You don't have to shoot, that is done automatically. You just move left and right and blast away the plutonains. It all starts quite calmly and you'll no doubt do a perfect clearance of the first few levels.

Read More at phaser.io

Read More at html5games.net

How To Play

You can start at Normal level 1 if you want to see how it all began. Typical space game with normal dodge and shoot action. You can even level up to the 20’s and still play a dodge and shoot game. However, it will drive you crazy and you will get bored.

The fun begins at about Fun level 20. Everything is faster and you quickly realize there is more to the game then just dodge and shoot. In fact dodging is no longer possible. There are explosions, lots and lots of explosions.

Plutonians are not happy with the reclassification of their home world to Dwarf Planet. So when they discovered a trick in the space time continuum they send an infinite number of drones to attack Earth. Earth learned just enough about their technology to use it to their own advantage. We created an energy weapon that can siphon off the energy from the drones weapons. This powers the Earth vessel and creates a powerful energy shield.

For desktop just press the space bar to start and then left and right arrows to move. That’s it.

For mobile just tap to start and then use your finger to move back and forth. It’s actually easier and more fun on mobile.

Levels go by pretty quickly. Hey, it’s a game with only two buttons and you can master it in 60 seconds. By level 20 it’s moving right along and by level 30 it’s actually pretty good. Have Fun!

Tip: Don’t let any aliens escape!

Pluto Attacks


Future Projects

I've been doing this for decades and now I want to be an HTML5 game devloper. I'm starting with a server! Well, I have very little experience with game development, graphics, animation, sound, so it's going to be a fun journey.

Stories in the pipeline:

  • VSCode Remote
  • Installing Docker, Docker-Compose
  • Nodejs with socket.io
  • Nodemon sounds like Pokemon, yep!
  • SSL and Letsencrypt certificates
  • Working with Apache, MySQL and PHP
  • Hosting your own VPS backend with Linode for $5 a month
  • HTML5 games and AJAX are best buds
  • HTML5 games and socket.io are even better buds

macOS - BitBar - Get Wi-Fi SSID with shell script

So, Jason Snell got me hooked on BitBar (BitBar (by Mat Ryer - @matryer) lets you put the output from any script/program in your Mac OS X Menu Bar.) and I've been working on a plugin ever since. Here's a quick way to get your current Wi-Fi SSID.

function display-ssid {
    echo "---"
ssid=$(/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I  | awk -F' SSID: '  '/ SSID: / {print $2}') 
    echo "Wi-Fi: $ssid | terminal=false bash='$0' param1=copy param2=$ssid"

}

Get wireless SSID through shell script on Mac OS X

Is there any way to get the SSID of the current wireless network through a shell script on Mac OS X?

Mark SzymanskiStack Overflow

SSID with shell script