First release of the Gimp 2.10.2/OSX port

There is no [yet] official dmg package of the Gimp Open Source Image Editor for OSX, so i created a new one. Work is mostly done, there are few non-critical issues i am planning to fix meantime. Also my plans are to merge my patches with an upstream, so hopefully this would become official port at some point.

Testers are welcome. OSX build could be found on project releases page.

Tagged , ,

How my Mac Book Pro 2017 destroyed 2 USB-C devices

Bad things happens

At morning my new Macbook was not working well – when i been disconnecting charger it was not detecting this properly, so i decided to reset SMC, and this resolved the problem. In the office i connected my passive USB-C hub with HDMI/USB output and it starts to smell very bad. I was stupid enough to connect my USB-C ubikey to the same socket and it was destroyed immediately, with the same smell and some lights. Both devices were destroyed. MacBook was working like nothing happens.

I realized that i already saw post about it on Reddit and been able to find original post Macbook Pro frying USB peripherals. It was looking exactly as my case. So i decided to validate it.

Measuring USB-C power voltage

I do have usb-c->microusb adapter from some charger + microusb power to power adapter plug. I connected to cables to it and been able to measure the voltage, thats how it looks:


Now i connected it to the voltmeter and plugged in to the affected port with a usb-c charger plugged in a different port:

20V!!! instead of maximum 5 allowed. All other sockets were provided ~1v, probably that is idle current when no data lines are connected:

I tried different combinations, but only top right socket was failing. So it seems to be another “known issue” in this new model, in addition to very problematic keyboard.


I been using only original charger with original cable but got usb-c devices fried. According to the post i provided below – i am not alone with such issue. Tomorrow i will send this Mac to repair and hopefully replacement will not be affected. I think that Apple engineers should consider this issue as very serious one, but giving the fact how they handle keyboard-related issues it seems to be unlikely.

Tagged , , ,

Fixing Google Music Manager on OSX

Sometime i am purchasing music on Google Music. Once i decided to download entire connection
and found that its not as easy as i exptected.

  1. With a browser you can download only album by album + it warns that download
    counter is limited to 2 times only (WTF?!?)
  2. Recommended way to download is “Google Music Manager” which should do everything automatically.

Okay google, lets try to install it. It installs fine, but download failing completely. On the web i found
that it was that way > 1 year already! (e.g. see this thread.

Also i tried to use Google support and it was as useless as possible.

So there is nothing to do but to try to fix it myself.

Starting debugging

Music Manager process name is MusicManagerHelper. This is QT4 (!) application.
Output of the lsof command shows that there is a log in the ~/Library/Logs/MusicManager/MusicManagerHelper.log.
Output shows that there is an error with certificate validation on every download attempt:

Failed to Verify Certificate: /C=US/ST=California/L=Mountain View/O=Google Inc/CN=* (unable to get local issuer certificate:0x00000000) [/Volumes/Android/buildbot/src/googleplex-android/jumper-stable/jumper/source/Shared/HttpClients/CurlHttpClientImpl.cpp:44 ::CurlSslVerifyCertificate()]

Ok, its better. Something i tried without any luck:

  • Adding google certs to the system keychain with a trust settings
  • Trying to find where its storing root certs (its compiled in)
  • Trying to rebuild libQtNetwork 4 on OSX (seems to be completely broken with a recent compiler/sdk)

Finally, solving issue using LLDB

Using debugger i found that libQtNetwork contains statically compiled OpenSSL.
After all i been able to identify function responsible for the certificate validation – it is ssl_verify_cert_chain.
Lets try to use lldb to override it return value!

  1. Starting lldb with lldb -p
  2. Adding breakpoint with breakpoint set -n ssl_verify_cert_chain --shlib libQtNetwork.4.dylib command.
  3. Attaching python script to the breakpoint:
    breakpoint command add –script-type python

    print "starting"
    thread = frame.GetThread()
    return_value =  lldb.frame.GetValueForVariablePath("*self")
    thread.ReturnFromFrame(frame, return_value)
    print "ending"
  4. Trying to download again. LLDB should print “starting” and “ending” on
    any download and it finally works!


  • Google is an Evil. I spent a lot of time to just download content i paid for! And support was completely useless.
  • Google Music Manager, at least on OSX, is insecure, broken and outdated application.
  • Putting root certificates to the bundle is a very poor coding style.
    Not sure if it comes from QT or from Google itself, but doing that way is embedding timebomb to your app.
  • Dtrace and LLDB are cool 🙂
Tagged , ,

C++ cross-compilation on Linux for the FreeBSD target using GCC or CLANG


Sometime it could be convenient to generate FreeBSD binaries on the Linux host. Just a few examples:

  • CI/CD deployment with a compilation check on the Linux Containers. It is especially the case for the SaaS environments where you are not able to select another OS (or it is not supported by the vendor)
  • Ability to automatically generate binaries for the all supported platforms with a minimal cost/efforts.
  • Using single docker or other linux-specific technology to cover all platforms.

I am using osxcross without any problem to generate OSX binaries, so decided to do the same with FreeBSD. This article shows how to do this and will provide some automated examples.

Using GCC

Most of the articles in the net i found are recommending to use GCC, which is default compiler on Linux distributions. GCC supports cross-compilation natively, but to achieve this you need to build entire kit from scratch.

Short overview of the process:

  1. Compile install latest binutils with --target=x86_64-pc-freebsd10 configure argument.
  2. Get FreeBSD libs/includes and install them to the buildroot location
  3. Compile and install GMP with --host=x86_64-pc-freebsd10 configure argument.
  4. Compile and install MPC with --host=x86_64-pc-freebsd10 configure argument.
  5. Finally compile GCC, you will have to specify sysroot path and all the libs location. Also you will have to manually define #define HAVE_ALIGNED_ALLOC 1 due to bug in the GCC autoconf scripts.

I created Dockerfile with all steps mentioned. GCC natively supporting only libstdc++ which is not available on the FreeBSD. Below is an example:

root@96de1e64fff1:/# /opt/cross-freebsd/bin/x86_64-pc-freebsd10-c++ -o helo helo.cpp
root@96de1e64fff1:/# file helo
helo: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/, for FreeBSD 10.3, not stripped
root@96de1e64fff1:/#  readelf -d helo|grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: []
 0x0000000000000001 (NEEDED)             Shared library: []
 0x0000000000000001 (NEEDED)             Shared library: []
 0x0000000000000001 (NEEDED)             Shared library: []

You can override this by overriding this using compiler/linker flags:

root@96de1e64fff1:/# /opt/cross-freebsd/bin/x86_64-pc-freebsd10-c++ -std=c++11 -I/opt/cross-freebsd/x86_64-pc-freebsd10/usr/include/c++/v1 -nostdinc++ -nodefaultlibs -lc++ -lm -lc -lgcc_s -lgcc -o helo helo.cpp

root@96de1e64fff1:/# readelf -d helo|grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: []
 0x0000000000000001 (NEEDED)             Shared library: []
 0x0000000000000001 (NEEDED)             Shared library: []
 0x0000000000000001 (NEEDED)             Shared library: []
 0x0000000000000001 (NEEDED)             Shared library: []

Some comments on the commandline:

  • -std=c++11 -nostdinc++ needed to avoid errors on libc++ headers
  • -nodefaultlibs -lc++ -lm -lc -lgcc_s -lgcc will tell gcc to not use with a predefined libraries but to use libc++ instead.

Problems with GCC cross-build:

  • Entire build chain need to be built from scratch. Not a big issue if you are using containers, but still takes some time to maintain it.
  • Natively only libstdc++ is supported which is now not part of the FreeBSD installation. To workaround this you can provide it with your code or to build static. It is possible to use libc++ instead but this required a lot of custom flags and may not work reliable.
  • Natively FreeBSD is not using gcc (with only exception of some ports), so behavior of the resulted code may be different due to some compiler differences.

Using Clang

After all i decided to take another approach. Clang is now (starting from FreeBSD 10) default compiler, as well as libc++ is used instead of libstdc++. Great news is that clang already supports cross-compilation without need to completely recompile entire toolset. I been able to get working FreeBSD binaries on default Ubuntu LTS buildhost.

Below is a part of the Dockerfile to fetch required headers and libraries, install them to /opt/cross-freebsd-10 and fix broken links:

# Get FreeBSD libs/headers, extract and fix broken links
RUN cd /tmp && wget \
&& mkdir -p /opt/cross-freebsd-10 \
&& cd /opt/cross-freebsd-10 \
&& tar -xf /tmp/base.txz ./lib/ ./usr/lib/ ./usr/include/ \
&& cd /opt/cross-freebsd-10/usr/lib \
&& find . -xtype l|xargs ls -l|grep ' /lib/' \
| awk '{print "ln -sf /opt/cross-freebsd-10"$11 " " $9}' \
| /bin/sh && \
rm -f /tmp/base.txz

Now it is possible to create FreeBSD binaries using additional compiler flags: -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/


root@4f9b820ae1c9:/# clang++ -target x86_64-unknown-freebsd10.0 --sysroot=/opt/cross-freebsd-10/ -o helo helo.cpp
root@4f9b820ae1c9:/# file helo
helo: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /libexec/, for FreeBSD 10.4, not stripped

Resulted binary will run on FreeBSD host only.

Lets check dependencies:

root@4f9b820ae1c9:/# readelf -d helo|grep NEEDED
0x0000000000000001 (NEEDED) Shared library: []
0x0000000000000001 (NEEDED) Shared library: []
0x0000000000000001 (NEEDED) Shared library: []
0x0000000000000001 (NEEDED) Shared library: []
0x0000000000000001 (NEEDED) Shared library: []

As we could see dependencies are fine and matching normal FreeBSD 10.4 installation. Of course you may have many buildroots to simplify multiply targets.


It was found that both GCC and CLANG are able to cross-compile to FreeBSD using Linux host. However, CLANG require less efforts for this, mostly due to implemented -target switch and natively supported libc++ used by the FreeBSD project. I think it is better to use it for this task, with only exception if your source code has some strict GCC dependencies.

I implemented cross compilation to the FreeBSD as part of the CircleCI tests for the smartomontools project. I am planning to play with other targets (ARM, PPC) as well.

Tagged ,

Network FreeBSD boot using Mikrotik router TFTP

Sometime bad things happens

One of my FreeBSD servers failed to boot after number of power outages on the
remote site. However IPMI was still working, so I been able to see remote state.

Problem was with damaged ZFS root pool, so single user mode was also not able to boot.

At this location i also had Mikrotik router connected to the same switch, so i
decided to try to fix this server using network (PXE) boot.
It was a challenge for me, because i never tried to boot from the
RouterOS device and was not sure if it will work at all.

Configuring Mikrotik DHCP server

To get network boot possible there are 2 minimal pre-requirements:

  • DHCP server to provide DHCP responses with a special parameters
    (file to boot).
  • TFTP server to host files required for network boot.

Normally FreeBSD also wants NFS for the remote booting, but in this case we will avoid it.

To configure DHCP on the Mikrotik i created new DHCP server and dedicated DHCP network for it, which includes boot-file-name property:

/ip dhcp-server
add interface=MYLAN name=tftpsever

/ip dhcp-server network
add address= boot-file-name=gpxelinux.0 dns-server= \
    gateway= netmask=24

Also static lease for the server ethernet card MAC address been added:

/ip dhcp-server lease
add address= always-broadcast=yes mac-address=\
      E4:1F:13:6C:12:34 server=tftpsever

Also i would recommend to enable DHCP logging to monitor status of the requests.

Configuring Mikrotik TFTP server

When DHCP configuration is completed, it is time to enable and configure TFTP on
the router. In the RouterOS you have to specify parameters for every hosted file.

Below is my configuration:

/ip tftp
add real-filename=gpxelinux.0 req-filename=gpxelinux.0
add real-filename=chain.c32 req-filename=chain.c32
add real-filename=pxelinux.cfg/default req-filename=\
add real-filename=memdisk req-filename=memdisk
add real-filename=menu.c32 req-filename=menu.c32
add real-filename=reboot.c32 req-filename=reboot.c32
add allow-rollover=yes real-filename=\
    mfsbsd-11.0-RELEASE-amd64.img req-filename=mfsbsd-11.0-RELEASE-amd64.img

Creating bootable mfsbsd installation on the TFTP server

To recover FreeBSD i decided to use mfsbsd project. This is FreeBSD live CD/USB
which loads to the memory (so no NFS needed) and provides a lot of useful tools
out of the box. Also due to it small size it was possible to fit it on the router flash memory, so no additional downloads or mounts were needed. And, of course, mfsbsd contains everything needed to repair broken ZFS pool. I been using USB image based on 11.0 RELEASE.

But mfsbsd alone is not enough – to boot from network we also need files from the syslinux project. I been using [outdated] version 4.04, just because i had some projects using it in the past and it seems that some modules were renamed in the recent version.

List of the files to upload:

gpxelinux.0 (syslinux-4.04/gpxe/gpxelinux.0)
chain.c32 (syslinux-4.04/com32/modules/chain.c32)
memdisk (syslinux-4.04/memdisk/memdisk)
menu.c32 (syslinux-4.04/com32/menu/menu.c32)
reboot.c32 (syslinux-4.04/com32/modules/reboot.c32)
mfsbsd-11.0-RELEASE-amd64.img (USB image from the mfsbsd web site)
pxelinux.cfg/default (configuration, see below)

To work properly with IPMI and boot mfsbsd image we need to create configuration. Line serial 1 115200 is to define serial port output, and menu ui is mostly to ensure that something useful is going on.

Content of the pxelinux.cfg/default file:

serial 1 115200
console 1
ui menu.c32
menu title Utilities

label mfsbsd
  menu label mfsBSD
  kernel memdisk
  initrd mfsbsd-11.0-RELEASE-amd64.img harddisk raw

Files needs to be copied to the router flash, i used sftp tool to upload them.

Configuring server

Make sure that you have enabled PXE boot in the BIOS (i been able to do this
using IPMI). Also, at least on my server, i had to enable not only Legacy PXE
(which is in use), but also UEFI IPMI or network boot was never starting.
If everything is done correctly you should see DHCP request followed by TFTP.
In my case it was 2 times:

  1. UEFI PXE, which failed because i am using legacy boot.
  2. Legacy PXE which succeed. After loading all required files boot menu was
    shown and i been able to select mfsbsd item.
  3. After selecting this item FreeBSD started to load, but no output been shown
    on IPMI console. This is because by default mfsbsd is not showing anything on the
    serial console. It should be easy to fix, but in my case it was not needed.

In a few minutes i found another DHCP request in the Mikrotik logs, this time
from the mfsbsd, and been able to reach the server using SSH (credentials are root/mfsbsd). It is possible to use RouterOS ssh client (/system ssh user=root

Finally fixing ZFS pool

My attempt to import failed zroot pool from the mfsbsd failed as well. Moreover –
zpool import -F zroot also been not working. Before giving up i been able to find non-documented -X switch, which together with -F been able to completely restore pool in ~30 minutes! After reboot server been able to boot normally.


  • Check what needs to be done to create UEFI compatible FreeBSD network boot.
  • Create additional menu items for RescueCD.
  • Create mfsbsd which sends output to the serial port 2, to be compatible with IPMI.
  • Utilize latest syslinux instead of very outdated one.
Tagged , , ,

How to monitor NVMe drives in the OSX

NVMe support in OSX

After upgrade to the latest Macbook Pro i found that smartctl is not able to find any smart capable drive. This is because Apple replaces SATA SSD with NVMe one and old SMART API is not working (it is very ATA specific). Smartmontools itself includes NVMe support for the Linux, Windows and FreeBSD, so i decided to try to add it to the Darwin as well. However it was not as easy as expected – Apple did not published any source code or documentation about NVMe device support or monitoring. Moreover – there is no any tool in OSX to show such statistic and old tools from SDK are useless because of API Change.

Starting to search for the API provider

After looking on the file tree i have found good candidate: /System/Library/Extensions/NVMeSMARTLib.plugin. Its done more or less similar to the /System/Library/Extensions/SMARTLib.plugin/ which provides SATA/ATA SMART support. As i mentioned – there is no documentation, so i had to use otool, nm and lldb to deal with it. As expected, it was found that API is similar to the ATA one. You can get list of the symbols and functions using this command: nm NVMeSMARTLib | c++filt -p -i. So i tried to connect to it using modified example from SDK for the SMART. Tricky part was to find kIONVMeSMARTUserClientTypeID and kIONVMeSMARTInterfaceID values which are using by CFPLUGIN infrastructure in the IOKit to initialize API interface. Fortunately library comparing this data during runtime, so with disasm i been able to find them. After successful connect to the interface i been able to reconstruct missing headers and use some of the functions (see below)

What is working and what is not.

The most important functions SMARTReadData and GetIdentifyData are working and result is provided in the structures matching with NVMe standard. I was not able to get GetLogPage function running, probably it expects pointer to some structure with defined data. If apple will release any consumer of it it would be easy to find this out.

Also there are some other, unknown functions in this API: GetFieldCounters (always returns error), ScheduleBGRefresh (no parameters, returns ok), GetSystemCounters and GetAlgorithmCounters (some driver info? or vendor-specific log pages?). Another interesting finding was string “Sandisk 401Z128G-4p-MLC” in the SMART log page, so possibly this NVMe is originally from this vendor.

SmartMontools support

I am working to add limited NVMe support to the smartctl and smartd for OSX. Now i already have working prototype, but need to cleanup and refactor some code. I am planning to add this before the next release. Below is an output from my disk:

smartctl 6.6 2017-09-14 r4434M [Darwin 16.7.0 x86_64] (local build)
Copyright (C) 2002-17, Bruce Allen, Christian Franke,


Model Number:                       APPLE SSD AP0512J
Serial Number:                      XXXXXX
Firmware Version:                   16.14.01
PCI Vendor/Subsystem ID:            0x106b
IEEE OUI Identifier:                0x000502
Controller ID:                      0
Number of Namespaces:               2
Local Time is:                      Wed Sep 20 08:56:36 2017 CEST
Firmware Updates (0x02):            1 Slot
Optional Admin Commands (0x0004):   Frmw_DL
Optional NVM Commands (0x0004):     DS_Mngmt
Maximum Data Transfer Size:         256 Pages

Supported Power States
St Op     Max   Active     Idle   RL RT WL WT  Ent_Lat  Ex_Lat
 0 +     0.00W       -        -    0  0  0  0        0       0

SMART overall-health self-assessment test result: PASSED

SMART/Health Information (NVMe Log 0x02, NSID 0x0)
Critical Warning:                   0x00
Temperature:                        33 Celsius
Available Spare:                    90%
Available Spare Threshold:          2%
Percentage Used:                    0%
Data Units Read:                    19,311,330 [9.88 TB]
Data Units Written:                 11,653,167 [5.96 TB]
Host Read Commands:                 50,388,833
Host Write Commands:                37,404,327
Controller Busy Time:               0
Power Cycles:                       2,320
Power On Hours:                     23
Unsafe Shutdowns:                   7
Media and Data Integrity Errors:    0
Error Information Log Entries:      0

Reconstructed API

If you want to play with the API yourself – you can use this header. Please let me know if you found how to use GetLogPage or any other useful information:

// NVMe definitions, non documented, experimental

// Constant to init driver
#define kIONVMeSMARTUserClientTypeID       CFUUIDGetConstantUUIDWithBytes(NULL,      \
                                        0xAA, 0x0F, 0xA6, 0xF9, 0xC2, 0xD6, 0x45, 0x7F, 0xB1, 0x0B, \
                    0x59, 0xA1, 0x32, 0x53, 0x29, 0x2F)

// Constant to use plugin interface
#define kIONVMeSMARTInterfaceID        CFUUIDGetConstantUUIDWithBytes(NULL,                  \
                    0xcc, 0xd1, 0xdb, 0x19, 0xfd, 0x9a, 0x4d, 0xaf, 0xbf, 0x95, \
                    0x12, 0x45, 0x4b, 0x23, 0xa, 0xb6)

// interface structure, obtained using lldb, could be incomplete or wrong
typedef struct IONVMeSMARTInterface

        UInt16 version;
        UInt16 revision;

                // NVMe smart data, returns nvme_smart_log structure
        IOReturn ( *SMARTReadData )( void *  interface,
                                     struct nvme_smart_log * NVMeSMARTData );

                // NVMe IdentifyData, returns nvme_id_ctrl per namespace
        IOReturn ( *GetIdentifyData )( void *  interface,
                                      struct nvme_id_ctrl * NVMeIdentifyControllerStruct,
                                      unsigned int ns );

                // Always getting kIOReturnDeviceError
        IOReturn ( *GetFieldCounters )( void *   interface,
                                        char * FieldCounters );
                // Returns 0
        IOReturn ( *ScheduleBGRefresh )( void *   interface);

                // Always returns kIOReturnDeviceError, probably expects pointer to some
                // structure as an argument
        IOReturn ( *GetLogPage )( void *  interface, void * data, unsigned int, unsigned int);

                /* GetSystemCounters Looks like a table with an attributes. Sample result:

                0x101022200: 0x01 0x00 0x08 0x00 0x00 0x00 0x00 0x00
                0x101022208: 0x00 0x00 0x00 0x00 0x02 0x00 0x08 0x00
                0x101022210: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x101022218: 0x03 0x00 0x08 0x00 0xf1 0x74 0x26 0x01
                0x101022220: 0x00 0x00 0x00 0x00 0x04 0x00 0x08 0x00
                0x101022228: 0x0a 0x91 0xb1 0x00 0x00 0x00 0x00 0x00
                0x101022230: 0x05 0x00 0x08 0x00 0x24 0x9f 0xfe 0x02
                0x101022238: 0x00 0x00 0x00 0x00 0x06 0x00 0x08 0x00
                0x101022240: 0x9b 0x42 0x38 0x02 0x00 0x00 0x00 0x00
                0x101022248: 0x07 0x00 0x08 0x00 0xdd 0x08 0x00 0x00
                0x101022250: 0x00 0x00 0x00 0x00 0x08 0x00 0x08 0x00
                0x101022258: 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x101022260: 0x09 0x00 0x08 0x00 0x00 0x00 0x00 0x00
                0x101022268: 0x00 0x00 0x00 0x00 0x0a 0x00 0x04 0x00
                0x101022488: 0x74 0x00 0x08 0x00 0x00 0x00 0x00 0x00
                0x101022490: 0x00 0x00 0x00 0x00 0x75 0x00 0x40 0x02
                0x101022498: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
        IOReturn ( *GetSystemCounters )( void *  interface, char *, unsigned int *);

                /* GetAlgorithmCounters returns mostly 0
                0x102004000: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004008: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004018: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004020: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004028: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004038: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004040: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004048: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004050: 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00
                0x102004058: 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004060: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004068: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004070: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004078: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004080: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004088: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004090: 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00
                0x102004098: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

        IOReturn ( *GetAlgorithmCounters )( void *  interface, char *, unsigned int *);
} IONVMeSMARTInterface;

Tagged , , , ,

Reassigning ESC key on the MacBook Pro with a touchbar

There is no escape

I like an idea of the touch-bar, but removing physical Esc button is nothing but a pain, especially if you are using vi/vim, but not only. I been touching it accidentally, closing some windows, etc. No way, really. So i had to find a way to remap.


OSX allows to remap Escape key, but its possible to use only few options (e.g. to use Caps instead). For me it was not looking like a good option. So i started to look for an alternative and found it.
Karabiner Elements allows you to remap any key. You can find name of the key in the Event Viewer. For me it was non_use_backslash (which is The plus-minus key “±”) to the escape.

Removing touch-bar Escape

To make touch-bar escape harmless i just re-assigned it to the “right shift” button. That`s how my my final configuration looks like:

That`s it. Remapping works in the GUI and terminal programs, no problems found so far. Interesting what key will be removed in the next model.


ZPA ZE312 counter RF output descriptopn

Some time ago i been able to read data from the ZPA ZE312 power meter, which seems to be popular in CZ. Data now automatically imported to Arduino every 5 minutes, i am planning to make a blog post about it. For now – just a description of the values which this device returns:

 'C.1.0(XXXXXXXXX)' # Meter serial number
 '0.0.0(XXXXXXXXXXXX)' # customer number = barcode
 '0.3.0(10000*imp/kWh)' # Active energy meter constant [imp/kWh]
 'F.F(000000)' # Error code
 '1.8.0(0010332.677*kWh)' # Energy a in total: a = |+a|+|-a|
 '1.8.1(0005757.422*kWh)' # Positive active energy (A+) in tariff T1 [kWh]
 '1.8.2(0004575.255*kWh)' # Positive active energy (A+) in tariff T2 [kWh]
## Registers of active energy per phases
 '21.8.0(0008995.585*kWh)' # Positive active energy (A+) in phase L1 total [kWh]
 '41.8.0(0001014.588*kWh)' # Positive active energy (A+) in phase L2 total [kWh]
 '61.8.0(0000322.503*kWh)' # Positive active energy (A+) in phase L3 total [kWh]
 '2.8.0(0000000.000*kWh)' # Negative active energy (A+) total [kWh]
 '22.8.0(0000000.000*kWh)' # Negative active energy (A-) in phase L1 total [kWh]
 '42.8.0(0000000.000*kWh)' # Negative active energy (A-) in phase L2 total [kWh]
 '62.8.0(0000000.000*kWh)' # Negative active energy (A-) in phase L3 total [kWh]
 'C.8.1(0207212145)' # Operating period of tariff register t1. Format RRMMDDhhmm, RR-year, MM-month, DD-date, hh-hours, mm-min.
 'C.8.2(0103181249)' # Operating period of tariff register t2. Format RRMMDDhhmm, RR-year, MM-month, DD-date, hh-hours, mm-min.
 'C.8.0(0305140414)' # Operating period in total +a. Format RRMMDDhhmm, RR-year, MM-month, DD-date, hh-hours, mm-min.
 'C.82.0(0000000000)' # Operating period in total -a. Format RRMMDDhhmm, RR-year, MM-month, DD-date, hh-hours, mm-min.
 'C.7.1(00000001)' # the number of power failures in phase L1
 'C.7.2(00000001)' # the number of power failures in phase L2
 'C.7.3(00000002)' # the number of power failures in phase L3
 '0.2.1(ver.02,100830,B526)' # SW version
 'C.2.1(1112221302)' # Date and time of the last parameterization. Format RRMMDDhhmm, RR-year, MM-month, DD-date, hh-hours, mm-min.
 'C.2.9(1112221302)' # Date and time of the last read-out. Format RRMMDDhhmm, RR-year, MM-month, DD-date, hh-hours, mm-min.
 'C.3.9(0000000000)' # number of trials of attacking by magnetic field (scaler, counter)
Tagged , ,

Home Automation – WIFI connected FAN in the bathroom with humidity sensor

Why do i need that?

To avoid mold in the house it needs to be properly ventilated. Bathrooms are in the danger zone, because of the high humidity and temperature. Some time ago i bough a ventilator which automatically turns on/off based on the humidity, but it was never working good. It has variable resistors to tune it + some complex analog electronic and in fact was never working as intended and in about 1 year controller completely died. So, i had to find a replacement and decided that this is a perfect task for the HA. First part of the task was to define the requirements:

  • Ventilator must be able to turn on when some humidity value is reached (e.g. 80%) and turn off on low threshold (e.g. 60%)
  • It should be easy to change this thresholds. I would expect that its possible for them to be different at winter/summer seasons, may be not.
  • It would be great to monitor Temperature/Humidity in the bathroom with the same device and report it to the DomoticZ server.
  • Additionally it should be possible to start ventilator by pressing a button (e.g. to test if it works or for manual action)
  • And to have a lot of fun it should be built on cheap and open source components.

Choosing the right platform

Initially i had an idea (and prototype) on the Arduino Nano + Relay board + DHT21 sensor + 5V power supply + some connectivity board (wifi or bluetooth). However, i found that there will be a lot of connected components + wifi boards for the Arduino are very limited and sometime expensive, a lot of custom code needs to be written, etc. So i decided to try ESP8266 platform based devices.
One of the known devices based on this chipset is Sonoff TH10/TH16 (only relay is different, 10A and 16A):
sonoff TH10

I found controller on the Ali Express, because on the official web site it was out of stock.

What is inside?

  1. ESP8266 module which provides SoC with wifi connectivity. Serial port (3.3v, be careful!) soldered on the board, but no pins connected (but easy to add)
  2. Internal power supply circuit to power 3.3V SoC from the 220V power line
  3. Mini audio jack socket to connect different sensors. DHT21 and few others are available from the vendor. I ordered mine with DHT21 which is Humidity + Temperature (and is much better compared to DHT11)
  4. Relay (10 or 16A) connected to the SoC GPIO and manageable from it.

Flashing Sonoff TH16

Native firmare works using a cloud and is integrated with the vendor services. This was not something i would like to have, so i decided to re-flash it. There are many options for the ESP8266 (Arduino sketches, NodeMCU, firmware from vendor, etc). After quick research i decided to use an ESP Easy firmware based on such features:

  • It is free and opensource
  • Comes with a handy web interface and support of many different sensors, so very easy to start with.
  • Supports DomoticZ, MTTQ and other connectivity options.
  • Allows limited scripting (Rules engine) to implement device-side logic

I decided to use version 2.0 (ESP Easy Mega) which is still under development, because release was lacking some of the functionality i need. It is very easy to flash firmware to the device – all you have to do is to solder 4 pins in front of the board, which are VCC, RX, TX, GND. To flash it you will need 3.3V TTL Serial converted with a 3.3v output to power the board.

⚠WARNING⚠!!! never try to flash the device when it is connected to the 220V powerline. There is no proper ground isolation and most likely it will kill your device, serial converter and PC. You should disconnect device from the 220v and power it from the TTL converted instead (or any other 3.3v source)

To flash the firmware i been using tool and such command: -b 115200 --port /dev/tty.usbserial-A900ZKU9 write_flash 0x0000 ESPEasy_v2.0.0-dev8_normal_1024.bin

Device needs to be programmed in the flash mode, which is entered by powering on device with the button pressed.

Of course serial port name will depend on your OS and controller. After flash you should reboot the device and it will automatically create an SSID ESP_0 with a WPA password configesp. On address there is a web interface to setup connection to the home WIFI network.

EasyESP initial configuration

After Sonoff device is connected to the wifi you can access it from the browser. First think i would recommend to do is to assign blue led to the WIFI status indication. This could be done in the Hardware section, by setting wifi status led to GPIO-13 ESP Easy - status led. Next thing is to define devices available on the board: button (GPIO-0), and DHT21 sensor (GPIO-14). Additionally i defined dummy device, which will be later used in the rules engine:
ESPEasy - devices

To report values to the DomoticZ controller you have to define it in the controller section:
Controller. Additionally you will have to create virtual devices (using virtual switch) in the DomoticZ for the Temperature + Humidity sensor and the switch. ID in devices section should match one from DomoticZ. Also you may want to setup syslogd ip to see logs from the device when not using serial. This is important, because in my case DHT sensor was not working properly when powered from TTL converter (properly not enough current) but its not possible to use serial when 220V is connected.

EasyESP rules

To avoid any dependency on DomoticZ controller i decided to put this simple logic in the device. There is a Rules engine (it needs to be enabled in the Advanced menu) which allows to define some simple device-side rules. It is very limited, but for my task it is enough. Some of the features i been using:

  • Virtual device as variable holder and event loop provider. Every virtual device allow to store up to 4 values and creates own event loop (loop time is set by “Delay” value).
  • Timers, which allows to call user-defined callback on specified timeout (and set a new one if needed)
  • Events from the device (button, temperature sensors, etc). Events can be used in the rules.
  • System startup event to define actions on a startups.
  • Simple (no nested) if/else controls.
  • Many functions which can be called from the code, e.g. to manager GPIO, do HTTP calls, etc.

Below is a ruleset i created. It defines threshold to turn on/off, reports FAN status to the DomoticZ, supports button which turns on ventilator for a 3 minutes even if conditions are not met:

On System#Boot do
  TaskValueSet,3,1,75.00 // temperature on dummy sensor
  TaskValueSet,3,2,70.00 // humidity on dummy sensor
  event FanOff

// main loop
On OnOffValues#HumidityOn do
  If [Temp#Humidity]>[OnOffValues#HumidityOn]
    event FanOn
  If [Temp#Humidity]<[OnOffValues#HumidityOff]
    event FanOffIfNotTimer // workaround for no nestled if

On FanOffIfNotTimer do
  If  [OnOffValues#TimerActive]=0
    event FanOff

// timer button is pressed
On Button#Switch=0.00 do
  If [OnOffValues#FanOn]=0 // do nothing if FAN is already on
    event FanOn
    timerSet,1,180 // turn off in a 3 minutes

// turn off FAN after timer
On Rules#Timer=1 do
   If [Temp#Humidity]<[OnOffValues#HumidityOn] // do not turn off if Humidity is High
     event FanOff

// command to turn on fan
On FanOn do
  TaskValueSet,3,3,1 // FAN is on

// command to turn off fan
On FanOff do
  If [OnOffValues#FanOn]=1
    TaskValueSet,3,3,0 // FAN is off

Additionally i can turn on FAN from the DomoticZ using HTTP call to the http://bath.local/tools?cmd=event+Button%23Switch URL. I used this as “On Action” for the “Push On” button switch. Of course, nice looking visualization is available:
Temperature/Humidity graph


Everything works as it should, however some of the things i would like to improve in the feature:

  • Solution is not secured properly. I am planning to use own SSID for the HA devices to solve this problem, ESP Easy do have password protection, but it is to secure only web access, API calls are still not secured.
  • Thresholds can be easily changed remotely using TaskValueSet command call
  • Should threshold depend on the temperature or it is overkill? How long will DHT21 survive in such wet environment ? Subject to test… Anyway, its cheap.
  • May be MQTT is better compared to DomoticZ HTTP API? Any comments on that?

As always, comments and suggestions are welcome 🙂

Tagged , , , ,

Acmetool utility port for the FreeBSD

I am actively using Lets Encrypt certificates for my private and business projects. Initially i been using official Python client to obtain them, and it was all kind of possible problems. At some point i migrated to the Acmetool client which works perfectly and allows me to maintain hundreds of the certificates with a minimal efforts. This is feature list from the web site:

✅ Zero-downtime autorenewal
✅ Supports any webserver
✅ Fully automatable
✅ Single-file dependency-free binary
✅ Idempotent
✅ Fast setup

Only problem for me was lack of the FreeBSD port – yes, you can grab FreeBSD binaries from the author web site, install them somewhere to the /opt/, but its not a Jedi Path. So i had to create FreeBSD port, which after few months of aging was finally accepted to the tree. There are small changes in the port compared to the author build – paths are FreeBSD-style and builds should be repeatable (i hope, at least). As usual – feel free to send me PR-s, bugreports and suggestions.

Lets Encrypt!

Tagged , , ,