Skip to content

Commit

Permalink
Merge branch 'master' into feat-risco_pir_rwx95p
Browse files Browse the repository at this point in the history
  • Loading branch information
ProfBoc75 authored Oct 22, 2024
2 parents 28c6c04 + 322e04f commit d2637e7
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 11 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
[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
[265] Risco 2 Way Agility protocol, Risco PIR/PET Sensor RWX95PA
[265] Rosstech Digital Control Unit DCU-706/Sundance/Jacuzzi
[266] Risco 2 Way Agility protocol, Risco PIR/PET Sensor RWX95PA
* Disabled by default, use -R n or a conf file to enable
Expand Down
3 changes: 2 additions & 1 deletion conf/rtl_433.example.conf
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,8 @@ convert si
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
protocol 265 # Risco 2 Way Agility protocol, Risco PIR/PET Sensor RWX95PA
protocol 265 # Rosstech Digital Control Unit DCU-706/Sundance/Jacuzzi
protocol 266 # Risco 2 Way Agility protocol, Risco PIR/PET Sensor RWX95PA

## Flex devices (command line option "-X")

Expand Down
15 changes: 12 additions & 3 deletions include/bit_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void reflect_nibbles(uint8_t message[], unsigned num_bytes);
/// @param num_bits message length in bits
/// @param dst target buffer for extracted nibbles, at least num_bits/5 size
/// @return number of successfully unstuffed nibbles.
unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
unsigned extract_nibbles_4b1s(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);

/// UART "8n1" (10-to-8) decoder with 1 start bit (0), no parity, 1 stop bit (1), LSB-first bit-order.
///
Expand All @@ -61,7 +61,16 @@ unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned n
/// @param num_bits message length in bits
/// @param dst target buffer for extracted bytes, at least num_bits/10 size
/// @return number of successful decoded bytes
unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
unsigned extract_bytes_uart(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);

/// UART "8o1" (11-to-8) decoder with 1 start bit (1), odd parity, 1 stop bit (0), MSB-first bit-order.
///
/// @param message bytes of message data
/// @param offset_bits start offset of message in bits
/// @param num_bits message length in bits
/// @param dst target buffer for extracted bytes, at least num_bits/11 size
/// @return number of successful decoded bytes
unsigned extract_bytes_uart_parity(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);

/// Decode symbols to bits.
///
Expand All @@ -73,7 +82,7 @@ unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num
/// @param sync symbol for sync bit, ignored at start, terminates at end
/// @param dst target buffer for extracted bits, at least num_bits/symbol_x_len size
/// @return number of successful decoded bits
unsigned extract_bits_symbols(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint32_t zero, uint32_t one, uint32_t sync, uint8_t *dst);
unsigned extract_bits_symbols(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint32_t zero, uint32_t one, uint32_t sync, uint8_t *dst);

/// CRC-4.
///
Expand Down
1 change: 1 addition & 0 deletions include/rtl_433_devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@
DECL(fineoffset_wh46) \
DECL(vevor_7in1) \
DECL(arexx_ml) \
DECL(rosstech_dcu706) \
DECL(risco_agility) \

/* Add new decoders here. */
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ add_library(r_433 STATIC
devices/rftech.c
devices/risco_agility.c
devices/rojaflex.c
devices/rosstech_dcu706.c
devices/rubicson.c
devices/rubicson_48659.c
devices/rubicson_pool_48942.c
Expand Down
42 changes: 37 additions & 5 deletions src/bit_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ uint8_t reverse8(uint8_t x)
uint32_t reverse32(uint32_t x)
{
uint32_t ret;
uint8_t* xp = (uint8_t*)&x;
uint8_t const* xp = (uint8_t*)&x;
ret = (uint32_t) reverse8(xp[0]) << 24 | reverse8(xp[1]) << 16 | reverse8(xp[2]) << 8 | reverse8(xp[3]);
return ret;
}
Expand All @@ -52,7 +52,7 @@ void reflect_nibbles(uint8_t message[], unsigned num_bytes)
}
}

unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
unsigned extract_nibbles_4b1s(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
{
unsigned ret = 0;

Expand All @@ -70,7 +70,7 @@ unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned n
return ret;
}

unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
unsigned extract_bytes_uart(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
{
unsigned ret = 0;

Expand All @@ -97,7 +97,39 @@ unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num
return ret;
}

static unsigned symbol_match(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint32_t symbol)
unsigned extract_bytes_uart_parity(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
{
unsigned ret = 0;

while (num_bits >= 11) {
int startb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
offset_bits += 1;
int datab = message[offset_bits / 8];
if (offset_bits % 8) {
datab = (message[offset_bits / 8] << 8) | message[offset_bits / 8 + 1];
datab >>= 8 - (offset_bits % 8);
}
offset_bits += 8;
int parityb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
offset_bits += 1;
int stopb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
offset_bits += 1;
int data_parity = parity8(datab);
if ((startb & 1) != 1)
break; // start-bit error
if ((parityb & 1) != data_parity)
break; // parity-bit error
if ((stopb & 1) != 0)
break; // stop-bit error
*dst++ = (datab & 0xff);
ret += 1;
num_bits -= 11;
}

return ret;
}

static unsigned symbol_match(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint32_t symbol)
{
unsigned symbol_len = symbol & 0x1f;

Expand All @@ -119,7 +151,7 @@ static unsigned symbol_match(uint8_t *message, unsigned offset_bits, unsigned nu
return symbol_len;
}

unsigned extract_bits_symbols(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint32_t zero, uint32_t one, uint32_t sync, uint8_t *dst)
unsigned extract_bits_symbols(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint32_t zero, uint32_t one, uint32_t sync, uint8_t *dst)
{
unsigned zero_len = zero & 0x1f;
unsigned one_len = one & 0x1f;
Expand Down
2 changes: 1 addition & 1 deletion src/devices/acurite.c
Original file line number Diff line number Diff line change
Expand Up @@ -2028,7 +2028,7 @@ r_device const acurite_590tx = {
.short_width = 500, // short gap is 500 us
.long_width = 1500, // long gap is 1500 us
.gap_limit = 2000, // (preceeding) sync gap is 3000 us
.reset_limit = 3500, // no packet gap, sync gap is 500 us
.reset_limit = 3500, // no packet gap, gap before sync is 500 us
.decode_fn = &acurite_590tx_decode,
.fields = acurite_590_output_fields,
};
10 changes: 10 additions & 0 deletions src/devices/oregon_scientific.c
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,16 @@ static int oregon_scientific_v2_1_decode(r_device *decoder, bitbuffer_t *bitbuff
else if (sensor_id == ID_BTHGN129) {
if (validate_os_v2_message(decoder, msg, 92, msg_bits, 19) != 0)
return 0;
// int comfort = msg[7] >> 4;
// char *comfort_str = "Normal";
// if (comfort == 0x4) comfort_str = "Comfortable";
// else if (comfort == 0x8) comfort_str = "Dry";
// else if (comfort == 0xc) comfort_str = "Humid";
// int forecast = msg[9] >> 4;
// char *forecast_str = "Cloudy";
// if (forecast == 0x3) forecast_str = "Rainy";
// else if (forecast == 0x6) forecast_str = "Partly Cloudy";
// else if (forecast == 0xc) forecast_str = "Sunny";
float temp_c = get_os_temperature(msg);
// Pressure is given in hPa. You may need to adjust the offset
// according to your altitude level (600 is a good starting point)
Expand Down
120 changes: 120 additions & 0 deletions src/devices/rosstech_dcu706.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/** @file
Rosstech Digital Control Unit DCU-706/Sundance.
Copyright (C) 2023 suaveolent
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"

/** @fn int rosstech_dcu706_decode(r_device *decoder, bitbuffer_t *bitbuffer)
Rosstech Digital Control Unit DCU-706/Sundance/Jacuzzi.
Supported Models:
Sundance DCU-6560-131, SD-880 Series, PN 6560-131
Jacuzzi DCU-2560-131, Jac-J300/J400 and SD-780 series, PN 6560-132/2560-131
Data coding:
UART 8o1: 11 bits/byte: 1 start bit (1), odd parity, 1 stop bit (0).
Data layout:
SS IIII TT CC
- S: 8 bit sync byte and type of transmission
- I: 16 bit ID
- T: 8 bit temp packet in degrees F
- C: 8 bit Checksum: Count 1s for each bit of each element:
Set bit to 1 if number is even 0 if odd
*/

static int rosstech_dcu706_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
uint8_t const preamble_data_transmission[] = {0xDD, 0x40};
// The Bond command also contains the temperature
uint8_t const preamble_Bond[] = {0xCD, 0x00};
int const preamble_length = 11;

// We need 55 bits
uint8_t msg[7];

if (bitbuffer->num_rows != 1
|| bitbuffer->bits_per_row[0] < 55
|| bitbuffer->bits_per_row[0] > 300) {
decoder_logf(decoder, 2, __func__, "bit_per_row %u out of range", bitbuffer->bits_per_row[0]);
return DECODE_ABORT_EARLY; // Unrecognized data
}

unsigned start_pos = bitbuffer_search(bitbuffer, 0, 0, preamble_data_transmission, preamble_length);

if (start_pos == bitbuffer->bits_per_row[0]) {

start_pos = bitbuffer_search(bitbuffer, 0, 0, preamble_Bond, preamble_length);

if (start_pos == bitbuffer->bits_per_row[0]) {
return DECODE_ABORT_LENGTH;
}
}

if (start_pos + 55 > bitbuffer->bits_per_row[0]) {
return DECODE_ABORT_LENGTH;
}

bitbuffer_extract_bytes(bitbuffer, 0, start_pos, msg, sizeof(msg) * 8);

uint8_t b[5] = {0};
unsigned r = extract_bytes_uart_parity(msg, 0, 55, b);
if (r != 5) {
decoder_logf(decoder, 2, __func__, "UART decoding failed. Got %d of 5 bytes", r);
return DECODE_ABORT_LENGTH;
}

int msg_type = b[0]; // S
int id = (b[1] << 8) | (b[2]); // I
int temp_f = b[3]; // T
int checksum = b[4]; // C

uint8_t calculated = 0xff ^ xor_bytes(b, 4);
if (calculated != checksum) {
decoder_logf(decoder, 2, __func__, "Checksum failed. Expected: %02x, Calculated: %02x", checksum, calculated);
return DECODE_FAIL_MIC;
}

/* clang-format off */
data_t *data = data_make(
"model", "Model", DATA_STRING, "Rosstech-Spa",
"id", "ID", DATA_FORMAT, "%04x", DATA_INT, id,
"msg_type", "Transmission Type", DATA_STRING, msg_type == 0xba ? "Data" : "Bond",
"temperature_F", "Temperature", DATA_FORMAT, "%d F", DATA_INT, temp_f,
"mic", "Integrity", DATA_STRING, "CHECKSUM",
NULL);
/* clang-format on */

decoder_output_data(decoder, data);
return 1;
}

static char const *const output_fields[] = {
"model",
"id",
"msg_type",
"temperature_F",
"mic",
NULL,
};

r_device const rosstech_dcu706 = {
.name = "Rosstech Digital Control Unit DCU-706/Sundance/Jacuzzi",
.modulation = OOK_PULSE_PCM,
.short_width = 200,
.long_width = 200,
.reset_limit = 2000,
.decode_fn = &rosstech_dcu706_decode,
.fields = output_fields,
};
3 changes: 3 additions & 0 deletions src/http_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,9 @@ static void handle_json_stream(struct mg_connection *nc, struct http_message *hm
// curl -D - -d "cmd=report_meta&arg=level" -X POST 'http://127.0.0.1:8433/cmd'
// http :8433/cmd cmd==center_frequency val==868000000'
// http --form POST :8433/cmd cmd=report_meta arg=level val=1
// xh :8433/cmd cmd==center_frequency val==433920123
// xh :8433/cmd cmd==sample_rate val==250000
// xh :8433/cmd cmd==gain arg==10
static void handle_cmd_rpc(struct mg_connection *nc, struct http_message *hm)
{
struct http_server_context *ctx = nc->user_data;
Expand Down

0 comments on commit d2637e7

Please sign in to comment.