KoblentsBlog Photography
Contact About
Published Mar 2, 2020
Recently I needed to sort a file of entries by the date in each entry, where the date was a human-readable string across a few whitespace breaks. The format of each line was like this:
1
ENTRY-0009      FAIL    Thu Sep  5 17:39:24 2019        PASS 7  FAIL 6
But the most obvious sort command
sort entries.txt -k7 -k4M -k5 -k6
didn't produce results sorted in the expected order (2019, Sep [month], 5, 17:39:24). Let me show you after the break:
 
Published Jul 10, 2019
We have some Brother label makers and I wanted to programmatically make one print stuff, from a mac. First, I installed the ptouch drivers from the Brother website. Took ages to fiddle with it just right, but the product is very simple. Here's an example with 12mm wide tape and 12-character-wide printing.
Brother PT 2730:
123
echo "0123456789AB" | \
	lpr -o media=12mm -o PageSize=Custom.30x99 -o page-top=8 \
	-o landscape -P Brother_PT_2730;
Brother PT D600:
123
echo "0123456789AB" | \
	lpr -o media=12mm -o PageSize=Custom.28x93 -o page-top=8 \
	-o landscape -P Brother_PT_D600;
You can see some small differences - details after the jump.
 
Published Jun 20, 2019
We wanted to set up some infrastructure that would send mail through a shared icloud account. Here's how we did that:
  1. Set up icloud account.
  2. Set up AppleID for said icloud account / the mac(s) running the infrastructure.
  3. Fully log in to your Apple ... stuff. Mac, icloud, apple ID, etc. You must use two-factor authentication to do so.
  4. Go to your AppleID management interface, once fully logged in and authenticated.
  5. Create an "app specific password."
You should now be fully set up and ready to go! Invoke your script. Let's assume your icloud account is myfakeaccount@icloud.com. This should be it!
123456789
python mailer.py \
	--user myfakeaccount \
	--passwd <app specific password in the format: aaaa-aaaa-aaaa-aaaa> \
	--host smtp.mail.me.com \
	--port 587 \
	--from_addr myfakeaccount@icloud.com \
	--to_addr <your address> \
	--subj "Your subject" \
	--attach your_file.txt
If that doesn't work, well, check the reference document we used to get going and see what's wrong.
 
Published Jun 20, 2019
Work based on a previous reference: my python script to send mail on MacOS. (As previously mentioned, on Linux I just use mail/sendmail.) I believe interacting with this script is cleaner and simpler. The password is hardcoded, but for the automation infrastructure we're using, something has to store the password, so why not the caller? We can probably do better ... but.
Script after the jump.
 
Published Jun 20, 2019
We recently needed to clone some SD cards - or, more precisely, copy a directory structure. Apparently SD card cloners are kind of expensive. We didn't really need a block-type copy, just a standard copy, so I whipped up a script. Details after the jump.
 
Published Jan 16, 2019
I have a Razer mouse. Linux Mint seems to switch the side buttons' actions, where the button that I feel means "forward" does "back," and vice versa. I wrote a startup script to solve this problem by flipping them around.
To start, I used xev to figure out which my side buttons were. I found that they were 8 and 9.
Next, I used xinput to figure out the buttons currently set up:
12
$ xinput | grep -i "usb optical mouse" | sed -e "s/.*id=\(\S*\)\s*.*/\1/"
8
So the USB optical mouse is ID 8. Next, check the button map:
12
$ xinput get-button-map 8
1 2 3 4 5 6 7 8 9 10 11 12 13 
Finally, to switch them:
1
xinput set-button-map 8 1 2 3 4 5 6 7 9 8 10 11 12 13
And it worked! Then I added the code to my ~/.profile :
123456789
MOUSE_SW_BTNS_ID=`xinput | grep -i "usb optical mouse" | sed -e "s/.*id=\(\S*\)\s*.*/\1/"`
if [ ! -z "$MOUSE_SW_BTNS_ID" ]; then
	MOUSE_SW_BTNS_MAP=`xinput get-button-map $MOUSE_SW_BTNS_ID`
	MOUSE_SW_BTNS_CMP="1 2 3 4 5 6 7 8 9 10 11 12 13 "
	if [ "$MOUSE_SW_BTNS_MAP" = "$MOUSE_SW_BTNS_CMP" ]; then
		MOUSE_SW_BTNS_SET="1 2 3 4 5 6 7 9 8 10 11 12 13"
		xinput set-button-map $MOUSE_SW_BTNS_ID $MOUSE_SW_BTNS_SET
	fi
fi
 
Published Apr 16, 2018
Well, I had a really good one today. Thankfully, I only wasted about an hour.
Here's the outline: I have a userspace driver that does some relatively generic things that I compiled as a dynamic library (let's call it libmydev_ctrl.dylib). On top of that, I have a device-specific userspace driver for specific functionality that I compiled as a dynamic library (let's call it libmydev_ctrl_spec.dylib). On top of that, I have binaries that use device-specific drivers (let's call it myexecutable).
Compiling is fairly straightforward. First, the "generic" dylib:
12345678910
DYLIB_ALL_NAME          := libmydev_ctrl.dylib
TARGET_DYLIB_ALL        := $(TARGET_DIR)/$(DYLIB_ALL_NAME)
INST_DYLIB_ALL          := $(INSTALL_DIR)/$(DYLIB_ALL_NAME)

$(TARGET_DYLIB_ALL): $(OBJECTS_ALL) | $(TARGET_DIR)
        @printf "%-16s %-8s %s\n" "link" "LLD" $(notdir $@)

        @$(COMPILER) -o $@                                      \
                -install_name $(INST_DYLIB_ALL) -dynamiclib     \
                $^ $(FLAGS) $(INCLUDES) $(LIBRARIES)
And then we do something very similar to compile the device-specific dylib; as you can see, the only real difference in the makefile is that the "generic" dylib is a pre-requisite of the "specific" dylib:
12345678910
DYLIB_PLAT_NAME         := libmydev_ctrl_$(TARGET_NAME).dylib
TARGET_DYLIB_PLAT       := $(TARGET_DIR)/$(DYLIB_PLAT_NAME)
INST_DYLIB_PLAT         := $(INSTALL_DIR)/$(DYLIB_PLAT_NAME)

$(TARGET_DYLIB_PLAT): $(OBJECTS_PLAT) $(TARGET_DYLIB_ALL) | $(TARGET_DIR)
        @printf "%-16s %-8s %s\n" "link" "LLD" $(notdir $@)

        @$(COMPILER) -o $@                                      \
                -install_name $(INST_DYLIB_PLAT) -dynamiclib    \
                $^ $(FLAGS) $(INCLUDES) $(LIBRARIES)
Finally, we compile the binary/executable; we make the "generic" and "specific" dylibs pre-requisites, along with the source file with the main function:
1234
$(TARGET): $(TARGET_DYLIB_ALL) $(TARGET_DYLIB_PLAT) $(SRC)
        @printf "%-16s %-8s %s\n" "compile/link" "C++/LLD" $(notdir $@)

        @$(COMPILER) -o $@ $^ $(FLAGS) $(INCLUDES) $(LIBRARIES)
If you're trying to follow along without make, the commands look like this:
1234567891011121314151617181920
c++ -o libmydev_ctrl.dylib							\
	-install_name /usr/local/opt/libmydev_ctrl.dylib -dynamiclib		\
	source1.o source2.o source3.o						\
	-Wall -Werror -Wextra -Wno-unused-variable				\
	-Wno-unused-parameter -Wno-unused-function				\
	-Wno-unused-private-field						\
	-std=c++1y -g

c++ -o libmydev_ctrl_spec.dylib							\
	-install_name /usr/local/opt/libmydev_ctrl_spec.dylib -dynamiclib	\
	spec_source.o libmydev_ctrl.dylib					\
	-Wall -Werror -Wextra -Wno-unused-variable				\
	-Wno-unused-parameter -Wno-unused-function				\
	-Wno-unused-private-field						\
	-std=c++1y -g


c++ -o myexecutable libmydev_ctrl.dylib libmydev_ctrl_spec.dylib dostuff.cpp	\
	-Wall -Werror -Wextra -Wno-unused-variable -Wno-unused-parameter	\
	-Wno-unused-function -Wno-unused-private-field -std=c++1y -g
And then I run it:
1
$ ./myexecutable
But what falls out? Not good things. Solution after the jump:
1234567
dyld: lazy symbol binding failed: Symbol not found: __Z4init8dev_type
  Referenced from: myexecutable
  Expected in: /usr/local/opt/libmydev_ctrl.dylib

dyld: Symbol not found: __Z4init8dev_type
  Referenced from: myexecutable
  Expected in: /usr/local/opt/libmydev_ctrl.dylib
 
Published Mar 28, 2018
MySQL has an interesting issue - I call it a problem, I think MySQL calls it documented and expected behavior - where if you attempt to insert a row into a table (InnoDB) and the insertion fails due to a constraint violation, it will still increment the auto-increment counter.
The solution, annoying as it is, is to basically do a check while inserting to not even attempt the insert if that particular constraint (or, really, any other constraint you decide) would fail.
Let's say I have a table of "seen devices." Let's say each device checks in once in a while, but I want to poll the list of active devices far more frequently. I don't want to insert entries for devices showing up present if an identical entry (ID and last-seen timestamp) is already present. (Actually, for safety, let's say that if an entry with the same ID and a greater-than-or-equal-to last-seen timestamp is present.) The code (using prepared statements) looks something like this:
123456
INSERT INTO devs_alive (dev_id, last_seen)
        SELECT * FROM (SELECT ?, ?) AS tmp
        WHERE NOT EXISTS (
                SELECT entry_id FROM devs_alive
                WHERE dev_id = ? AND last_seen >= ?
        ) LIMIT 1;

And since we're using prepared statements, you obviously have to bind the parameters, which might look something like:
1234
$stmt = $conn->prepare($query);
$stmt->bind_param('iiii', $dev_id, $last_seen, $dev_id, $last_seen);
$stmt->execute();
$stmt->close();

Or
123
$stmt = $conn->prepare($query);
$rows = $stmt->execute($dev_id, $last_seen, $dev_id, $last_seen);
$stmt->finish;
 
 
Archive: August 2017 »
© Copyright Koblents.com, 2012-2024