Tag Archives: hardware

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 , ,

Reading DHT11 temperature sensor on Raspberry Pi under FreeBSD

Connecting sensor to the RPi

DHT-11 is a very cheap temperature/humidity sensor which is commonly used in the IoT devices. It is not very accurate, so for the accurate measurement i would recommend to use DHT21 instead. Anyway, i had DHT-11 in my tool box, so decided to start with it. DHT-11 using very simple 1 wire protocol – host is turning on chip by sending 18ms low signal to the data output and then reading 40 bytes of data. Details about the protocol could be found in the specification. To read data from the chip it should be connected to the power (5v) and gpio pin. I used pin 2 as VCC, 6 as GND and 11 as GPIO (it is GPIO17, see pinout):

FreeBSD support

There is no support for this device out of the box. I found some sample code on the github, see lex/freebsd-gpio-dht11 repository. This code was a good starting point, but soon i found 2 issues with it:

  1. Results are very unreliable, probably due to gpio decoding algorithm.
  2. Checksum is not validated, so sometime values are bogus.

Initially i was thinking to fix this myself, but later found kernel module for this purpose, 1 wire over gpio. This module contains DHT11 kernel driver (gpio_sw) which implements DHT-11 protocol in the kernel space and exporting /dev/sw0 for the userland. Driver compiles on FreeBSD11/ARM without any changes. Use make install to install the driver.

Putting all the things together

  • To specify GPIO pin with a sensor put hint.gpio_sw.0.pin=17 into /boot/loader.conf.
  • I found that gpio_sw.ko needs to be loaded after kernel initialization, or device is not created. So i have added /sbin/kldload gpio_sw.ko to the /etc/rc.local file.
  • To make /dev/sw0 available for the non-root users you should add devfs_system_ruleset="localrules" to the /etc/rc.conf and add into /etc/devfs.rules this section:
add path 'sw0' mode 0644
  • Sample program (test.c) shows non human-readable data, use something like printf("h:%d.%d %%, t:%d.%d C\n",Buf[0],Buf[1],Buf[2],Buf[3]); if you want to get humidity and temperature, e.g.
root@rpi-b:/home/freebsd/gpio_sw # ./test
h:22.0 %, t:12.0 C

That is it, after reboot you should have working /dev/sw0 device.

Solving problems with LUA

Final goal was to add this sensor to the domoticz software. It is using LUA scripting to extend it functionality, e.g. to obtain data from non-supported or non standard devices. So, i decided to read /dev/sw0 from the LUA. I wrote simple test script:

file = io.open ("/dev/sw0", "rb")
out = file:read (5)

However script was always returning nil and i had to use truss tool to understand the problem. This is part of the trace:

open("/dev/sw0",O_RDONLY,0666)             = 3 (0x3)
fstat(3,{ mode=crw-r--r-- ,inode=96,size=0,blksize=4096 }) = 0 (0x0)
ioctl(3,TIOCGETA,0xbfbfe28c)             = 0 (0x0)
read(3,0x2065b000,4096)              ERR#22 'Invalid argument'

As you could see – LUA trying to read 4096 bytes, despite the fact that we specified 4. And driver checks this and returns the error. To fix this i did a small patch to avoid error and make LUA happy:

-- gpio_sw/gpio_sw.c    2014-05-12 11:26:51.000000000 +0000
+++ gpio_sw.mod/gpio_sw.c   2017-01-14 14:10:33.736813000 +0000
@@ -273,9 +273,10 @@
   duprintf("read - start, uio_resid=%i\n", uio->uio_resid);
   struct gpio_sw_softc *sc = cdev->si_drv1 ;
-  if ( uio->uio_resid >= sc->BufSize) return EINVAL ;
+  if ( uio->uio_resid >= sc->BufSize) sc->Len=sc->BufSize-1 ; // to work with buffered IO
+  else sc->Len=uio->uio_resid;
   if ( ! sc->GpioStatus) return ENXIO ;
-  sc->Len = uio->uio_resid ;
   int i = 0 ;
   while ( i < sc->Len)

After modification script works as it should:

[root@rpi-b /home/freebsd]# lua52 test.lua

Now chip is connected to the domoticz and reporting actual temperature/humidity.

Tagged , , ,

ICMP Watchdog in the Ubiquiti Networks devices

About watchdog

I am using wireless devices from the Ubiquiti Networks. Usually everything works fine, but in rare cases of software/hardware bug it would be great to automatically restart device when needed. AirOS provides this functionality, it is called “ping watchdog” and is located in the web interface, “services” tab. However there is no a lot of documentation about how it works, so i decided to research this. Screenshot of the watchdog interface with default values provided below: Screen Shot 2016-07-18 at 08.38.52.

Under the hood

Ubnt AirOS is OpenWRT based OS with ssh enabled, so we can ssh to the device to find how this watchdog works. If ping watchdog is enabled in the web interface you should see something like this in the process list:

/bin/pwdog -d 300 -p 300 -c 3 -m 300 -e /bin/support /tmp/emerg /etc/persistent/emerg.supp emerg 0; reboot -f

This “pwdog” service is a custom busybox applet which is based on busybox ping implementation with modifications to implement watchdog functionality. I been able to find it source code on the github.

So there is detailed description of the pwdog service logic:

  1. On system start it waits -d seconds (300 by default), to allow initialization of the hardware and software. I would not recommend to reduce this value, or you will have a chance that device will never start. In the web interface it is “Startup Delay:” value.
  2. After initial delay it will send ICMP ping to the specified host (last parameter) and will wait -p seconds (300 by default, “Ping Interval:” in the web interface). After this step 2 will be repeated.
  3. If there is no reply -c times (by default – 3) pwdog will run command specified in the -e argument (/bin/support /tmp/emerg /etc/persistent/emerg.supp emerg 0; reboot) or just reboot if it is not specified. In this example watchdog also saves support information. In the web interface you can modify this value using “Failure Count To Reboot.:” parameter.
  4. There is also -m parameter which defines low memory threshold. It is enabled by default and is not configurable via web interface.

Below i tested how it works in the command line, with modified parameters:

XM.v5.6.6# /bin/pwdog -d 1 -p 3 -c 3 -m 300 -e /usr/bin/echo -v
pwdog[993]: pwdog: do_now=0, initial_sleep=1, timeout=3, retry_count=3, low_mem=300 exec=`/usr/bin/echo`
pwdog[993]: PING Watchdog is checking (
pwdog[993]: Missed 1 ping replies in a row.
pwdog[993]: Missed 2 ping replies in a row.
pwdog[993]: Missed 3 ping replies in a row.
pwdog[993]: 4 ping replies missed. Executing `/usr/bin/echo`.


ICMP watchdog in AirOS is not a very smart service and default configuration does not look optimal for me – in fact its enough to miss only 3 ICMP packets to start reboot process. Also it will fire only after 15 (300*3) minutes of the link failure. So i would probably recommend to increase number of counts and decrease ping interval. Also i am thinking about porting apinger to this device, because it provides much more advanced icmp check functionality.

Tagged , , ,

Upgrading TP-Link Archer C7 AC1750 to use with OpenWRT

Why OpenWRT?

One of my home access points is TP-Link Archer C7. I purchased it to get all benefits of the 5Ghz 802.11ac standard for the laptop and 2.4Ghz band for the older devices. However, it was never working for me well:

  • In 5Ghz band Apple devices were working very unstable
  • Sometime i had to reboot router because of wifi stability issues. After reboot it was working until next issue. There are no debug options/logs in the native firmware.
  • Device was spamming network with STP packets and some other data, no way to disable.
  • After upgrading to the new firmware versions i had to reconfigure it completely. And in fact difference between regullary updated versions was minimal
  • Native firmware configurable only via web interface, probably backdoors are included ūüôā

So i decided to reflash it to the OpenWRT and found, that i am “happy” owner of the TP-Link Archer C7v1, with AR1A (v1) variant of QCA9880 chip, not supported in the open source ath10k driver. So there is no way to use 5Ghz with OpenWRT at all. Only good thing that 5Ghz chip is not soldered on the board, but connected to the PCIe mini card socket. So i decided to replace it.

Router upgrade

  • I been able to find on the eBay Compex WLE900VX Atheros QCA9880 card. It supports 802.11AC 1.3Gbps 3×3 MIMO 5ghz and is supported by ath10k driver.
  • Before replacing WIFI card you should install OpenWRT or device wont boot at all. I used OpenWRT CC 15.05 for the Archer C7 V1.X, upgrade was done via web interface
  • After OpenWRT is up and running – turn off device and replace WiFi card. Be careful with pigtails, it is very easy to damage them.
  • OpenWRT recognized this card without any additional packages and now working well. You may also want to use alternate firmware from Candela Technologies, there are some reports that it works better then one from vendor.


  • Hardware NAT is not supported. I am not using NAT on it, so i dont really care. Probably on speeds up to 300Mbit it does not matter.
  • Device has only 8Mb of flash. It is enough for the OpenWRT installation (including Luci). There are also 2 USB2 ports, so its easy to extend storage size if needed.


So far everything works great. It is too early to say if stability issues are gone or not, but at least i am now able to do full debug and tuning if needed. I am planning to benchmark router later.

Tagged , ,

How to access Integrated Management Module on IBM System x3650 M3 server under FreeBSD

IBM System x3650 M3 server provides nice looking Integrated Management Module (IMM) GUI/CLI which can be accessed remotely (using dedicated network interface) or directly from host. In this short article I will describe how to do this from FreeBSD host machine.All tests were done with FreeBSD 10.1-RELEASE-p6 using GENERIC kernel.

  1. We will need to find virtual network card provided by IMM (RNDISCDC ETHER IBM):
    root@host /root]# usbconfig
    ugen0.1: <UHCI root HUB Intel> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=SAVE (0mA)
    ugen2.1: <EHCI root HUB Intel> at usbus2, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
    ugen1.1: <UHCI root HUB Intel> at usbus1, cfg=0 md=HOST spd=FULL (12Mbps) pwr=SAVE (0mA)
    ugen4.1: <UHCI root HUB Intel> at usbus4, cfg=0 md=HOST spd=FULL (12Mbps) pwr=SAVE (0mA)
    ugen3.1: <UHCI root HUB Intel> at usbus3, cfg=0 md=HOST spd=FULL (12Mbps) pwr=SAVE (0mA)
    ugen6.1: <EHCI root HUB Intel> at usbus6, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
    ugen5.1: <UHCI root HUB Intel> at usbus5, cfg=0 md=HOST spd=FULL (12Mbps) pwr=SAVE (0mA)
    ugen3.2: <RNDISCDC ETHER IBM> at usbus3, cfg=1 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
    In our case it is ugen3.2.
  2. This USB device supports 2 USB configuration – default (and active on boot) – RNDIS or alternate – CDC. FreeBSD works fine with CDC, so we need to switch this USB device to it:
    root@host /root]# usbconfig -d ugen3.2 set_config 1
    After this device should be detected by FreeBSD and dmesg should contain something like this:
    umodem0: at uhub4, port 2, addr 2 (disconnected)
    cdce0: on usbus3
    ue0: on cdce0
    ue0: Ethernet address: e6:1f:13:5e:ab:cd
  3. Now only thing left is to run dhclient on the new network interface:
    [root@host /root]# dhclient ue0
    DHCPREQUEST on ue0 to port 67
    DHCPACK from
    bound to -- renewal in 300 seconds.

    Here we can see that address of the IMM is We can use it to connect with telnet or https to get IMM interface.
  4. Username should be admin, and password could be changed using “ipmitool” utility:
    [root@host /root]# ipmitool user set password 2

Thats it ūüôā Using IMM you can manage your hardware, monitor server and do many other interesting things.

Tagged , , , ,

MCI730 – status and plans

So far I did a big progress with this device, so decided to write some summary post:

  • Source code and root access is obtained, hooray.
  • WIFI bug is kernel related.
  • It is possible to run non-vendor software, but before it will be useful – a lot of R&D needs to be done. CPU is powerful enough to play all popular audio formats.
  • Vendor software is closed source blob without documentation, scripts or SDK. It is unlikely that it would be possible to improve it, e.g. by adding new formats. But it is possible to suspend it and do anything you want with hardware

It is yet unknown how to control FM, CD and sound mixer. Other hardware is pretty standard. I see  some different ways on improving knowledge about hardware:

  1. It is possible to use strace (kernel supports it), but in current strace code there is no support for I2C and SPI ioctl`s. It should be not very hard to add this code to strace.
  2. It would be even easer to add more debug in the kernel itself. Only problem is that we will need to write new kernel to the flash – in case of problems we will get a dead device. It should be much safer if I will be able to get serial data to control uboot. Also it should be possible to get kernel from tftp then to avoid any risks.
  3. To find specification on the used chips. I don`t think that it will help a lot without full schematic, but it may help to 1. and 2.

For me primary goal is to have some “magic” button sequence causing switching to my software (and back). It also interesting to find some easy-to-program frame buffer interface (something like curses “dialog”) to simplify this task.

Currently I do not have a lot of time to continue this efforts, so if you owner of such device and want to join to development – please drop me a note.

Tagged , , , ,

MCI730 Linux status update

After getting root access i was able to do a lot of interesting tricks with my sound system. Some of them:

  • I was able to compile and run mplayer and mpg123. Mplayer perfectly plays audio in all known formats. It also able to play from remote streams, seems to be more reliable then player software. CPU seems to be to slow to play video (running at 150Mhz).
  • Sound interface is OSS, but mixer is controlled not (or at least not only) with /dev/mixer, so it is not yet known how to control volume.
  • Mount my NAS music folder by NFS. It is also possible to browse it and play files from it (supported by firmware formats only). With mplayer it possible to play any format. Tried FLAC, MP3 and WAVPACK without any issues.
  • Player software is keeping /dev/dsp open only while playing, so it is possible to use it without unloading it.
  • WIFI problem caused by buggy WIFI driver. After some time device may hang completely. Currently i completely disabled internal WIFI by unloading driver.
  • In the “Sleep” mode (when clocks are displayed) device is not really sleeping – Linux is functioning as usual.
  • Its possible to record from FM Radio (!) to the file, by reading /dev/dsp. I tried with¬† “/dev/dsp > /tmp/sda1/nfs/123/out.raw” and then reading this file on desktop with aplay -f dat¬† /nfs/out.raw and it works fine (Signed 16 bit Little Endian, Rate 48000 Hz, Stereo)

And a lot of other interesting findings. I will do¬† “rooting device” post a little later. Now, to consolidate all knowledge and to share Philips GPL code i created SourceForge project.

Tagged , , , , ,

MCI 730 – got root access!

Finally was able to get the root. It was done via “fake” update from USB + some modifications on the configuration partition. I will post more details and root package later. Now some output:

# uname -a
Linux (none) 2.6.10_dev-VT8610 #295 Wed Oct 13 11:48:35 CST 2010 armv5tejl unknow

# cat /proc/cpuinfo
Processor       : ARM926EJ-Sid(wb) rev 5 (v5l)
BogoMIPS        : 151.60
Features        : swp half thumb fastmult edsp java
CPU implementer : 0x41
CPU architecture: 5TEJ

# cat /proc/meminfo
MemTotal:       110868 kB
MemFree:         56164 kB

# cat /proc/mtd
dev: size erasesize name
mtd0: 00c50000 00010000 "filesystem"
mtd1: 00280000 00010000 "mini_filesystem"
mtd2: 00180000 00010000 "mini_kernel"
mtd3: 00400000 00010000 "font_lib"
mtd4: 00050000 00010000 "sysconf"
mtd5: 00170000 00010000 "kernel"
mtd6: 00180000 00010000 "wifi"
mtd7: 00010000 00010000 "ECD_key"
mtd8: 00030000 00010000 "uboot"
mtd9: 00010000 00010000 "uboot var1"
mtd10: 00010000 00010000 "uboot var2"
mtd11: 00010000 00010000 "vload"

Continue reading

Tagged , , , , ,

Updates on Philips MCI 730

I finally was able to get source code package from Philips. Initially my request (via support) was denied. Then i sent message to the open.source@philips.com and finally got source tar. It contains a lot of interesting, including user interface binaries and kernel source/tool-chain. Currently i am far from my home, but soon will return and will try to root this device. The package also contains some scripts to create firmware update package and uboot source code. Firmware is based on MontaVista Linux 4.0 with 2.6.10 kernel. I think it should be possible to get root access without serial console. Stay tuned ūüôā

Tagged , , , , , ,

Philips MCI730 hacking – preparation

I am owner of the Philips MCI730 device. It runs Linux inside and has WIFI and Ethernet ports. It supports MP3 and Internet Radio. Also device supports UPNP/DLNA, so i am able to listen music directly from my NAS. Device is working mostly fine, but there are some very annoying problems.

  • WIFI works VERY unstable. I tried with 2 different routers. Sometime it just loosing AP. As workaround i am using Ethernet-connected access point in the “Client” mode.
  • No compressed lossless formats are supported. For me it sounds very stupid – there is MP3/WMA support, but no FLAC, wavepack or ape. As workaround my NAS converts lossless files to the LPCM on the fly.
  • No gap-less playback from UPNP device. I think it is limitations of the Firware.
  • Control point is implemented with a lot of bugs.

Despite all this problems i like the device, because it works good with my favorite radio-stations and FM tuner is also very good, i had much more expensive receiver before, but quality of radio was poor (bad reception zone). I think that WIFI problem should be easy-to-fix. Probably software is one-big-blob, so it would not be possible to add more formats. For control point interface probably some telnet-based workaround could be found. Problem is lack of  root access. I tried several options to get root on the device, but no luck so far. Some findings:

  1. There is no web interface. NMAP shows that ports 111/tcp, 1024/tcp and 8888/tcp are open. On 8888 Mediabolic UPNP/DLNA server is running. It is unclear what is on 1024 ports, tcp connection could be established, but it is closed in a short time.
  2. According to NMAP system is running Linux 2.6.X.
  3. I used tcpdump on my router to capture protocol between device and Philips servers. Protocol is HTTP (no TLS) with all data sent in the message body. Data is encrypted somehow.
  4. On USB only FAT formatted drives are detected.
  5. There is no GPL code or firmware sources/binaries on the vendor web site.

So i assume that only way to hack this device is to physically open it.What could be done then:

  • There should be somewhere serial interface, soldered or not.
  • JTAG (likely) or removable flash (unlikely).
  • If CPU is not hidden there will be more chances to find what is running on this box.

I am going to open the box in the nearest time. I found no stickers on the case, so warranty should not be affected. If you have positive experience with hacking this type of the devices – please drop me a comment.

Tagged , , , , ,