After the disappointing results of the Orange Pi Plus 2, I got serious and shelled out more dollars for something that appears to be in the top of its class. Let's find out!
PROS: | CONS: |
|
|
|
|
|
|
|
|
|
|
List of Materials
- ODROID-XU4
- 5vdc 4 amp power supply included with XU4
- I prefer to use 32GB Samsung EVO SD cards
- USB 3 to SATA III adapter
- Homemade enclosure from a sheet of Acrylic or Polycarbonate
- Optional, large passive heatsink
- Spare 2.5" sata drive
- Miscellaneous standoffs and screws
Upgrade Legacy Drive to SSD
Install Armbian
First, head on over to the Armbian Download page. Download then write the appropriate OdroidXU4 image onto your sd card. You want the image without a desktop. Boot from the sd card and follow the first time use instructions.Once you get to a command prompt, get all your updates:
sudo apt-get update
sudo apt-get upgrade
Initial Prep
We want to use ntpdate instead of ntp since ntpdate does not reside in memory:
sudo apt-get purge ntp
sudo apt-get install ntpdate
Now add the following to the root crontab:
0 0 * * * /usr/sbin/ntpdate-debianMake sure the jessie-backports repo is enabled in the file /etc/apt/sources.list. In my case, this was already enabled:
deb http://httpredir.debian.org/debian jessie-backports main contrib non-freeWe will need the following packages:
sudo apt-get install git php5-common php5-gd php5-mysql php-pear mariadb-server fcgiwrap php5-fpm nginx gdebi-core dh-make-perl ssl-cert ffmpeg libvlc-dev libvlccore-dev vlcThe Debian Jessie repos are missing a required perl library, so let's build that now. Note that the dh-make-perl tool uses your git configuration to create an entry in the package changelog. It will abort if your name and email are not set. So let's set that!
git config --global user.email "your_email@email.com"I was asked several questions during the dh-make-perl build process above and just accepted the defaults, with one exception. One step asked to put a bunch of junk into my .profile, which I said no to.
git config --global user.name "Your Name Here"
dh-make-perl --build --cpan Sys::MemInfo
sudo gdebi libsys-meminfo-perl_0.99-1_armhf.deb
Build a ZoneMinder package from Master
We have created a build script for you so this is far easier than it might sound.
wget https://raw.githubusercontent.com/ZoneMinder/ZoneMinder/master/utils/do_debian_package.sh
chmod a+x do_debian_package.sh
./do_debian_package.sh `lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'` `date +%Y%m%d`01 local masterNaturally, the name of the resulting package will vary.
sudo gdebi zoneminder_1.30.0-jessie-2016121001_armhf.deb zoneminder-doc_1.30.0-jessie-2016121001_all.deb
Followup Configuration
Now that ZoneMinder is installed, we have several configuration steps to follow. Create the file /etc/php5/fpm/pool.d/zoneminder.conf with the following contents:1 2 3 4 5 | [www] # These settings prioritize memory conservation over performance pm = ondemand pm.max_children = 10 pm.process_idle_timeout = 10s |
Remove the default nginx configuration file:
sudo rm /etc/nginx/sites-enabled/defaultCreate an unsigned certificate for the site:
sudo make-ssl-cert generate-default-snakeoilAdd our own configuration and save it as /etc/nginx/conf.d/zoneminder.conf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | server { listen 80 default_server; listen [::]:80 default_server; # SSL configuration listen 443 ssl default_server; listen [::]:443 ssl default_server; include snippets/snakeoil.conf; root /usr/share/nginx/html; index index.php; autoindex off; server_tokens off; sendfile on; large_client_header_buffers 4 32k; # Auto-redirect HTTP requests to HTTPS if ($scheme != "https") { rewrite ^/?(zm)(.*)$ https://$host/$1$2 permanent; } location / { return 301 zm; } location /zm/cgi-bin { gzip off; alias /usr/lib/zoneminder/cgi-bin; include /etc/nginx/fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_pass unix:/var/run/fcgiwrap.socket; } location /zm { gzip off; alias /usr/share/zoneminder/www; index index.php; location ~ \.php$ { if (!-f $request_filename) { return 404; } expires epoch; include /etc/nginx/fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_index index.php; fastcgi_pass unix:/var/run/php5-fpm.sock; } location ~ \.(jpg|jpeg|gif|png|ico)$ { access_log off; expires 33d; } location /zm/api/ { alias /usr/share/zoneminder/www/api; rewrite ^/zm/api(.+)$ /zm/api/index.php?p=$1 last; } } } |
Edit the file /etc/php5/fpm/php.ini and set your timezone:
1 2 3 4 | [Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone date.timezone = America/New_York |
Fix the zoneminder config file:
sudo chgrp www-data /etc/zm/zm.confFix the API:
sudo ln -s /tmp /usr/share/zoneminder/www/api/app/tmp
Stop mariadb and move the sql files onto the hard disk:
sudo suNow create the file /etc/systemd/system/var-lib-mysql.mount and add the following to it:
systemctl stop mysql
cd /mnt
mkdir sda1
mount /dev/sda1 /mnt/sda1
chown mysql:mysql /mnt/sda1
mv /var/lib/mysql/* /mnt/sda1/
umount /mnt/sda1
exit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # systemd mount unit for mysql storage [Unit] Description=systemd mount unit for mysql storage Before=mysql [Mount] What=/dev/disk/by-uuid/put_the_uuid_of_mmcblk1_here Where=/var/lib/mysql Type=ext4 Options=defaults,noatime,commit=120,data=writeback [Install] WantedBy=multi-user.target |
Enable and start the mount unit:
sudo systemctl enable var-cache-zoneminder-events.mountNow, let's move the ZoneMinder events folder to the hard drive as well. Create the file /etc/systemd/system/var-cache-zoneminder-events.mount and add the following to it:
sudo systemctl start var-cache-zoneminder-events.mount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # systemd mount unit for ZoneMinder event storage [Unit] Description=systemd mount unit for ZoneMinder event storage Before=zoneminder [Mount] What=/dev/disk/by-uuid/put_the_uuid_of_sda1_here Where=/var/cache/zoneminder/events Type=ext4 Options=defaults,noatime,commit=120,data=writeback [Install] WantedBy=multi-user.target |
Edit /etc/fstab, comment out the existing swap file, and add the swap partition:
1 2 3 4 5 | # Original swapfile shipped with Armbian #/var/swap none swap sw 0 0 # Use a swap partition on the ssd instead UUID=put_the_uuid_of_sda2_here swap swap defaults 0 0 |
Disable the old swap file then enable the new swap partition:
sudo swapoff -aAlmost done, enable and start your services:
sudo swapon -a
sudo systemctl enable fcgiwrapNow from another machine, point your web browser to the ip or hostname of the Odroid. Your browser will warn you the site's certificate is unsigned.
sudo systemctl enable php5-fpm
sudo systemctl enable nginx
sudo systemctl enable zoneminder
sudo systemctl restart php5-fpm
sudo systemctl restart nginx
From the ZoneMinder web console, click Options -> Paths and set PATH_ZMS to /zm/cgi-bin/nph-zms.
Congratulations. You're done. You can begin adding cameras now.
Performance
Here is a summary using sysbench:- cpu - 223.7535s
- event storage drive - 974.36Kb/sec
- database - 307.77 transactions per sec
UPDATE: After replacing the legacy hard drive with the same make and model SSD I used in the Raspberry Pi 3, sysbench reported the transfer rate increased to 7.906Mb/sec. This is certainly an improvement, but the Raspberry Pi 3, with its USB 2.0 bus, still got a sysbench rating more than twice that. This will likely remain a mystery as my attention is now on other priorities.
Cameras
Thanks to 2GB of RAM on the ODROID XU4, we don't have to worry quite as much about memory usage. Thanks to the faster cpu in the XU4, the values in the table below are much more reasonable for a 1080p camera, when compare to the same data from the Raspberry Pi 3.camera | format | resolution | fps | ring buffer (frames) | mmap (MB) | Max swap buffer (MB) | Zma (%) | Zmc (%) | Zms (%) |
Airlink777W | mjpeg | VGA | 5 | 35 | 42 | 24 | 20 | 10 | 15 |
raspicam | h264 | 720p | 5 | 35 | 124 | 74 | tbd | tbd | tbd |
USGLBH245S400 | h264 | 1080P | 5 | 35 | 277 | 176 | 50 | 40 | 35 |
Using this data we can see that two 1080p cameras are quite doable, and three are possible after increasing the size of the /dev/shm ramdisk to make a little more headroom. I'm testing two 1080p cameras right now and they are working quite well.
Conclusion
If you intend to stream 1080p resolution cameras then the ODROID XU4 is the way to go.One can think of the XU4 as the "gaming pc" of single board computers in the sense that you do have to pay a premium for the extra performance, and one could rightly argue that the total cost of ownership is on par with a low end desktop pc. However if small size, no noise, and low power consumption are desirable to you, then this would be an excellent solution.