offset \ˈȯf-ˌset\ noun

a force or influence that makes an opposing force ineffective or less effective

Family DLC

Every time I try writing something I end up in a state resembling a writer's block. Days pass and when I sit down to write an article, I quickly realize I don't have anything to report. In actuality I have loads of things to report, but no point in writing about them since they're not complete yet. I'm either busy wrapping things up for weeks or resigned to waiting for things beyond my control to resolve. Another cold period approaches and it is not helping either.

Still, I need to write about something, else I'll slow down so much I am afraid I'll be going in reverse. While I won't write about the things that are not yet completed, I'll write about one thing that definitely is. Our small family is not two, but four now. Twins Kida and Tenzin have joined our little club and are taking away our sleep, our time, our sanity, but bringing in some joy, calm and are keeping us from obsessing over meaningless things.


/media/images/tenzin-kida.jpeg

Getting a household ready for cats is not a trivial task. To fit our overall smart-home project, we opted to immediately introduce some smart gadgets - the ones we could afford and fit into our small apartment. We now have two automated food dispensers (dry only), a smart water fountain (they're interested in drinking the running water) and a single cat flap door.

The flap door we needed for Kida as she's a fussy eater - slower than her brother, who started to steal her food, and she also prefers to have audience and encouragement while she does it (we've since learnt that she's what's referred to as "affection eater").

He has no such trouble. He's growing way faster than her and is over five kg now. A true gentle giant. At the time of this writing, they're currently just over seven months old. Time is flying, though.

Aside from providing food and water logistics, we've set up two litter boxes in the hallway, which we'd love to replace with an automatic one, but that's both expensive and impractically large at this point.

Vesna bought every toy from every top list of cat toys and then some, we've set up a number of nooks where they can curl into for a nap, as well as two cat trees that they can climb, perch from and observe us from a height. Most of the time they sleep on the windowsill or above and below our bed.

They also have very distinct personalities. Tenzin is quick to sneak a cuddle or two, or three, and is friendly with everyone (which terrifies Vesna as if he ever escaped, nobody would ever return the glorious affectionate furball that he is). Kida is very skittish, but loves to explore and play, and vocalizes it frequently. She's not super into being cuddled, but will follow us from one room to another. We're working on it.

We also took the time to teach them some tricks. Their repertoire consists of responding to their name, sitting, giving high five, fist bump and low five, giving handshake, a hug, jumping over a leg or an arm, nose bumping and the list continues to grow. Right now we're teaching them to react to "no" - basically turning their attention from the illicit activity to us and using positive reinforcement when it works.

When weather permits, we try to take them for a walk on a leash, although that can prove to be challenging with them either trying to dash after something (Tenzin) or getting scared of strangers and freezing in place (Kida). It sure makes our lives less boring, and hopefully theirs more interesting.

The challenge ahead of us will also be switching them to a vegan diet. Their digestion can react temporarily, but we've done our research and it shouldn't cause long term issues. There are several brands that offer balanced food options for cats in the vegan department, but none of them are going into specialized territory like "kitten only", or "sterilized kitten" foods. Top that with what they had in the previous household, we are taking it slow.

They were also fixed relatively recently and they recovered nicely. Her procedure did involve some sleepless nights on our part, spent streaming relaxing cat music, but it mostly worked on Vesna. Luckily, that milestone is behind us now.

They've changed our lives profoundly in a very short time and we love them unconditionally, but I do sometimes wish they could learn how to work so Vesna and I are not the sole breadwinners in the family, or at least to cast some useful spells in the spellcaster's familiar vein.

Genealogy and DNA Analysis

In short, genealogy is the study of family history. Aside from studying birth records, historical lists and articles and other available sources, relatively recently popular method of studying family history is DNA analysis, to see how related people within a DNA database are. There are two biggest consumer focused companies out there for humans: Ancestry, which is mostly focused on North America and MyHeritage, which is mostly focused on Europe.


/media/images/dna.jpeg

My uncle started doing genealogy on MyHeritage and I was kinda fed up myself with not knowing all the cousins, their spouses, children. I also wanted to have my DNA sequenced. After all, I used to work in such a company, but eventually I opted to first enter the data in Ancestry because their DNA database of humans is the biggest there is at the moment, they offer traits display, as well as ancestry, and there's an option to export the data from them and import it into MyHeritage. It took some manual work to export the data from Ancestry, with usual disclaimers, of course, then import it to MyHeritage and wait for them to analyze it.

DNA is assembled by combining some parts in the DNA strain of the individual with the reference genome. Humans are mostly the same so there are no big differences between us regarding genetics.

All of the calculations are done by finding similarities of the submitted DNA with the rest of the DNA samples in the database.

The ancestry analysis is done by comparing the number of DNA subsequences of the individual with the sampled population grouped by their place of living. It is a static picture of things. People migrated and there's considerable room for getting it wrong, but there is truth to it, especially because ancestry can be distinguished way back throughout generations.

The traits display is there to see things like free vs attached earlobes, alcohol flush, sprinter gene and so on. Ancestry got almost all of my traits correct. Traits are usually determined by finding genetic similarities of a user within the DNA database that is marked up by user submitted answers.

More interesting is the PRS (Polygenic Risk Score) that can determine predisposition to various traits. Diseases being a very interesting part of it. Cancers and such. Of course, we're talking about statistical probability, which is definitely not the singular cause, but a possible contributing factor. For instance, just because one might be an alcoholic, genetically speaking, if they're not drinking, it can hardly be the case. PRS are also most viable in the populations with European ancestry, since they're the most researched group, but can fail in other groups. Take it with a grain of salt if you're checking things out for health. Ancestry does not give out PRS related to health. If one wants that, they should sequence their genome with 23andMe instead.

DNA analysis, as expected, depends largely on the sample size, as well as other factors, like epigenetics, additive genetic effects, etc. It is an interesting area of study.

It took about a month to get the results. The kit gets ordered, sent, then it's activated, sample is collected via saliva, stabilizing fluid is added to it and it's mailed back. It's a long wait then. They need to receive the sample, extract the DNA and run analysis on it. It depends on the lab and the amount of work they have. Import/export to another service (from Ancestry to MyHeritage in our case) was a matter of days and a bit of manual work.

As for my ancestry, I didn't get swapped at birth. The DNA matches it produced are correct, from both sides of the family (calculated by chromosomes because this is how inheritance works), but the ancestry is different from what I was expecting. My family is Slavic, to be precise: West and South Slavs. In Ancestry.com instead of Czechia, it got a lot of Southern Poland. It also threw out some similarities in their model with Germanic Europe, Baltic, Sweden and Denmark, then a bit of Norway. MyHeritage used a different model because it has different groups and has different samples. They placed my ancestry correctly in Czechia, but also found some similarities with Greek and Italian groups, Scandinavian, Iberian and Finnish. Apparently the families migrated from the north towards the south of Europe. Can't really blame them. My path was going back and a bit west. I'm in Ireland now and I love the climate here. I even got the citizenship just a few days ago ☘ Something to mess up the static image of ancestry once again :)

Way Away

We picked up wanderlust some six years ago when we were traveling to Australia. There's no way we'll see all the countries in the world during our lifetime, but there's a strong chance we'll succeed in seeing all of Europe's. Humans often focus on wrong things. Our apartment could burn down, but we would move on. Material things are not that important. It's important that we have each other. But we are lucky enough that our fundamental needs have been met at this point in time so we have some space to pursue our desires.

I wasn't writing for a while since we were away from home for a month and a half. I was called to an off-site in Panama and an on-site in New York was planned to be soon after. We chose to take our holidays in between so we didn't have to do two transatlantic flights. Planes are leaving a substantial carbon footprint as is. We saw a fair chunk of Mexico and Caribbean as well. The trip was long and enjoyable, but I can say Aegean islands do beat the Caribbean in terms of what you can see. It's hard to pack a lot in limited time, and the cultural sites, which we prefer to visit, are more tightly packed in the former.

As for the nature, Yucatan peninsula is full of cenotes that are a sight to be seen. The time we spent in Mexico was the top experience of our journey. It had some nice natural and historical sites. From ancient Mayan ruins, to reefs and groundwater pools.

Our first flight was from Dublin to Madrid, for a long layover towards Panama City. We saw the Panama canal and the city itself. The work was exhausting, trying to get a new feature off the ground within a very tight deadline is always hard, but I got to see people I hadn't seen in a while. For Panama we also opted to get vaccinated. Our bodies are not really used to the conditions there. The vaccination went well and some protections we took (DTP, Hep A and Typhoid) will last a long time. This will be useful for us in the future.

After Panama, we went to Cancún. It was a mixture of nature and history. We saw the city itself because we had accommodation near the center. It's not a very walkable city, and we're not car people, but it does have good public transport. We jumped off to some guided tours towards Chichén Itzá and Tulum. We admired the Mayan architecture and took a dip in the sea and some sinkholes, which made me want to start a scuba course one day.


/media/images/tulum.jpg

After Cancún, we went to Orlando as our jumping off point to the islands. We had some mean tostadas over there that we immediately tried to replicate back home. Those tostadas and the Colombian empanadas we had in Panama were two food items that we enjoyed the most. The rest of our culinary experience ranged from average to sadly subpar, and left us with the impression that vegan scene in North America is just not that developed yet. The highlight in Orlando was the Universal Studios amusement park. We managed to go to all the adrenaline rides that we wanted.

The Caribbean islands/territories/countries we visited from Orlando were the US Virgin Islands, Saint Martin (both French and Dutch parts), Antigua and Barbuda, Dominican Republic and Puerto Rico. The culture over there is diverse and influenced by the previous colonialism era and dramatic historical overturns. We enjoyed some historical sites and the cities themselves. It was a long round trip that took us back to Orlando again.

Back in Orlando, we decided to stay for a few days before traveling for the New York on-site. The US is still expensive as is, but Orlando is cheaper than New York. We went to see the Kennedy Space Center and all the US space program exhibitions. We got to fondle a moon rock sample. We did miss an actual rocket launch, because it got postponed so many times. Eventually we packed our bags (that were not many because we always travel light) and flew to New York.

In New York it was the usual on-site work, the combination of rooftop bars that the company usually goes for and an evening of personal time that we used to see the Edge skydeck and Manhattan from a higher vantage point. By then we were getting homesick and were looking forward to going back to Dublin.

Those first days at home were us just trying to catch up, wash all our clothes, get things in order. I had my hair cut a bit, installed a bug net on the balcony. We were getting ready to spend a summer at home. As luck would have it, less than two weeks after we came back, I got laid off together with around a third of the company. I really strive not to obsess over things I can't control. After all, the job market situation is very bad recently, especially in IT. Layoffs are happening all over the world.

Right now I'm out there on the job market, as well as doing some personal stuff. Losing a job really messes with one's head. Looking for a job is not helping it. Constant impostor syndrome, questioning self-worth, being worried all the time. I feel like this is not talked about enough. Life goes on, really. Time stops for nobody.

P.S. While I was writing this, my citizenship application got approved so I guess there's some more bureaucracy in that department. Time indeed does not stop for anybody and tends to be very turbulent. :)

Convert KML Placemarks to Zones for Home Assistant with Python

I have a habit of tracking the places we've been to in Google Earth Pro. I have a list of folders that are named after countries and, inside them, a list of places that we've been to. Sure, I can export to a KML/KMZ format but Google Maps refuses to load the file because of the size. I would also like to display the places in the Home Assistant, but there's no easy way and I really don't want to over-engineer this.

Home Assistant is self-hosted and I can control it, so I decided to whip up a quick script in Python to help me accomplish seeing the places in Home Assistant.

  1. I opened Google Earth and selected all the places, then exported them to a KML file that I called places.kml. I saved it to a location where I put the Python script.

/media/images/google-earth-places.png
  1. The script is in a file called kml2zones.py and safely nested in a virtual environment on Python 3.10.x. I installed the requirements with pip (pykml and PyYAML) and ran the script python kml2zones.py which in turn output the zones.yaml file in the same folder. Here are the contents:
from pykml import parser
from yaml import dump

# load kml into object
with open("places.kml") as f:
    root = parser.parse(f).getroot()

# iterate through the kml,
# extract what is needed in to a dict,
# then append that dict to to the list
data = []
for country in root.Folder.Folder:
    for placemark in getattr(country, "Placemark", []):
        try:
            coordinates = str(placemark.Point.coordinates).split(",")
        except Exception:
            coordinates = str(placemark.MultiGeometry.Point.coordinates).split(",")
        data.append({
            "name": str(placemark.name),
            "latitude": float(coordinates[1]),
            "longitude": float(coordinates[0]),
        })

# dump the list to a yaml format file
with open("zones.yaml", "w") as f:
    dump(data, f)
  1. I copied over the zones.yaml to the Home Assistant configuration folder and edited the configuration.yaml in it to have: zone: !include zones.yaml at the end, then I restarted the Home Assistant.
  2. I planned to load them in the Map card, but that card accepts only a list of entities which are generated from zones when the Home Assistant loads. I got the list of entities with Developer Tools in Home Assistant. Under Template, I put the following:
{% for item in states | map(attribute='entity_id') | list %}{% if item.startswith("zone") %}
  - entity: {{ item }}{% endif %}{% endfor %}

/media/images/home-assistant-template-zones.png

Good enough of that black magic, except the first result in the list which I had to indent manually. I copied the entities.

  1. I created a new tab on the dashboard with only one card so it expands, the type was Map, I added two zones in visual editor, as well as set the zoom to 3, then switched over to the code editor. This showed me how I wanted it to look like.

/media/images/home-assistant-map-card.png
  1. I removed those two zones under entities and in their place put the clipboard content obtained from step 4. Then I searched for the ones that I had from before in that list that are not from the zones.yaml (like zone.home or the local stores that I previously had saved in the Home Assistant database) and removed them. I finished editing the card.

/media/images/home-assistant-map.png

That's pretty much it. It really shows how it's easy to do things with Python.

As of this moment, I did a number of small stupid scripts for doing various things. Some of them grew into a full fledged service like Mellow. Mellow was more an opportunity to play with what AWS has to offer than anything else. The kml2zones.py could maybe be converted into a service as well but I cannot be bothered and, what's more likely, people would not really use it, but it is there if someone wants to nibble on it and help themselves. Even executing it without a file, through REPL itself.

Some of the scripts I did end up as a snippet, some of them as a repository. Of the top of my head I made:

  1. Mellow - the conversion from Trello board to Coggle mind map
  2. kml2zones.py - the conversion from KML file to zones.yaml for Home Assistant
  3. geotag-gallery - making a KML file with placemarks from photos and tagging them with convolution AI results
  4. led-morse - blinking LED light on Arduino in a Morse code
  5. Shamrock - getting plant data from a 3rd party service.

Probably more. Writing those things is easy and the possibilities are endless.

The script in this article is an example of how things can be done quick and dirty if one only wants to invest a bit of time. I remember seeing some videos of people using Python as a scripting language much like a macro in an operating system. It would open browser, start some pages, click through some of the options and so on. Generally automating a plethora of mundane tasks. I'm sure people could utilize it in their own life, too.

Room-Level Presence Tracking

While ordering PC components, I also ordered Raspberry PI Zero 2 W. Ideally I'd have one more so I can have three and a proper Paxos distribution, but they are notoriously difficult to obtain these days. In the end I used my original PI 4 and Zero 2 W to create a two-node system for room level presence detection. The third one will have to wait so I might go for it this year if it turns available.

I installed Raspbian on the PI Zero 2 W and connected it to the network. Then I made the IP static on the router so it's not changing anymore. The same is done for the Raspberry PI 4, but in reality, all the devices that are our own have a static IP in the network. It's easier to address them and the configuration is not always catering to the dynamic ones.

The project I used was room-assistant and I installed it to both devices via Docker. PI Zero 2 W only has room-assistant, and the PI 4 has Mosquitto, Home Assistant and Room Assistant. The Room Assistant describes that you should have local.yml configuration and mine is as follows on PI 4:

global:
  instanceName: "Living Room"
  integrations:
    - homeAssistant
    - bluetoothLowEnergy
cluster:
  autoDiscovery: false
  weight: 2
  port: 6425
  peerAddresses:
    - <IP_v4 of the Raspberry PI Zero 2 W>:6425
homeAssistant:
  mqttUrl: "mqtt://<IP_v4 of the Raspberry PI 4>:1883"
  mqttOptions:
    username: <mqtt username>
    password: <mqtt password>
bluetoothLowEnergy:
  maxDistance: 20
  allowedlist:
    # bluetooth mac of the device you want to track,
    # for example, phone. There's a chance LE physical address
    # is rotated, if that's the case, you can go into
    # Home Assistant Android app, go under:
    # Settings -> Companion App -> Manage Sensors -> BLE Transmitter
    # and enable it, the format will be
    # UUID_WITHOUT_DASHES-major-minor
    - 112233445566

PI Zero 2 W has the same configuration file, but with a different instanceName (being in bedroom), weight of 1 so it's not picked as the leader if possible (the higher the number, the bigger the chance it will be the leader, and also that's why I'd like to have three devices at least - Paxos, remember), peerAddresses has the IP of the Raspberry PI 4, but the rest are the same as the configuration above. Be sure to change the values where they are required.

As for the Mosquitto, it's an MQTT broker that is coming recommended for Home Assistant use. Room Assistant detects a Bluetooth device, then sends a message to the queue. After that, the Home Assistant picks it up.

I am not very happy with the devices reporting their location. It would depend on the load of the device and the quality as well. I tried using bluetoothClassic integration at first, but switched to bluetoothLowEnergy because it was more accurate. Still, I think I might have to change the devices themselves since the signal drops, or investigate more into it to tweak the configuration. The walls will also affect this.

On the other side, once the Home Assistant picks up the integration, all that is left is to detect the presence. The integration makes sensors out of your devices, for example: sensor.fairphone_3_ble_room_presence. To get it into automations, it's the easiest to create the template automation trigger somewhat like this:

{{ is_state("sensor.fairphone_3_ble_room_presence", "Living Room") }}

When the above triggers the automation, the action can follow. For instance, turn off the lights in the other parts of the apartment, start home theater if it's evening, things like that... That said, I'll keep using it and see if I can improve on it.