The hazelnut flowers now have bright magenta protrusions popping out of the buds
And the pollen is starting to emerge too.
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.
Crocus flowers are starting to sprout up around the yard — years ago, Anya and I planted crocus bulbs randomly throughout the front yard. Some have split into three or four plants already, and some are still single little flowers. We’ve even got some sprouting up elsewhere — maybe they’re spreading seeds too?
We collected nine gallons of sap with SG of 1.009 = 2.3 Brix
We ran all of the sap through the reverse osmosis system at 60psi and had sap with SG 1.011 = 2.8 Brix
We ran the concentrated sap through the reverse osmosis system a second time, this time at 80psi and had sap with SG 1.022 = 5.6 Brix.
The “pure water” output SG was about 1.003 — we re-ran this through the RO as well.
At the end of the day, we have about 4 gallons of sap at 5.6% sugar, another gallon from the “pure water” run that’s a lower SG, and four gallons of water that’s removed.
Notes for the future:
When we are decommissioning a website (or web server), I always watch the log files to ensure there aren’t a lot of people still accessing it. Sometimes there are and it’s worth tracking them down individually to clue them into the site’s eminent demise. Usually there aren’t, and it’s just a confirmation that our decommissioning efforts won’t be impactful.
This python script looks for IP addresses in the log files and outputs each IP & it’s access count per log file. Not great if you’ll see a bunch of IP addresses in the recorded URI string, but it’s good enough for 99% of our log data.
import os
import re
from collections import Counter
def parseApacheHTTPDLog(strLogFile):
regexIPAddress = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
with open(strLogFile) as f:
objLog = f.read()
listIPAddresses = re.findall(regexIPAddress,objLog)
counterAccessByIP = Counter(listIPAddresses)
for strIP, iAccessCount in counterAccessByIP.items():
print(f"{strLogFile}\t{str(strIP)}\t{str(iAccessCount)}")
if __name__ == '__main__':
strLogDirectory = '/var/log/httpd/'
for strFileName in os.listdir(strLogDirectory):
if strFileName.__contains__("access_log"):
#if strFileName.__contains__("hostname.example.com") and strFileName.__contains__("access_log"):
parseApacheHTTPDLog(f"{strLogDirectory}{strFileName}")
We’re about to start incubating eight duck eggs, so I wanted to record the temperature and humidity settings that I’ve found for the chicken, duck, and turkey eggs (well, future turkey eggs! We managed to get five male turkeys last year)
DUCKS | |||
Start | End | Temp | Humidity |
1 | 25 | 99.5 | 55-58% |
26 | 28 | 98.5 | 65% |
28 | hatching | 97 | 70-80% |
CHICKENS | |||
Start | End | Temp | Humidity |
1 | 18 | 99.5-100.5 | 45-55% |
19 | Hatching | 99.5 | 65-70% |
TURKEYS | |||
Start | End | Temp | Humidity |
1 | 24 | 99-100 | 50-60% |
25 | Hatching | 99 | 65-70% |
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.
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.