Darci Door Bell

We have a cat named Darci. During the summer time she likes to take strolls through our backyard, checking out other frequent visitors like rabbits, chipmunks, squirrels, birds, and the like. She does this on an extended leash so to avoid her chasing these visitors and get lost into the wild. If you are curious, then visit her on Instagram.

We of course turn on the air conditioner on most days of the summer, so when Darci wants to come back into the house, she sits by the backyard sliding door and await one of us to open the door for her. If we are busy, she waits patiently for quite some time. My wife came up with the door bell idea. Instead of scratching the glass pane of the sliding door, which is mostly silent, we will train her to hit a door bell, which will alert us to let her in.

This is how I was assigned the Darci Door Bell project. This is another excellent opportunity to create a gadget. My first thought is to create a Raspberry Pi with a camera that uses an AI image classifier on the backend. I thought this would be a good opportunity to get my feet wet in AI. However, when dealing with a camera, and a Raspberry Pi, we are now talking about power and the need to be “plugged in”. We wanted a gadget that is wireless and battery operated. A battery based solution will severely restrict the power budget, so back to a WiFi based remote door bell idea.

After more research, I decided to use an ESP8266 MCU with WiFi and a simple step-down buck converter to convert 9V to 3.3V. I had worked with the ESP8266 before when I was attempting to use it to create my garage door opener. That was over six years ago. ESP8266 just came out and has yet to be integrated into the Arduino platform. Today, it is now much easier to work with the ESP8266. Using the Arduino IDE, one can simply program the ESP8266 natively as an MCU without even requiring an Arduino board.

From a previous project, I built a small circuit using an USB FTDI interface that will accept the ESP8266 ESP-01 board. This way I can plug the ESP8266 using USB to my computer and program it with the Arduino IDE. I wrote the following sketch, and programmed the ESP8266 ESP-01 board.

 #include <ESP8266WiFi.h>
 #include <ESP8266HTTPClient.h>

 #define SERVER_IP "192.168.1.111"
 
 #ifndef STASSID
 #define STASSID "myssid"
 #define STAPSK  "adsjfkdajfioeujfngjhf"
 #endif
 
 void setup() {
 
   WiFi.begin(STASSID, STAPSK);
 
   while (WiFi.status() != WL_CONNECTED) {
     delay(250);
   }
 
   WiFiClient client;
   HTTPClient http;

   // configure traged server and url
   http.begin(client, "http://" SERVER_IP "/IOTHandler.php"); //HTTP
   http.addHeader("Content-Type", "application/x-www-form-urlencoded");
 
   // start connection and send HTTP header and body
   http.POST("id=darciButton");
 
   http.end();
 
   ESP.deepSleep(0);
 }
 
 void loop() {
   ESP.deepSleep(0);
 }
 

The above program is pretty simple. When the board wakes up, it connects to my WiFi and then send an HTTP-POST request to my server that will handle the request based on the id, which in this case, it will be darciButton. As soon as the request is sent, the MCU will go into a deep sleep.

Completed Circuit

This way, the door bell will be a physical button that is hooked to the RST pin of the ESP8266 causing the ESP8266 to boot and send this POST request and immediately goes to sleep. The deep sleep is important, because while the device is in this deep sleep mode, the current draw from the 9V battery is negligible (<< 1mA). The only time the battery is used is when the button is pressed and released, and the ESP8266 is sending out the POST request. Using this power conservation approach, it is my hope that the 9V battery will last for the entire year of operation.

I used my 3D printer to print a little box for the whole thing and gave it some packaging padding, making sure the switch is on the top and properly supported. The final result looks something like this.

Packaged in a box

We then created a cardboard top cover that snugly fit the box, so that the top cover can freely move up and down the containing, plastic box. The switch itself has a little spring to it that allows the top cover to return back to its original position after being pressed. The finished product looks like this:

Finished Product

The top cover has a nickel on there so that Darci has a good target to train on.

Remember the server receiving the POST request? Well, I did some simple php programming on the server so that once the POST is received, I send out another HTTP request. This time to the Homebridge server with the homebridge-button-platform plugin installed. Homebridge is something that I already have and use to connect all non-compliant HomeKit accessories so that I can use those accessories via Siri. With this new plugin, I can connect this custom WiFi button to the HomeKit ecosystem within the house.

In effect, whenever this button is pressed, my HomeKit service will register an accessory button being pressed, and I can program a HomeKit scene that gets executed. I programmed a scene to play an audio file on all of my HomePods in the house. The audio file plays an audible door bell twice which I previously added to my Music library.

The final reward as shown by Darci herself. Watch the video below:

Darci Approves!

Of course with the button hooked up to HomeKit, we can now use this wireless button to do whatever HomeKit can do, unlock doors, turn lights on or off, etc. We will explore those possibilities in the future.

Resizing LVM Volume with Cache

I had to increase the size of my media LVM logical volume again. In a previous post, I provided the instructions. I have done this many times. However, this time around, I ran into a snag.

Apparently this is the first time I try to increase the logical volume after I implemented LVM caching, which I wrote about in this post.

The steps in the “Linux LVM Super Simple to Expand” post are the same right up to and including the step involving the resizing of the physical volume. Afterwards, in order to resize the logical volume, we first have to disable the cache temporarily.

sudo lvconvert --splitcache /dev/airvideovg2/airvideo

Once the logical volume is no longer cached, then we can proceed with the resizing.

sudo lvresize -l +100%FREE /dev/airvideovg2/airvideo

Once the resize is completed, we can unmount the volume and perform the required resizing of the filesystem.

sudo systemctl stop smbd.service

sudo systemctl stop mpd.service

sudo systemctl stop apache2.service

sudo umount /mnt/airvideo

sudo e2fsck -y -f /dev/airvideovg2/airvideo

sudo resize2fs -p /dev/airvideovg2/airvideo

Note that e2fsck and resize2fs will take some time, between thirty minutes to an hour each. Once the file system is resized, we can reattach the cache.

sudo lvconvert --type cache --cachepool airvideovg2/lv_cache airvideovg2/airvideo

Usually it is a good idea to reboot the server after this just to make sure it mounts properly.

This is a small snag and LVM is still super simple to expand.

Update on Prius Charging Economics

In my previous post, I talked about how charging the Prius Prime at home versus filling up its gas tank. Well we are in a very special time right now with gasoline prices hovering between $1 / L to $1.05 / L. The electricity rate has also changed to a flat $0.128 / KWh to be applied around the clock until October 31st, 2020.

I figured that I provide an update with these new conditions. With the lowered gasoline prices, the 4.4 L / 100 Km milage rating of the Prius Prime, it would now yield 22.7 km / $ assuming $1 / L as our cost.

Hidden Electrical Costs

When we use the per KWh charge of $0.128 for time of use; $0.0098 for delivery; $0.0039 for regulatory; yielding a total of $0.1417 / KWh, our Prius plugin yields (40 Km / 8.8 KWh / $0.1417) 32.078 km / $ when using the battery alone as an EV.

Clearly 32 km is still better than 23 km. Therefore, it is still better to charge the Toyota Prius Prime at any time of the day now because the electricity cost is the same around the clock.

I left out the monthly delivery and regulatory flat rates because I have to pay that regardless whether I’m charging the Prius or not. Also this calculation does not consider additional savings when charging due to the current Ontario Electricity Rebate that is in effect.

I hope you find this up to date information useful.

HTML5 Video on iOS 13

This past weekend, I was writing a simple HTML5 utility that provides certain videos that I have in my own personal library. The idea is that I can make a limited selection of videos and present it on a web page, so that the user can simply click on the cover art of the video and plays inline on the web page.

I thought it was a pretty simple requirement and I should be able to whip this up in a few minutes. I used the HTML5 <video> tag. Everything worked on my Mac and my iPad. It even worked on my LG OLED TV. However, when it came to the iPhone, mobile Safari would load the movie but it would not play. I was even able to seek through the movie by scrubbing the scroll bar, but when I press the play/pause button, nothing would happen.

After many hours scouring the web, I found out many caveats when serving videos on iOS with the iPhone.

  • Videos behind an authorized location may not work on an iPhone because when Safari passes this information to the player, the player does not inherit the previously authorized identity. To get around this, I had to create a token based technique, where the main page have to pass this token to a PHP page that checks this token and serves the video contents.
  • The PHP used to serve the video also need to handle HTTP Range based requests. This wonderful contribution from GitHub really helped me out!
  • Multichannel audio such as 5.1 audio encoded in AAC will load but not play on my iPhone XS currently running iOS 13. The video will play if I re-encode the audio to either AAC stereo, or 5.1 multichannel in AC3 encoding.
  • Multiple audio streams also did not work. The iOS player was only happy with a single compatible audio stream.
  • If you want to make the video autoplay while inlined within the page, it must first be muted.

Lots of things to consider here. I lost about a day and halve researching and experimenting with this, so here it is all recorded just in case I forget in the future. I also hope that this information will help you out as well.

Plug-in Economics for Prius Prime

According to Toyota, our new 2020 Prius Prime PHEV gets around 4.3L / 100km of city driving. We will use this number since it is not too far off of the combine driving number of 4.4L / 100km. This means at the time of writing this post, the current fuel price at our neighbourhood pump is at $1.15 / L. If you do some fancy math, the Prime will yield us 20.2km per dollar invested at the pump (20.2 km/$).

Ontario Electricity Costs (Fall of 2019)

As depicted by the chart on the right, in Ontario we have three tiers of charging rates. The Prime in the winter can do about 35km with a 9kWh battery. The exact numbers are 40km / 8.8kWh, but this is perfect condition, and we use some battery for heating the vehicle. This will yield us the following:

TierYield
On-Peak18.7km/$
Mid-Peak27.0km/$
Off-Peak38.5km/$

So by comparing the above numbers, it makes perfect sense to charge the vehicle during Off and Mid Peak hours, and not so much during On-Peak hours. However the On-Peak comparison is so close that if the mileage rating was at 4.5L/100km then it is a wash.

With a bit more fancy math, you can actually calculate how much does gas have to cost per Litre before On-Peak charges make sense. This turns out to be around $1.24/L.

Hopefully you find this information helpful.

Let’s Plug-In

On October 30th, 2019, we purchased a Toyota Prius Prime 2020, choosing the Upgrade trim without the technology package. We traded in our 2012 Toyota Sienna 8 passenger Minivan with approx. 90,000km for $11,000. After all the government incentives, fees, taxes, and dealer’s rebates, we ended up forking out less than $27,000 for the vehicle. The only thing we opted for was the rust protection device.

We now have this plug-in hybrid electrical vehicle (PHEV) for almost a week. The vehicle is very comfortable to drive, and much more refined than my 2013 Subaru Impreza. The Prius comes in three drive modes, Eco, Normal and Power. I find the Eco mode to be too slow and has too much accelerator latency. I prefer the Normal mode. The Power mode can be pretty fun especially when you have a fully charged battery.

There are plenty of YouTube videos and written articles already talking about how the car drives, and I agree with their positive take on the Prius Prime. Therefore, I won’t repeat what has already been said. I will focus on what impact the ownership of a Prius Prime has on our residential electrical consumption.

We have yet to invest in a level 2 charger (240V – 16A) for the house yet, so we are just using our regular 120V plug to charge the 8.8kWh battery for the vehicle. So instead of charging the vehicle in 2 hours with the level 2 charger, we find that it takes around 5 hours to fully charge the vehicle. Toyota’s charging specification is pretty dead on and accurate here.

I raided our utility company’s web site and was able to extract the following graphs. Either click on the image or this link to open the graphs.

The consumption graphs above points to a day with no electrical vehicle as a baseline, followed by three days of charging the Prius Prime in the evenings. It looks like charging the Prius only amounts to an average of 1.5 kWh increase from baseline per hour of charge. The graph shows about four hours of heavy charging follow by a lower power charge during the last hour and a half.

At the current off-peak rate of ~$0.10 per kWh, we are looking at about an increase of less than a $1 per day, and this gives you about a realistic 36km of pure EV mode (all electric) of range per charge. So for a month, $30 will give you around 1,000km of range!

We have driven the car for about 5.5 days, and racked up in excess of 300km. We still have 7/8 of a gas tank left, and the only reason why we used the gas is due to a test drive to the Toronto Premium Outlet mall in Milton. Otherwise our daily usage pattern, which consists of largely local errands, would allow us to just keep on using the battery.

Now the game is up. How long do you have to wait for me to update this blog entry when I fuel up our new Prius Prime for the first time? Watch and see, any wagers?

Leviton Decora Smart Dimmer with HomeKit

I purchased these DH6HD HomeKit compatible dimmer switches from Leviton from February of 2018 (over 1 1/2 years now).

When they work, they are great. BUT! My HomeKit app frequently report these switches with “Not Responding”. The only remedy that I know of is to remove the accessory and then re-add it again.

The process of adding the accessory is extremely frustrating and time consuming. Adding the accessory to the WiFi network is a hit and miss affair. It really is a crapshoot.

Today after three tries adding the Leviton without success, I almost gave up. Finally I discovered the following process in this reddit article. Even the technique outlined by the article did not work until I restarted the avahi-daemon.service on my Linux server, figuring that it may interfere with the Bonjour discovery process when adding the accessory.

Using the WiFi setup of the iPhone to add the Leviton device to the WiFi network definitely works smoother than using the Home app. Here are the steps:

  1. Reset the light switch by pressing and holding the on position of the switch until its LED light switches rapidly from red and amber. This can take more than 10 seconds.
  2. Set the iPhone to the appropriate WiFi network.
  3. Goto the iPhone WiFi menu, and you will the Leviton switch available for adding to the WiFi network. Add this device to the network.
  4. If an error is encountered when adding to the network, then restart the avahi-daemon service (or other mDNS service that may be competing).
  5. Once the switch is added to the network, proceed to add the switch with the Home app.

Apparently there is a firmware update for these switches. However, the update from 1.4.13 to 1.4.32 fail with the Leviton iOS app.

If you are thinking of getting a light switch for your home automation project, I would steer away from these switches!

NAS RAID-1 Fail

This past weekend my media NAS server was intolerably slow. When I investigated, I found out that one of the RAID-1 partitions is experiencing read errors and is timing out. I decided to risk a reboot and to my surprise the RAID-1 partition did not recover with one fail drive, but mdstat recorded with an inactive status, something like this:

md2 : inactive sdc1[0](S)

After some Google search, I found that I had to do the following to resurrect the md2 device.

madam --stop /dev/md2
mdadm --assemble --force /dev/md2

This reactivated the md2 partition. I replaced the failed drive and re-added the new drive to the md2 device. The RAID-1 partition is now rebuilding.

The inactive state is a new experience for me, so this was a bit of a surprise.

During this exercise I also found out that the SATA connectors on my SATA add-on card were loose causing intermittent connections. I will have to find a way to address this in the future.

Old Media Server with OpenVPN

I am in the process of building and configuring a media server for my parents. After my recent media server upgrade, I have extra gear lying around. By purchasing a power supply and a small case, I can cobble together another media server with my old processor and motherboard. I will call this my parent’s media server. The goal is to replace the current Raspberry PI unit that is currently running OSMC acting as their media server. Although the OSMC solution with Raspberry PI has been working really well, it is under powered to play any HEVC encoded video at full 1080p HD resolution.

I wanted to convert the majority of our video media to HEVC simply to save storage space. If I do this with my media library, I will not be able to share our media with them because of their under powered Raspberry PI.

To solve this issue, I installed Ubuntu 18.04 along with Kodi on my parent’s media server that I just created. I have been testing this solution for the past couple of weeks and both the hardware and media player works really well.

I also configured the box to auto mount USB disks, and installed SAMBA so that both videos and music files can be shared with other devices on the same network. The SAMBA is primarily used by my parents with their SONOS speakers.

With this media server at their location, I can also consider future upgrades such as replacing their WiFi network with a Ubiquiti solution, and even ponder on a site-to-site VPN solution with both of our networks.

Perhaps that is looking too far into the future. My immediate concern is how to remotely administer the box. With the Raspberry PI, I just had a simple SSH setup. However with the extra horse power, and a full blown Ubuntu distribution, I can now setup OpenVPN.

I followed these instructions on the DigitalOcean site, and it worked flawlessly. During the setup, I made a major error. I skipped the firewall (ufw) setup on the box, thinking that I don’t need a firewall because an external firewall already exists. However, OpenVPN will not route external traffic to the internal private network if IP masquerading (NAT) is not setup properly. Thanks to a coworker’s advice, I configured the firewall with IP forwarding NAT, but also change all default actions to ACCEPT so that the firewall only function as a NAT router. Lesson learned!

Since this VPN will only be used by me for remote management, I will not configure any HTTPS tunnelling or install and configure ObfsProxy. We will continue to use UDP and stick with the default 1194 port.

We will do some final testing before finally deploying it to my parent’s place.

NVMe SSD with LVM Cache

I have been a huge fan of Apple’s fusion drives. They are an excellent compromise for affordable mass storage while still able to give you SSD performance. The concept is simple pair a fast but small SSD drive with a large but slow and much affordable, mechanical HDD. You get good performance and have lots of storage without breaking the bank.

I have falsely assumed that this capability only existed with Apple’s macOS operating system. This week I was pleasantly surprised to have discovered that LVM Cache can do more or less the same thing on Linux. This new found knowledge along with an excellent deal on a 500GB NVMe Samsung 970 Evo Plus M.2 drive gave me the itch to experiment this weekend with my NAS media server.

The hardware was easy enough to install, but I had to move one of the existing SATA connection because the M.2 slot on the motherboard shared a PCIe bus with a pair of SATA connections. Luckily I bothered to check the motherboard manual, otherwise I would have been scratching my head while the server fail to boot.

The software configurations were a bit more involved. Before I purchased the NVMe card, I did some experimentation with two external USB drives, one SSD and one HDD. I found this article to be super helpful in configuring LVM Cache with my test drives. However, these configurations were not fully restored after a reboot. After many hours of research on the Internet, I found this article indicating that my Ubuntu Linux distribution was missing the thin-provisioning-tools package. I also had experimented between the two different cache modes that were available, writethrough and writeback. I found out that the write back mode was a bit buggy and did not sync the cache and the storage drive. Yet another article to the rescue.

lvchange --cachesettings migration_threshold=16384 vg/cacheLV

I preferred the write back mode due to its better write performance characteristics. Apparently to fix the issue, I have to increase the migration threshold to something larger than the default of 2048 because the chunk size was too large.

Here are the steps that I did to configure my existing logical volume (airvideovg2/airvideo) to be cached by the NVMe drive that I just purchased. I first have to partitioned the NVMe drive.

Model: Samsung SSD 970 EVO Plus 500GB (nvme)
 Disk /dev/nvme0n1: 500GB
 Sector size (logical/physical): 512B/512B
 Partition Table: gpt
 Disk Flags: 
 

 Number  Start   End    Size   File system  Name     Flags
  1      1049kB  500GB  500GB               primary

Create an LVM physical volume with the NVMe partition that was created previously /dev/nvme0n1p1 and add it to the existing airvideovg2 volume group.

sudo pvcreate /dev/nvme0n1p1


sudo vgextend airvideovg2 /dev/nvme0n1p1

Create a cache pool logical volume and set its cache mode to write back and establish the migration threshold setting.

sudo lvcreate --type cache-pool -l 100%FREE -n lv_cache airvideovg2 /dev/nvme0n1p1



sudo lvchange --cachesettings migration_threshold=16384 airvideovg2/lv_cache

sudo lvchange --cachemode writeback airvideovg2/lv_cache

Finally link the cache pool logical volume to our original logical volume.

sudo lvconvert --type cache --cachepool airvideovg2/lv_cache airvideovg2/airvideo

Now my original logical volume is cached and I have gained SSD performance economically on my 20TB RAID setup for less than $200. Below is my final volume listing.

$ sudo lvs -a
   LV               VG          Attr       LSize   Pool       Origin           Data%  Meta%  Move Log Cpy%Sync Convert
   airvideo         airvideovg2 Cwi-aoC---  20.01t [lv_cache] [airvideo_corig] 0.01   11.78           0.00            
   [airvideo_corig] airvideovg2 owi-aoC---  20.01t                                                                    
   [lv_cache]       airvideovg2 Cwi---C--- 465.62g                             0.01   11.78           0.00            
   [lv_cache_cdata] airvideovg2 Cwi-ao---- 465.62g                                                                    
   [lv_cache_cmeta] airvideovg2 ewi-ao----  64.00m                                                                    
   [lvol0_pmspare]  airvideovg2 ewi-------  64.00m      

We can also use the command below to get a more detail listing.

sudo lvs -a -o+name,cache_mode,cache_policy,cache_settings,chunk_size,cache_used_blocks,cache_dirty_blocks

Upgrade completed. We’ll see how stable it is in the future.