FROGGIT DL5000 Weather Data Logger

Posted on Sun 28 October 2018 in projects

The Data Logger

Froggit DL5000

Some time ago I've bought a Froggit weather data logger with the intention to connect it to my home server. I've chosen this one as it was the cheapest device I came across with an USB port and some sort of Software.

This Device is actually sold by many distributors, I've seen some Amazon listings with the same device and just some other brandname on it. (MISOL, ELV to name a few)

So its totally possible that this will work with other data loggers too.

Powersupply

After some time the original powersupply got a bit flakey and soon died on me.

So the only modification I've done on the device was to route the 5V USB power from the USB port all the way to the other side.

Froggit DL5000 Inside Modification

Now the logger runs from the USB Port, and much more stable than before.

USB Communication

With the OEM Software and with the help of a Windows VM (as the Software supplied with the logger is windows only) and wireshark I was able to sniff the USB traffic and reverse engineer the polling protocol for all the sensors.

The Protocol

The data is queried by sending a block of 64 bytes to the device with the first 4 bytes with the values 0x7b 0x03 0x40 0x7d and the rest 0x00

The logger will answer with 64 bytes of data, with 3 bytes for each sensor connected.

  • The first two bytes (int_16) are the temperature in <Measured Value>*10 as measured by the sensor.
  • The last byte (uint_8) is the relative humidity as measured by the sensor.
  • Unknown or not connected sensors are transmitted with 0xff 0xff 0xff

Connecting it to InfluxDB

With the protocol figured out putting the data to good use is pretty straigt forward.

This will pull the data off the logger and print it as InfluxDB Textdata and can be easily called by Telegraf.

#!/usr/bin/env python

import struct

import sys
import usb.core
import usb.util

data = [0x00] * 64
data[0] = 0x7b
data[1] = 0x03
data[2] = 0x40
data[3] = 0x7d


def main():
        dev = usb.core.find(idVendor=0x0483, idProduct=0x5750)
        dev.reset()
        # was it found?
        if dev is None:
                print('no device found', file=sys.stderr)
                return 1

        for config in dev:
                for i in range(config.bNumInterfaces):
                        if dev.is_kernel_driver_active(i):
                                dev.detach_kernel_driver(i)

        dev.set_configuration()

        # get an endpoint instance
        cfg = dev.get_active_configuration()
        # print(cfg)
        intf = cfg[(0, 0)]

        out = usb.util.find_descriptor(
                intf,
                # match the first OUT endpoint
                custom_match= \
                        lambda e: \
                                usb.util.endpoint_direction(e.bEndpointAddress) == \
                                usb.util.ENDPOINT_OUT)

        in_ = usb.util.find_descriptor(
                intf,
                # match the first OUT endpoint
                custom_match= \
                        lambda e: \
                                usb.util.endpoint_direction(e.bEndpointAddress) == \
                                usb.util.ENDPOINT_IN)

        assert out is not None
        assert in_ is not None
        if out is None or in_ is None:
                print('error initializing device', file=sys.stderr)
                return 1

        out.write(data)
        in_data = in_.read(64)
        for sensor_id in range(0, 8):
                dat = struct.unpack('!hB', in_data[1 + 3 * sensor_id:1 + 3 * (sensor_id + 1)])
                if dat[1] == 255 and dat[0] == 32767:
                        continue
                print('froggit,sensor_id={sensor} temperature={temperature:f},humidity={humidity:d}'.format(
                        sensor=sensor_id,
                        temperature=dat[0] / 10,
                        humidity=dat[1]))

        return 0


if __name__ == '__main__':
        sys.exit(main())