Category: Home Automation

Zoneminder – Don’t forget to set the server

We got some new IP cameras — devices that support direct RTSP access to the video stream — but I could not get them to work with Zoneminder. No matter what I tried, it reported that shm is not connected. My /dev/shm directory wasn’t full, the permissions were fine. In short, there was no reason that the memory map file couldn’t have been created. I could not figure it out — and, in trying to delete a 2 GB log file so it would be more readable … the server crashed and would only boot in recovery mode.

Sigh! Fortunately, I was able to repair the file system and get the server back online. I was working, so Scott looked at the cameras and had them working almost immediately. Turns out the default, when you add a new device, is that the server is set to ‘None’ … which evidently leads to the “unable to connect to monitor”, “Monitor shm is not connected”, and “Can’t open memory map file” errors I was seeing. He just selected the zoneminder server from the dropdown, saved it, and voila — a camera stream.

Reolink Wireless Doorbell – First Impressions

A friend of Scott’s got a Eufy doorbell on sale from Amazon, so we started checking out camera/doorbell devices again. Eufy didn’t seem to allow local access to the video stream. We found three companies that did offer direct access to the RTSP stream: Doorbird, Amcrest, and Reolink. The Doorbird ones were like a thousand dollars … and, for way under a grand, I could DIY something. Amcrest looked like a viable solution, but Amazon had the Reolink ones for sixty bucks less — including a $10 “prime member” discount price. We bought two and set them up inside the house.

The physical hardware is an oval shaped plastic box with a camera & IR ring near the top and a glowing button (you can turn the LED light off in the config) for visitors to press. I wish the logo wasn’t printed onto the plastic, though.

Once you enable RTSP under the advanced network settings, you can access the primary (high resolution) video feed at rtsp://username:password@doorbell.example:554/h264Preview_01_main and the secondary (640×480) video feed at rtsp://username:password@doorbell.example:554/h265Preview_01_sub

I like that you can set up a “read only” user — our Zoneminder installation doesn’t need to be able to configure the devices. It will also grab a photo to make a time lapse series — while seeing the driveway over time might not be too interesting, having a time lapse of our front yard will be really cool. This requires adding an SD card to the doorbell, but still very cool.

5GHz worked fine in the house, but we had a lot of drop-outs once it was mounted at the door.

You can upload your own key pair for the web server, so visiting the https page doesn’t throw an invalid certificate error. This is a personal thing that really bothers me with a lot of IoT implementations. It’s such a simple thing — there’s already a locally generated key pair, why not let me upload my own with a hostname or SAN that matches what I will be accessing. Even if you don’t have your own CA — you can get a free cert from Let’s Encrypt.

The fisheye camera catches a large field — we can see the entire front entrance — although I now understand why there are dual-camera doorbells with a “package camera”. If the camera is angled so you can see the face of someone pressing the button, you cannot see their feet. Or the ground where a package would be placed.

I don’t like that there doesn’t appear to be any way to ring the house door chime. There also doesn’t seem to be a way to use different tones for different doorbells. While we’ll get motion alerts from Zoneminder and be able to view both doorbell video feeds to see where the ring occurred … it would be nice to assign unique chimes to each doorbell.

Adding Sony SNC-DH220T Camera to Zoneminder

We recently picked up a mini dome IP camera — much better resolution than the old IP cams we got when Anya was born — and it took a little trial-and-error to get it set up in Zoneminder. The first thing we did was update the firmware using Sony’s SNCToolbox, configure the camera as we wanted it, and add a “Viewer” user for zoneminder.

With all that done, the trick is to add an FFMPEG source with the right RTSP address. On the ‘General’ tab, select “Ffmpeg” as the source type:

On the ‘Source’ tab, you need to use the right source path. For video stream one, that is rtsp://zmuser:password@mycamera.example.com/media/video1 — change video1 to video2 for the second video stream, if available. And, obviously, use the account you created on your camera for zoneminder and whatever password. Since it’s something that gets stored in clear text, I make a specific zmuser account with a password we don’t use elsewhere. We’ve used both ‘TCP’ and ‘UDP’ successfully, although there was a lot of streaking with UDP.

Save, give it a minute, and voila … you’ve got a Sony SNC-DH220T camera in Zoneminder!

 

 

Farm Automation

Scott set up one of the ESP32’s that we use as environmental sensors to monitor the incubator. There’s an audible alarm if it gets too warm or cold, but that’s only useful if you’re pretty close to the unit. We had gotten a cheap rectangular incubator from Amazon — it’s got some quirks. The display says C, but if we’ve got eggs in a box that’s 100C? They’d be cooked. The number is F, but the letter “C” follows it … there’s supposed to be a calibration menu option, but there isn’t. Worse, though — the temperature sensor is off by a few degrees. If calibration was an option, that wouldn’t be a big deal … but the only way we’re able to get the device over 97F is by taping the temperature probe up to the top of the unit.

So we’ve got an DHT11 sensor inside of the incubator and the ESP32 sends temperature and humidity readings over MQTT to OpenHAB. There are text and audio alerts if the temperature or humidity aren’t in the “good” window. This means you can be out in the yard or away from home and still know if there’s a problem (since data is stored in a database table, we can even chart out the temperature or humidity across the entire incubation period).

We also bought a larger incubator for the chicken eggs — and there’s a new ESP32 and sensor in the larger incubator.

Building Gerbera on Fedora

There is a great deal of documentation available for building Gerbera from source on a variety of Linux flavors. Unfortunately, Fedora isn’t one of those (and the package names don’t exactly match up to let you replace “apt-get” with “yum” and be done). So I am quickly documenting the process we followed to build Gerbera from source.

The Fedora build of Gerbera has the binaries in /usr/bin and the manual build places the gerbera binary in /usr/local/bin — the build updates the unit file to reflect this change, but this means you want to back up any customizations you’ve made to the unit file before running “make install”.

You need the build system — cmake, g++, etc and the devel packages from the following table as required by your build options

Additional packages that we needed to install: automake, autoconf, libtool

Library Fedora Package Required? Note Compile-time option Default
libpupnp libupnp-devel XOR libnpupnp pupnp
libnpupnp Build from source (if needed) XOR libupnp I was only able to locate this as a source, not available from Fedora repos WITH_NPUPNP Disabled
libuuid libuuid-devel Required Not required on *BSD
pugixml pugixml-devel Required XML file and data support
libiconv glibc-headers Required Charset conversion
sqlite3 sqlite-devel Required Database storage
zlib zlib-devel Required Data compression
fmtlib fmt-devel Required Fast string formatting
spdlog spdlog-devel Required Runtime logging
duktape duktape-devel Optional Scripting Support WITH_JS Enabled
mysql mariadb-devel Optional Alternate database storage WITH_MYSQL Disabled
curl libcurl-devel Optional Enables web services WITH_CURL Enabled
taglib taglib-devel Optional Audio tag support WITH_TAGLIB Enabled
libmagic file-devel Optional File type detection WITH_MAGIC Enabled
libmatroska libmatroska-devel Optional MKV metadata required for MKV WITH_MATROSKA Enabled
libebml libebml-devel Optional MKV metadata required for MKV WITH_MATROSKA Enabled
ffmpeg/libav ffmpeg-free-devel Optional File metadata WITH_AVCODEC Disabled
libexif libexif-devel Optional JPEG Exif metadata WITH_EXIF Enabled
libexiv2 exiv2-devel Optional Exif, IPTC, XMP metadata WITH_EXIV2 Disabled
lastfmlib liblastfm-devel Optional Enables scrobbling WITH_LASTFM Disabled
ffmpegthumbnailer ffmpegthumbnailer-devel Optional Generate video thumbnails WITH_FFMPEGTHUMBNAILER Disabled
inotify glibc-headers Optional Efficient file monitoring WITH_INOTIFY
libavformat libavformat-free-devel Required for 2.0
libavutil libavutil-free-devel Required for 2.0
libavcodec libavcodec-free-devel Required for 2.0

Then follow the generalized instructions — cd into the folder where you want to run the build and run (customizing the cmake line as you wish):

git clone https://github.com/gerbera/gerbera.git
mkdir build
cd build
cmake ../gerbera -DWITH_MAGIC=1 -DWITH_MYSQL=1 -DWITH_CURL=1 -DWITH_INOTIFY=1 -DWITH_JS=1 -DWITH_TAGLIB=1 -DWITH_AVCODEC=1 -DWITH_FFMPEGTHUMBNAILER=0 -DWITH_EXIF=1 -DWITH_EXIV2=1 -DWITH_SYSTEMD=1 -DWITH_LASTFM=0 -DWITH_DEBUG=1
make -j4
sudo make install

As with the Gerbera binary, the Fedora build places the web content in /usr/share/gerbera and the manual build places the web content into /usr/local/share/gerbera — yes, you can change the paths in the build, and I’m sure you can clue Gerbera into the new web file location. I opted for the quick/easy/lazy solution of running

mv /usr/share/gerbera /usr/share/gerbera/old
ln -s /usr/local/share/gerbera /usr/share/

To symlink the location my config thinks the web components should be located to the new files.

On the first start of Gerbera, SQL scripts may be run to update the database — don’t stop or kill the service during this process there’s no checkpoint restart of the upgrade process. We backed up /etc/gerbera/gerbera.db prior to starting our Gerbera installation. We’ve also wiped the database files to start from scratch and test changes that impacted how items are ingested into the database.

Fin.

Gerbera – Searching for Playlists

Summary: Playlist items are not returned from searches initiated on my uPNP client. The playlist is visible when browsing the Gerbera web UI under Playlists->All Playlists->Playlist Name and Playlists->Directories->Playlists->Playlist Name

Action: In a uPNP client, search using the criteria upnp:class = "object.container.playlistContainer" and dc:title = "Playlist Name",

Expected Results: Playlist matching search criteria is returned
Actual Results: No results are returned

Investigation:
From the Gerbera debug log, the search being executed is:

SELECT DISTINCT "c"."id", "c"."ref_id",
"c"."parent_id", "c"."object_type", "c"."upnp_class", "c"."dc_title",
"c"."mime_type" , "c"."flags", "c"."part_number", "c"."track_number",
"c"."location", "c"."last_modified", "c"."last_updated"
FROM "mt_cds_object" "c"
INNER JOIN "mt_metadata" "m" ON "c"."id" = "m"."item_id"
INNER JOIN "grb_cds_resource" "re" ON "c"."id" = "re"."item_id"
WHERE (LOWER("c"."upnp_class")=LOWER('object.container.playlistContainer'))
AND (LOWER("c"."dc_title")=LOWER('Playlist Name'))
ORDER BY "c"."dc_title" ASC;

The playlists do not have a row in the grb_cds_resource table, so the “INNER JOIN” means the query returns no records.

I am able to work around this issue by manually inserting playlist items into the grb_cds_resource table

INSERT INTO grb_cds_resource (item_id, res_id, handlerType) VALUES (1235555,0,0);

If I have some time, I want to test changing join2 to be a left outer join and see if that breaks anything.

Reverse Proxying WebSockets through mod_proxy — HTTP Failback

I’ve been successfully reverse proxying MQTT over WebSockets via Apache HTTPD for quite some time now. The last few weeks, my phone isn’t able to connect. There’s no good rational presented (and manually clicking the “send data” button on my client successfully connects). It was time to upgrade the server anyway. Once I got the latest Linux distro on the server, I couldn’t connect at all to my MQTT server. The error log showed AH00898: Error reading from remote server returned by /mqtt

Evidently, httpd 2.4.47 added functionality to upgrade and tunnel in accordance with RFC 7230. And that doesn’t work at all in my scenario. Haven’t dug in to the why of it yet, but adding ProxyWebsocketFallbackToProxyHttp Off to the reverse proxy config allowed me to successfully communicate with the MQTT server through the reverse proxy.

(Not) Finding the Rygel Log File

We’ve spent a lot of time trying to get a log file from the rygel server … setting the log level in the config file didn’t seem to do anything useful. And I cannot even find a log file. The only output we’re able to find is formed by running the binary from the command line. Where is that log file?!? Hey — there isn’t one. All of this log level setting has to do with what’s written to STDOUT and STDERR. You can either modify the unit file to tee the output off to a file or run it from the command line

To get debugging output, use

G_MESSAGES_DEBUG=all rygel -g 5

To tee the output off to a file,
rygel -g *:5 2>&1 | tee -a /path/to/rygel.log

 

Home Automation and Gardening

Something like 20 years ago, I tried to grow a plumeria flower in my apartment. I had a broad-spectrum light, plenty of heat, and plenty of humidity. But getting the light turned on and off at the right times wasn’t easy (especially if I was at work all day!).

This seems like a really good use for home automation — our home automation system tracks the sunrise and sunset times for our zip code. It’s possible to essentially cron “stuff” off of these times — e.g. get the birds ten minutes before sunset. I could easily track sunrise and sunset in Honolulu then have my light turn on at sunrise (or first light) and off at sunset (or last light). Voila — “sunlight” that runs for the proper duration every day.

Blocking Device Internet Access

We block Internet access for a lot of our smart devices. All of our control is done through the local server; and, short of updating firmware, the devices have no need to be chatting with the Internet. Unfortunately, our DSL modem/router does not have any sort of parental control, blocking, or filtering features. Fortunately, ISC DHCPD allows you to define per-host options. Setting the router to the device’s IP (0.0.0.0 may work as well) allows us to have devices that can communicate with anything on their subnet without allowing access out to other subnets or the Internet.