tag:blog.katriel.co.uk,2014:/sitemapkatriel2021-10-27T11:30:25-07:00Katriel Cohn-Gordonhttps://blog.katriel.co.ukme@katriel.co.ukSvbtle.comtag:blog.katriel.co.uk,2014:Post/staff-meetings2021-10-27T11:30:25-07:002021-10-27T11:30:25-07:00Secret Cabal meetings<p>I run a biweekly meetup for the <a href="https://staffeng.com">staff+ engineers</a> in my local organisation. A couple different folks asked about whether meetings like these have been worthwhile and how you might go about setting one up, so here is my approach. YMMV.</p>
<p>Overall, I’ve found these meetings to be pretty valuable in a couple of ways: they help build relationships between the staff+ engineers in the local org, serve as a social outlet where we can discuss things freely in a way that isn’t often possible with a wider audience, and act as a sort-of informal lightweight mentorship program where people share what’s worked for them in tough situations. It’s also sometimes useful as a bidirectional channel between engineers and Leadership that’s a little more direct than ad-hoc 1-1s.</p>
<h1 id="invitees_1">invitees <a class="head_anchor" href="#invitees_1">#</a>
</h1>
<p>We don’t have precise invitation criteria other than “staff+”, and the attendance list is a little fuzzy—it mostly overlaps with “the set of engineers in my local office reporting to my skip-skip-manager” but with some edge cases where people relocated or have different reporting chains.</p>
<p>I send out a calendar invite for half an hour every two weeks, and also have a private group for posting agendas and taking notes. If I can’t make it to a meeting, I’ll ask someone else in the group to host. We also have a chat channel with the same members.</p>
<h1 id="topics_1">topics <a class="head_anchor" href="#topics_1">#</a>
</h1>
<p>I’m pretty aggressive about having an agenda, since there are usually 6+ folks without a lot of free time attending; this also means cutting people off to make sure we get through most topics.</p>
<p>The day before the meeting I:</p>
<ul>
<li>ask my local org leader if they have anything they want to raise to their local senior engineers</li>
<li>post a poll for agenda topics, which doubles as a reminder for the meeting the next day</li>
</ul>
<p>Some weeks the polls are busy; often, I supply a couple of conversation prompts. </p>
<h2 id="example-topics_2">example topics <a class="head_anchor" href="#example-topics_2">#</a>
</h2>
<ul>
<li>whaddya all think about the new reorg?</li>
<li>so-and-so has joined to work on Fancy New Project, let’s ask them to talk about it for a bit</li>
<li>Local Org Leader has a new initiative e.g. updated hiring goals, they’ve joined for a minute to talk about it and answer questions</li>
<li>X has someone on their team who is struggling with $challenge; how have you all helped people in similar situations?
<ul>
<li>“challenge"s may include unrealistic promotion expectations, excessive negativity, insuffient technical quality, infectiously bad work-life balance <em>cough me cough</em>, etc</li>
</ul>
</li>
<li>Y wants to make a Big Technical Change, which of you should they set up small-group meetings with? what might go wrong? who else should be involved?</li>
<li>Z has noticed some ownership gaps where stuff is falling through the cracks between a few teams; do attendees agree with that observation? who should be in a follow-up meeting to discuss?</li>
</ul>
<h1 id="what-we-don39t-do_1">what we don’t do <a class="head_anchor" href="#what-we-don39t-do_1">#</a>
</h1>
<p>We don’t make decisions: no technical deep dives or strategic directions—those stay in public fora and have a wider audience.</p>
<p>We don’t broadly announce the existence of said meeting. This is mainly a consequence of the fact that FB keeps IC levels relatively confidential, but also helps avoid the impression that people who aren’t invited are being cut out of important decisions, a pitfall which hadn’t occurred to me until it was pointed out on <a href="https://rands-leadership.slack.com">Slack</a>.</p>
<p>We don’t invite managers, even if they were previous attendees who switched to the manager track. This was the topic of some discussion but it’s what works for us now; your mileage may vary.</p>
<p>We don’t go over time—this is strictly half an hour, which helps to make sure that it’s a good use of a lot of temporally-challenged attendees’ calendar space.</p>
tag:blog.katriel.co.uk,2014:Post/spotifyd2017-11-11T01:48:32-08:002017-11-11T01:48:32-08:00spotifyd<p>This is all pretty obvious, but recording it here for posterity. <a href="https://github.com/Spotifyd/spotifyd">spotifyd</a> is an open-source, lightweight Spotify client for Premium accounts. We use it for our home server, which runs a couple of instances to enable Spotify Connect to the home speakers.</p>
<p>Setup is pretty easy but requires a little systemd messing around. Step 1 is to clone the repo and build spotifyd (which needs Rust’s <code class="prettyprint">cargo</code>), and then symlink it into <code class="prettyprint">/usr/bin</code>. I’m using the pulseaudio backend, so the command to build is <code class="prettyprint">cargo build --release --features pulseaudio_backend</code>. Step 2: write </p>
<pre><code class="prettyprint">[Unit]
Description=A spotify playing daemon
Documentation=https://github.com/Spotifyd/spotifyd
[Service]
ExecStart=/usr/bin/spotifyd --no-daemon
Restart=always
RestartSec=12
[Install]
WantedBy=default.target
</code></pre>
<p>to <code class="prettyprint">/etc/systemd/user/spotifyd.service</code> and chmod it to readable for everyone. Step 3: for each user that wants to run spotifyd, make <code class="prettyprint">~/.config/spotifyd/spotifyd.conf</code> containing</p>
<pre><code class="prettyprint">[global]
username = ...
password = ...
device_name = ...
</code></pre>
<p>where <code class="prettyprint">username</code> and <code class="prettyprint">password</code> are your spotify credentials and <code class="prettyprint">device_name</code> is the name you want to appear in your Spotify Connect menus. (Ours is “skald”, to continue the Asgard-based naming tradition.)</p>
<p>Finally, step 4 is </p>
<pre><code class="prettyprint">systemctl --user enable spotifyd.service
systemctl --user start spotifyd.service
</code></pre>
<p>and it should start up. You can check the logs with <code class="prettyprint">journalctl --user-unit spotifyd -xe -f</code>.</p>
tag:blog.katriel.co.uk,2014:Post/user-pulseaudio2017-11-10T11:34:35-08:002017-11-10T11:34:35-08:00user pulseaudio<p><a href="http://www.michaelpj.com/">Michael</a> and I have a home server running <a href="https://github.com/Spotifyd/spotifyd">spotifyd</a> (which is really a story for another post); each running a user systemd service to keep it up.</p>
<p>This seemed to confuse pulseaudio a little. The default ubuntu configuration runs one pulseaudio service per user, and only the “active user” gets to actually make sounds come out of the speakers. The definition of active user wasn’t entirely obvious; if someone was logged in to a graphical session then they got it, and otherwise it seemed to take turns based on who was actually playing.</p>
<p>Anyway, apparently it’s <a href="https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/WhatIsWrongWithSystemWide/">not recommended</a> to run pulseaudio as a system user, mostly for security reasons, but as an Official Security Person I can clearly ignore all of these and just run it anyway. So, to get it working:</p>
<pre><code class="prettyprint">sudo systemctl enable pulseaudio
sudo systemctl start pulseaudio
</code></pre>
<p>then for each user that should play music, add that user to the <code class="prettyprint">audio</code> and <code class="prettyprint">pulse-access</code> groups, then disable their user pulseaudios:</p>
<pre><code class="prettyprint">systemctl --user stop pulseaudio
systemctl --user disable pulseaudio # to stop it starting again
systemctl --user restart spotifyd
</code></pre>
<p>Now you can even play multiple spotify streams into the same speakers. Which sounds great, by the way.</p>
tag:blog.katriel.co.uk,2014:Post/fish-history-sync2017-04-20T05:34:25-07:002017-04-20T05:34:25-07:00fish history sync<p>I use <a href="https://fishshell.com/">fish</a> in <a href="https://tmux.github.io/">tmux</a> with maybe two dozen shells open at a time, for various projects that I have hanging around. By adding</p>
<pre><code class="prettyprint"># history across fishes
function save_history --on-event fish_preexec
history --save
end
alias hr 'history --merge' # read and merge history from disk
bind \e\[A 'history --merge ; up-or-search'
</code></pre>
<p>to <code class="prettyprint">~/.config/fish/config.fish</code>, reverse search now syncs across all history in all shells (or you can bring a shell up to date with all other shells using <code class="prettyprint">hr</code>). That feels good.</p>
tag:blog.katriel.co.uk,2014:Post/ibutton-hackery2014-08-05T08:12:05-07:002014-08-05T08:12:05-07:00iButton hackery<p>To get in to various places around Oxford, many places use little iButton fobs, which run on the Dallas Semiconductors 1-Wire protocol. When you tap them against a “master” device, they broadcast their unique ID, which the master can then look up in its list of people. </p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/5/56/I-button.jpg" alt="iButton fob" title="iButton fob"></p>
<p><a href="mailto:kamilner@kamilner.ca">Kevin</a> and I decided that this was excessively simple, and that we should build something to read and impersonate these fobs. Fortunately, the 1-Wire protocol they use is relatively standard, and there’s already an <a href="http://playground.arduino.cc/Learning/OneWire">Arduino library</a> to handle them.</p>
<p>The circuit you need is simple: connect some pin to a 4.7k resistor, +5v power and the centre of the fob, and ground the outside. Then run the following and the serial monitor should spit out the unique ID of any iButton you tap.</p>
<pre><code class="prettyprint">#include <OneWire.h>
// This is the pin with the 1-Wire bus on it
OneWire ds(PIN_D0);
// unique serial number read from the key
byte addr[8];
// poll delay (I think 750ms is a magic number for iButton)
int del = 1000;
// Teensy 2.0 has an LED on port 11
int ledpin = 11;
void setup() {
Serial.begin(9600);
pinMode(ledpin, OUTPUT);
}
void loop() {
byte result;
// search looks through all devices on the bus
ds.reset_search();
if(result = !ds.search(addr)) {
// Serial.println("Scanning...");
} else if(OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("Invalid CRC");
delay(del);
return;
} else {
for(byte i=0; i<8; i++) {
Serial.print(addr[i], HEX);
Serial.print(" ");
}
Serial.print("\n");
digitalWrite(ledpin, HIGH);
delay(1000);
digitalWrite(ledpin, LOW);
}
delay(del);
return;
}
</code></pre>
<p>That’s the easy part, but the real trick is doing it the other way around and opening a door with the Arduino. This is a little less well-supported, but there’s a <a href="https://github.com/MarkusLange/OneWireSlave">library</a> for it. Sure enough, if you run this on one board and impersonate a reader on the other, the reader will report a successful read of an iButton fob.</p>
<p><img src="http://i.imgur.com/wlGOF16.jpg" alt="iButton reader connected to iButton impersonator" title="iButton reader connected to iButton impersonator"></p>
<p>Buoyed by our success, we hooked up the fake fob to our office door to reveal… nothing. Not even a “wrong fob” beep. After performing the usual <code class="prettyprint">println</code> binary search for debugging, we worked out that when the board attempted to read the eight-bit command the door was sending, its timing was a little bit off and it only got four bits in before losing synchronisation and timing out.</p>
<p>I should explain a little bit about how the 1-Wire protocol works. As the name suggests, all the communication is done by pulling the voltage of a single wire either high or low. A handshake begins with a long (540μs) low “reset” pulse sent by the master device, in this case our office door. The fob should reply “I’m here” by pulling the bus low for about 150μs. If that works, the master may then send an eight-bit command, with bits communicated by high or low voltages in timeslots separated by an 8-ish μs delay. The only command sent by our office door was 0x33, or “READ ROM”, to which the fob is meant to reply with its ID in the same format.</p>
<p>Now, the underlying problem we had was that that the OneWireSlave library we used above used hardcoded timings to read out the bits of the master device’s command. It was getting about four or five timeslots through said command, but then lost track of the rest of the command. The clear fix, then, is to remove the hardcoded timings and instead follow the master, by waiting as long as it takes for the voltage to flip. (The Arduino runs at 16MHz, or about 60ns/clock cycle, so there should be plenty of time to pick up the μs changes.)</p>
<p>And lo and behold, when Kevin <a href="https://github.com/katrielalex/iButton_1990a">implemented</a> this, the door opened!</p>
tag:blog.katriel.co.uk,2014:Post/yosemite-broke-my-git-svn2014-07-30T10:06:59-07:002014-07-30T10:06:59-07:00Yosemite broke my git svn<p>Previously on Mavericks:</p>
<pre><code class="prettyprint">$ git svn rebase
Can't locate SVN/Core.pm in @INC (@INC contains: /usr/local/Cellar/git/1.8.4/lib /Library/Perl/5.16/darwin-thread-multi-2level /Library/Perl/5.16 /Network/Library/Perl/5.12/darwin-thread-multi-2level /Network/Library/Perl/5.16 /Library/Perl/Updates/5.16.4 /System/Library/Perl/5.16/darwin-thread-multi-2level /System/Library/Perl/5.16 /System/Library/Perl/Extras/5.16/darwin-thread-multi-2level/System/Library/Perl/Extras/5.16 .) at /usr/local/Cellar/git/1.8.4/libexec/git-core/git-svn line 41.
</code></pre>
<p>Solution: since the system Perl 5.16 contains SVN::Core, link it in from <code class="prettyprint">/Applications/Xcode.app/Contents/Developer/Library/Perl/5.16</code>.</p>
<p>Now on Yosemite:</p>
<pre><code class="prettyprint">$ git svn rebase
Can't locate SVN/Core.pm in @INC (you may need to install the SVN::Core module) (@INC contains: /usr/local/git/lib/perl5/site_perl /Applications/SourceTree.app/Contents/Resources/git_local/lib/perl5/site_perl /Library/Perl/5.18/darwin-thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.2 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level /System/Library/Perl/Extras/5.18 .) at /Applications/SourceTree.app/Contents/Resources/git_local/lib/perl5/site_perl/Git/SVN/Utils.pm line 6.
</code></pre>
<p>Solution? We don’t have Perl 5.18 from Xcode.app – so instead just install SVN from CPAN.</p>
<pre><code class="prettyprint">$ sudo cpan SVN::Core
...
$ git svn rebase
error: git-svn died of signal 11
</code></pre>
<p>Hey, a feature! Now it segfaults! I can’t be bothered to debug this properly, but got around it by changing the shebang in git-svn to require perl5.16. Yuck.</p>
<pre><code class="prettyprint">locate git-svn
emacs -q .../git-svn
</code></pre>
<p>EDIT: apparently a reinstall also fixes it.</p>
tag:blog.katriel.co.uk,2014:Post/zotero-emacs-latex-awesome2014-07-15T07:25:13-07:002014-07-15T07:25:13-07:00zotero + emacs + latex = awesome<p>As a PhD student, I have to reference a lot of stuff, which I do with Zotero. It struck me a while ago that it would be nice if this integrated with my <a href="http://www.gnu.org/software/emacs/">LaTeX editor of choice</a>, and so I spent a morning doing just that. Now, I can add references straight from Firefox, and immediately add a BibTeX citation to them in Emacs with <code class="prettyprint">C-c [</code>.</p>
<ol>
<li>Install Zotero and set it up.</li>
<li>Install the fantastic <a href="http://www.rtwilson.com/academic/autozotbib">AutoZotBib</a> Zotero extension. <em>Take care</em>: it looks like a Firefox extension, but you install it from Zotero’s add-on menu not Firefox’s.</li>
<li>Configure AutoZotBib to dump your Zotero library to a .bib file somewhere.</li>
<li>
<p>Enable the <a href="http://www.gnu.org/software/auctex/reftex.html">RefTeX</a> minor mode (which you should already have as part of Emacs). If using biber, you also have to tell RefTeX that <code class="prettyprint">\addbibresource</code> gives the path to the bibliography.</p>
<pre><code class="prettyprint">(add-hook 'LaTeX-mode-hook 'reftex-mode)
(setq reftex-plug-into-AUCTeX t)
(setq reftex-bibliography-commands '("bibliography" "nobibliography" "addbibresource"))
</code></pre>
</li>
</ol>
<p>That’s it – if you add a reference to Zotero, it’ll get dumped automatically to your BibTeX database by AutoZotBib, which RefTeX picks up and searches.</p>