Wednesday, January 18, 2023

New Yankee Workshop Now On Youtube!

I just noticed this week that The New Yankee Workshop is now officially on Youtube!  The New Yankee Workshop is an iconic woodworking show that ran on PBS for 21 years.  The Youtube channel doesn't have all the episodes but even the official website didn't have them all.  The only way to get all the episodes was to buy the complete series DVD which costs $3000.


They seem to have a lot of difficulties bringing the episodes online or at least was bringing them online very slowly.  As of this writing, the official website has had most of its contents removed and has a message saying they're rebuilding it.

Monday, January 16, 2023

Nier:Automata Ver1.1a Anime Reaction

Nier:Automata is one of my favorite games of all time.  It was a game that at the conclusion of the game, I just sat there staring at the screen thinking and FEELING the experience that I just went through.  Yeah, I loved the game.

When it was announced that there will be an anime adaptation to be released in January, 2023, I was excited but also worried.  I wondered if the anime can really capture the same feeling that I had while playing the game?  



So far two episodes have been released.  Episode 1 tried to be very faithful to the game and creates many of the scenes, but I still walked away more worried.  The game just felt more epic and the computer art felt more aligned with the tone of the world so the anime failed to match.

Episode two diverged from just trying to recreate the game and that felt much better.  The story of the second episode felt like it can fit within Nier:Automata and I enjoyed.

How will the rest of the season go?  I'm not sure.  I will continue to watch and I hope they utilize the music of the original Nier:Automata more since it is a beautiful soundtrack which fans and newcomers will enjoy.  I can't imagine anyone being disappointed if they don't hear original new composition in the anime.


Goodbye OnHub!

 On January 11, 2023  Google shutdown support for the 7 years old OnHub WIFI router.  Technically, Google shutdown the Google Home App support of the OnHub because OnHub devices were technically made and sold by other companies (either ASUS or TP-Link) depending on which OnHub you had.  However, since the software was all handled by Google, if the software doesn't work then you can't do anything with it.  It will still "run" but no configuration changes can be made nor can you see any info about the device.  The only thing you can still do is to factory reset and delete the whole network.  It's unfortunate that once Google decided to stop supporting the device that they are essentially dead.

I found the OnHub to have been a great WIFI router that was powerful and easy to manage.  It had enough customization for my uses and didn't require me to be an IT admin for it. Even though there were probably a few features that I wished it added, it was balanced enough that I was willing to sacrifice those features.  I wished that before its end-of-life, Google provided a way to download its setting and load it to a new network.  Even though I replaced the OnHub with a Google Wifi (not the Nest Wifi), I had to manually put in all the setting information including tracking down all the devices that connects to it so that I can give each a recognizable name.  Other settings like groups, schedules, reserved IPs, IP range, etc. all had to be manually entered.  Most of it is pretty quick but the device naming is a pain.

Over on the OpenWRT forum there are developers trying to give the hardware additional life by replacing the software on it so it is not reliant on Google and Google's cloud.  That would be great as it saves devices from going to landfills and honestly the hardware is still perfectly fine even to this day.

Setting Up Windows with CyberPower UPS

To set up a Microsoft Windows PC to power down during a power outage does not require installing any proprietary software.  

Simply create a new power profile in Windows and go to the advance setting to set the conditions you want to power down.  



For example, the machine can be configured to power down when the battery reaches a certain point.  This works because when the CyberPower UPS is connected to the Windows machine through a USB connection, Windows will sees it as being on battery power like a laptop.  It will see how much power is left.

More details about the battery probably will need the CyberPower software but for simple shutdowns no additional software is needed.

Setting Up Fedora Linux With Cyberpower UPS

These are my notes on how I set up my Fedora Linux desktop to listen to a Cyberpower UPS to known when to shutdown when there is a power outage.  This is only for one machine connected directly to the UPS through usb and doesn't cover when there are multiple machines that needs to be shutdown.

The simplest way to configure your Linux system to work with a Cyberpower UPS is probably to use Cyberpower's PowerPanel for Linux software, but I didn't use it since I wanted to see if I can use non-proprietary software.  Instead, I used the open-source Network UPS Tools (NUT) but it required a bit of manual work to get it configured.

All I want to do is to have my PC shutdown a few minutes after the power go out of the house so I bought a Cyberpower UPS and use the direct USB connection for it to communicate with the PC.

Once connected, check that Linux can see the UPS:

# lsusb

You should see the UPS listed among the list of USB devices.

Install the NUT software:

# sudo dnf install nut nut-client

This will install NUT and there are 5 key configuration files to be aware of:

  1. ups.conf - settings for UPS driver
  2. upsd.conf - settings for UPS daemon
  3. upsd.users - access control file for the UPS daemon
  4. upsmon.conf - settings for the UPS monitoring daemon
  5. upssched.conf - settings for scheduler daemon

Once NUT is installed, you can use one of its tools to identify the UPS and it will give you info that you can use in the config files:

# sudo nut-scanner

Add the information to the /etc/ups/ups.conf

[cps1500avr]
        driver = "usbhid-ups"
        port = "auto"
        vendorid = "0764"
        productid = "0501"
        product = "ST Series"
        vendor = "CPS"
        bus = "004"

The cps1500avr can be anything you want.  It is the name you'll be using to identify the UPS.  "usbhid-ups" is the driver for Cyberpower UPS.  All of this info came from the nut-scanner.

Add a udev rule, /etc/udev/rules.d/50-usp.rules,  so that Linux understand the UPS:

SUBSYSTEM=="usb", ATTR{idVendor}=="0764", ATTR{idProduct}=="0501", GROUP="nut" TAG+="systemd", ENV{SYSTEMD_WANTS}+="nut-server.service nut-monitor.service"

The TAG+ part is something I found on this blog for an issue with the system service not seeing the UPS and thus not able to start when the system starts up. 

Reload the UDEV rule:

# sudo udevadm control --reload-rules
# sudo udevadm trigger

Test that the driver can start and then start/enable the service:

# sudo upsdrvctl start
# sudo systemctl start nut-driver-enumerator.service
# sudo systemctl enable nut-driver-enumerator.service

Now we need to add the NUT user that will be used to monitor the UPS to /etc/ups/upsd.users

[nutmon]
        password = <password>
        uspmon primary
        action = SET
        instcmds = ALL

"nutmon" can be anything you like and then you can start the server and ask it to print out the UPS info that it sees.

# sudo systemctl start nut-server.service
# sudo systemctl enable nut-server.service
# upsc cps1500avr

Edit /etc/ups/upsmon.conf by adding:

MONITOR cps1500avr@localhost 1 nutmon  <password> primary

Start and enable the monitoring service

# sudo systemctl start nut-monitor.service
# sudo system enable nut-monitor.service

Finally, we need to tell NUT what to do when certain events happens such as when the battery is low or when it notices that the power is out.  Edit /etc/ups/upssched.conf (thanks to this article for the example)

# Gives the script to run the commands for various signals
CMDSCRIPT /usr/bin/upssched-cmd

PIPEFN /var/lib/ups/upssched.pipe
LOCKFN /var/lib/ups/upssched.lock

# Send alerts immediately on change in line power
AT ONBATT * EXECUTE onbatt
AT ONLINE * EXECUTE onpower

# (Optional) Silence the beeper after 2 minutes
AT ONBATT * START-TIMER mute_beeper 120
AT ONLINE * CANCEL-TIMER mute_beeper

# Shutdown after 5  minutes on battery (5 * 60 = 300)
AT ONBATT * START-TIMER onbatt_shutdown 300

# Cancel timer if power's restored
AT ONLINE * CANCEL-TIMER onbatt_shutdown

# Battery replacement indicated by cron'd quick test
AT REPLBATT * EXECUTE replace_batt

Then edit the command script you put in (in my case it is /usr/bin/upssched-cmd):

UPS_USERNAME="nutmon"
UPS_PASSWORD="<password>"
UPS_LINK="cps1500avr@localhost"


case $1 in
    onbatt)
        # make sure beeper is enabled
        upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${UPS_LINK} beeper.enable
        # alert
        message="Power outage, on battery"
        logger -t upssched-cmd "$message"
        ;;
    onpower)
        message="Power restored"
        logger -t upssched-cmd "$message"
        ;;
    mute_beeper)
         message="(2) minute limit exceeded, muting beeper"
         upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${UPS_LINK} beeper.mute
         ;;
    onbatt_shutdown)
        message="Triggering shutdown after (5) minutes on battery"
        logger -t upssched-cmd "$message"
        /sbin/upsmon -c fsd
        ;;
    replace_batt)
        message="Quick self-test indicates battery requires replacement"
        logger -t upssched-cmd "$message"
        ;;
    *)
        logger -t upssched-cmd "Unrecognized command: $1"
        ;;
esac
Test that it will shutdown by sending it the same shutdown signal from the UPS:
sudo upsmon -c fsd

If all goes well, get the service to start on boot:

# sudo systemctl enable nut.target
# sudo systemctl enable nut-driver.target

From now on, if the power outtage lasts more then 5 minutes (i.e. the UPS is running on battery), your system will shut down.  You'll need to manually turn the system back on when the power returns.

Notes

  • I'm not sure if something automatically started and enabled the specific driver (nut-driver@cps1500avr.service) or if I did it and just forgot to note it down.
  • This article from the Archlinux wiki described a problem that sounds like the same problem that the UDEV TAG part addresses but uses a different approach.

Sunday, January 15, 2023

Life for the Stadia Controller Post-Stadia

Update:  The official instructions to enable Bluetooth mode on the Stadia controller has been published.  The deadline to enable this is December 31, 2023.


Google Stadia will be shutting down on Jan 18, 2023 and while I wish Stadia had found more success the shutdown won't impact me that much given that Google is paying people back for the money they spent on Stadia game and hardware purchases.  I was surprised by this as I'm not sure I remember any other company willing to refund you money on things you bought years ago when they close.  One thought that I did have when the shutdown announcement was made was what will I do with the controllers?

The Stadia controller is pretty nice and well-built and it seem a shame to just throw them away.  I looked to see if I can use them with my PC which was possible but only through a wired connection... until now.   Despite Stadia going away, Google announced that they will release an update for the controller that will enable it to be used as a bluetooth controller.  

Learning About Lights

On a bulb, there might be a number such as F32T8/TL741 but what does the numbers mean?
  • F32 means it is a 32W bulb.
  • T8 gives the size (T8 is a 1" diameter tube).
  • 7 - I'm not sure what this means.
  • 41 means the color temperature is 4100 Kelvin.
    • 2000 K is like sunset/sunrise
    • 3000 K is warm yellow light
    • 4000 K is a warm white light like early day light (has a bit of yellow)
    • 5000 K is also daylight and is a good option for a garage.
    • 6000 K gives a noticeable blue tinge.
What the number doesn't indicate is the brightness (i.e. Lumen) or the color rendering index (CRI).

When it comes to lumen, the right number depends on what the area you want to light up.   A 60W incandescent bulb is about 700 lumens.  Putting a 5000 lumen light in your bedroom will be too bright and harsh but it might be just right for a 2 car garage.

The CRI is a number from 0 to 100 where 100 gives the best color reproduction on the object while a 1 will make everything look like a single color.

Saturday, January 7, 2023

Kernel 6.0.16 (and 6.0.1.17?) Causes Freeze (and how to keep previous kernels)

Update 4: Kernel 6.0.18 works!

Update 3: According to users on Reddit, 6.0.17 still exhibit the problem.  One user said that 6.0.18 has the fix.

Update 2: Decided to remove the back kernel package using the dnf remove command in the previous update rather then dnf history since I only wanted to remove the kernel.  That removed the .16 kernel from the boot loader and had the .15 as the default.

sudo dnf remove $(rpm -qa | grep ^kernel | grep 16-300)

Update:  Seems like others are also affected by the same issue with a suggestion on how to remove and block the 6.0.16 kernel.  

Find and remove  6.0.16 kernel packages:

sudo dnf remove $(rpm -qa | grep ^kernel | grep 16)


Blacklist the 6.0.16 packages from getting installed again by editing /etc/dnf/dnf.conf

# Bad packages
excludepkgs=kernel*-6.0.16-300.fc37.x86_64

Tracking bugs on Fedora:


---------------------------------------------------------------------------

Today I did a typical update of my Fedora system which included a new kernel (kernel-6.0.16-300.fc37.x86_64), but when I rebooted and logged in the system will freeze.  This might be the first time (or at least it's been a long time) that I've had a Fedora upgrade not be seamless.

Fortunately, when Fedora upgrades the kernel, it keeps copies of the previous two versions so switching back simply requires watching for the GRUB boot loading screen and picking the previous kernel.  Just make sure you do this before the system automatically boots to the latest version.

I was able to determine the freeze is caused by the kernel since booting the previous kernel showed no problems after logging in.  Knowing that I have at least one working kernel, I had two choices.  Uninstall the latest kernel or keep using the old one and wait to see if any future updates fixes the problem.

I've not uninstalled a kernel on Fedora before and was unsure what would happen.  I could also simply try to revert the entire update, but that still leaves the same question.  Using dnf, you can review what was done by:

sudo dnf history

To see the details of a specific transaction, use the ID that the history command gives and use:

sudo dnf history info <id>

With dnf, you can chose to undo or rollback a transaction.  Undo will do the opposite of what was done (e.g. uninstall or reinstall the packages) of the specific reaction while rollback will undo everything between the between the transaction and the current system.

Since I didn't want to do either since this involved the kernel, I decided to just keep rebooting to the previous kernel even though it is inconvenient and hope that it gets a fix for whatever is causing the problem.

Protecting the Previous Kernel

What if it took a few more kernel updates before the problem gets fixed and the working kernel gets removed during the update?

The versionlock plugin will lock and keep the kernel on the system.

sudo dnf install python3-dnf-plugins-extras-versionlock
sudo dnf versionlock add kernel-6.0.15-300.fc37.x86_64
The delete option will let you remove the lock:
sudo dnf versionlock delete kernel-6.0.15-300.fc37.x86_64

Thursday, January 5, 2023

Add Build info to a Go Binary

Having the build info directly in a binary is useful in helping to identify one binary from aonther especially if you do a lot of compilations.  Manually updating that information in to the source before build is cumbersome and error prone so it's better to automate it.

This can be done in Go using -ldflags with the build command.  For example, if you have a main.go file such as this:

package main                                                                    

import "fmt"
var(
    build string
)

func main() {
    fmt.Printf("build date: %v\n", build)                            
 
)
Then you can build it with -ldflags to change the value of build with the current date when using the go build command:
go build -ldflags "-X main.build=`date`" main.go

Be careful that other parts of your program doesn't change the value during runtime since it is just a variable.

To make it a little safer, you can put the variables into another package and don't allow it to be updated.   You can, for example, create a package called "buildinfo"

package buildinfo                                                                      
                                                                                   
var (                                                                              
    builddate = "0"                                                                
)                                                                                  
                                                                                   
func GetBuild() string {                                                           
                                                                                   
    return builddate                                                               
}                                                                                  

that is called by your main.go:

package main                                                                       
                                                                                   
import (                                                                           
    "fmt"                                                                          
                                                                                   
    "example/buildinfo"                                                                
)                                                                                  
                                                                                   
func main() {                                                                      
                                                                                   
    fmt.Printf("build date: %v\n", build.GetBuild())                                                             
                                                                                
}

You will then build your application with:

go build -ldflags="-X 'example/buildinfo.builddate=`date`'"

Running the program will now output something like this:

build date: Thu Jan  5 12:33:38 PM

Sunday, January 1, 2023

Dust Collection and Portable Table Saw Carts

Working in a limited space means that I have to constantly move equipment around in order to have access to what I need.  This takes times and takes away some of the fun since it feels like that I spent more time setting up than I am actually building things.  To help myself setup faster, I made two mobile carts.  One is for my shop vac dust collection and the second is for my portable table saw.

Dust Collection Cart



The cart is pretty basic and holds the shop vac on the bottom and the sawdust separator on top.   The connectors detaches easily so I can quickly connect tools to it and the outlet strip gives me access to power when I need it.  Now I don't find myself dragging along the separator, vac, power strip and tools separately and can roll them all to wherever I'm working.

Table Saw Cart



My workflow doesn't center around a table saw so I usually keep it on the side until I need to use it.  That means having to find a place to set it up, plug it into the dust collector, and put up a out feed table to support the cut-off.  By putting the saw on a cart with wheels, I can move it around easily.  The area under the saw can hold saw accessories and the fold-up out feed table makes it more convenient then having a separate table.

I can how roll the two cart to where I'm going to use them and quickly connect the saw to the dust collector and start working!