10 Posts for developer_board Technology close
"Letting AI do some things."
2026/06/21 3:12 PM

AI Comfort Levels

For quite a while I have been reluctant to invest much time into using AI for more than setting alarms, timers, and adding things to my reminders. But, I've been playing around with some of the free tools lately and I'm pretty impressed with whats possible now.

Siri AI

With the beta versions of iOS 27 and MacOS 27 I have been able to ask Siri to find info buried in my personal data. The assistant has been much more useful than in the past. It can perform more complex tasks with multiple steps.

One thing Siri AI doesn't seem to be very good at is programming. They seem to have limited it for these initial releases. You can use the other popular models with X-Code now, but I haven't given that a try yet.

Codex

I have also been playing with ChatGPT and Codex. I'm only using the free version for now. It looks like it can get expensive quick. That's one of the reasons I hope Apples new OS's will be able to get close to whats possible with Codex.

Using Codex to fix filename issues

One thing I used Codex for recently was fixing the names of music video mp4s I have in my collection. There are around 4500 files in this folder. Some files are named poorly and there are even a few duplicates.

I started by asking Codex to look at the folder and verify how many files there were. Then I told it what the file name pattern should be and asked it to compile a list of files that did not meet this pattern. There were about 250 files it found that were not named correctly. I was going to turn this into a renaming script, but I asked Codex to do this for me.

Not only did Codex create the script, but it also properly renamed the files based on the pattern I previously described. It was able to smartly determine which parts were the artist name, which parts were the song name, and when there was extranous data that was ok to remove. I verified that the file was correct and ran the script in the terminal.

The next task was to identify duplicate files. It was able to find 12 or so files that might have duplicates. Some of these were live versions that I did not change. But, again it did find a few files that were duplicates, even though the file names were different.

This all saved me several hours.

Using Codex to create an application

I use Jellyfin to serve up video files, movies, tv shows, and Music Videos on our local network. I'm not really happy with most of the clients on the Apple TV. They work, but never in the way I want.

I spent a few hours over the last couple weeks creating a proof of concept client in Javascript and HTML to login to our server and play content. I was able to get shuffle play working properly for our music video library.

What I want to do is the same thing in an Apple TV App that works the way I want it to. I decided to use Codex to create the first version of this App. I described what I wanted to Codex. It created a new project for me, that almost worked. I had to tell it to fix a few things to make it work correctly in X-Code. A few minutes later I had a basic App that will let me login to our Jellyfin server, navigate through the Libraries, view items in the libraries, and play MP4s.

There were a few issues with images that I was able to get it to fix with another prompt. It was also loading all the items in the music video library at once. So I asked it to add pagination to that view. Again, in just a few minutes it made the change and had most of the functionality my prototype had.

Unfortunately that was when I received a warning that I was about to run our of usage for the month. So, in a 10-15 minutes I was able to duplicate most of what I had done by hand in 4-5 hours. Kind of amazing really.

All of this is easier to manage when you know what to ask for and how to describe what you want.

I'm constantly amazed by what these tools can and can't do. Some things that seem incredible are easy for them, while other things that we take for granted are very hard for these tools to get right. Hmm, so I wonder how much it would be to run my own models for development locally?

"New Stuff"
2025/04/13 10:58 AM

Mac Studio Upgrade - M4 Max

I originally got the first Mac Studio with an M1 Max. I loved it. This year I upgraded to the new M4 Max. Noticeably faster than the M1.

What I Got This Time

  • Apple M4 Max chip with 16‑core CPU, 40‑core GPU, 16‑core Neural Engine
  • 64GB unified memory
  • 2TB SSD storage

Great desktop computer, fast as hell. Should be great for years.

Also

Some minor site updates. Mostly in the Toy-Box.

  • Changed controls to menus
    • Menus work via right-click or button that shows up for mobile.
  • Added Mandelbrot toy.
"So expensive, but I want it."
2023/06/07 2:10 PM

WWDC 2023

I watched the keynote, but I still need to watch the Platform state of the Union


Watch on YouTube

It was a packed presentation with a bunch of cool new features and a new device.

New Macs

They announced a new 15" Macbook Air, an updated Mac Studio, and an updated Mac Pro. The Pro is basically the same as the studio, but with more ports, better cooling, and lots of card slots. If I were updating my main computer this year, I would probably go for a nearly maxed out Mac Studio. But, my M1 Max Mac Studio is still going strong. I should wait till the next update.

OS Updates

There were a bunch of great updates to all of the OS's, but I think I'm the most interested in the Watch OS updates, and the iPad OS updates.

Apple Vision Pro

All of the rumors had me super hyped for this part of the presentation. And, it was better than I expected. They pitched it as a productivity AR centric device. But, they showed plenty of VR functionality that has me hopefull for VR games as well. I think showing it as an entertainment and productivity device is a really smart way to sell it. The price is high ($3499), too high for just a gaming device.

Don't get me wrong it will have to be a good gaming device as well. But, that's in addition to everything else. I think they will reveal VR controller support at some future point. It's just an obvious addition.

"So Many Text Editors"
2023/01/23 9:50 AM

Saving Time

I recently found myself needed to rename a bunch of files in a fairly repetitive way. Many files, similar changes, but different enough to require visual inspection.

After doing the first set manually, I thought it would be easy to write a script to handle it, but that seemed like overkill. My next thought was to use BBEdit and regular expressions to manipulate the files.

BBEdit has two features that made this much easier than I expected.

  • Apply Text Transform
    • Found in the Text menu "Apply Text Transform..." is a feature that lets you manipulate text in one or more files in a programatic way. In my case I added line numbers to the front of a list of file names.
  • Pattern Playground
    • Found in the Search menu "Pattern Playground" is a great tool for testing regular expressions against your current text. Once you have perfected your expressions you can use them in to find and replace text in your document.

I used these tools to prepend line numbers, then change the text to a list of unix move commands with the line number replacing part of the destination file name.

There are so many features in BBEdit that I haven't used, but I continue to find it to be better than fancier code editors that I have paid more money to use.

"Quick Review"
2022/12/12 1:34 PM

Apple Watch Ultra

This year, I got the Apple Watch Ultra as an early gift. It does everything the Series 8 does plus:

  • Larger screen
  • Brighter screen
  • Titanium case
  • Larger case
  • 100m water resistance
  • Larger / Longer battery life
  • More precise GPS
  • Depth Gauge
  • Water Temperature sensor
  • Better speakers
  • additional button
  • Emergency siren

I can't really explain why, but it feels better on my wrist than the regular large Apple Watch. I think the size is just a better fit for my wrist. I've also had much less of a problem with it locking while I'm wearing it. I'm not sure if the sensors are better or if it's how it fits on my wrist.

This is the first time I've had cellular on the watch, but for now I have not activated it. I'm never without the phone. So, I can't really justify spending extra for cellular on the watch.

It's a tougher, better looking Apple Watch. It has a bunch of features that I will likely never use, but I really love the way it looks and feels.

Stream Deck and Homekit update.

I mentioned previously using HomeBridge to help control a fan with the Elgato Stream Deck. It felt like overkill and I later found a much more stable solution for this that I'll talk about below. However, Robert Hawdon sent me an update to the original code I was using that saves the current state of the switch so that it can restore the state through a HomeBridge restart or crash.


const port = 3000;

const express = require('express');
const bodyParser = require('body-parser');
const stateFile = './state.json';
var fs = require('fs');
let app = express();
app.use(bodyParser.text({ type: 'text/*' }))

var switches = {};

function saveState() {

	var data = JSON.stringify(switches);

	fs.writeFile(stateFile, data, function (err) {
		if (err) {
			console.log('There has been an error saving the switch state.');
			console.log(err.message);
			return;
		}
		console.log('State saved successfully.')
	});
}

function loadState() {

	if (fs.existsSync(stateFile)) {

		var data = fs.readFileSync(stateFile);

		try {
			switches = JSON.parse(data);
		}
		catch (err) {
			console.log('There has been an error reading the switch state.');
			console.log(err);
		}

	}
}

function getSwitchValue(switchName, trueValue, falseValue) {

	let value = switches[switchName];

	if (trueValue === undefined) {

		trueValue = true;
	} 

	if (falseValue == undefined) {

		falseValue = false;
	}

	if (value === undefined || value == false) {

		return falseValue;

	} else {
		
		return trueValue;
	}
}

function setSwitchValue(switchName, valueAsBoolean) {

	// Don't care about current state of switch - or if it exists or not at this point.
	switches[switchName] = valueAsBoolean;
	saveState();
}

// ==================
// General purpose getter to show the state of all switches in the browser.

app.get('/', (request, response) => {
	
	// return current state of all known switches
	response.setHeader('Content-Type', 'application/json');
	response.send(JSON.stringify(switches, null, 4));	
});


// HomeBridge http switch end points.
app.get('/switches/:switchName/on', (request, response) => {

	let switchName = request.params.switchName;

	//console.log("switchOn called for switch: ", switchName);
	setSwitchValue(switchName, true);

	let switchValue = getSwitchValue(switchName, "1", "0");
	response.setHeader('Content-Type', 'text/plain');
	response.send(switchValue);	
});

app.get('/switches/:switchName/off', (request, response) => {

	let switchName = request.params.switchName;

	//console.log("switchOff called for switch: ", switchName);

	setSwitchValue(switchName, false);

	let switchValue = getSwitchValue(switchName, "1", "0");
	response.setHeader('Content-Type', 'text/plain');
	response.send(switchValue);	
});

app.get('/switches/:switchName/status', (request, response) => {

	let switchName = request.params.switchName;

	//console.log("switchStatus called for switch: ", switchName);

	let switchValue = getSwitchValue(switchName, "1", "0");
	response.setHeader('Content-Type', 'text/plain');
	response.send(switchValue);	
});


// ==================
// Stream Deck MCControl endpoints.

app.get('/switches/:switchName', (request, response) => {

	let switchName = request.params.switchName;

	//console.log("got status request for switch: ", switchName);

	let switchValue = getSwitchValue(switchName, "ON", "OFF");

	response.setHeader('Content-Type', 'application/json');
	response.send(JSON.stringify({ state: switchValue }));
});


app.post('/switches/:switchName', (request, response) => {
	
	let switchName = request.params.switchName;

	//console.log("switch set post called for switch: ", switchName);

	var data = request.body;
	console.log("Data: ", data);

	if (data == "ON") {

		switchState = true;

	} else if (data == "OFF") {

		switchState = false;
	}

	setSwitchValue(switchName, switchState);

	let switchValue = getSwitchValue(switchName, "ON", "OFF");
	response.setHeader('Content-Type', 'application/json');
	response.send(JSON.stringify({ state: switchValue }));
});



app.listen(port, (err) => {
	if (err) {
		return console.log('something bad happened', err)
	}

	loadState();
	console.log(`server is listening on ${port}`)
});


These days I'm not using HomeBridge at all. But, I still use the fan and turn it on and off with the StreamDeck. I do this with HomeControl for the Mac. This app lets you control all of your home kit devices and scenes with a menu on your mac. It also lets you use control devices with callback urls via the command line. You can create a script and execute that script with a button on the StreamDeck. However, It doesn't show the current state of the devine on the StreamDeck button with this technique.


#!/bin/bash

open -g "homecontrol://x-callback-url/run-action?action-type=switch-device-status&item-type=device&item-name=Fan&home-name=Home&activation-mode=toggle&authentication-token=1234"

You need to get the url to use here with the HomeControl app. There is an auth token that will be unique to your computer. I hope this update helps anyone trying to do something simmilar.

Hello Computer

"MagSafe PopSocket"
2022/06/28 8:19 AM

Better than I expected

I heard someone talking about these on a podcast. I've never liked the way PopSockets work with the sticky back. I use Qi charging every night with my phone, so I have to be able to have the back of my phone clear. This PopSocket uses the MagSafe magnets and it's amazing how well it holds on to the back of the phone. It only comes off when I want it to. I also did not realize that you could buy grips with an amazing variety of designs on them.

So, I'm pretty happy with this. It makes it easier to hold on to the phone. It's easy to remove, and it stays attached all day. The only downside is that it makes the phone thicker, and if your pocket is already tight it might make it harder to get it out of your pocket.

MagSafe PopSocket