Add support for Arexx Multilogger (#2487)
This commit is contained in:
parent
43758a3836
commit
8fa97e2aa0
5 changed files with 159 additions and 0 deletions
|
@ -349,6 +349,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
|
|||
[261] Geevon TX16-3 outdoor sensor
|
||||
[262] Fine Offset Electronics WH46 air quality sensor
|
||||
[263] Vevor Wireless Weather Station 7-in-1
|
||||
[264] Arexx Multilogger IP-HA90, IP-TH78EXT, TSN-70E
|
||||
|
||||
* Disabled by default, use -R n or a conf file to enable
|
||||
|
||||
|
|
|
@ -490,6 +490,7 @@ convert si
|
|||
protocol 261 # Geevon TX16-3 outdoor sensor
|
||||
protocol 262 # Fine Offset Electronics WH46 air quality sensor
|
||||
protocol 263 # Vevor Wireless Weather Station 7-in-1
|
||||
protocol 264 # Arexx Multilogger IP-HA90, IP-TH78EXT, TSN-70E
|
||||
|
||||
## Flex devices (command line option "-X")
|
||||
|
||||
|
|
|
@ -271,6 +271,7 @@
|
|||
DECL(geevon) \
|
||||
DECL(fineoffset_wh46) \
|
||||
DECL(vevor_7in1) \
|
||||
DECL(arexx_ml) \
|
||||
|
||||
/* Add new decoders here. */
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ add_library(r_433 STATIC
|
|||
devices/ant_antplus.c
|
||||
devices/arad_ms_meter.c
|
||||
devices/archos_tbh.c
|
||||
devices/arexx_ml.c
|
||||
devices/atech_ws308.c
|
||||
devices/auriol_4ld5661.c
|
||||
devices/auriol_aft77b2.c
|
||||
|
|
155
src/devices/arexx_ml.c
Normal file
155
src/devices/arexx_ml.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
/** @file
|
||||
Arexx Multilogger.
|
||||
|
||||
Copyright (C) 2023 Christian W. Zuckschwerdt <zany@triq.net>
|
||||
Protocol analysis by MacH-21, TSN-70E by inonoob.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "decoder.h"
|
||||
|
||||
/**
|
||||
Arexx Multilogger.
|
||||
|
||||
- Arexx IP-HA90 (MCP9808 sensor) s.a. #2388
|
||||
- Arexx IP-TH78EXT
|
||||
- Arexx TSN-70E (Sensirion SHT-10 sensor) s.a. #2482
|
||||
|
||||
The IP-HA90 has a Microchip RFPIC12f675f at 433.92M and a Microchip MCP9808 temperature sensor.
|
||||
The TSN-70E has a Sensirion SHT-10 temperature and humidity and temperature sensor.
|
||||
|
||||
FSK modulated with Manchester encoding, half-bit width is 208 us (2400bps MC).
|
||||
The sensors transmit approx. every 45 seconds alternating Temperature/Humidity.
|
||||
Polarity is inverted (IEEE MC) and the preamble+sync is aaaaaaaa55.
|
||||
|
||||
Integrity check is done using CRC8 using poly=0x31 init=0x00.
|
||||
|
||||
Example raw messages:
|
||||
|
||||
55555555aa f8 71fe fedf f777 5b a4 ff
|
||||
55555555aa f8 71fe fedf f727 80 7f ff
|
||||
55555555aa f8 71fe fedf f6e7 8e 71 ff
|
||||
55555555aa f8 71fe fedf f69f b4 4b ff
|
||||
55555555aa f8 71fe fedf f66f c0 3f ff
|
||||
55555555aa f8 71fe fedf f63f 1b e4 ff
|
||||
55555555aa f8 71fe fedf f61f 38 c7 ff
|
||||
55555555aa f8 71fe fedf f607 67 98 ff
|
||||
55555555aa f8 71fe fedf f5f7 46 b9 ff
|
||||
55555555aa f8 71fe fedf f5d7 65 9a ff
|
||||
55555555aa f8 71fe fedf f5b7 00 ff ff
|
||||
55555555aa f8 71fe fedf f59f e1 1e ff
|
||||
55555555aa fa 15b2 e90f 6c ff faf7 7b1c e3
|
||||
55555555aa fa 14b2 f90e 51 ff faf7 7b1a e41
|
||||
55555555aa fa 14b2 f991 01 ff faf7 7b2a 401
|
||||
55555555aa fa 15b2 e678 0f ff faf7 7bf8 41
|
||||
|
||||
Message format (preamble 5555aa then invert):
|
||||
|
||||
LEN:8h ID:<16h SENS:16h ?:8h8h CHK:8h CHKINV:8h 16x
|
||||
|
||||
Message layout:
|
||||
|
||||
LL IIII SSSS UUUU XX YY
|
||||
|
||||
- L : 8 bit: message length 7 or 5 (including length byte, excluding checksum)
|
||||
- I : 16 bit: ID, little-endian, even number = Temperature
|
||||
- S : 16 bit: raw sensor value
|
||||
- U : 16 bit: optional extra data, unknown
|
||||
- X : 8 bit: CRC, poly 0x31, init 0xc0
|
||||
- Y : 8 bit: inverted CRC check, only IP-HA90
|
||||
|
||||
*/
|
||||
|
||||
static int arexx_ml_decode(r_device *decoder, bitbuffer_t *bitbuffer)
|
||||
{
|
||||
uint8_t const preamble[] = {0xaa, 0xaa, 0x55}; // 24 bits
|
||||
|
||||
if (bitbuffer->num_rows != 1) {
|
||||
return DECODE_ABORT_EARLY; // we expect a single row
|
||||
}
|
||||
if (bitbuffer->bits_per_row[0] < 64 || bitbuffer->bits_per_row[1] > 130) {
|
||||
return DECODE_ABORT_EARLY; // we expect around 88 to 104 bits
|
||||
}
|
||||
bitbuffer_invert(bitbuffer);
|
||||
|
||||
int msg_len = -1;
|
||||
uint8_t b[9]; // allow up to 9 byte messages
|
||||
for (int i = 0; i < bitbuffer->num_rows; ++i) {
|
||||
unsigned pos = bitbuffer_search(bitbuffer, i, 0, preamble, 24);
|
||||
pos += 24;
|
||||
|
||||
if (pos + 64 > bitbuffer->bits_per_row[i])
|
||||
continue; // too short or not found
|
||||
|
||||
bitbuffer_extract_bytes(bitbuffer, i, pos, b, sizeof(b) * 8);
|
||||
msg_len = b[0];
|
||||
break;
|
||||
}
|
||||
if (msg_len <= 0) {
|
||||
decoder_log(decoder, 2, __func__, "Couldn't find preamble");
|
||||
return DECODE_FAIL_SANITY;
|
||||
}
|
||||
|
||||
int chk = crc8le(b, msg_len, 0x31, 0x00);
|
||||
if (chk != b[msg_len]) { // || (chk ^ b[msg_len + 1]) != 0) {
|
||||
decoder_log(decoder, 2, __func__, "CRC fail");
|
||||
return DECODE_FAIL_MIC;
|
||||
}
|
||||
|
||||
// Extract data from buffer
|
||||
int id = (b[2] << 8) | (b[1]); // little-endian
|
||||
int sens_val = (b[3] << 8) | (b[4]); // big-endian?
|
||||
int is_humi = id & 1; // even number: Temperature, odd number: Humidity
|
||||
|
||||
// MCP9808 Ambient Temperature Register "5-4":
|
||||
int temp_alert = (sens_val >> 13) & 7;
|
||||
int temp_raw = (int16_t)(sens_val << 3); // uses sign-extend
|
||||
float temp_c = temp_raw / 128;
|
||||
|
||||
if (msg_len == 5) { // not sure if this is the proper check
|
||||
// SHT10 Temperature
|
||||
temp_c = sens_val * 0.01f - 40.0f; // offset actually varies by Vdd
|
||||
}
|
||||
// SHT10 Humidity
|
||||
float humidity = -2.0468 + 0.0367 * sens_val - 1.5955E-6 * sens_val * sens_val;
|
||||
|
||||
/* clang-format off */
|
||||
data_t *data = data_make(
|
||||
"model", "", DATA_STRING, "Arexx-ML",
|
||||
"id", "ID", DATA_FORMAT, "%04x", DATA_INT, id,
|
||||
"temperature_C", "Temperature", DATA_COND, !is_humi, DATA_FORMAT, "%.2f C", DATA_DOUBLE, temp_c,
|
||||
"temperature_alert", "Alert", DATA_COND, !is_humi, DATA_FORMAT, "%x", DATA_INT, temp_alert,
|
||||
"humidity", "Humidity", DATA_COND, is_humi, DATA_FORMAT, "%.1f %%", DATA_DOUBLE, humidity,
|
||||
"sensor_raw", "Sensor Raw", DATA_FORMAT, "%04x", DATA_INT, sens_val,
|
||||
"mic", "Integrity", DATA_STRING, "CRC",
|
||||
NULL);
|
||||
/* clang-format on */
|
||||
|
||||
decoder_output_data(decoder, data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char const *const arexx_ml_output_fields[] = {
|
||||
"model",
|
||||
"id",
|
||||
"temperature_C",
|
||||
"temperature_alert",
|
||||
"humidity",
|
||||
"sensor_raw",
|
||||
"mic",
|
||||
NULL,
|
||||
};
|
||||
|
||||
r_device const arexx_ml = {
|
||||
.name = "Arexx Multilogger IP-HA90, IP-TH78EXT, TSN-70E",
|
||||
.modulation = FSK_PULSE_MANCHESTER_ZEROBIT,
|
||||
.short_width = 208, // 2400bps MC
|
||||
.long_width = 208, // not used
|
||||
.reset_limit = 450,
|
||||
.decode_fn = &arexx_ml_decode,
|
||||
.fields = arexx_ml_output_fields,
|
||||
};
|
Loading…
Add table
Reference in a new issue