Entries tagged 'cat:Computer' (Page 4)

Not turning my old Laptop into a cool-looking, silent HTPC Entry created on 2022-03-12 Authors: steeph (370) Categories: Computer (78) HTPC (1) Projects (41) Languages used: en (255) Topics: Projects → Case Modding (9) Projects → Ideas (8) edit

When my old laptop was finally broken enough that I bought a new one, I disassembled it and reluctantly put its components next to a Pentium II board and an awesome old SCSI hardware RAID controller into a drawer. The display is still good, and so is its motherboard and IO boards. Still a working peace of tech, but without a working battery, solid case and fully functioning keyboard it's of no use to me. Unless I had a use case for another computer that's neither good for travelling nor powerful enough to justify being a stationary PC, this thing would rot in this drawer. But I had an idea for a case that would give it a new purpose as a media station. One mSATA system SSD, three 2.5" media HDDs (or SSDs), a wooden enclosure, six large copper heat sinks that would protrude the left wall to allow for passive cooling of the CPU and GPU. The picture in my mind is really nice, it has a 4th gen mobile i7 CPU, a decent GPU, a good enough DAC, all relevant video outputs, I have the parts, drive bays, heat sinks, heat pipes, wood, ... But, it was apparently never important enough to me to get started. I doubt I'd use an HTPC much. And so it is still rotting in that drawer.

Does anybody want that PC? I'd build it.

Now my new laptop has started to degrade. Battery, keyboard, touch pad. all the parts that wouldn't be required to turn it into a stationary HTPC. It lacks the four SATA ports. But it has a fast NVME and a fast enough USB for more than four SATA ports, needs less power, the mainboard is much smaller. So it would also be a good candidate for such a PC. But I still don't need it except as a travel notebook. Sooo, I guess that's the end of this PC case idea.

Comment via email
On Notetaking; Minimalist Web Notepad (and an edit function for SBWG) Entry created on 2022-02-28 Authors: steeph (370) Categories: Computer (78) Editor (1) SBWG (18) Shared (17) Software (52) Web Application (1) Languages used: en (255) edit

There are so many ways to take and organise notes… I stopped thinking about it. I stopped trying to organise the right kind of notes in the right place, right kind of software or in the right structure. Some things I write on a piece of paper, which may or may not lie around and in the way for weeks, or I put it in a file, or create a bookmark. Or a write it in a terminal so that I can grep it from the history later. Or I send myself an email. Yes, that's still something people do. I do it even though I know there are better ways to save and sync notes across devices. There are so many better ways that I can't decide on which I want to use. There are so cool, sweet and genius little (nd not so little) apps, CLI tools, TUIs and web UIs that people recommend. I don't want to spend years testing them so that I can decide which I want to use with which config. But there is one that I adopted qhickly and gladly. I guess I stumbled over it just at the right time or I wouldn't have installed it, and wouldn't still use it years later.

It's called Minimalist Web Notepad. I'm not sure if the linked Github is from the originl author. Feel free to check yourself. There are quite some forks. One reason for that may be that its name is very much a complete description of what it is, and the minimalism is enforced by the maintainer. If you want any feature on top of the core functionality, you have to add it yourself or look through the forks. Upon installation you choose or create a directory in which the notes are saved. Then you can pass a file path through the URL when you open the app, and it will display the contents of the file. If you edit anything in the notepad, it will be saved immedietly to the file (if JS is enabled). If the file didn't exist, it will be created. So, this notepad can be used as a simple addition to the practice of collecting a convoluted mess of text files that contain notes, which is perfect for me. There is no password protection (in the original version). But Apache can already do that.

And I found another use for minimalist-web-notepad. I started SBWG on the idea that more things should be files. The concept of everything being a file works great in Unix-like systems, which device drivers and kernel components that create those files as sensible interfaces to things. But I like the idea of things being files independently of sensibility and efficiency. Maybe that's why I like minimalist-web-notepad. There, notes are files, in SBWG, blog entries are files, in my etherpad-lite, pads are files. Wait a moment… if I use the entries directory of a SBWG web site as the notes directory of minimalist-web-notepad, I could edit blog entries in the web browser. And so I did that, and added a hook to the settings file of draft0 that includes a link to every entry that links to the notepad of that entry. For a while now there has been a hidden edit link in every draft0 entry that allows me to edit blog entries quickly without moving away from my principle of not adding any client-to-server interaction to SBWG.

See, that's why it's great to agree on formats (and standards in general). The author of this minimalist-web-notepad didn't know about SBWG, but just kept the tool simple and file-based, and thereby created a blog entry editor for SBWG web sites that fits perfectly, accidently.

Just in case anybody wants to add the same hook to their SBWG settings file, here it is:


# Add an edit link to every entry's title section (when the entry is displayed on its own page)
hook_entry_title_tags_after() {
  echo "edit" >> "${outfile}"
}

Replace https://edit.draft0.de with the URL to your minimalist-web-notepad (or other editor) installation. Make sure to protect it from anonymous access, unless you like surprises, I guess. If you want to hide the link, too, use CSS or change the link text to '.' or place it differently by using a different hook or be creative or use a browser extension instead of the hook.

Comment via email
SBWG 0.10.2 Entry created on 2022-02-08 (edited 2022-02-08) Authors: steeph (370) Categories: Bash (31) Code (31) Computer (78) Linux (35) Projects (41) SBWG (18) Scripts (28) Software (52) Languages used: en (255) Topics: Projects → Code → Bash Scripts → SBWG (16) edit

I know, my entries on SBWG are too chaotic to follow what's happening with the project in detail. But who cares, really? I'll just continue to write broadly about the progress that I make with the script.

So, after re-deciding that I'm not going to make a version 1.0 because it's just not the kind of software that can ever claim for itself the thoroughness that I myself would expect from a piece of software that's labeled v1.0, I finished the testing and bug squashing that I, for a short while, had intended to lead to version 1.0 to my satisfaction, and started implementing new features again. Great, now I can make the script take longer to finish again. :)

During my testing and bug squashing spree I already implemented a routine that I call the pathreducer. If enabled through command line option, it reduces paths to conform with the file and directory name restrictions of most file systems out there. I took this a bit far and it can now even conform to filenames of the 6.3 format, if the user wishes. I have ideas to improve this further, including making it automatically conform to the exact limitations of individual file systems instead of stripping and replacing characters that aren't allowed in file names in many file systems whether it would have been necessary in the present case or not. But that's for another time. For now it works well for what it is supposed to be: a workaround for too long and otherwise invalid file names that would be generated by the script when naming files after categories, topics and other tags, as well as a solution to problems that might occur if SBWG would be used to generate a web site onto a file system that has more restrictions than those commonly used on Unix-like systems.

As part of the improvements made during the no-new-feature time, I fixed many bugs that I didn't expect at all when I started (which is why I prohibited myself from implementing new features in the first place), learned a lot about Bash again, and made some small improvements that I wouldn't call new features, but are still neat to have. One of them makes tag lines more intuitive. Forbidden characters are removed or replaced and leading and trailing whitespaces are removed, leading coincidentally to the fact that you can use a space after the tag type (e.g. 'cat: Example' instead of 'cat:Example') or not and the tag will be recognised as being identical in both cases. I'm mentioning this because the first person to type a SBWG tag line besides me typed a space intuitively and I had to tell them that that's not how that works. Well, now it is, if you prefer it. Maybe case-insensitivity will be next. I'm considering it. Wouldn't be hard to add. I'm not sure if I want it, though.

Another thing that improved drastically in that time is the time it takes to generate huge web sites. SBWG never had problems with giant files, even entry files with gigabytes of text, because the content body isn't parsed. But with thousands of entries or thousands of tags in one entry, generation time would previously go into hundreds of years (theoretically/calculated, of course). By improving some routines and caching some parts during the generation process I got the generation time of an example torture web site that I created, from over 300 years down to just short of 72 hours on my Core-i5 ultrabook onto an NVMe drive. Any reasonably sized web site even with a relatively large weblog is completely generated much quicker. So it would be possible to e.g. let SBWG re-generate a web site automatically multiple times a day without problems. I have other ideas that will speed up the generation process significantly, namely parallel processing and skipping of existing unchanged content. But both those features are not mature enough, yet. I will probably attend to them again when I have packed SBWG with so many features that slow down the process compared to the current version that I feel more parallelisation and more drastic caching will be necessary.

So, the first new feature on the list were entry pictures. A way to bind pictures, image files, to entries without having to include <img> tags. This feature now already developed into a general way to attach files to entries. Images are resized, embedded and linked to their originals, audio files are embedded as an audio player if the browser supports this, and other files are linked to allow visitors to download them. Video files will also be embedded as a player in future version. The file attachments feature is not done, yet. Enclosures in the RSS feed, presentation of the download links and many small things have to be improved. But the initial idea of entry pictures already works. There is a naming convention that makes a file an attachment to a certain entry. (The same naming convention as is used for style sheet sets.) See the README of version 0.10.2 or above for detailed information.

The next feature on the list is comment links below blog entries. Simple mailto links to let readers e-mail comments on entries to the author. I will probably start to work on multiple features at the same time again, as I did before.

So, I've published SBWG version 0.10.2 now. I hope I'll find the time to create and publish new versions more frequently again in the near future. But I doubt I will.

Comment via email
SBWG 1.0.0 Delayed To Next Life Entry created on 2021-12-28 Authors: steeph (370) Categories: Bash (31) Code (31) Computer (78) Linux (35) Projects (41) SBWG (18) Scripts (28) Software (52) Languages used: en (255) Topics: Projects → Code → Bash Scripts → SBWG (16) edit

I've decided to not publish version 1.0.0 of SBWG.

Very early on I devided against a versioning approach that allowed me to stay below version 1.0 for a very long time by only incrementing the version number by 0.0.1 for important changes but rather chose to increment the version and publish a new version whenever. I stick to this approach because it allowes me to express felt overall progress in the version number. But now that the goals that I at some point set for version 1.0.0 are nearly reached (they pretty much are), this leaves me in a spot where publishing version 1.0.0 would be the next thing to do despite the fact that it's not actually really absolutely perfect, yet. Absolute perfection isn't really my approach. It's still more like a learning project.

So to avoid having published a version that looks perfect on the label but isn't inside, I will skip this version number. Don't get me wrong. My goals are. I've tested it more than I thought I would and thought of potential problems and fixed bugs that I'd argue are not something you'd expect most shell scripters to catch. It definitely works reliably for what it is intended and at least works well for much more than I thought it would in the first few months of starting this project.

So, there is no link in this entry. No new version published today. The next version will be 1.x.x something.

Alright. Now that that's done, I can start to implement new features again next year.

Comment via email
backup.sh Entry created on 2021-12-05 Authors: steeph (370) Categories: Backups (4) Bash (31) Code (31) Computer (78) Linux (35) Projects (41) Scripts (28) Software (52) Languages used: en (255) Topics: Projects → Code (26) edit
This entry is an update of the entry 'Backup Shell Script'.

I've updated/improved my backup script again.

Download


#!/bin/bash
#2021-11-03

budir="/mnt/backup"
num=8
list="/root/backup-list"
hostname=$(</etc/hostname)
srcdir="$1"
#NAME=${SRCDIR//\//--}
name="$2"

function usage () {
  echo "This script requires either one or two arguments."
  echo "Usage:"
  echo "$0 JOBLIST"
  echo "$0 SOURCE_DIRECTORY NAME"
  echo
  echo "JOBLIST File that contains one backup job per line in the format SOURCE_DIRECTORY NAME"
  echo "SOURCE_DIRECTORY Directory that should be backed up. Please, no trailing slash."
  echo "NAME A string that is used to name the backup in the destination."
  exit 1
}

function single() {
  if grep -qs "$budir " /proc/mounts
  then
    fullname="$budir/$hostname/$name"
    printf "\n"
    printf "Attempting backup of source directory '%s' to '%s'.\n" "$srcdir" "$fullname"
    printf "Number of differential backups to keep: %s\n" "$num"
    printf "Removing oldest backup... "
#    rm -rf "$fullname.$num"
    rsync --archive --delete "$budir/empty/" "$fullname.$num/"		# This is quicker than rm.
    printf "Done.\n"
    for ((i=$num; i>=2; i--)); do
      printf "Renaming '%s' to '%s' ... " "$fullname.$((i-1))" "$fullname.$i"
      mv "$fullname.$((i-1))" "$fullname.$i"
      printf "Done.\n"
    done
    printf "Duplicating last backup ('%s' to '%s')... " "$fullname.0" "$fullname.1"
    [[ -d $fullname.1 ]] && exit 1							# This directory should not exist at that point.
    cp -al "$fullname.0" "$fullname.1"
#    rsync --archive --acls --xattrs --hard-links "$fullname.0/" "$fullname.1/"
    printf "Done.\n"
    now=$(date)
    printf "\n\n\n" >> "$fullname.log"
    printf "STARTING INCREMENTAL BACKUP AT %s\n" "$now" >> "$fullname.log"
    printf "Starting new incremental backy uppy at '%s.0'..." "$fullname"
    if rsync --exclude ".cache" --archive --no-links --delete "$srcdir/" "$fullname.0/" 2>&1 | tee -a "$fullname.log"
    then
      printf " Done.\n"
      printf "Done.\n" >> "$fullname.log"
    else
      printf " Failed.\n"
      printf "Failed.\n" >> "$fullname.log"
    fi
    now=$(date)
    printf "\nIf this line is here the script finished (with or without errors) at %s\n" "$now" >> "$fullname.log"
  else
    printf "'%s' is not mounted. Aborting." "$budir"
    exit 1
  fi
}

function fromlist() {
  while read job; do
    if [ -n "$job" ]; then
      name="${job#* }"
      srcdir="${job% *}"
      single
    fi
  done < "$list"
}

mkdir "$budir/empty"									# Empty directory for a quicker method to delete a large directory.

case $# in
0)
  mount "$budir"
  printf "Reading backup jobs from list. Defaulting to %s.\n" "$list"
  fromlist
  ;;
1)
  mount "$budir"
  list="$1"
  printf "Reading backup jobs from %s." "$list"
  fromlist
  ;;
2)
  mount "$budir"
  single
  ;;
3)
#  I can't decide whether to make the third argument num or budir. I don't need it anyway.
#  num=$3
#  budir=$3
#  mount $budir
#  single
  usage
  ;;
*)
  usage
  ;;
esac

exit 0
Comment via email
SBWG - The Pathshortener And Other Recent Changes Entry created on 2021-12-05 Authors: steeph (370) Categories: Bash (31) Code (31) Computer (78) Linux (35) Projects (41) SBWG (18) Scripts (28) Software (52) Languages used: en (255) Topics: Projects → Code → Bash Scripts → SBWG (16) edit

I made it my goal to harden SBWG before I start to implement new features. Before I call the next version of this project 1.0 I want to make sure that unexpected input from the command line or from source files, absurd numbers of absurdly long tags and content items, stupidly weird filenames or random binary data as tag values as well as purposfully created traps in the various places where input is processed are handled well, meaning that nothing fails unless there is no sensible way around it, and if something fails, that nothing breaks. Data should be filtered carefully, errors should be handled well and whereever possible data should be made processible if it was supplied in an unprocessible form to reduce the chances of errors. On top of that I wanted to make sure that the script did its job in a reasonable amount of time considering the circumstances. I mean, it will never be very fast. Bash is just not the right language for that. But there certainly were some repetitive tasks that could be improved. Fot the latter I created a simple caching functionality that will probably be extended in the future. I managed to reduce the (calculated/estimated) generation time of my biggest test web site from almost 300 years to a few days. Actual web sites will of course not take that long to generate, even on a slow machine. A huge web site will maybe take up to one day to generate completely, even without the new options that keep the script from re-generating existing unchanged parts of the web site. But before sombody will try to create such a big web site with SBWG I will probably have improved speed further. And even then it's a worst-case time.

As part of the aforementioned goals I have started working on last new feature before version 1.0. I call it the pathreducer. Since many of the files created by SBWG are named after the tags they represent, they can become quite long and contain almost any printible character, including multi-byte unicode characters or characters of character sets I haven't even heard of. I definitely don't want to restrict more than I already have what characters and how many of them tag values can contain. Especially filesystems used by operating systems from Microsoft are relatively restrictive in maximum allowed directory, path and filename length and allowed characters. By default the pathreducer is not used. But if enabled via command line option or in a web site's settings file, it will filter directory and filenames and shorten them to a user-defined maximum length. If the pathreducer decides to change a path elements it also adds a 6-character hash value to make shortened or otherwise reduced path elements as good as unique.

That works well for now and even can create 8.3 or 6.3 filenames for old DOS filesystems. But the result is not very nice because it isn't aware of what filesystem it is going to write a file to. To be save it removes more characters than it would have to for ext and NTFS filesystems. In the future I may extend the pathreducer to detect the filesystem at least of the root of the output directory automatically and decide how exactly path elements should be reduced according to the actual limitations of the present filesystem. Than it may even be enabled by default, even though it can increase the generation time quite a bit.

There are still some tests that I want to do and I will probably find some more things that I want to fix before version 1.0. But I see light.

Comment via email
Generating Bitmap Files With Bash Entry created on 2021-10-17 Authors: steeph (370) Categories: Bash (31) Bitmaps (1) Code (31) Computer (78) Linux (35) Scripts (28) Software (52) Languages used: en (255) Topics: Projects → Code → Bash Scripts (23) edit

I needed a large amount of image files to try something. I wanted them to be different images. But what's in them didn't matter. So I looked at a BMP file to see how I could create one byte for byte automatically. Bitmap is just the first uncompressed format that I thought of. This is what I came up with:


rbmp() {
  echo -n -e '\x42\x4D\x2A\x02\x00\x00\x00\x00\x00\x00\x7A\x00\x00\x00\x6C\x00\x00\x00\x10\x00\x00\x00\x09\x00\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\xB0\x01\x00\x00\x23\x2E\x00\x00\x23\x2E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42\x47\x52\x73\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x'
  c=$(</dev/urandom tr -dc '0123456789ABCDEF' | head -c864 | sed 's/.\{2\}/&\\x/g')
  echo -n -e "$c"'00'
}

Or, if you would like to do run a command for each pixel/color before it is generated, you can do it like this:


# Create a 24 bit bitmap file of 16x9 randomly colored pixels
randombmp() {
  echo -n -e '\x42\x4D\x2A\x02\x00\x00\x00\x00\x00\x00\x7A\x00\x00\x00\x6C\x00\x00\x00\x10\x00\x00\x00\x09\x00\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\xB0\x01\x00\x00\x23\x2E\x00\x00\x23\x2E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42\x47\x52\x73\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
  i=1
  while (( i < 433 )); do
    c=$(</dev/urandom tr -dc '0123456789ABCDEF' | head -c2)
    echo -n -e '\x'"$c"
    i=$((i+1))
  done
}

I'm sure I did something wrong. I just copied the header of some BMP file with the right format that I don't even know what it was created with. I didn't actually look up how the header of a BMP file is composed. But it worked.

Comment via email
USB/Serial PWM Fan Controller Using an Arduino Entry created on 2020-11-22 (edited 2021-10-15) Authors: steeph (370) Categories: Arduino (4) Case Modding (11) Code (31) Computer (78) DIY (16) Electronics (16) Fans (1) Hardware (16) Projects (41) incomplete (22) Languages used: en (255) Topics: Projects → Arduino (4) Projects → Case Modding (9) edit

I wanted to be able to control the speed of the fans in my big NAS, Fred, individually. Even though the mainboard in use has five PWM fan connectors, the chipset can only control the speed of all fans together. There are probably good fan controllers commercially available that solve this problem better than I did. But they seemed overpriced and it seemed like a fun learning project for me.

The fan controller that I made uses an Arduino Nano clone that listens to it's serial port, waiting for a command to change the speed of a fan. When a command is recognised the continuous PWM signal for that fan is changed accordingly. It's possible to control up to six fans this way with an Arduino Nano. I'm only using three though since I only have three fan groups that need to be controlled separately.

The Arduino sketch/C code for the Arduino Nano that I used is as follows.




//fan speed sensor wire attached to digital pin 2 with a 10kohm pullup resistor
//fan PWM control wire attached directly to digital pin 9

#include <PWM.h> //include PWM library http://forum.arduino.cc/index.php?topic=117425.0

volatile int half_revolutions1; //allow half_revolutioins to be accesed in intterupt
volatile int half_revolutions2; //allow half_revolutioins to be accesed in intterupt
int rpm1; //set rpm as an integer
int rpm2; //set rpm as an integer
int pwm=255;
const byte numChars = 5;
char receivedChars[numChars];

boolean newData = false;

void setup()
{
  InitTimersSafe(); //not sure what this is for, but I think i need it for PWM control?
  bool success = SetPinFrequencySafe(9, 25000); //set frequency to 25kHz
  pwmWrite(9, 51); // 51=20% duty cycle, 255=100% duty cycle

  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  analogWrite(5, 170);
  analogWrite(6, 255);
  pinMode(2,INPUT_PULLUP); //set RPM pin to digital input
  pinMode(3,INPUT_PULLUP); //set RPM pin to digital input
  half_revolutions1 = 0;
  rpm1 = 0;
  half_revolutions2 = 0;
  rpm2 = 0;

  Serial.begin(9600);
}



void loop()
{
  sei(); //enable intterupts
  attachInterrupt(0, fan_rpm1, RISING); //record pulses as they rise
  delay(1000);
  detachInterrupt(0);
  attachInterrupt(1, fan_rpm2, RISING); //record pulses as they rise
  delay(1000);
  detachInterrupt(1);
  cli(); //disable intterupts

  rpm1 = (half_revolutions1/2)*60;

  Serial.print("1");
  Serial.println(rpm1);

  rpm2 = (half_revolutions2/2)*60;

  Serial.print("2");
  Serial.println(rpm2);

  rpm1 = 0;
  half_revolutions1 = 0;

  rpm2 = 0;
  half_revolutions2 = 0;

  pwm = 255;
  recvWithStartEndMarkers();
  processCommand();
}

void fan_rpm1()
{
  ++half_revolutions1; //increment before returning value
}


void fan_rpm2()
{
  ++half_revolutions2; //increment before returning value
}


void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = 's';
    char endMarker = '\n';
    char rc;
 
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void processCommand() {
    if (newData == true) {
        Serial.print("s");
        Serial.println(receivedChars);
        switch (receivedChars[0])
        {
            case '1':
                receivedChars[0] = '0';
                sscanf(receivedChars, "%d", &pwm);
                analogWrite(5, pwm);
                break;
            case '2':
                receivedChars[0] = '0';
                sscanf(receivedChars, "%d", &pwm);
                analogWrite(6, pwm);
                break;
            case '3':
                receivedChars[0] = '0';
                sscanf(receivedChars, "%d", &pwm);
                
                break;
//            default:
//                Serial.println("I don't know what that means.");
        }
        newData = false;
    }
}

Well, how should I put it? It works, usually.

(tbc?)

(tba:photos)

Comment via email
Go To Navigation Page
Show/Hide Navigation
Mastodon