Code Monkey home page Code Monkey logo

weewx-hp3000's Introduction

weewx-hp3000
Copyright 2016 Matthew Wall
Distributed under terms of the GPLv3

This is a driver for weewx that collects data from HP-3000 temperature/humidity
sensors.  The HP-3000 is a small console that receives data wirelessly from up
to 8 temperature/humidity sensors.  It is branded as WS-3000 by Ambient.

Installation

0) install weewx (see the weewx user guide)

1) download the driver

wget -O weewx-hp3000.zip https://github.com/matthewwall/weewx-hp3000/archive/master.zip

2) install the driver

wee_extension --install weewx-hp3000.zip

3) configure the driver

wee_config --reconfigure --driver=user.hp3000

4) start weewx

sudo /etc/init.d/weewx start

weewx-hp3000's People

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

weewx-hp3000's Issues

Inadequate readme

Hi

Problem description:
As a user I can not install the driver by following the installation instructions in the readme file.
The installation instructions are not mentioning that I need to check out the usb branch of weewx and build it.

Advice:
The driver needs to have working installation instructions.

Won't work - Get error No module named weeusb

Thanks a lot for taking the time to make a driver for the HP3000 type of weather station. I just received mine from China, and I am hoping to make it work! However, right now, your driver throws an error!

OS:
Ubuntu 1604
&
Debian 8.9

Weewx version: weewx_3.7.1-1
Weewx package installed: weewx_3.7.1-1_all.deb
Weewx-hp3000 version: Downloaded master on 18.09.2017

Error:
After following your installation instructions to the point; and after configuring, the "SELECT DRIVER" "menu" in wee_config shows error "No module named weeusb"

After saving settings, when having performed "SELECT DRIVER", the error
"ImportError: No module named weeusb"

I have looked online, and cannot find reference to "weeusb" anywhere. Is this a typo?
How can I get your driver to work?

weewx with HP3000 stops with error

Hi Matthew,

First of all thank you very much for you work on the HP3000 driver for weewx. I have purchased a HP3000 branded as Froggit DL5000. The availability of the HP3000 driver for weewx was the main reason for choosing this product.

I am now in the process of installing the software on my home server running Ubuntu 18.04.

I followed the advice given in the other posts and installed posts and installed it from a github clone of weewx using weeusb. I then installed the HP3000 driver and reconfigured weewx as described. So far so good.

If I try to start weewx with "./bin/weewxd weewx.conf"
it starts, but exits with error and following console output:

**Traceback (most recent call last): File "./bin/weewxd", line 64, in <module> weewx.engine.main(options, args) File "/home/weewx/bin/weewx/engine.py", line 871, in main engine.run() File "/home/weewx/bin/weewx/engine.py", line 187, in run for packet in self.console.genLoopPackets(): File "/home/weewx/bin/user/hp3000.py", line 452, in genLoopPackets self._station.send_sequence() File "/home/weewx/bin/user/hp3000.py", line 520, in send_sequence self.send_cmd(0x06) File "/home/weewx/bin/user/hp3000.py", line 517, in send_cmd self.write([0x7b, cmd, 0x40, 0x7d]) File "/home/weewx/bin/user/hp3000.py", line 493, in write return self._write(buf) File "/home/weewx/bin/weeusb/usbhid_pyusb1.py", line 83, in _write timeout=timeout) File "/usr/lib/python2.7/dist-packages/usb/core.py", line 1043, in ctrl_transfer self.__get_timeout(timeout)) File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 883, in ctrl_transfer timeout)) File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 595, in _check raise USBError(_strerror(ret), ret, _libusb_errno[ret]) usb.core.USBError: [Errno 32] Pipe error**

The respective syslog section is:

Jul 25 18:55:28 marvin weewx[6309]: engine: Initializing weewx version 3.8.0 Jul 25 18:55:28 marvin weewx[6309]: engine: Using Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34) #012[GCC 7.3.0] Jul 25 18:55:28 marvin weewx[6309]: engine: Platform Linux-4.15.0-29-generic-x86_64-with-Ubuntu-18.04-bionic Jul 25 18:55:28 marvin weewx[6309]: engine: Locale is 'LC_CTYPE=en_US.UTF-8;LC_NUMERIC=en_GB.UTF-8;LC_TIME=en_GB.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=en_GB.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=en_GB.UTF-8;LC_NAME=en_GB.UTF-8;LC_ADDRESS=en_GB.UTF-8;LC_TELEPHONE=en_GB.UTF-8;LC_MEASUREMENT=en_GB.UTF-8;LC_IDENTIFICATION=en_GB.UTF-8' Jul 25 18:55:28 marvin weewx[6309]: engine: Using configuration file /home/weewx/weewx.conf Jul 25 18:55:28 marvin weewx[6309]: engine: Loading station type HP3000 (user.hp3000) Jul 25 18:55:28 marvin weewx[6309]: hp3000: driver version is 0.6 Jul 25 18:55:28 marvin weewx[6309]: hp3000: usb info: pyusb_version=1.0.0 Jul 25 18:55:28 marvin weewx[6309]: hp3000: sensor map: {'outHumidity': 'h_2', 'extraHumid6': 'h_8', 'extraHumid4': 'h_6', 'extraHumid5': 'h_7', 'extraHumid2': 'h_4', 'extraHumid3': 'h_5', 'extraHumid1': 'h_3', 'extraTemp6': 't_8', 'extraTemp4': 't_6', 'extraTemp5': 't_7', 'extraTemp2': 't_4', 'extraTemp3': 't_5', 'extraTemp1': 't_3', 'outTemp': 't_2', 'inHumidity': 'h_1', 'inTemp': 't_1'} Jul 25 18:55:28 marvin weewx[6309]: usbhid: pyusb_version=1.0.0 Jul 25 18:55:28 marvin weewx[6309]: usbhid: Found USB device with VendorID=0x0483 ProductID=0x5750 Jul 25 18:55:28 marvin weewx[6309]: engine: StdConvert target unit is 0x1 Jul 25 18:55:28 marvin baloo_file.desktop[3562]: UdevQt: unhandled device action "bind" Jul 25 18:55:28 marvin upowerd[2317]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:14.0/usb3/3-14/3-14:1.0 Jul 25 18:55:28 marvin weewx[6309]: wxcalculate: The following values will be calculated: barometer=prefer_hardware, windchill=prefer_hardware, dewpoint=prefer_hardware, appTemp=prefer_hardware, rainRate=prefer_hardware, windrun=prefer_hardware, heatindex=prefer_hardware, maxSolarRad=prefer_hardware, humidex=prefer_hardware, pressure=prefer_hardware, inDewpoint=prefer_hardware, ET=prefer_hardware, altimeter=prefer_hardware, cloudbase=prefer_hardware Jul 25 18:55:28 marvin weewx[6309]: wxcalculate: The following algorithms will be used for calculations: altimeter=aaNOAA, maxSolarRad=RS Jul 25 18:55:28 marvin weewx[6309]: engine: Archive will use data binding wx_binding Jul 25 18:55:28 marvin weewx[6309]: engine: Record generation will be attempted in 'hardware' Jul 25 18:55:28 marvin weewx[6309]: engine: Using archive interval of 300 seconds (specified in weewx configuration) Jul 25 18:55:28 marvin weewx[6309]: manager: Created and initialized table 'archive' in database 'weewx.sdb' Jul 25 18:55:28 marvin weewx[6309]: manager: Created daily summary tables Jul 25 18:55:28 marvin weewx[6309]: engine: Using binding 'wx_binding' to database 'weewx.sdb' Jul 25 18:55:28 marvin weewx[6309]: manager: Starting backfill of daily summaries Jul 25 18:55:28 marvin weewx[6309]: restx: StationRegistry: Registration not requested. Jul 25 18:55:28 marvin weewx[6309]: restx: Wunderground: Posting not enabled. Jul 25 18:55:28 marvin weewx[6309]: restx: PWSweather: Posting not enabled. Jul 25 18:55:28 marvin weewx[6309]: restx: CWOP: Posting not enabled. Jul 25 18:55:28 marvin weewx[6309]: restx: WOW: Posting not enabled. Jul 25 18:55:28 marvin weewx[6309]: restx: AWEKAS: Posting not enabled. Jul 25 18:55:28 marvin weewx[6309]: engine: Starting up weewx version 3.8.0 Jul 25 18:55:28 marvin weewx[6309]: engine: Starting main packet loop. Jul 25 18:55:28 marvin weewx[6309]: engine: Caught unrecoverable exception in engine: Jul 25 18:55:28 marvin weewx[6309]: **** [Errno 32] Pipe error Jul 25 18:55:28 marvin weewx[6309]: **** Traceback (most recent call last): Jul 25 18:55:28 marvin weewx[6309]: **** File "/home/weewx/bin/weewx/engine.py", line 871, in main Jul 25 18:55:28 marvin weewx[6309]: **** engine.run() Jul 25 18:55:28 marvin weewx[6309]: **** File "/home/weewx/bin/weewx/engine.py", line 187, in run Jul 25 18:55:28 marvin baloo_file.desktop[3562]: UdevQt: unhandled device action "unbind" Jul 25 18:55:28 marvin weewx[6309]: **** for packet in self.console.genLoopPackets(): Jul 25 18:55:28 marvin upowerd[2317]: unhandled action 'unbind' on /sys/devices/pci0000:00/0000:00:14.0/usb3/3-14/3-14:1.0 Jul 25 18:55:28 marvin weewx[6309]: **** File "/home/weewx/bin/user/hp3000.py", line 452, in genLoopPackets Jul 25 18:55:28 marvin weewx[6309]: **** self._station.send_sequence() Jul 25 18:55:28 marvin weewx[6309]: **** File "/home/weewx/bin/user/hp3000.py", line 520, in send_sequence Jul 25 18:55:28 marvin weewx[6309]: **** self.send_cmd(0x06) Jul 25 18:55:28 marvin weewx[6309]: **** File "/home/weewx/bin/user/hp3000.py", line 517, in send_cmd Jul 25 18:55:28 marvin weewx[6309]: **** self.write([0x7b, cmd, 0x40, 0x7d]) Jul 25 18:55:28 marvin weewx[6309]: **** File "/home/weewx/bin/user/hp3000.py", line 493, in write Jul 25 18:55:28 marvin weewx[6309]: **** return self._write(buf) Jul 25 18:55:28 marvin weewx[6309]: **** File "/home/weewx/bin/weeusb/usbhid_pyusb1.py", line 83, in _write Jul 25 18:55:28 marvin weewx[6309]: **** timeout=timeout) Jul 25 18:55:28 marvin weewx[6309]: **** File "/usr/lib/python2.7/dist-packages/usb/core.py", line 1043, in ctrl_transfer Jul 25 18:55:28 marvin weewx[6309]: **** self.__get_timeout(timeout)) Jul 25 18:55:28 marvin weewx[6309]: **** File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 883, in ctrl_transfer Jul 25 18:55:28 marvin weewx[6309]: **** timeout)) Jul 25 18:55:28 marvin weewx[6309]: **** File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 595, in _check Jul 25 18:55:28 marvin weewx[6309]: **** raise USBError(_strerror(ret), ret, _libusb_errno[ret]) Jul 25 18:55:28 marvin weewx[6309]: **** USBError: [Errno 32] Pipe error Jul 25 18:55:28 marvin weewx[6309]: **** Exiting.

As it states "usbhid: Found USB device with VendorID=0x0483 ProductID=0x5750"
I guess it has recognized the device plugged into a USB port.

But then it somehow breaks and I have no idea why and how to continue from here.
Can you give me hint what I can try to make it work?

best regards, Joerg

USBError with HP3000 on RaspberryPi 3

I was about to go through the tedious process of decoding packets when I came across this driver. It is really great you went through the effort to make a driver for the WS-3000 weather station, thank you!

Anyways, it looks like everything installed correctly as it starts up with no issues and finds my device. However, when it starts the main packet loop, I get an USB error when the program tries to send a message. I have embedded programming experience but when it comes to Linux/Raspbian I usually have to google my way through for answers. I am sure I am not setting up something correctly ( I usually find it to be permissions related) or not doing something simple but I have not been able to figure it out yet. I was hoping you may be able to help me? Below is the log when I start weewx, let me know if you need anything else. Thank you in advance.

Nov 30 13:05:42 raspberrypi systemd[1]: Starting LSB: weewx weather system...
Nov 30 13:05:42 raspberrypi weewx[1418]: engine: Initializing weewx version 3.8.0a2
Nov 30 13:05:42 raspberrypi weewx[1418]: engine: Using Python 2.7.9 (default, Sep 17 2016, 20:26:04]
Nov 30 13:05:42 raspberrypi weewx[1418]: engine: Platform Linux-4.9.35-v7+-armv7l-with-debian-8.0
Nov 30 13:05:42 raspberrypi weewx[1418]: engine: Locale is 'en_GB.UTF-8'
Nov 30 13:05:42 raspberrypi weewx[1418]: engine: pid file is /var/run/weewx.pid
Nov 30 13:05:42 raspberrypi weewx[1422]: engine: Using configuration file /home/weewx/weewx.conf
Nov 30 13:05:42 raspberrypi weewx[1422]: engine: Loading station type HP3000 (user.hp3000)
Nov 30 13:05:42 raspberrypi weewx[1408]: Starting weewx weather system: weewx.
Nov 30 13:05:42 raspberrypi systemd[1]: Started LSB: weewx weather system.
Nov 30 13:05:43 raspberrypi weewx[1422]: hp3000: driver version is 0.5
Nov 30 13:05:43 raspberrypi weewx[1422]: hp3000: usb info: pyusb_version=1.0.2
Nov 30 13:05:43 raspberrypi weewx[1422]: hp3000: sensor map: {'outHumidity': 'h_2', 'extraHumid6': }
Nov 30 13:05:43 raspberrypi weewx[1422]: usbhid: pyusb_version=1.0.2
Nov 30 13:05:43 raspberrypi weewx[1422]: usbhid: Found USB device with VendorID=0x0483 ProductID=0x0
Nov 30 13:05:43 raspberrypi weewx[1422]: engine: StdConvert target unit is 0x1
Nov 30 13:05:43 raspberrypi weewx[1422]: wxcalculate: The following values will be calculated: baroe
Nov 30 13:05:43 raspberrypi weewx[1422]: wxcalculate: The following algorithms will be used for calS
Nov 30 13:05:43 raspberrypi weewx[1422]: engine: Archive will use data binding wx_binding
Nov 30 13:05:43 raspberrypi weewx[1422]: engine: Record generation will be attempted in 'software'
Nov 30 13:05:43 raspberrypi weewx[1422]: engine: Using archive interval of 300 seconds (specified i)
Nov 30 13:05:43 raspberrypi weewx[1422]: engine: Using binding 'wx_binding' to database 'weewx.sdb'
Nov 30 13:05:43 raspberrypi weewx[1422]: manager: Starting backfill of daily summaries
Nov 30 13:05:43 raspberrypi weewx[1422]: restx: StationRegistry: Registration not requested.
Nov 30 13:05:43 raspberrypi weewx[1422]: restx: Wunderground: Posting not enabled.
Nov 30 13:05:43 raspberrypi weewx[1422]: restx: PWSweather: Posting not enabled.
Nov 30 13:05:43 raspberrypi weewx[1422]: restx: CWOP: Posting not enabled.
Nov 30 13:05:43 raspberrypi weewx[1422]: restx: WOW: Posting not enabled.
Nov 30 13:05:43 raspberrypi weewx[1422]: restx: AWEKAS: Posting not enabled.
Nov 30 13:05:43 raspberrypi weewx[1422]: engine: Starting up weewx version 3.8.0a2
Nov 30 13:05:43 raspberrypi weewx[1422]: engine: Starting main packet loop.
Nov 30 13:05:43 raspberrypi weewx[1422]: engine: Caught unrecoverable exception in engine:
Nov 30 13:05:43 raspberrypi weewx[1422]: **** [Errno 32] Pipe error
Nov 30 13:05:43 raspberrypi weewx[1422]: **** Traceback (most recent call last):
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "/home/weewx/bin/weewx/engine.py", line 8n
Nov 30 13:05:43 raspberrypi weewx[1422]: **** engine.run()
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "/home/weewx/bin/weewx/engine.py", line 1n
Nov 30 13:05:43 raspberrypi weewx[1422]: **** for packet in self.console.genLoopPackets():
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "/home/weewx/bin/user/hp3000.py", line 45s
Nov 30 13:05:43 raspberrypi weewx[1422]: **** self._station.send_sequence()
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "/home/weewx/bin/user/hp3000.py", line 51e
Nov 30 13:05:43 raspberrypi weewx[1422]: **** self.send_cmd(0x06)
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "/home/weewx/bin/user/hp3000.py", line 51d
Nov 30 13:05:43 raspberrypi weewx[1422]: **** self.write([0x7b, cmd, 0x40, 0x7d])
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "/home/weewx/bin/user/hp3000.py", line 49e
Nov 30 13:05:43 raspberrypi weewx[1422]: **** return self._write(buf)
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "/home/weewx/bin/weeusb/usbhid_pyusb1.py"e
Nov 30 13:05:43 raspberrypi weewx[1422]: **** timeout=timeout)
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "build/bdist.linux-armv7l/egg/usb/core.pyr
Nov 30 13:05:43 raspberrypi weewx[1422]: **** self.__get_timeout(timeout))
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "build/bdist.linux-armv7l/egg/usb/backendr
Nov 30 13:05:43 raspberrypi weewx[1422]: **** timeout))
Nov 30 13:05:43 raspberrypi weewx[1422]: **** File "build/bdist.linux-armv7l/egg/usb/backendk
Nov 30 13:05:43 raspberrypi weewx[1422]: **** raise USBError(_strerror(ret), ret, libusb)
Nov 30 13:05:43 raspberrypi weewx[1422]: **** USBError: [Errno 32] Pipe error
Nov 30 13:05:43 raspberrypi weewx[1422]: **** Exiting.

Old Raspberry Pi and Timeouts

Tried with the old Raspberry Pi 2 and it works fine. The only issue was when the htmls (and graphics) were updated (after REC), I got "Operation time out" sending/reading USB. After the timeout, the weewx crashed.

I did extend the timeout period to 2000 in all three:
def write(self, buf): def read(self, timeout=2000): def recv(self):

and it is now running rock solid.

When the timeout happened, the USB was unusable until reset.

Small C code to reset USB:
#include <stdio.h> #include <fcntl.h> #include <errno.h> #include <sys/ioctl.h> #include <linux/usbdevice_fs.h> void main(int argc, char **argv) { const char *filename; int fd; filename = argv[1]; fd = open(filename, O_WRONLY); ioctl(fd, USBDEVFS_RESET, 0); close(fd); return; }

The resetTemp.sh looks like this:
#!/bin/sh /root/resetusb lsusb -d 0483:5750 | awk ' { print "/dev/bus/usb/" $2 "/" $4 }' | awk -F':' '{ print $1 }'

And did a custom weewx start script:
`#!/bin/sh

while true
do
echo "Staring WeeWx"
/home/weewx/bin/weewxd /home/weewx/weewx.conf
sleep 2
echo "Resetting USB"
/root/resetTemp.sh
sleep 2
done
`

A.

Bug in the driver (patch inside)

A fellow user has been able to identify a bug in the weewx-hp3000 driver.
This being Open Source, I am attempting to help out here, by collecting all these facts into one but Github issue on a volunteer basis. I really recommend reading the entire mail thread from start to finish, to see how it is going when users are attempting to use the driver (https://www.mail-archive.com/[email protected]/msg09025.html).

Original bug report: https://www.mail-archive.com/[email protected]/msg09025.html

--
Hi again,

I did some more troubleshooting, and I now have the feeling that the driver
isn't doing exactly what it should.

First of all, a disclaimer: I am no developer and I know next to nothing
about the USB protocol, so please don't be too harsh on me if what I am
saying is complete BS.

Now, I wrote a small python script to try to read data from the WS-3000 and
I actually managed to get this working fine. So I can safely confirm that
the problem doesn't come from the hardware or from the host. The setup I am
using is working fine, the issue must be coming from weewx or the HP3000
driver.

According to the output from Wireshark and from what I've read in the
driver's code, I believe that there are two issues:

  1. one is that the driver is sending commands using the 'control' channel.
  2. probably not directly related to the error I am seeing, but I don't
    understand the point of sending all the 0x41, 0x06, 0x08, 0x09, 0x05, 0x03,
    0x04 commands. The only interesting ones are 0x03 (current data) and 0x05
    (calibration, assuming it must be taken into account to get the 'corrected'
    temperature).

You can find the small script I wrote attached. The only problem I have is
that I have to unplug and replug the station between each run, I probably
don't reset everything properly.
You can easily compare the output when sending each of the 0x41, 0x06,
0x08, 0x09, 0x05, 0x03, 0x04 commands, or when sending only 0x03 commands.
By the way, this also means that contrary to what is mentioned in the
driver, the correct way to distinguish between current data and calibration
data is to keep track of which command was sent...

Please let me know if this makes sense or not. I am willing to do any
additional test you need in order to get this working correctly.

Thanks a lot.

Test script : https://www.mail-archive.com/[email protected]/msg09026.html
Wireshark findings:
When I connect the station to a Windows VM, I can successfully read the
data using EasyTemp. So I tried to compare what EasyTemp and weewx are
sending on the USB bus, using wireshark. Unfortunately, although there are
obvious differences, I can't tell what's causing the error.
The two files are attached: https://www.mail-archive.com/[email protected]/msg09001.html

Patched code:

#!/usr/bin/env python
# Copyright 2016 Matthew Wall
# Distributed under the terms of the GNU Public License (GPLv3)

"""
Collect data from the HP-3000 console via USB.

  Ambient Weather WS-3000-X5
  Ambient Weather WS-3000-X3

The HP-3000 supports up to 8 remote temperature/humidity sensors.  The console
has a 3"x4" TFT color display, with graph and room for 5 sensor displays.  The
sensor display regions can cycle through different sensors when more than 5
sensors are connected.

Every configuration option in the console can be modified via software.  These
options includes:

 - archive interval
 - date/time
 - date/time format
 - timezone
 - which sensors should be displayed in the 5 display regions
 - horizontal graph axis scaling
 - vertical graph axis
 - calibration for temperature/humidity from each sensor
 - alarms
 - historical data

Historical data are saved to the (optional) microSD card.  If no card is
installed, no data are retained.

Each sensor has its own display of temperature and humidity.

Each sensor is identified by channel number.  The channel number is set using
DIP switches on each sensor.  The DIP switches also determine which units will
be displayed in each sensor.

There are 4 two-position DIP switches.  DIP 4 determines units: 0=F 1=C
DIP 1-3 determine which of 8 channels is selected.

Each sensor uses 2 AA batteries.  Nominal battery life is 1 year.

The console uses 5V DC from an AC/DC transformer.

Data from sensors are received every 60 seconds.

Dewpoint and heatindex are calculated within the console.

Temperature sensors measure to +/- 2 degree F

Humidity sensors measure to +/- 5 %

Calibrations are applied in the console, so the values received from the
console are calibrated.  Calculations in the console are performed in degree C.

The console has a radio controlled clock.  During RCC reception, no data will
be transmitted.  If no RCC is received, attempt will be made every two hours
until successful.

This driver was developed without any assistance from Ambient Weather (the
vendor) or Fine Offset (the manufacturer).

===============================================================================
Messages from console

The console sends data in 64-byte chunks.  It looks like the console reuses a
buffer, because each message shorter than the previous contains bytes from the
previous message.  The byte sequence 0x40 0x7d indicates end of data within a
buffer.

Many of the console messages correspond with the control messages sent from
the host.

configuration state (30 bytes)
00 7b
01 00 graph type
02 48 graph hours
03 01 time format
04 00 date format
05 00 dst
06 fb timezone
07 01 units
08 00
09 00
0a 00
0b 07 area1
0c 00
0d 00
0e 00
0f 00 area2
10 00
11 00
12 00
13 00 area3
14 00
15 00
16 00
17 00 area4
18 00
19 00
1a 00
1b 00 area5
1c 40
1d 7d

interval (4 bytes)
00 7b
01 05 interval in minutes
02 40
03 7d

unknown (9 bytes)
00 7b
01 01
02 01
03 00
04 00
05 00
06 00
07 40
08 7d

current data (27 bytes)
00 7b
01 00 ch1 temp MSB
02 eb ch1 temp LSB    t1 = (MSB * 256 + LSB) / 10.0
03 25 ch1 hum         h1 = hum
04 7f ch2 temp MSB
05 ff ch2 temp LSB
06 ff ch2 hum
07 7f ch3 temp MSB
08 ff ch3 temp LSB
09 ff ch3 hum
0a 7f ch4 temp MSB
0b ff ch4 temp LSB
0c ff ch4 hum
0d 7f ch5 temp MSB
0e ff ch5 temp LSB
0f ff ch5 hum
10 7f ch6 temp MSB
11 ff ch6 temp LSB
12 ff ch6 hum
13 7f ch7 temp MSB
14 ff ch7 temp LSB
15 ff ch7 hum
16 7f ch8 temp MSB
17 ff ch8 temp LSB
18 ff ch8 hum
19 40
1a 7d

calibration (27 bytes)
00 7b
01 00 ch1 temp MSB
02 00 ch1 temp LSB    tcal1 = (MSB * 256 + LSB) / 10.0
03 00 ch1 hum         hcal1 = hum
04 00 ch2 temp MSB
05 00 ch2 temp LSB
06 00 ch2 hum
07 00 ch3 temp MSB
08 00 ch3 temp LSB
09 00 ch3 hum
0a 00 ch4 temp MSB
0b 00 ch4 temp LSB
0c 00 ch4 hum
0d 00 ch5 temp MSB
0e 00 ch5 temp LSB
0f 00 ch5 hum
10 00 ch6 temp MSB
11 00 ch6 temp LSB
12 00 ch6 hum
13 00 ch7 temp MSB
14 00 ch7 temp LSB
15 00 ch7 hum
16 00 ch8 temp MSB
17 00 ch8 temp LSB
18 00 ch8 hum
19 40
1a 7d

humidity alarm configuration (19 bytes)
00 7b
01 5a ch1 hi    0x5a = 90 %
02 14 ch1 lo    0x14 = 20 %
03 5a ch2 hi
04 14 ch2 lo
05 5a ch3 hi
06 14 ch3 lo
07 5a ch4 hi
08 14 ch4 lo
09 5a ch5 hi
0a 14 ch5 lo
0b 5a ch6 hi
0c 14 ch6 lo
0d 5a ch7 hi
0e 14 ch7 lo
0f 5a ch8 hi
10 14 ch8 lo
1a 40
1b 7d

temperature alarm configuration (35 bytes)
00 7b
01 01 ch1 hi  (0x01*256 + 0x2c) / 10.0 = 30.0 C
02 2c
03 00 ch1 lo  (0x00*256 + 0x64) / 10.0 = 10.0 C
04 64
05 01 ch2 hi
06 2c
07 00 ch2 lo
08 64
09 01 ch3 hi
0a 2c
0b 00 ch3 lo
0c 64
0d 01 ch4 hi
0e 2c
0f 00 ch4 lo
10 64
11 01 ch5 hi
12 2c
13 00 ch5 lo
14 64
15 01 ch6 hi
16 2c
17 00 ch6 lo
18 64
19 01 ch7 hi
1a 2c
1b 00 ch7 lo
1c 64
1d 01 ch8 hi
1e 2c
1f 00 ch8 lo
20 64
21 40
22 7d

===============================================================================
Messages to console

Each command buffer is terminated by the bytes 0x40 0x7d.

The host sends a sequence of what appear to be empty commands, approximately
every 30 seconds:

7b 06 40 7d
7b 08 40 7d
7b 09 40 7d
7b 05 40 7d
7b 03 40 7d
7b 04 40 7d
7b 41 40 7d

Other commands are sent when a specific action is performed in the software:

set configuration command (0x10)
00 7b
01 10
02 00 graph type  0=temperature 1=humidity 2=dewpoint 3=heatindex
03 48 graph hours 0x0c=12H 0x18=24H 0x30=48H 48=72H
04 00 time format 0='h:mm:ss' 1='am h:mm:ss' 2='h:mm:ss am'
05 00 date format 0='dd-mm-yyyy' 1='mm-dd-yyyy' 2='yyyy-mm-dd'
06 00 dst         0=off 1=on
07 fb timezone    0xNN - 0x100 if (0xNN & 0xf0 == 0xf0) else 0xNN
08 00 units       1=F 0=C
09 00
0a 00
0b 00
0c 07 area1 01=temp 02=dew 03=temp/dew 07=temp/dew/heat
0d 00
0e 00
0f 00
10 08 area2 08=temp 20=heat 38=temp/dew/heat  (3f=1+2=temp/dew/heat ?)
11 00
12 00
13 00
14 00 area3?
15 00
16 00
17 00
18 00 area4?
19 00
1a 00
1b 00
1c 00 area5?
1d 40
1e 7d

set calibration command (0x11)
00 7b
01 11
02 00
03 0a ch1.T  t*10
04 00 ch1.H
05 00
06 14 ch2.T  t*10
07 00 ch2.H
08 00
09 00 ch3.T
0a 00 ch3.H
0b 00
0c 00 ch4.T
0d 00 ch4.H
0e 00
0f 32 ch5.T  t*10
10 00 ch5.H
11 00
12 00 ch6.T
13 00 ch6.H
14 00
15 00 ch7.T
16 00 ch7.H
17 00
18 00 ch8.T
19 00 ch8.H
1a 40
1b 7d

sync time command (0x30)
00 7b
01 30
02 07 year MSB
03 e0 year LSB
04 0c month
05 11 day-of-month
06 00 hour
07 27 minute
08 0c second?
09 06
0a 40
0b 7d

set interval command (0x40)
00 7b
01 40
02 05 interval in minutes (5-240)
03 40
04 7d

"""

# FIXME: set backlight (enable/disable; on time; off time)
# FIXME: re-register sensors
# FIXME: set alarms (temp on/off; hum on/off; hi/lo temps; hi/lo hums)
# FIXME: clear min/max
# FIXME: get min/max values
# FIXME: verify encoding of negative temperature values
# FIXME: verify encoding of negative timezone offsets

from __future__ import with_statement
import syslog
import time

import weeusb
import weewx.drivers

DRIVER_NAME = 'HP3000'
DRIVER_VERSION = '0.6'

def loader(config_dict, _):
    return HP3000Driver(**config_dict[DRIVER_NAME])

def confeditor_loader():
    return HP3000ConfigurationEditor()


def logmsg(level, msg):
    syslog.syslog(level, 'hp3000: %s' % msg)

def logdbg(msg):
    logmsg(syslog.LOG_DEBUG, msg)

def loginf(msg):
    logmsg(syslog.LOG_INFO, msg)

def logerr(msg):
    logmsg(syslog.LOG_ERR, msg)


def _fmt(buf):
    if buf:
        return "%s (len=%s)" % (' '.join(["%02x" % x for x in buf]), len(buf))
    return ''


class HP3000ConfigurationEditor(weewx.drivers.AbstractConfEditor):
    @property
    def default_stanza(self):
        return """
[HP3000]
    # This section is for HP-3000 temperature/humidity sensors

    # The model name such as Ambient WS-3000-X5
    model = WS-3000

    # The driver to use
    driver = user.hp3000
"""


class HP3000Driver(weewx.drivers.AbstractDevice):

    DEFAULT_MAP = {
        'inTemp': 't_1',
        'inHumidity': 'h_1',
        'outTemp': 't_2',
        'outHumidity': 'h_2',
        'extraTemp1': 't_3',
        'extraHumid1': 'h_3',
        'extraTemp2': 't_4',
        'extraHumid2': 'h_4',
        'extraTemp3': 't_5',
        'extraHumid3': 'h_5',
        'extraTemp4': 't_6',
        'extraHumid4': 'h_6',
        'extraTemp5': 't_7',
        'extraHumid5': 'h_7',
        'extraTemp6': 't_8',
        'extraHumid6': 'h_8'}

    def __init__(self, **stn_dict):
        loginf('driver version is %s' % DRIVER_VERSION)
        loginf('usb info: %s' % weeusb.USBHID.get_usb_info())
        self._model = stn_dict.get('model', 'HP3000')
        self._max_tries = int(stn_dict.get('max_tries', 5))
        self._retry_wait = int(stn_dict.get('retry_wait', 3))
        self._ping_interval = int(stn_dict.get('ping_interval', 5))
        self._sensor_map = dict(HP3000Driver.DEFAULT_MAP)
        if 'sensor_map' in stn_dict:
            self._sensor_map.update(stn_dict['sensor_map'])
        loginf('sensor map: %s' % self._sensor_map)
        self._station = HP3000Station()
        self._station.open()

    def closePort(self):
        self._station.close()

    @property
    def hardware_name(self):
        return self._model

    def genLoopPackets(self):
        cnt = 0
        last_send = 0
        while cnt < self._max_tries:
            cnt += 1
            try:
                now = time.time()
                if now - last_send > self._ping_interval:
                    self._station.send_sequence()
                    last_send = now
                    raw = self._station.recv()
                    cnt = 0
                    data = HP3000Station.raw_to_pkt(raw)
                    logdbg('data: %s' % data)
                    if data and data.get('type') == 'sensor_values':
                        pkt = self._data_to_packet(data)
                        logdbg('packet: %s' % pkt)
                        yield pkt
                time.sleep(self._ping_interval)
            except weewx.WeeWxIOError, e:
                loginf("Failed attempt %d of %d: %s" %
                       (cnt, self._max_tries, e))
                logdbg("Waiting %d seconds before retry" % self._retry_wait)
                time.sleep(self._retry_wait)
        else:
            msg = "Max retries (%d) exceeded" % self._max_tries
            print msg
            logerr(msg)
            raise weewx.RetriesExceeded(msg)

    def _data_to_packet(self, data):
        # map sensor data to database fields
        pkt = {'dateTime': int(time.time() + 0.5), 'usUnits': weewx.METRICWX}
        for x in self._sensor_map:
            if self._sensor_map[x] in data:
                pkt[x] = data[self._sensor_map[x]]
        return pkt


class HP3000Station(weeusb.USBHID):
    # usb values obtained from 'sudo lsusb -v'
    USB_ENDPOINT_IN = 0x82
    USB_ENDPOINT_OUT = 0x01
    USB_PACKET_SIZE = 0x40 # 64 bytes

    def __init__(self):
        super(HP3000Station, self).__init__(0x0483, 0x5750)

    def write(self, buf):
        logdbg("write: %s" % _fmt(buf))
        return self.dev.write(endpoint=HP3000Station.USB_ENDPOINT_OUT, data=buf, timeout=100)

    def read(self, timeout=100):
        buf = self._read(endpoint_in=HP3000Station.USB_ENDPOINT_IN, sz=HP3000Station.USB_PACKET_SIZE, timeout=timeout)
        if not buf:
            return None
        logdbg("read: %s" % _fmt(buf))
        if len(buf) != 64:
            logdbg('read: bad buffer length: %s != 64' % len(buf))
            return None
        if buf[0] != 0x7b:
            logdbg('read: bad first byte: 0x%02x != 0x7b' % buf[0])
            return None
        idx = None
        for i in range(0, len(buf) - 1):
            if buf[i] == 0x40 and buf[i + 1] == 0x7d:
                idx = i
                break
        if idx is None:
            logdbg('read: no terminating bytes in buffer: %s' % _fmt(buf))
            return None
        return buf[0: idx + 2]

    def send_cmd(self, cmd):
        self.write([0x7b, cmd, 0x40, 0x7d])

    def send_sequence(self):
        #self.send_cmd(0x06)
        #self.send_cmd(0x08)
        #self.send_cmd(0x09)
        #self.send_cmd(0x05)
        self.send_cmd(0x03)
        #self.send_cmd(0x04)
        #self.send_cmd(0x41)

    def recv(self):
        return self.read(timeout=100)

    GRAPH_TYPE = {
        0: 'temperature',
        1: 'humidity',
        2: 'dewpoint',
        3: 'heatindex'}
    TIME_FORMAT = {
        0: 'h:mm:ss',
        1: 'AM h:mm:ss',
        2: 'h:mm:ss AM'}
    DATE_FORMAT = {
        0: 'dd-mm-yyyy',
        1: 'mm-dd-yyyy',
        2: 'yyyy-mm-dd'}
    DST = {
        0: 'off',
        1: 'on'}
    UNITS = {
        0: 'degree_C',
        1: 'degree_F'}

    @staticmethod
    def decode_timezone(x):
        if (x & 0xf0) == 0xf0:
            return x - 0x100
        return x

    @staticmethod
    def raw_to_pkt(buf):
        logdbg("raw: %s" % _fmt(buf))
        pkt = dict()
        if not buf:
            return pkt
        if len(buf) == 4: # archive interval
            pkt['type'] = 'interval'
            pkt['interval'] = buf[1]
        elif len(buf) == 30: # configuration
            pkt['type'] = 'configuration'
            pkt['graph_type'] = HP3000Station.GRAPH_TYPE.get(buf[1])
            pkt['graph_hours'] = buf[2]
            pkt['time_format'] = HP3000Station.TIME_FORMAT.get(buf[3])
            pkt['date_format'] = HP3000Station.DATE_FORMAT.get(buf[4])
            pkt['dst'] = HP3000Station.DST.get(buf[5])
            pkt['timezone'] = HP3000Station.decode_timezone(buf[6])
            pkt['units'] = HP3000Station.UNITS.get(buf[7])
            pkt['area1'] = buf[11]
            pkt['area2'] = buf[15]
            pkt['area3'] = buf[19]
            pkt['area4'] = buf[23]
            pkt['area5'] = buf[27]
        elif len(buf) == 19: # humidity alarm
            pkt['type'] = 'alarm_humidity'
            for ch in range(8):
                idx = 1 + ch * 2
                pkt['hhi_%s' % (ch + 1)] = buf[idx]
                pkt['hlo_%s' % (ch + 1)] = buf[idx + 1]
        elif len(buf) == 35: # temperature alarm
            pkt['type'] = 'alarm_temperature'
            for ch in range(8):
                idx = 1 + ch * 4
                pkt['thi_%s' % (ch + 1)] = (buf[idx] * 256 + buf[idx + 1]) / 10.0
                pkt['tlo_%s' % (ch + 1)] = (buf[idx + 2] * 256 + buf[idx + 3]) / 10.0
        elif len(buf) == 27: # sensor values or sensor calibration
            # there is no way to distinguish between calibration and values.
            # so we assume that none of the sensors have been calibrationed;
            # a buffer with all zeros must thus be a calibration packet.
            if buf[1: -2] == [0] * 24:
                pkt['type'] = 'sensor_calibration'
                for ch in range(8):
                    idx = 1 + ch * 3
                    pkt['tc_%s' % (ch + 1)] = (buf[idx] * 256 + buf[idx + 1]) / 10.0
                    pkt['hc_%s' % (ch + 1)] = buf[idx + 2]
            else:
                pkt['type'] = 'sensor_values'
                for ch in range(8):
                    idx = 1 + ch * 3
                    if buf[idx] != 0x7f and buf[idx + 1] != 0xff:
                        pkt['t_%s' % (ch + 1)] = (buf[idx] * 256 + buf[idx + 1]) / 10.0
                    if buf[idx + 2] != 0xff:
                        pkt['h_%s' % (ch + 1)] = buf[idx + 2]
        else:
            logdbg("unknown data: %s" % _fmt(buf))
        return pkt


# define a main entry point for basic testing of the station.  invoke this as
# follows from the weewx root dir:
#
# PYTHONPATH=bin python bin/user/hp3000.py

if __name__ == '__main__':

    import optparse

    usage = """%prog [options] [--debug] [--help]"""

    syslog.openlog('hp3000', syslog.LOG_PID | syslog.LOG_CONS)
    syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_INFO))
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('--version', action='store_true',
                      help='display driver version')
    parser.add_option('--debug', action='store_true',
                      help='display diagnostic information while running')
    parser.add_option('--test', default='station',
                      help='what to test: station or driver')
    (options, args) = parser.parse_args()

    if options.version:
        print "driver version %s" % DRIVER_VERSION
        exit(1)

    if options.debug:
        syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_DEBUG))

    if options.test == 'driver':
        driver = HP3000Driver()
        try:
            for p in driver.genLoopPackets():
                print p
        finally:
            driver.closePort()
    else:
        with HP3000Station() as s:
            last_ping = 0
            while True:
                try:
                    now = time.time()
                    if now - last_ping > 30:
                        s.send_sequence()
                        last_ping = now
                        raw = s.recv()
                        print "raw: %s" % _fmt(raw)
                        pkt = HP3000Station.raw_to_pkt(raw)
                        print "pkt: %s" % pkt
                except weewx.WeeWxIOError, e:
                    print "fail: %s" % e
                time.sleep(1)

Pipe Error

Hi Matt,

It took some time to get somewhere. I followed instructions from other two tickets, cloned weewx usb branch, ran ./setup.py install. My weewx is located in /home/weewx

Then i followed instructions as per the README. It was still giving weeusb not found. I figured it was something about paths that was missing. I added lines into your driver in the beginning:

import sys
sys.path.append('/home/weewx')
sys.path.append('/home/weewx/bin')

I suppose this should work as well, for some reason it doesn't:
export PYTHONPATH=$PYTHONPATH:/home/weewx/bin:/home/weewx

I haven't coded Python before, so maybe i'm doing something wrong. I have WS-3000-X3 connected through USB datacable to Raspberry Pi. This is the output from syslog when i plug it in:

Feb 3 19:57:49 localhost kernel: [202842.134086] usb 1-1.4: USB disconnect, device number 5
Feb 3 19:57:53 localhost kernel: [202846.264314] usb 1-1.4: new full-speed USB device number 7 using dwc_otg
Feb 3 19:57:53 localhost kernel: [202846.397659] usb 1-1.4: New USB device found, idVendor=0483, idProduct=5750
Feb 3 19:57:53 localhost kernel: [202846.397668] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Feb 3 19:57:53 localhost kernel: [202846.397672] usb 1-1.4: Product: By viewtool
Feb 3 19:57:53 localhost kernel: [202846.397676] usb 1-1.4: Manufacturer: MyUSB_HID
Feb 3 19:57:53 localhost kernel: [202846.397680] usb 1-1.4: SerialNumber: 8C6487D20934
Feb 3 19:57:53 localhost kernel: [202846.400775] hid-generic 0003:0483:5750.0006: hiddev0,hidraw0: USB HID v1.10 Device [MyUSB_HID By viewtool] on usb-3f980000.usb-1.4/input0
Feb 3 19:57:54 localhost mtp-probe: checking bus 1, device 7: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4"
Feb 3 19:57:54 localhost mtp-probe: bus: 1, device: 7 was not an MTP device

When i try to run wee_device, script just dies, i looked at the source, i can't understand why there is no output saying something more than just crickets. I did run wee_config --reconfigure with your driver specified.

pi@raspberrypi:/home/weewx $ ./bin/wee_device 
Using configuration file /home/weewx/weewx.conf
pi@raspberrypi:/home/weewx $ 

When i try to run your script directly it gives me a "pipe error":

pi@raspberrypi:/home/weewx $ sudo PYTHONPATH=bin python bin/user/hp3000.py
Traceback (most recent call last):
  File "./user/hp3000.py", line 663, in <module>
    s.send_sequence()
  File "./user/hp3000.py", line 525, in send_sequence
    self.send_cmd(0x06)
  File "./user/hp3000.py", line 522, in send_cmd
    self.write([0x7b, cmd, 0x40, 0x7d])
  File "./user/hp3000.py", line 498, in write
    return self._write(buf)
  File "/home/weewx/bin/weeusb/usbhid_pyusb1.py", line 83, in _write
    timeout=timeout)
  File "/usr/lib/python2.7/dist-packages/usb/core.py", line 1043, in ctrl_transfer
    self.__get_timeout(timeout))
  File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 883, in ctrl_transfer
    timeout))
  File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 595, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 32] Pipe error

I see that my EP IN and OUT for this device is 0x82 and 0x01 instead of 0x82 and 0x02 that your driver defines inside the script. So i tried adjusting it to 0x01 value, but still got "Pipe Error".

My device shows up as /dev/usb/hiddev1 and here is output from lsusb -v:

Bus 001 Device 007: ID 0483:5750 STMicroelectronics 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0483 STMicroelectronics
  idProduct          0x5750 
  bcdDevice            2.00
  iManufacturer           1 MyUSB_HID
  iProduct                2 By viewtool
  iSerial                 3 8C6487D20934
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           41
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              300mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      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      33
          Report Descriptor: (length is 33)
            Item(Global): Usage Page, data= [ 0x8c ] 140
                            Bar Code Scanner Page (POS)
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Local ): Usage, data= [ 0x03 ] 3
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x00 0xff ] 65280
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x40 ] 64
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x04 ] 4
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x00 0xff ] 65280
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x40 ] 64
            Item(Main  ): Output, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               2
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               2
Device Status:     0x0001
  Self Powered

I run a small boutique Data Center, and i need to get 3 temperature/humidity readings. Outside, inside cold side, and inside hot side. I don't need historical data, just the live numbers. I have those 3 wireless sensors in place, and central piece is reading them fine.

My app that reads data from equipment is written in NodeJS. I was going to just use weewx to write current data to a JSON file at like 30 second interval, and NodeJS app to read the file and take stats along with other data and push to ElasticSearch.

Since you decoded the protocol this device uses, perhaps you would know if there is a way to just read the data directly from the device using something like https://github.com/tessel/node-usb?

I mean that library should allow claiming a USB device and sending commands to specific hw address and receiving temperature data back from it. But even just making it work through weewx would be already a huge help.

Thanks for making this driver btw, i've been breaking my head for days how to get this done, i'm as far along as ordering Rasperry Zero with sensor boards to make custom temperature/humidity devices. But that might be unnecessary work, if only i could get this thing working =))

Cheers.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.