Sunday, June 26, 2011

Hacking Technoline WS 585 weatherstation


Technoline WS 585 is a simple consumer weatherstation offering builtin indoor temperature sensor and outdoor wireless (433MHz) temperature sensor. But as funny extra, it comes with wireless USB dongle which, being attached to computer running special (Windows) software, transmits to the base station weather forecast for next few days as well as extra weather data for today.

There're two problems with that: I prefer my weather forecast site, not one hardcoded by the vendor, and, I don't have constantly running Windows box. Besides, this device is essentially low-resolution wireless LCD (albeit with funny pixel shape), so one may want to show build status or loadavg on it.

So, I wanted to hack a Linux driver for it for a long time. Wider-scope, I wanted to grok USB and hack driver for it for longer time. Few times before I had a look at usbsnoop log of something, It seemed for overwhelming and I didn't really put much effort into it.

So well, I read up USB docs (Usb in a NutShell is a good summarization of the spec), and started to look at USB descriptors and logs with understanding eye.

Here are info and descriptors for WS585 dongle btw:

dmesg:

[1118327.253222] usb 2-1.3: new low speed USB device using ehci_hcd and address 3
[1118327.524340] usbcore: registered new interface driver hiddev
[1118327.527975] input: Tenx Non standard Device as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/2-1.3:1.0/input/input51
[1118327.528162] generic-usb 0003:1130:0202.0001: input,hidraw0: USB HID v1.10 Device [Tenx Non standard Device] on usb-0000:00:1d.0-1.3/input0
[1118327.530011] input: Tenx Non standard Device as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/2-1.3:1.1/input/input52
[1118327.530182] generic-usb 0003:1130:0202.0002: input,hidraw1: USB HID v1.10 Device [Tenx Non standard Device] on usb-0000:00:1d.0-1.3/input1
[1118327.530554] usbcore: registered new interface driver usbhid
[1118327.530557] usbhid: USB HID core driver

lsusb:
Bus 002 Device 003: ID 1130:0202 Tenx Technology, Inc. 

lsusb -v:

Device: ID 1130:0202 Tenx Technology, Inc. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x1130 Tenx Technology, Inc.
  idProduct          0x0202 
  bcdDevice            1.00
  iManufacturer           0 
  iProduct                2 Tenx Non standard Device
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           59
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      41
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              10
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      23
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              10
Device Status:     0x0000
  (Bus Powered)

So, it uses well-known programmable microcontroller chip from Tenx Technology, found in bunch of other devices like USB missile launchers, etc.

By the end of day I had a PyUSB app which implemented the protocol seen in usbsnoop log. It received all the same (way, similar) responses from the chip. But it didn't exhibit external behavior. Specifically, under Windows, LED on the dongle blinks about every 55s (sic, less than whole minute), and right at the same time weather station updates its display. Under Linux with my app, LED never blinks, and no updates are shown on the display. I tried to to adjust my app to use the same delays between requests as seen in the original log, but no avail.

So, I have 2 ideas here: I made some mistake transcribing log into PyUSB calls, or, it's all timing related, and I didn't get the timing right. I tried to capture USB log around the blink, and don't see any request which could make explicit "transmit" request. I have following hypothesis: base station doesn't listen air all the time, it turns on it radio only ~ once a minute. So, dongle at first synchronizes to the base station. Then, it just transmits data at predefined intervals. And control requests from host don't transmit stuff immediately, but put it into buffer for the next transmission.

Is that true or not, hard to tell. But this device is for sure more complicated than other Tenx-based ones due to its wireless and trickle-transmit features.

I've put my current code together with USB logs to git at https://gitorious.org/homeauto/homeauto-devices

1 comment:

Jardo said...

I have similar weather station with probably same usb transmitter. I think 55sec is transmision interval to read temperature sensor. Reading from external sensor connected to win PC is much longer. In manual to my weather station it says that this interval is after start and than after 3hours.
I have wifi router Asus 500g with linux running on it (unoficial olegs firmware with possiblity to add own aplication). Router has 2 usb interfaces, so I had idea of writing own application to run in this router and update weather in weather station.