Working Ninja
2019-10-15T22:05:34

lirc mysteriously stopped working when I upgraded to kernel 4.19.66-v7+ on my Raspberry Pi a while back. After an initial battle that lead to no success, I let it collect dust until this fateful night when she returned to her full functionality.

tl;dr

The kernel module lirc_rpi has been replaced with two modules: gpio_ir_recv (for receiving) and gpio_ir_tx (for sending, naturally). There are handful of configurations that need to point to and load the new modules.

My setup

  • GPIO 22 for IR transmission.
  • lircd 0.9.4c
  • kernel 4.19.66-v7+
  • Raspbian GNU/Linux 9 (stretch)

/boot/config.txt

Replace lirc-rpi with gpio-ir-tx. Take note that gpio_out_pin is now gpio_pin (see /boot/overlays/README for more info [search for gpio-ir-tx]).

dtoverlay=lirc-rpi,gpio_out_pin=22
dtoverlay=gpio-ir-tx,gpio_pin=22

/etc/lirc/hardware.conf

Replace loading of lirc_rpi with gpio_ir_tx.

MODULES="lirc_rpi"
MODULES="gpio_ir_tx"

/etc/modules

Remove lirc_* in /etc/modules (or comment out).

lirc_dev
lirc_rpi gpio_out_pin=22

/etc/lirc/lircd.conf

I had my remote configurations in lircd.conf and the upgrade to kernel 4.19. These were blown away, unfortunately. Fortunately, I had copies elsewhere. The new lircd.conf contains a single line that loads in all .conf files in /etc/lirc/lircd.conf.d/. I copied my remote conf files here and called it good (just in case another update blows things away =]

/etc/lirc/lirc.conf.d/devinput.lircd.conf

This file was unnecessary for my setup so I renamed it so it would not be loaded. See /etc/lirc/lircd.conf.d/README.conf.d for more info.

mv devinput.lircd.conf devinput.lircd.conf.dist

Extra Help:

  • If you need IR receive functionality, the dtoverlay will be gpio-ir (and not gpio-ir-recv, like the module). See /boot/overlays/README for more information. Also see modinfo gpio-ir-recv and modinfo gpio-ir-tx for more info.
2019-09-16T20:53:45

Add the following to your ~/.bash_profile for simple merging of PDFs:

pdfmerge() { 
    gs -dPDFSETTINGS=/prepress -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@
}

Usage:

pdfmerge merged.pdf first.pdf second.pdf

Source:
https://stackoverflow.com/questions/2507766/merge-convert-multiple-pdf-files-into-one-pdf

2019-06-16T20:41:19

I recently ran into a situation where I needed to copy some CSV data residing on a Windows machine to a Linux machine. The remote desktop client software I was using (on my Linux machine) wasn't set up to nativiely allow copy and paste to and from the server. It just so happened that I was recently working with netcat and thought this would be a great way to send the data to my destination machine. Sadly, Windows does not include netcat, so I dug around a bit and found that telnet would be able to take its place. So with a tool to use on both the sending and receiving side of things, I set out to implement what I'm calling "'universal' copy and paste".

So on my Linux machine (destination), I set up the netcat to listen on port 1234:

netcat -l 1234

On the Windows machine (source), I used telnet to connect to my Linux machine on port 1234, like so:

telnet 1.2.3.4 1234

I could then paste the CSV data on my Windows machine and it would immediately start outputting on my Linux machine. Ta-da, simple and "universal" copy and paste.

Finally, I would be remis if I did not mention that--while this is a working approach--it is not a secure one. The connection is not encrypted so everything is transmitted in clear-text.

2019-06-06T20:49:55

A situation arose where I was unable to use nc to send some metrics to a local Graphite server. Thanksfully, Python was installed (albeit, quite a dated version) that allowed me to set up a socket to send the data over the wire.

import commands
import socket
import time


def get_device_stats(device):
    # Retrieve 1 second average from `iostat` for device.
    status, output = commands.getstatusoutput('iostat 1 2 -kd -p /dev/%s | awk NR==7' % device)
    values = output.split()
    timestamp = int(time.time())

    send_metric(device, 'iops', values[1], timestamp)
    send_metric(device, 'read', values[2], timestamp)
    send_metric(device, 'write', values[3], timestamp)


def send_metric(device, metric, value, timestamp):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('1.2.3.4', 2003))
    # New-line character is important here, otherwise Graphite will not parse the sent data.
    s.sendall('disks.%s.%s.total %s %s\n' % (device, metric, value, timestamp))
    s.close()


devices = ['sda', 'sdb', 'sdc']

for device in devices:
    get_device_stats(device)

 

2019-02-27T21:06:20

Take the following HTML snippet:

<ul>
    <li></li>
    <li></li>
    <li></li>
    <li>Second to Last</li>
    <li></li>
</ul>

We would like to select the second to last list item (<li>). Here's how we'd go about doing that:

ul li:nth-last-child(2) { color: blue; }

Or, the inverse (everything but the second to last element):

ul li:not(:nth-last-child(2)) { color: red; }
2019-01-26T09:36:57

Objective: Sort dictionary by nested dictionary value

Let's say we want to sort the following JSON by the nested dictionary value of count.

{
  "Mail": {
    "count": 20,
    "users": ["lukeskywalker", "darthvader"]
  },
  "Droid Sync": {
    "count": 5,
    "users": ["lukeskywalker"]
  }
}

Method 1: lambda

apps_sorted = sorted(apps.items(), key=lambda x: (x[1]['count']))

Method 2: key function

def sort_by_count(x):
    # key=lambda x: (x[1]['count'])
    key, data = x
    return data['count']

apps_sorted = sorted(apps.items(), key=sort_by_count)

Source: https://stackoverflow.com/questions/4110665/sort-nested-dictionary-by-value-and-remainder-by-another-value-in-python

2018-12-21T07:46:50

First, list the shares available from the server:

smbclient -L <server> -U <user>

Next, make sure cifs-utils is available (so we can pass in the credentials option):

sudo apt install cifs-utils

Finally, add the desired share to /etc/fstab:

//ip/share /mnt/point cifs vers=3,credentials=/path/to/credentials,noexec 0 0
2018-11-27T07:37:07

Email contents of a file:

echo -e "Subject: subject\n\n" | cat - /file | sendmail address

Email stdout:

output=`cmd` 
echo -e "Subject: subject\n\n$output" | sendmail address
2018-10-31T20:18:39

Here's a simple shell wrapper that prints all sockets opened by Firefox.

1. Add the following function to your ~/.bashrc:

function ffsocks() {
    netstat -anp --inet | awk '/firefox/ { print $5 }'
}

2. Reload your shell (or run source ~/.bashrc) to make ffsocks callable from your shell environment.

3. Finally, execute ffsocks!

$ ffsocks
8.8.8.8:443
8.8.4.4:80

The power of shell wrappers comes from their ability to "codify" a more complex command (or series of commands, what flags are used, etc) and also in their reusable nature (we can call ffsocks any time we want!). Thus, shell wrappers are a good option for complex commands that are called often (or for those hard to remember ones that you don't call too often--I guess they're just all around good to use whenever!).

2018-09-26T20:30:58

By default, a ModelForm is populated with all its objects from the database. Sometimes it's desirable to limit these results as they are returned to the view. After setting up our ModelForm (forms.py) there is only one thing we need to do to make this happen. Within our view (views.py), we update the queryset as follows:

# forms.py
class PollForm(ModelForm):
    class Meta:
        model = Poll
        fields = ('question',)

# views.py
form = PollForm()
form.fields['question'].queryset = Poll.objects.filter(question__startswith="How")

This will filter Polls that start with "How".

Source: http://www.wkoorts.com/wkblog/2009/08/10/pre-populate-django-modelform-with-specific-queryset/