Run Jupyter Notebooks as a Service on macOS

I was looking for a way to run jupyer notebook without using a constantly open terminal or a screen session. On macOS there is a way to create services using a .plist file and the launchctl command.

Because I use different environments for all Python related stuff, it wasn’t immediately clear to me how to do this when I’ve installed Jupyter only in a pyenv. After some fiddling around, I finally solved it. The key was to set the working directory parameter to the directory in which the environment is loaded. In my case this is ~/notebooks where I automatically load the env by using a .python-version file.

Below you find the .plist file, that enables you to start/stop the notebook server using launchctl <start|stop> local.jupyter.notebook.

It assumes that you have a Python environenment in /Users/USERNAME/notebooks. So simply change it to your needs. Put the file into /Users/USERNAME/Library/LaunchAgents and call launchctl load PATH_TO_FILE once to load it. After this you can start/stop the service as described above.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Disabled</key>
    <false/>
    <key>KeepAlive</key>
    <false/>
    <key>Label</key>
    <string>local.jupyter.notebook</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/USERNAME/.pyenv/shims/jupyter</string>
        <string>notebook</string>
        <string>--notebook-dir</string>
        <string>/Users/USERNAME/notebooks</string>
        <string>--no-browser</string>
    </array>
    <key>StandardErrorPath</key>
    <string>/Users/USERNAME/Library/LaunchAgents/jupyter-notebook.stderr</string>
    <key>StandardOutPath</key>
    <string>/Users/USERNAME/Library/LaunchAgents/jupyter-notebook.stdout</string>
    <key>WorkingDirectory</key>
    <string>/Users/USERNAME/notebooks</string>
</dict>
</plist>

 

QuickFolders – a BitBar plugin

I’m a big fan of BitBar, an application that allows you to “Put anything in your Mac OS X menu bar” (macOS nowadays). People have already created more than 250 plugins which allow you to show plenty of information in the menubar. Basically any script that can be executed on the terminal and has some kind of output can be used to display this output.

This is how my BitBar output looks at the moment:

It shows me (from left to right):

  • GitHub notifications
  • Bitcoin price at bitcoin.de
  • QuickFolders – the plugin this blog post is about
  • Online status of two remote servers I manage (plugin not published)
  • Battery status of Macbook, keyboard and trackpad

You can click on every item and depending on the plugin get to see more information.

QuickFolders is a plugin that might help if you often need files that are sorted in a certain kind of folder structure.

You specify a directory and using various kinds of bash commands the script outputs all subfolders below this directory that have files inside (empty subdirectories are omitted). You can also specify which kind of suffix you want to be considered (e.g. only pdf) and which files you want to ignore (e.g. everything starting with a dot). The plugin then only shows directories that match these criteria.

You could use it the following way (just an fictitious example):

Have a folder for each semester and inside this folder another one for every course you’re going to visit. Put all the course materials into the corresponding folders and add the path to the script

The actual folder structure looks like this:

The “Homework” folder doesn’t show up, because it contains only DOC files and I changed the plugin to only show folders with PDF files.

If you click on any of those subdirectories in the BitBar menu it will open the corresponding folder in the finder.

For now the plugin is available in the “quickfolders” branch (inside the “System” folder) of my fork of the bitbar-plugins repository. I’ve created a pull request, so hopefully it will be in the official bitbar repository soon.

Show Download and Upload speed on your LaMetric Time

Following a request at the LaMetric forum I wrote a small Python script for displaying your current download and upload speed  on a LaMetric Time. The script can run on your own laptop or server (preferred).

Basically you need to do two things:

  • Create an app for the LaMetric Time
  • run the script that performs the speed test and push the results to the device

1. Create an indicator app

This is quite an easy thing to do. You need an account for the LaMetric developer area (it’s free, so don’t worry). In the developer area you can create a new app – in this case select indicator application.

On the new page, you can create the layout of the app. You need two text frames, one for the download speed and one for the upload speed. Also choose an icon for each frame, I decided to use a green down and green up arrow. It’s important that you select “Push” so that you can send your information to the LaMetric Time.

My design looks like this, but I later decided to drop the “Mbit/s”. It made the text too long, which is ok, the text will scroll on the display, but it means you have to wait for the scrolling to end, before the next frame is displayed. Plus I know that it’s Mbit/s. I’m also thinking about dropping the “UL” and “DL” prefix, since the arrows give me enough information.

Next you need to enter some information about the app, that is displayed in the store. You nee an App name and a short description, also make sure to check the “Private app” field.

Click “Save” and the app is ready to be published. On the next page you will see the URLs and the access token that is needed to send data to the app. Copy the “Local Push URL” and “Access token”. You could also use the “Push URL” instead of the local one, but I prefer it that way. I find it unnecessary  to send the data from my server at home to the LaMetric servers from where it comes back to my LaMetric Time which stands 5m away from my server.

Hit “Publish” and after a few minutes you should get a mail telling you that your app is ready.

Now you can install the app on your LaMetric Time. The following four screenshots describe how to do this:

Now your LaMetric Time is ready to receive data.

2. Run the script periodically on your server to update the values

The script can be found on GitHub: lm_connection_speed – if you don’t know how to clone a repository, you can also directly download the files: Download

I recommend Python 3, but it should work (no guarantee) with Python 2. It has three dependencies (requests, json and speedtest-cli). Please make sure install those before running the script.

Open the connection_speed.py in an text editor and look for lines 21/22 and insert the access token and push url from above. Save the file and you are good to go.

If you remember I said that I don’t want to see the “Mbit/s” – if you want to see it, you need to change two more lines in the file:

dl_rate = "DL {:.2f}".format(DL / 1000 / 1000)
dl_icon = "i402"
ul_rate = "UL {:.2f}".format(UL / 1000 / 1000)
ul_icon = "i120"

needs to be:

dl_rate = "DL {:.2f} Mbit/s".format(DL / 1000 / 1000)
dl_icon = "i402"
ul_rate = "UL {:.2f} Mbit/s".format(UL / 1000 / 1000)
ul_icon = "i120"

Now you can run the script

python3 connection_speed.py

Have a look the remarks in the README and for running the script periodically please consult your preferred search engine.

LaMetric Firmware 1.7.5

A new firmware for the LaMetric Time is out – version 1.7.5 has some nice things to offer for those of us who would like to use the device in home automation (sadly the documentation is not yet updated). While this has been announced in the change log for 1.7.4, there have been some bugs and there are still one or two things that needs fixing, but that’s just minor stuff.

So, lets dive right in: You can control the LaMetric time nearly completely via the REST-API. You can

  • switch between apps (previous or next, just like hitting the buttons on the device)
  • switch directly to a specific app
  • control the radio (on, off, switch channel – but not add or edit channels)
  • set alarms and enable or disable them
  • start/stop/reset the stopwatch
  • start/stop/reset/set the countdown

This is all on top off the already existing features (accessing device information about WiFi, Bluetooth, volume, display etc.)

This means nearly everything that had to be done using the iOS/Android app before, can now be done using any programming language you want.

I explained in my previous articles how to sent notifications – and it’s basically the same with the new controls. I’ve used PHP in the articles, because it’s what most people in the forum requested, but personally I use Python.

Until now I had written some scripts, without a specific library,  just a bunch of requests in a file which did the things I wanted. But when I discovered the new features I chose to clean my code and maybe make a Python package out of it –  at least a simple class for interacting with the device.

As any programmer should do, I did a search on GitHub to see if there are already some libraries. And of course I found one – lmnotify was relatively up to date and so I forked it and added some new code. Today I sent my pull request and it was already merged. This package is also available via PIP and it  supports all the features that I mentioned above.

Feel free to use this package, sent bugs, feature requests, pull requests.

 

Next I’ll be working on adding support for the LaMetric Time to Home Assistant – a platform for home automation that I’ve been using for a while and I think I already saw something LaMetric related, but without the features from the new firmware it’s useless for me.

Review: Bragi – The Dash

For nearly six months now I’ve been using The Dash as my sole earbuds. Before that I used the headphones Apple delivered with whatever iPhone I owned and I was quite happy with it – so you can see, that I don’t care that much about audio quality. I’ve tried high-end headphones but for me it’s not worth the money, simply because I didn’t hear that big of a difference. YMMV. This applies to everything in the review – it is deliberately subjective and I can’t promise that you will have the same experience but I think I can give you a good overview. If you are an athelete or music enthusiast who wants to know if the Dash is worth it, I’ll probably disappoint you – since I’m neither I probably don’t value the things that are important for you very much.
Continue reading “Review: Bragi – The Dash”

Log your played iTunes tracks

A few days ago I was looking for a way to log all tracks that I listen to in iTunes. Something like Last.fm but that works local and for macOS. I did a quick search and couldn’t find anything (maybe there is something already). So I decided to built something simple on my own using AppleScript, which allows me to easily access the iTunes information I need.

Doing some research I found an article at Doug’s AppleScripts that described the problem I wanted to solve. Copy the code below in the Script Editor (or get from GitHub), change the path to the text file and save as an application and don’t forget to check the “Stay open after run handler”.

Save Dialog of Script Editor

Run the app and voilà! I haven’t looked into possibilities to hide the dock icon or anything else. And I guess you can run the code with some modifications as a shell script in the background. Maybe I’ll look into it later.

# based on http://dougscripts.com/itunes/itinfo/idle00.php

global latest_song

on run
	tell application "System Events"
		if not (exists process "iTunes") then return
	end tell
	
	set latest_song to ""
end run

on idle
	tell application "iTunes"
		try
			copy name of current track to current_tracks_name
			if current_tracks_name is not latest_song then
				copy current_tracks_name to latest_song
				copy artist of current track to current_track_artist
				set output to current_track_artist & " - " & latest_song
				set dateString to do shell script "date +'%Y-%m-%d %H:%M'"
				
				do shell script "echo " & dateString & " - " & output & " >> ~/Desktop/test.txt"
			end if
		on error
			return 20
		end try
		return 10
	end tell
end idle

LaMetric & local push

UPDATE: This doesn’t work with firmware 1.6.0 – see updated article here: LaMetric Firmware 1.6.0 and local push

With the latest firmware upgrade (1.50) the LaMetric finally got support for local push – allowing you to sent messages to the LaMetric without needing an internet connection. Because some people in the support forums asked how to use local push I decided to write a tutorial (I do this on OS X).

Continue reading “LaMetric & local push”