Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed typo in method for THPacket #150

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 175 additions & 35 deletions bin/user/sdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def logerr(msg):
logmsg(syslog.LOG_ERR, msg)

DRIVER_NAME = 'SDR'
DRIVER_VERSION = '0.87'
DRIVER_VERSION = '0.93'

# The default command requests json output from every decoder
# Use the -R option to indicate specific decoders
Expand Down Expand Up @@ -171,6 +171,11 @@ def to_F(v):
v = v * 1.8 + 32
return v

def to_C(v):
if v is not None:
v = 5 / 9 * (v - 32)
return v

def to_mph(v):
if v is not None:
v *= 0.621371
Expand All @@ -181,6 +186,10 @@ def to_in(v):
v /= 25.4
return v

def to_v(v):
if v is not None:
v /= 1000
return v

class AsyncReader(threading.Thread):

Expand Down Expand Up @@ -1009,7 +1018,7 @@ def parse_json(obj):
pkt['temperature'] = Packet.get_float(obj, 'temperature_F')
elif 'temperature_C' in obj:
pkt['temperature'] = to_F(Packet.get_float(obj, 'temperature_C'))
return Packet.insert_ids(pkt, Acurite515Packet.__name__)
return Acurite.insert_ids(pkt, Acurite515Packet.__name__)


class AlectoV1TemperaturePacket(Packet):
Expand Down Expand Up @@ -1172,8 +1181,25 @@ def parse_text(ts, payload, lines):
pkt = Packet.add_identifiers(
pkt, sensor_id, CalibeurRF104Packet.__name__)
return pkt
class Cotech367959Packet(Packet):
#{"time" : "2022-03-01 14:11:42", "model" : "Cotech-367959", "id" : 24, "battery_ok" : 1, "temperature_F" : 46.900, "humidity" : 62, "rain_mm" : 18.600, "wind_dir_deg" : 16, "wind_avg_m_s" : 0.600, "wind_max_m_s" : 0.700, "mic" : "CRC"}
IDENTIFIER = "Cotech-367959"


@staticmethod
def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['usUnits'] = weewx.METRIC
sensor_id = obj.get('id')
pkt['battery'] = 0 if obj.get('battery') == 'OK' else 1
pkt['temperature'] = to_C(Packet.get_float(obj, 'temperature_F'))
pkt['humidity'] = Packet.get_float(obj, 'humidity')
pkt['wind_gust'] = Packet.get_float(obj, 'wind_max_m_s')
pkt['wind_speed'] = Packet.get_float(obj, 'wind_avg_m_s')
pkt['wind_dir'] = Packet.get_float(obj, 'wind_dir_deg')
pkt['total_rain'] = Packet.get_float(obj, 'rain_mm')
pkt = Packet.add_identifiers(pkt, sensor_id, Cotech367959Packet.__name__)
return pkt
class EcoWittWH40Packet(Packet):
# This is for a WH40 rain sensor

Expand Down Expand Up @@ -1285,9 +1311,6 @@ class FOWHx080Packet(Packet):
# Month: 25
# Day: 70

# {"time" : "2020-10-13 14:04:48", "model" : "Fine Offset Electronics WH1080/WH3080 Weather Station", "msg_type" : 0, "id" : 14, "battery" : "OK", "temperature_C" : 24.400, "humidity" : 35, "direction_deg" : 225, "speed" : 0.000, "gust" : 0.000, "rain" : 41.400, "mic" : "CRC"}
# todays rtl_433 output
# {"time" : "2020-10-13 14:04:48", "model" : "Fineoffset-WHx080", "subtype" : 0, "id" : 14, "battery_ok" : 1, "temperature_C" : 24.400, "humidity" : 35, "wind_dir_deg" : 225, "wind_avg_km_h" : 0.000, "wind_max_km_h" : 0.000, "rain_mm" : 41.400, "mic" : "CRC"}

# apparently there are different identifiers for the same packet, depending
# on which version of rtl_433 is running. one version has extra spaces,
Expand All @@ -1298,6 +1321,13 @@ class FOWHx080Packet(Packet):
# this assumes rain total is in mm (as of dec 2019)
# this assumes wind speed is kph (as of dec 2019)

# {"time" : "2020-10-13 14:04:48", "model" : "Fine Offset Electronics WH1080/WH3080 Weather Station", "msg_type" : 0, "id" : 14, "battery" : "OK", "temperature_C" : 24.400, "humidity" : 35, "direction_deg" : 225, "speed" : 0.000, "gust" : 0.000, "rain" : 41.400, "mic" : "CRC"}
# todays rtl_433 output
# {"time" : "2020-10-13 14:04:48", "model" : "Fineoffset-WHx080", "subtype" : 0, "id" : 14, "battery_ok" : 1, "temperature_C" : 24.400, "humidity" : 35, "wind_dir_deg" : 225, "wind_avg_km_h" : 0.000, "wind_max_km_h" : 0.000, "rain_mm" : 41.400, "mic" : "CRC"}

#{"time" : "2022-08-17 15:58:42", "model" : "Fineoffset-WHx080", "subtype" : 0, "id" : 14, "battery_ok" : 1, "temperature_C" : 28.100, "humidity" : 36, "wind_dir_deg" : 338, "wind_avg_km_h" : 0.000, "wind_max_km_h" : 1.224, "rain_mm" : 614.400, "mic" : "CRC"}
#{"time" : "2022-08-14 17:22:30", "model" : "Fineoffset-WHx080", "subtype" : 2, "uv_sensor_id" : 225, "uv_status" : "OK", "uv_index" : 1, "lux" : 2223.200, "wm" : 3.255, "mic" : "CRC"}

#IDENTIFIER = "Fine Offset Electronics WH1080 / WH3080 Weather Station"
#IDENTIFIER = "Fine Offset Electronics WH1080/WH3080 Weather Station"
#IDENTIFIER = "Fine Offset Electronics WH1080"
Expand All @@ -1308,30 +1338,28 @@ def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['usUnits'] = weewx.METRIC
# older versions of rlt_433 user 'station_id'
if 'station_id' in obj:
pkt['station_id'] = obj.get('station_id')
# but some newer versions of rtl_433 seem to use 'id'
if 'id' in obj:
msg_type = obj.get('subtype')
pkt['msg_type'] = msg_type

if msg_type == 0:
pkt['station_id'] = obj.get('id')
pkt['msg_type'] = Packet.get_int(obj, 'msg_type')
pkt['msg_type'] = Packet.get_int(obj, 'subtype')
pkt['temperature'] = Packet.get_float(obj, 'temperature_C')
pkt['humidity'] = Packet.get_float(obj, 'humidity')
pkt['wind_dir'] = Packet.get_float(obj, 'wind_dir_deg')
pkt['wind_speed'] = Packet.get_float(obj, 'wind_avg_km_h')
pkt['wind_gust'] = Packet.get_float(obj, 'wind_max_km_h')
rain_total = Packet.get_float(obj, 'rain_mm')
if rain_total is not None:
pkt['rain_total'] = rain_total / 10.0 # convert to cm
pkt['battery'] = 0 if obj.get('battery_ok') == 1 else 1
pkt['signal_type'] = 1 if obj.get('signal_type') == 'WWVB / MSF' else 0
pkt['hours'] = Packet.get_int(obj, 'hours')
pkt['minutes'] = Packet.get_int(obj, 'minutes')
pkt['seconds'] = Packet.get_int(obj, 'seconds')
pkt['year'] = Packet.get_int(obj, 'year')
pkt['month'] = Packet.get_int(obj, 'month')
pkt['day'] = Packet.get_int(obj, 'day')
pkt['battery'] = 0 if obj.get('battery_ok') == 1 else 1
pkt['temperature'] = Packet.get_float(obj, 'temperature_C')
pkt['humidity'] = Packet.get_float(obj, 'humidity')
pkt['wind_dir'] = Packet.get_float(obj, 'wind_dir_deg')
pkt['wind_speed'] = Packet.get_float(obj, 'wind_avg_km_h')
pkt['wind_gust'] = Packet.get_float(obj, 'wind_max_km_h')
rain_total = Packet.get_float(obj, 'rain_mm')
if rain_total is not None:
pkt['rain_total'] = rain_total / 10.0 # convert to cm

if msg_type == 2:
pkt['station_id'] = obj.get('uv_sensor_id')
pkt['uv_status'] = 0 if obj.get('uv_status') == 'OK' else 1
pkt['uv_index'] = Packet.get_float(obj, 'uv_index')
pkt['luminosity'] = Packet.get_float(obj, 'lux')
pkt['radiation'] = Packet.get_float(obj, 'wm')

return FOWHx080Packet.insert_ids(pkt)

@staticmethod
Expand Down Expand Up @@ -1766,17 +1794,19 @@ class FOWH0290Packet(Packet):
# This is for a WH0290 Air Quality Monitor (Ambient Weather PM25)

#{"time" : "@0.084044s", "model" : "Fine Offset Electronics, WH0290", "id" : 204, "pm2_5_ug_m3" : 9, "pm10_0_ug_m3" : 10, "mic" : "CHECKSUM"}
#{"time": "2022-09-08 19:48:38", "model": "Endoffset-WH0290", " id ": 142," battery_ok ": 0.800," pm2_5_ug_m3 ": 2," estimated_pm10_0_ug_m3 ": 2," family ": 65," unknown1 ": 0," mic ":" CRC "}

IDENTIFIER = "Fine Offset Electronics, WH0290"
IDENTIFIER = "Fineoffset-WH0290"

@staticmethod
def parse_json(obj):
pkt = dict()
pkt['usUnits'] = weewx.METRIC
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['station_id'] = obj.get('id')
pkt['battery'] = 0 if Packet.get_int(obj, 'battery_ok') == 1 else 0
pkt['pm2_5_atm'] = Packet.get_float(obj, 'pm2_5_ug_m3')
pkt['pm10_0_atm'] = Packet.get_float(obj, 'pm10_0_ug_m3')
pkt['pm10_0_atm'] = Packet.get_float(obj, 'estimated_pm10_0_ug_m3')
return FOWH0290Packet.insert_ids(pkt)

@staticmethod
Expand Down Expand Up @@ -1810,6 +1840,38 @@ def insert_ids(pkt):
station_id = pkt.pop('station_id', '0000')
return Packet.add_identifiers(pkt, station_id, FOWH31LPacket.__name__)


class FOWS80Packet(Packet):
# This is for a Fine Offset Electronics WS80 weather station

#{"time" : "2022-07-06 21:06:18", "model" : "Fineoffset-WS80", "id" : 589862, "battery_ok" : 1.170, "battery_mV" : 3280, "temperature_C" : 17.700, "humidity" : 67, "wind_dir_deg" : 268, "wind_avg_m_s" : 1.300, "wind_max_m_s" : 1.800, "uvi" : 0.000, "light_lux" : 0.000, "flags" : 170, "mic" : "CRC"}

IDENTIFIER = "Fineoffset-WS80"

@staticmethod
def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['usUnits'] = weewx.METRICWX
pkt['station_id'] = obj.get('id')
pkt['temperature'] = Packet.get_float(obj, 'temperature_C')
pkt['humidity'] = Packet.get_float(obj, 'humidity')
pkt['wind_dir'] = Packet.get_float(obj, 'wind_dir_deg')
pkt['wind_speed'] = Packet.get_float(obj, 'wind_avg_m_s')
pkt['wind_gust'] = Packet.get_float(obj, 'wind_max_m_s')
pkt['rain_total'] = Packet.get_float(obj, 'rainfall_mm')
pkt['uv_index'] = Packet.get_float(obj, 'uvi')
pkt['light'] = Packet.get_float(obj, 'light_lux')
#pkt['battery'] = 0 if obj.get('battery_ok') == 1 else 1
pkt['voltage'] = to_v(Packet.get_float(obj, 'battery_mV'))
return FOWS80Packet.insert_ids(pkt)

@staticmethod
def insert_ids(pkt):
station_id = pkt.pop('station_id', '0000')
return Packet.add_identifiers(pkt, station_id, FOWS80Packet.__name__)


class AuriolHG02832Packet(Packet):
IDENTIFIER = "Auriol-HG02832"

Expand Down Expand Up @@ -1921,7 +1983,7 @@ def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['usUnits'] = weewx.METRIC
pkt['rolling_code'] = obj.get('rc')
pkt['rolling_code'] = obj.get('id')
pkt['channel'] = obj.get('channel')
pkt['temperature'] = Packet.get_float(obj, 'temperature_C')
if 'wind_avg_mi_h' in obj:
Expand Down Expand Up @@ -1969,6 +2031,7 @@ class HidekiRainPacket(Packet):
# {"time" : "2017-01-16 04:38:50", "model" : "HIDEKI Rain sensor", "rc" : 0, "channel" : 4, "battery" : "OK", "rain" : 2622.900}
# {"time" : "2019-11-24 19:13:52", "model" : "HIDEKI Rain sensor", "rc" : 0, "channel" : 4, "battery" : "OK", "rain_mm" : 274.400, "mic" : "CRC"}
# {"time" : "2021-02-07 03:45:10", "model" : "Hideki-Rain", "id" : 0, "channel" : 4, "battery_ok" : 1, "rain_mm" : 1382.500, "mic" : "CRC"}
# {"time" : "2023-11-10 14:42:06", "model" : "Hideki-Rain", "id" : 0, "channel" : 4, "battery_ok" : 1, "rain_mm" : 2255.400, "mic" : "CRC"}

# IDENTIFIER = "HIDEKI Rain sensor"
IDENTIFIER = "Hideki-Rain"
Expand All @@ -1992,7 +2055,7 @@ def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['usUnits'] = weewx.METRIC
pkt['rolling_code'] = obj.get('rc')
pkt['rolling_code'] = obj.get('id')
pkt['channel'] = obj.get('channel')
if 'rain_mm' in obj:
pkt['rain_total'] = Packet.get_float(obj, 'rain_mm')
Expand Down Expand Up @@ -2048,6 +2111,26 @@ def parse_json(obj):
return pkt


class KedsumTHPacket(Packet):
# {"time" : "2022-06-17 00:23:59", "model" : "Kedsum-TH", "id" : 235, "channel" : 1, "battery_ok" : 0, "flags" : 8, "temperature_F" : 59.000, "humidity" : 74, "mic" : "CRC"}

IDENTIFIER = "Kedsum-TH"

@staticmethod
def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['usUnits'] = weewx.US
sensor_id = obj.get('id')
pkt['temperature'] = Packet.get_float(obj, 'temperature_F')
pkt['humidity'] = Packet.get_float(obj, 'humidity')
pkt['battery'] = 0 if obj.get('battery_ok') == 1 else 1
pkt['channel'] = obj.get('channel')
pkt['flags'] = obj.get('flags')
pkt = Packet.add_identifiers(pkt, sensor_id, KedsumTHPacket.__name__)
return pkt


class LaCrosseBreezeProPacket(Packet):
# sample json output from rtl_433
# {"time" : "2020-12-14 22:22:21", "model" : "LaCrosse-BreezePro", "id" : 561556, "seq" : 2, "flags" : 0, "temperature_C" : 19.800, "humidity" : 50, "wind_avg_km_h" : 0.000, "wind_dir_deg" : 262, "mic" : "CRC"}\n']
Expand Down Expand Up @@ -2528,7 +2611,7 @@ class OSTHR228NPacket(Packet):
# Battery: OK
# Temperature: 24.70 C

IDENTIFIER = "Thermo Sensor THR228N"
IDENTIFIER = "Oregon-THR228N"
PARSEINFO = {
'House Code': ['house_code', None, lambda x: int(x)],
'Channel': ['channel', None, lambda x: int(x)],
Expand All @@ -2544,6 +2627,17 @@ def parse_text(ts, payload, lines):
pkt.update(Packet.parse_lines(lines, OSTHR228NPacket.PARSEINFO))
return OS.insert_ids(pkt, OSTHR228NPacket.__name__)

# "time" : "2022-06-07 08:17:09", "model" : "Oregon-THR228N", "id" : 211, "channel" : 1, "battery_ok" : 0, "temperature_C" : -19.900}
@staticmethod
def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['usUnits'] = weewx.METRIC
pkt['house_code'] = obj.get('id')
pkt['channel'] = obj.get('channel')
pkt['battery'] = 0 if obj.get('battery') == 'OK' else 1
pkt['temperature'] = Packet.get_float(obj, 'temperature_C')
return OS.insert_ids(pkt, OSTHR228NPacket.__name__)

class OSUV800Packet(Packet):
# 2017-01-30 22:00:12 : OS : UV800
Expand Down Expand Up @@ -2816,7 +2910,7 @@ def parse_json(obj):
pkt['humidity'] = Packet.get_float(obj, 'humidity')
pkt['battery'] = 0 if obj.get('battery') == 'OK' else 1
pkt['channel'] = obj.get('channel')
pkt = Packet.add_identifiers(pkt, sensor_id, PrologueTHPacket.name)
pkt = Packet.add_identifiers(pkt, sensor_id, PrologueTHPacket.__name__)
return pkt


Expand Down Expand Up @@ -2984,6 +3078,34 @@ def insert_ids(pkt):
return pkt


class Bresser7in1Packet(Packet):
# {"time" : "2023-06-11 17:09:05", "model" : "Bresser-7in1", "id" : 50437, "temperature_C" : 23.500,
# "humidity" : 67, "wind_max_m_s" : 0.000, "wind_avg_m_s" : 0.000, "wind_dir_deg" : 102, "rain_mm" :
# 3.500, "light_klx" : 8.592, "light_lux" : 8592.000, "uv" : 1.000, "battery_ok" : 1, "mic " : "CRC"}
IDENTIFIER = "Bresser-7in1"

@staticmethod
def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['usUnits'] = weewx.METRICWX
pkt['station_id'] = obj.get('id')
pkt['temperature'] = Packet.get_float(obj, 'temperature_C')
pkt['humidity'] = Packet.get_float(obj, 'humidity')
pkt['wind_gust'] = Packet.get_float(obj, 'wind_max_m_s')
pkt['wind_speed'] = Packet.get_float(obj, 'wind_avg_m_s')
pkt['wind_dir'] = Packet.get_float(obj, 'wind_dir_deg')
pkt['rain_total'] = Packet.get_float(obj, 'rain_mm')
pkt['lux'] = Packet.get_int(obj, 'light_lux')
pkt['uv'] = Packet.get_float(obj, 'uv')
pkt['battery'] = 1 if Packet.get_int(obj, 'battery_ok') == 0 else 0
return Bresser7in1Packet.insert_ids(pkt)

@staticmethod
def insert_ids(pkt):
station_id = pkt.pop('station_id', '0000')
pkt = Packet.add_identifiers(pkt, station_id, Bresser7in1Packet.__name__)
return pkt


class BresserProRainGaugePacket(Packet):
Expand Down Expand Up @@ -3070,6 +3192,24 @@ def parse_json(obj):
return Hideki.insert_ids(pkt, TFATwinPlus303049Packet.__name__)


class TFADropPacket(Packet):

# {"time" : "2022-06-19 09:18:57", "model" : "TFA-Drop", "id" : 549565, "battery_ok" : 1, "rain_mm" : 0.000, "mic" : "CHECKSUM"}

IDENTIFIER = "TFA-Drop"

@staticmethod
def parse_json(obj):
pkt = dict()
pkt['dateTime'] = Packet.parse_time(obj.get('time'))
pkt['rain_total'] = Packet.get_float(obj, 'rain_mm')
pkt['usUnits'] = weewx.METRICWX
pkt['battery'] = 0 if obj.get('battery') == 'OK' else 1
sensor_id = pkt.pop('id', '0000')
pkt = Packet.add_identifiers(pkt, sensor_id, TFADropPacket.__name__)
return pkt


class TSFT002Packet(Packet):
# time : 2019-12-22 16:57:58
# model : TS-FT002 Id : 127
Expand Down
31 changes: 31 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
0.93 12nov2023
* change rc to id in Hideki Rain/Wind, thanks to promy (#181)

0.92 12nov2023
* fixed typo in Acurite-515 parse json

0.91 12june2023
* add bresser 7in1 thanks to farmabep (179)

0.90 09sept2022
* cleanup Fineoffset-WH0290 identifier and fields, add battery thanks to
* farmabep (166)

0.90 07jul2022
* add battery voltage for WS80 thanks to fankyy (#153)

0.90 06jul2022
* add json pars section for WS80 thanks to fankyy (#153)

0.90 22jun2022
* add json pars section for Kedsum-TH thanks to user Sar6e (#157)

0.90 20jun2022
* add json pars section for TFA-Drop thanks to user modussiam (#156)

0.89 07jun2022
* add json parse section for Oregon THR228N thanks to user modussiam

0.88 03mar2022
* fixed typo in method for THPacket thanks to olpayras (#149)

0.87 21jan2021
* added support for Acurite515 refrigerator/freezer sensors
* added support for LaCross LTV-R3 rain sensor thanks to srhuston (#145)
Expand Down