KODi on ubuntu on Intel NUC NUC5i5RYH / NUC5i5RYK

The currently new Intel NUCs are great hardware, but they need some special treatment for them to work with ubuntu und KODi. So here’s my experience and what steps I had to take to make this functional.

Hardware

  • Intel NUC5i5RYH
  • 64GB SanDisk Solid State Disk 2.5″ (6.4cm) SATA 6Gb/s MLC asynchron
  • 2 * 2GB Crucial ValueRAM DDR3-1600 SO-DIMM CL11 Single

Update BIOS

This is fairly important, make sure that you update your BIOS first. I tried to install the newest version which was available from the Intel website, but I got an error, stating that the choosen BIOS cannot be installed. So I first upgraded to the previous versions step by step, until I reached the newest BIOS. Prior to 0247, the IR receiver won’t work, so updating the BIOS is fairly necessary to get a HTPC to work.

Initial Install with Ubuntu 15.04

You won’t have any luck with Ubuntu 14.04 or 14.10, as the graphic drivers in the installer don’t work with the HD6000 from the broadwell processor. So download at least Ubuntu 15.04 as an ISO-Image and store it to your disk.

Download the Universal USB Installer, choose the previously downloaded image and create a bootable USB-Stick. Afterwards, plug it into your Intel NUC and give it power. Be sure to have a keyboard, mouse, Network and HDMI/DisplayPort-Display attached to your device. Hit „F10“ and choose the USB-stick.

Choose „Install Ubuntu“ and use all default values that are presented to you except for the login – make sure that this is automatic and that you don’t have to enter a password. Of course, you can change your username. At the end, your NUC is rebooted, be sure to remove your USB-stick.

Things to do after the first boot of 15.04

There are some lists out there in the internet, but there are two things you should consider when using the NUC as a HTPC:

  • Disable/Uninstall/Remove Amazon
  • Disable the screen saver (and the „Lock“-Feature)
  • Remove libsane (because it’s responsible for the crash if you get a „System program problem detected“ after login.

Remote Control

Ubuntu 15.04 is using rc_core, no longer lirc. Installing ir-keytable will make a new directory /etc/rc_keymaps:

sudo apt-get install ir-keytable
cd /etc/rc_keymaps

In my case, I use a Logitech Harmony One, which is configure to four devices:

  • TV (for showing the content)
  • Receiver (for Volume)
  • Intel NUC (this is ONLY needed to turn it on and off)
  • MCE (EVERY OTHER button should be mapped to this device)

It should look something like this. I guess you get the idea, even if some text is in german:

Logitech Remote

For your buttons from the remote to work, you must change some of the keys to the shortcuts from KODi. Create a new file /etc/rc_keymaps/rc-rc6-mce and put the following inside of it:

0x800f0400 KEY_0
0x800f0401 KEY_1
0x800f0402 KEY_2
0x800f0403 KEY_3
0x800f0404 KEY_4
0x800f0405 KEY_5
0x800f0406 KEY_6
0x800f0407 KEY_7
0x800f0408 KEY_8
0x800f0409 KEY_9
0x800f040a KEY_Q
0x800f040b KEY_ENTER
0x800f040c KEY_SLEEP
0x800f040d KEY_MEDIA
0x800f040e KEY_MUTE
0x800f040f KEY_I
0x800f0410 KEY_VOLUMEUP
0x800f0411 KEY_VOLUMEDOWN
0x800f0412 KEY_CHANNELUP
0x800f0413 KEY_CHANNELDOWN
0x800f0414 KEY_F
0x800f0415 KEY_R
0x800f0416 KEY_P
0x800f0417 KEY_RECORD
0x800f0418 KEY_SPACE
0x800f0419 KEY_X
0x800f041a KEY_DOT
0x800f041b KEY_COMMA
0x800f041c KEY_NUMERIC_POUND
0x800f041d KEY_NUMERIC_STAR
0x800f041e KEY_UP
0x800f041f KEY_DOWN
0x800f0420 KEY_LEFT
0x800f0421 KEY_RIGHT
0x800f0422 KEY_ENTER
0x800f0423 KEY_BACKSPACE
0x800f0424 KEY_ESC
0x800f0425 KEY_TUNER
0x800f0426 KEY_C
0x800f0427 KEY_ZOOM
0x800f0432 KEY_MODE
0x800f0433 KEY_PRESENTATION
0x800f0434 KEY_EJECTCD
0x800f043a KEY_BRIGHTNESSUP
0x800f0446 KEY_TV
0x800f0447 KEY_AUDIO
0x800f0448 KEY_PVR
0x800f0449 KEY_CAMERA
0x800f044a KEY_VIDEO
0x800f044c KEY_LANGUAGE
0x800f044d KEY_TITLE
0x800f044e KEY_PRINT
0x800f0450 KEY_RADIO
0x800f045a KEY_SUBTITLE
0x800f045b KEY_Q
0x800f045c KEY_GREEN
0x800f045d KEY_YELLOW
0x800f045e KEY_TAB
0x800f0465 KEY_POWER2
0x800f046e KEY_PLAYPAUSE
0x800f046f KEY_PLAYER
0x800f0480 KEY_BRIGHTNESSDOWN
0x800f0481 KEY_SPACE

Afterwards, load these keycodes and test them:

root@nuc:/etc/rc_keymaps# ir-keytable -w rc-rc6-mce
Wrote 63 keycode(s) to driver
root@nuc:/etc/rc_keymaps# ir-keytable -t
Testing events. Please, press CTRL-C to abort.

Install KODi

Now this step is pretty straightforward:

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:team-xbmc/ppa
sudo apt-get update
sudo apt-get install kodi

Autostarting KODi after boot

We’ll make sure that KODi is started no matter which user starts the desktop. We can achieve this by adding a file to /etc/xdg/autostart:

/etc/xdg/autostart/kodi.desktop:

[Desktop Entry]
Type=Application
Name=Kodi
Exec=/opt/kodi.sh

As sometimes kodi drops to desktop (i.e. crashes), we want to make sure that it’s automatically restarted. That’s why we create another file, /opt/kodi.sh:

/opt/kodi.sh:

#!/bin/bash
killall pulseaudio
while true
do
AE_SINK=ALSA /usr/bin/kodi --standalone
done

Make sure that this file is executable:

root@nuc:/opt# chmod a+x /opt/kodi.sh

Get rid of PULSEAUDIO

Pulseaudio did not work well with my receiver, so I chose to disable it. As the default login user (NOT root), execute this command:

nuc@nuc:~$ echo "autospawn = no" > $HOME/.config/pulse/client.conf

Configure KODi

Now that we have a working KODi (simply reboot to make sure that this is true), we have to change some settings for it to work properly with the Intel NUC.

  • Language / Location / Keyboard (if necessary)
  • Audio Device (HDMI)
  • Change further settings in ~/.kodi/userdata/advancedsettings.xml (if you did this before and know what you’re doing)

Monitor ODROID C1 temperature from an external server

After a while, I got another device as a mediaplayer, called ODROID C1. This one has a much stronger cpu and has a gigabit ethernet interface. I can’t use OpenELEC on this one, as ARMv7 isn’t supported by now. So I stick with the default Ubuntu 14.04, which has its advantages, as it’s a complete Linux OS.

To monitor the temperature of this ODROID as I did before with my Raspberry Pis, I had to change the scripts a bit to get it working, my Ubuntu 14.04 uses upstart:

root@odwz:# ps -p1 | grep systemd && echo systemd || echo upstart
upstart

Of course, the prerequesite is socat:

sudo apt-get install socat

/opt/tempservice/t.sh

#!/bin/bash
cat /sys/devices/virtual/thermal/thermal_zone0/temp

/opt/tempservice/socat-service.sh

#!/bin/bash
socat -T 1 -d -d tcp-l:9888,reuseaddr,fork,crlf system:"/opt/tempservice/t.sh"

/etc/init/socat.conf

description "Socat service for temperature monitoring"
 
start on runlevel [2345]
 
stop on runlevel [016]
 
exec /opt/tempservice/socat-service.sh >>/var/log/socatservice.log 2>&1
sudo initctl reload-configuration
sudo initctl start socat

postfix: Reject some recipient adresses while using catchall on a domain

If you have a catchall on a domain – like anginf.de – you will probably get spam on some adresses which you would like to exclude from the general catchall. This can be achieved by doing some simple steps.

First you have to create a file /etc/postfix/recipient_block with all those email adresses you want rejected:

spam@anginf.de REJECT
morespam@anginf.de REJECT

To be useable for postfix, you have to postmap this file.

root@host:~# postmap /etc/postfix/recipient_block

In your /etc/postfx/main.cf, add a new line to your smtpd_recipient_restrictions:

hash:/etc/postfix/recipient_block

Now you only have to reload postfix and all mails to those mentioned in /etc/postfix/recipient_block will be rejected:

root@host:~# service postfix reload

Configure IR Remote for ODROID C1

  1. sed -i 's/debug_enable\ =\ 0/debug_enable\ =\ 1/' /etc/odroid_remote.conf
  2. odroid_remote /etc/odroid_remote.conf
  3. tail -f /var/log/kern.log
  4. Now press the buttons on your IR remote. You will get an error code which changes in the first letters. The last four letters are the factory code.
  5. Replace the ZZZZ in the following with the four letters command and execute the command.
    sed -i 's/factory_code.*/factory_code\ =\ 0xZZZZ0001/' /etc/odroid_remote.conf
  6. odroid_remote /etc/odroid_remote.conf
  7. tail -f /var/log/kern.log
  8. The custom error code will be replaced by „scancode is ...., invalid key is 0x....
  9. The LAST two letters of the „scancode“ are the needed keycodes. Enter it under key_begin and repeat_key_begin in your /etc/odroid_remote.conf
  10. odroid_remote /etc/odroid_remote.conf
  11. If you’re satisfied with the result, disable the debug_enable flag again:
  12. sed -i 's/debug_enable\ =\ 1/debug_enable\ =\ 0/' /etc/odroid_remote.conf
  13. And one final last time, run the odroid_remote-program:
  14. odroid_remote /etc/odroid_remote.conf

Here’s my sample /etc/odroid_remote.conf, I configured it using a YAMAHA RV520 remote control:

factory_code = 0x1f000001
work_mode = 0
repeat_enable = 1
repeat_delay = 40
repeat_peroid = 39
release_delay = 121
debug_enable = 1
 
key_begin
        0x45 2   # Key "1"
        0x41 3   # Key "2"
        0x5e 4   # Key "3"
        0x49 5   # Key "4"
        0x4d 6   # Key "5"
        0x51 7   # Key "6"
        0x58 8   # Key "7"
        0x5c 9   # Key "8"
        0x5d 10  # Key "9"
#       0x00 11  # Key "0"
        0x1f 25  # Remote ">" (Play), Kodi "Play", Key "P"
        0x13 33  # Remote ">>" (FFWD), Kodi "Fast Forward", Key "F"
        0x15 19  # Remote "<<" (RWND), Kodi "Rewind", Key "R"
#       0x00 57  # Remote "||" (Pause), Kodi "Pause/play", Key "<SPACEBAR>"
        0x14 14  # Remote STOP, Kodi STOP, Key "X"
        0x1c 105  # Remote Left, Kodi Left, Key Left
        0x1d 106  # Remote Right, Kodi Right, Key Right
        0x1e 103  # Remote Up, Kodi Up, Key Up
        0x1a 108  # Remote Down, Kodi Down, Key Down
        0x4a 28  # Remote Select, Kodi Select, Key "<ENTER>"
        0x1b 14  # Remote Return, Kodi Back, Key "<BACKSPACE>"
        0x1b 1   # Remote Exit, Kodi Previous Menu/Home Screen, Key "<ESC>"
        0x40 71  # Remote Home, Kodi Top Menu, Key "<HOME>"
key_end
 
repeat_key_begin
        0x45 2   # Key "1"
        0x41 3   # Key "2"
        0x5e 4   # Key "3"
        0x49 5   # Key "4"
        0x4d 6   # Key "5"
        0x51 7   # Key "6"
        0x58 8   # Key "7"
        0x5c 9   # Key "8"
        0x5d 10  # Key "9"
#       0x00 11  # Key "0"
        0x1f 25  # Remote ">" (Play), Kodi "Play", Key "P"
        0x13 33  # Remote ">>" (FFWD), Kodi "Fast Forward", Key "F"
        0x15 19  # Remote "<<" (RWND), Kodi "Rewind", Key "R"
#       0x00 57  # Remote "||" (Pause), Kodi "Pause/play", Key "<SPACEBAR>"
        0x14 14  # Remote STOP, Kodi STOP, Key "X"
        0x1c 105  # Remote Left, Kodi Left, Key Left
        0x1d 106  # Remote Right, Kodi Right, Key Right
        0x1e 103  # Remote Up, Kodi Up, Key Up
        0x1a 108  # Remote Down, Kodi Down, Key Down
        0x4a 28  # Remote Select, Kodi Select, Key "<ENTER>"
        0x1b 14  # Remote Return, Kodi Back, Key "<BACKSPACE>"
        0x1b 1   # Remote Exit, Kodi Previous Menu/Home Screen, Key "<ESC>"
        0x40 71  # Remote Home, Kodi Top Menu, Key "<HOME>"
repeat_key_end

And here are the keycodes you’ll need for each key:

Key keycodes
ESC 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
0 11
12
= 13
BS 14
TAB 15
Q 16
W 17
E 18
R 19
T 20
Y 21
U 22
I 23
O 24
P 25
[ 26
] 27
ENTER 28
L CTRL 29
A 30
S 31
D 32
F 33
G 34
H 35
J 36
K 37
L 38
; 39
40
` 41
L SHIFT 42
\ 43
Z 44
X 45
C 46
V 47
B 48
N 49
M 50
, 51
. 52
/ 53
R SHIFT 54
* 55
L ALT 56
SPACE 57
CAPS LOCK 58
F1 59
F2 60
F3 61
F4 62
F5 63
F6 64
F7 65
F8 66
F9 67
F10 68
NUM LOCK 69
SCROLL LOCK 70
HOME 7 71
UP 8 72
PGUP 9 73
74
LEFT 4 75
5 76
RT ARROW 6 77
+ 78
END 1 79
DOWN 2 80
PGDN 3 81
INS 82
DEL 84
F11 87
F12 88
R ENTER 96
R CTRL 97
/ 98
PRT SCR 99
R ALT 100
Home 102
Up 103
PgUp 104
Left 105
Right 106
End 107
Down 108
PgDn 109
Insert 110
Del 111
Pause 119

Helpful links for this article:

Lokales Suchen auf einem Linux-System und Bereitstellen der Ergebnisse

Auf einem Samba-Laufwerk, welches auf einem Linux-Rechner liegt und für die Windows-Computer freigegeben wurde, liegen sehr viele Dateien vor. Statt aus dem Windows Explorer heraus zu suchen (was aufgrund des Netzwerks und des Samba-Dienstes selbst ziemlich langsam ist), wird durch das Erstellen eines Ordners eine Suche definiert.

Hierzu wird ein neuer Ordner „_search“ verwendet. Alle unter diesem Ordner erstellten Unterordner lassen das Linux-System automatisch lokal eine Suche nach dem Namen des Ordners ausführen. Die gefundenen Dateien werden per Softlink im Verzeichnis bereitgestellt. Für Windows erscheint es dann so, als ob die Dateien direkt unterhalb des Unterordners liegen.

Am besten in /etc/rc.local das Skript aufrufen, oder direkt einen neuen Dienst erstellen.

inotify.sh

#!/bin/bash
# This example uses ".jpg" files
SEARCHPATH="/var/smb/"
mkdir -p ${SEARCHPATH}/_search
inotifywait -mq -e moved_to -e create --format %f ${SEARCHPATH}/_search | while read FILE
do
	# Nur auf Verzeichnisse reagieren, nicht auf Dateien
	if [ -d "${SEARCHPATH}/_search/${FILE}" ]
	then
		if [ `expr "${FILE}" : ".*Neuer Ordner"` -ne 0 ] # Auch Abwandlungen hiervon
		then
			continue
		fi
		rm -f "${SEARCHPATH}/_search/${FILE}/"* # Falls umbenannt wurde
		rm -f "${SEARCHPATH}/_search/${FILE}/.ready"
		SEARCH=`echo "${FILE}" | sed s/\ /*/g`
		find ${SEARCHPATH}/ -wholename '${SEARCHPATH}/_search' -prune -o -type f -iname "*${SEARCH}*.jpg" -printf "ln --backup=t --suffix=\".bak\" -s \"%p\" \"${SEARCHPATH}/_search/${FILE}/\"\n" | sh
		cd "${SEARCHPATH}/_search/${FILE}"
		# Duplicates have wrong extensions. TODO: Do this for any filename?
		for bkp in "${SEARCHPATH}/_search/${FILE}/"*.~*; do mv "${bkp}" "${bkp/%\~/.jpg}"; done >;/dev/null 2>&1
		# Mark for Windows user when we've finished. (Only necessary if local system is really slow or data is huge)
		touch "${SEARCHPATH}/_search/${FILE}/.ready"
	fi
done

Monitor temperature and humidity with DHT11 sensor on raspberry pi

The DHT11 sensor includes a temperature and a humidity sensor. I connected it with my raspberry pi and transmit the data to an external cacti server, which polls the data regularly from the raspberry pi.

Step 1: Wire the sensor

While facing the open side of the sensor (NOT the one with the sticker on it), connect the pins as following

  • Leftmost pin = V+ — connect with 3V3 (Pin 1) from raspberry pi
  • Second pin = DATA — connect with GPIO4 (Pin 7) from raspberry pi AND via a 4.7k-10k resistor with 3V3
  • Third pin = Do NOT connect
  • Rightmost pin = GND — connect with GND (Pin 6) from raspberry pi
Raspberry PI Rev2 GPIO pinout
Raspberry PI Rev2 GPIO pinout

Step 2: Get the BCM2835 library and compile / install

The latest version can always be found here: http://www.airspayce.com/mikem/bcm2835/
As the time of writing, this was 1.36

cd
mkdir -p work/bcm2835
cd work/bcm2835
wget http://www.open.com.au/mikem/bcm2835/bcm2835-1.36.tar.gz
tar xvfz bcm2835-1.36.tar.gz
cd ./bcm2835-1.36
./configure
make
sudo make install

Step 3: Get the Adafruit python code

sudo apt-get update
sudo apt-get -y install git
git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code
cd ./Adafruit-Raspberry-Pi-Python-Code
cd ./Adafruit_DHT_Driver
make

After successfully compiling the Adafruit Driver, you can check if your sensor is already working. Keep in mind that the DHT11 is SLOW and won’t react if asked more than once within 2 or 3 seconds. If you don’t get any result after the first query, wait a few seconds (at least 3) and try again. If the problem persists, your wiring might be wrong.

sudo ./Adafruit_DHT 11 4

Step 4: Modify Adafruit python code

The original Adafruit code is giving too much information for simple cacti input parameters. A modification of the source code is necessary. Along with changing the output, I also removed all references to DHT22 and AM2302 to make the file a bit smaller:

ada_sm.c

//  How to access GPIO registers from C-code on the Raspberry-Pi
//  Example program
//  15-January-2012
//  Dom and Gert
// Access from ARM Running Linux
#define BCM2708_PERI_BASE        0x20000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <bcm2835.h>
#include <unistd.h>
#define MAXTIMINGS 100
 
#define DHT11 11
 
int readDHT(int type, int pin);
 
int main(int argc, char **argv)
{
  if (!bcm2835_init())
        return 1;
 
  if (argc != 3) {
        printf("usage: %s [11] GPIOpin#\n", argv[0]);
        printf("example: %s 11 4 - Read from an DHT11 connected to GPIO #4\n", argv[0]);
        return 2;
  }
  int type = 0;
  if (strcmp(argv[1], "11") == 0) type = DHT11;
  if (type == 0) {
        printf("Select 11 as type!\n");
        return 3;
  }
  int dhtpin = atoi(argv[2]);
  if (dhtpin <= 0) {
        printf("Please select a valid GPIO pin #\n");
        return 3;
  }
  readDHT(type, dhtpin);
  return 0;
} // main
 
int bits[250], data[100];
int bitidx = 0;
 
int readDHT(int type, int pin) {
  int counter = 0;
  int laststate = HIGH;
  int j=0;
 
  // Set GPIO pin to output
  bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);
 
  bcm2835_gpio_write(pin, HIGH);
  usleep(500000);  // 500 ms
  bcm2835_gpio_write(pin, LOW);
  usleep(20000);
 
  bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT);
 
  data[0] = data[1] = data[2] = data[3] = data[4] = 0;
 
  // wait for pin to drop?
  while (bcm2835_gpio_lev(pin) == 1) {
    usleep(1);
  }
 
  // read data!
  for (int i=0; i< MAXTIMINGS; i++) {
    counter = 0;
    while ( bcm2835_gpio_lev(pin) == laststate) {
        counter++;
        //nanosleep(1);         // overclocking might change this?
        if (counter == 1000)
          break;
    }
    laststate = bcm2835_gpio_lev(pin);
    if (counter == 1000) break;
    bits[bitidx++] = counter;
 
    if ((i>3) && (i%2 == 0)) {
      // shove each bit into the storage bytes
      data[j/8] <<= 1;
      if (counter > 200)
        data[j/8] |= 1;
      j++;
    }
  }
 
  if ((j >= 39) &&
      (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) ) {
     if (type == DHT11)
        printf("temp:%d hum:%d\n", data[2], data[0]);
    return 1;
  }
 
  return 0;
}

Compile the file with this command line (if you saved the above .c-file as „ada_sm.c“)

gcc ada_sm.c -l bcm2835 -std=gnu99 -o ada_sm

The output should be compatible with cacti:

$ sudo ./ada_sm 11 4
temp:23 hum:33

Step 5: Add a socat service

I’ve explained how to achieve this in another post, you only need a new shell script which will make sure that the readouts were given:

/usr/local/bin/dht11.sh

#!/bin/bash
result=""
while [ -z "${result}" ];
do
result=$(sudo /home/pi/work/dht11/ada_sm 11 4)
sleep 3
done
echo ${result}

Here the contents the configuration file for socat:

/etc/default/socat

OPTIONS="-T 30 -t 30 tcp-l:9889,reuseaddr,fork,crlf system:\"/usr/local/bin/dht11.sh\""

Step 6: Read data from the socat service on the cacti host

This is explained in another post as well, but the needed script in the site/scripts-directory is a bit different, here’s what I used. Keep in mind that you have to change „PI-IP“ to your local DNS or IP-Adress of the Raspberry Pi.

/usr/share/cacti/site/scripts/dht11.sh

#!/bin/bash
outstring=$(/bin/nc PI-IP 9889  | tr -d '\r')
echo "${outstring}"

Resources on the internet

These links helped me set this up:
http://www.messtechniklabor.de/artikel-h0000-temperatur_und_luftfeuchtigkeit_messen.html
https://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/wiring
http://www.airspayce.com/mikem/bcm2835/

Monitor Raspberry Pi temperature from an external server

I’m using a raspberry pi with XBMC as a mediaplayer. As I didn’t want to have a lot of trouble maintaining it, I decided to try OpenELEC. It works fine, but it’s really limited to only the media-related parts.

I wanted to know how much the temperature changes when using my raspberry pi and I already had a working cacti-server in my LAN. But what would be the best way to read the temperature from the pi without pushing too many binaries onto the system?

The answer is „socat“ – and of course, the binary is NOT part of the OpenELEC-distribution. But I was able to compile the socat as a static binary on another raspberry pi, which was runnning raspbian.

./configure LDFLAGS="-static"
make

Copy the resulting binary socat to the OpenELEC-raspberry. If you can’t create the binary yourself, you can download it from here:

socat 1.7.2.4 statically linked

socat: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.26, BuildID[sha1]=8ca6f5b38a7836cefe0721295d946dd9f90fb98e, not stripped

Put the socat in a new directory called /storage/tempservice/.

Add the following two files in the same directory /storage/tempservice/:

socat-service.sh

#!/bin/bash
/storage/tempservice/socat -T 1 -d -d tcp-l:9888,reuseaddr,fork,crlf system:"/storage/tempservice/t.sh"

t.sh

#!/bin/bash
cat /sys/class/thermal/thermal_zone0/temp

socat-service.sh will later start the service, while t.sh reads the temperature itself.

To make sure that the service is started on startup, we introduce a new system service in system.d: Change to the directory /storage/.config/system.d and add the following file:

socat.service

[Unit]
Description=SocatTempServer
 
[Service]
Type=simple
ExecStart=/storage/tempservice/socat-service.sh
 
[Install]
WantedBy=multi-user.target

And enable the service:

systemctl enable socat.service

Reboot and test from the other system in the LAN whether we can read the temperature:

nc PI-IP 9888 | tr -d '\r'

Now all you have to do is include the result in a cacti script and show the result. 🙂

Here’s what it may look like:

An example for a cacti picture measuring raspberyy pi temperatures
An example for a cacti picture measuring raspberry pi temperatures

Raspberry Pi on LG 42LH9000 with OpenELEC and IR Remote


UPDATE: Newest kernels require you to add the GPIO-Information directly into the config.txt, otherwise the LIRC won’t be available:

Append this to your /boot/config.txt (if you attach the IR receiver to GPIO 23 as stated in the article below):

dtoverlay=lirc-rpi,gpio_in_pin=23

I attached a Raspberry PI (Model B) via HDMI to my LG 42LH9000, a 42″ LED-TV from 2009. With the newest version of OpenELEC 4.0.0, I was suprised to find out that the most commands via CEC work out nicely. The only trouble I had was, that the „Back“ and „Exit“-Buttons didn’t work at all. Instead, I had to press „STOP“ and „OK“ directly after each other in a short time for „Back“ and „STOP“ and „PAUSE“ for an „Exit“.

As I was using an IR remote control anyways, I thought the raspberry could receive the data for the two missing buttons directly. At first, I needed an IR receiver diode. That was easy, as I still had an old, broken mini-helicopter which was steered using IR. As the helicopter itself was useless, I desoldered the IR receiver. I couldn’t make out a model number, so I simply guessed.

Facing the side with the receiver (that’s the side with the little bump), you can see three legs coming out of it. The left one I used for „DATA“, the middle one for „GND“ and the right one for „Vs“. As the helicopter was working with a lithium battery, I simply guessed that the receiver will work out nicely with only 3.3V.

Next step was wiring the receiver to the Raspberry PI. I needed +3.3V, GND and a useful GPIO-pin. Searching the web, I found this great view of the GPIOs. I’m sorry that I can’t give any credit to the one who created this graphic, as there are no copyright notices anywhere to find.

Raspberry PI Rev2 GPIO pinout
Raspberry PI Rev2 GPIO pinout

I attached the left („DATA“)-leg to GPIO 23, the middle leg to GND and the right leg („Vs“) to +3.3V.

After logging into my Raspberry PI, which was already running OpenELEC, I tried these commands to test if the IR receiver was working:

modprobe lirc_rpi gpio_in_pin=23 debug=1
dmesg

The dmesg should return something like this:

[118254.914704] lirc_dev: IR Remote Control driver registered, major 248
[118254.915686] lirc_rpi: module is from the staging directory, the quality is unknown, you have been warned.
[118254.939532] lirc_rpi: is_right_chip bcm2708_gpio 0
[118254.939904] lirc_rpi: to_irq 193
[118255.831302] lirc_rpi: auto-detected active low receiver on GPIO pin 23
[118255.831921] lirc_rpi lirc_rpi.0: lirc_dev: driver lirc_rpi registered at minor = 0
[118255.831946] lirc_rpi: driver registered!

Now we want to make sure that the receiver is actually working. Grap your remote control, run this command and see if anything happens on the console.

mode2 -d /dev/lirc0

This is my example output when I hit the „BACK“-Button on my remote control:

space 2189447
pulse 9022
space 4473
pulse 571
space 611
pulse 520
space 567
pulse 584
space 1658
pulse 588
space 541
pulse 588
space 552
pulse 590
space 542
pulse 587
space 541
pulse 568
space 571
pulse 585
space 1659
pulse 586
space 1696
pulse 544
space 547
pulse 562

The IR receiver actually works and we just saw the RAW input from the sensor!

To make sure that the next time the Raspberry PI is started, that the module is loaded correctly, type in this command:

echo "options lirc_rpi gpio_in_pin=23" &gt;/storage/.config/modprobe.d/lirc_rpi.conf

Make sure that no LIRCD is running:

killall lircd

And start recording the input from the two buttons:

mkdir -p ~/work/lirc
cd ~/work/lirc
irrecord -d /dev/lirc0 inputlg

The last command guides you through a wizard, the two buttons are called BTN_BACK and KEY_EXIT. I added the RED button as well and mapped it to KEY_C, as this is the context menu for the KODI.

As a result, you should have a file inputlg with these contents:

# Please make this file available to others
# by sending it to &lt;lirc@bartelmus.de&gt;
#
# this config file was automatically generated
# using lirc-0.9.1-git(default) on Sun May 11 22:47:19 2014
#
# contributed by
#
# brand:                       inputlg.conf
# model no. of remote control:
# devices being controlled by this remote:
#
 
begin remote
 
  name  inputlg.conf
  bits           16
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100
 
  header       9006  4492
  one           565  1677
  zero          565   566
  ptrail        562
  repeat       9008  2246
  pre_data_bits   16
  pre_data       0x20DF
  gap          108236
  toggle_bit_mask 0x0
 
      begin codes
          KEY_EXIT                 0x14EB
          KEY_MENU                 0xDA25
          KEY_C                    0x4EB1
      end codes
 
end remote

As you can see I really only added the two buttons that I still needed. If you want to add any more buttons, you must know the correct names for them. These can be retrieved with a simple command. As there are MANY possible buttons available, I limit the output to those which might be useful for me. The following command for example shows me the „EXIT“-Button:

irrecord --list-namespace | grep -i exit

I assigend my „BACK“-Button from the remote to „KEY_EXIT“, as this works like a „back-button“ within KODI. The „EXIT“-Button from my remote is used as a „MENU“ key.

If you want to know which buttons are used by KODI (and in what manner), the answers lie inside the file /usr/share/kodi/system/Lircmap.xml with the section

Now copy the file to the correct location:

cp inputlg /storage/.config/lircd.conf

And reboot:

sync
reboot

If you want to add other keys, which are normally not part of the remote control, here are the steps to work it our correctly:

Make sure that you have the Lircmap.xml from the system in your storage:

cp /usr/share/kodi/system/Lircmap.xml /storage/.kodi/userdata/Lircmap.xml

And add in the last section which starts with <remote device="devinput"> the following information:

KEY_C

Here are the links that helped me set this up:
http://wiki.openelec.tv/index.php?title=Guide_To_lirc_rpi_GPIO_Receiver
http://wiki.openelec.tv/index.php?title=Guide_To_Test_a_Remote_and_Remap_Keys

Copy a complete filesystem containing hardlinks, symlinks, different user names etc. via TCP/IP

I had to move a LOT of data from an old linux server to a new one. As both systems had four disks configured as a software RAID-5, I couldn’t connect all drives to one computer. I was simply out of ports to plug the drives into. 🙂

I wanted to use rsync, that way I could make sure that all the permissions etc. will stay intact. This was important for me, as a part of the data was from the BackupPC-directory, and BackupPC uses a special user and uses a LOT of hardlinks.

Simply copying everything with rsync wasn’t a success, the underlying SSH worked well, but the speed was by far too slow (~20MB/s). The „old“ machine wasn’t simply powerful enough to handle RAID-5, SSH and rsync with maximum performance at the same time.

Using a differenct cyper (-c arcfour) helped a bit, but the speed was still too slow (~40MB/s). As both computers were in the same secured LAN, I figured I didn’t need the additional protection and could use the rsync itself.

In the config file and the commands below you must change „hostname“ to the name of the „server“ and the „sharename“ accordingly. If you’re using a different IP range, change this as well.

On the server (here: the old machine) I created a file „rsyncd.conf“ with the following contents:

use chroot = true
hosts allow = 192.168.0.0/24
log file = /var/log/rsyncd.log
log format = %h %o %f %l %b
 
[sharename]
comment = sharename
path = /
read only = no
list = yes
uid = root
gid = root

And run this command on the server:

rsync --config=rsyncd.conf --daemon

On the client (here: the new, receiving machine) run this command:

rsync --delete -avPH hostname::sharename

Extract Images from a website and produce a video out of them

I had a big website with a lot of images embedded inside, which were dynamically added by users. The pictures were all of the same size, so I thought it would be easy to create a video out of it. Here are the steps to reproduce it:

Step 0 – Prerequisites

  • You’ll need python and http://code.google.com/p/youtube-upload/downloads/list to upload the video directly from the server. If you want to upload yourself, ignore this line and step 5.
  • md5sum
  • avconv – on ubuntu, this is available through sudo apt-get install libav-tools

Step 1 – Extract the images

Save the website you’re about to process to a local file, you only need the html part. (This only works with embedded pictures, for static pictures, try downloading the website with wget -m). Call the following script with the filename of the saved HTML-file.

#!/bin/bash
file=${1}
mkdir -p result
echo "Processing ${file}."
cat ${file} | sed -e 's/>/>\n/g; s/<img/\n<img/g; s/^$//g' | grep 'data:image/jpeg;base64' | sed -e 's/<img src="data:image\/jpeg;base64,//; s/" .*//' >out
count=0
while read line
do
let "count+=1"
echo ${line} | base64 -d >$(printf "result/%05d.jpg\n" ${count})
done <out

Step 2 – Images should be unique

We must delete all the files that are twice in our results.

#!/bin/bash
declare -a list=( ./* );
declare -a sums;
cnt=${#list[@]}
 
echo "creating md5sum list"
for ((x = 0; x < $cnt -1; x++))
do
    sums[$x]=`md5sum ${list[$x]} | cut -d ' ' -f 1`
done
 
echo "doing compare"
for ((x = 0; x < $cnt -1; x++))
do
  for ((y = x+1; y < $cnt; y++))
  do
    if [ "${sums[$x]}" == "${sums[$y]}" ];then
      if [ ${list[$x]} != ${list[$y]} ];then
        #remove '#' in next line to enable
        echo "Delete file ${list[$y]}" # && rm -f ${list[$y]}
      fi
    fi
  done
done

Step 3 – Renumber

The avconv-Tool can arrange all the images, but they must start with 00000.jpg and strongly increasing numbers. Therefore, we renumber all the jpg-Files accordingly.

#!/bin/bash
find . -type f -iname '*.jpg' | sort -n >filelist
seq=0
while read line
do
        mv ${line} $(printf "%05d.jpg\n" ${seq})
        let "seq+=1"
done <filelist

Step 4 – Create the video

We want to output a video with 25 fps and want to simulate that the images are a video with 3 fps. If you want slower changes in the images, increase the „-r 3“ to your wishes. If you want it quicker, you can decrease it down to „-r 1“.

avconv -f image2 -r 3 -i %05d.jpg -r 25 out.mpg

Step 5 – Upload to youtube

Make sure that you have the correct username and a channel created. This part is quite tricky, if you keep getting the 403-Error, make sure that you’ve logged in into youtube and you don’t get any Captchas.

python youtube_upload.py --email=USERLOGIN --password=PASSWORD --title="The title" --description="The description" --category=Comedy --keywords="keywords" out.mpg