• 10 dec 2017: forum version update. In case of issues use this topic.
  • 30 nov 2017: pilight moved servers. In case of issues use this topic.
Hello There, Guest! Login Register


Bresser 3Ch weather sensors
#11
Hi,
any news about, how to use Bresser Weather Station Temeo with pilight?

many thanks
Luk
 
Reply
#12
found the code on Github under github.com/giulio93/Backeng_433mhz_Arduino  

i used the information to write a protocol file and can succefully encode the needed parameter.
Please inform me of any errors you find.

BRESSER TEMEO HYGRO QUADRO - THERMO
3 Thermo- / hygrometer sensors 

01111100 10010000 11111101 11110010 0110             
01111100 <== ID
01111100 1 <==Battery
01111100 10
01111100 1001 <==Channel
01111100 10010000 1111 <== Temperatur in Celsius
01111100 10010000 11111011 1111 <== Celsius/ Fahrenheit Flag
01111100 10010000 11111011 11110010 0110 <== Humidity

protocol sends 72 pulses after one SYNC Pulse like

Code:
1953 479 982 490 984 475 1956 492 982 475 984 489 971 487 986 487
1942 491 1959 490 1957 476 1955 494 1954 493 1940 493 983 491 967 489
1957 493 1941 491 1955 494 1940 492 982 491 967 491 1958 490 969 490
982 490 969 486 1960 491 1942 492

3905
487 979     0
493 1955     1
479 1953     1
494 1954     1
493 1939     1
496 1953     1
494 965     0
492 980     0
502 1934 489 982 491 969 488 1959 491 967 490 985 474 983 490 969
488 1959 490 1960 474 1956 493 1954 493 1941 493 1954 494 965 493 981
490 1944 488 1960 490 1941 492 1954 494 969 489 981 492 1943 489 984
490 968        0
489 1438     1
518 1960     1
475 1956     1

136 4506 952 91 942 155 90 140 190 107 87 177 91 366 378 153 585 253 596 197 843 125 201 89 225 695 159 137 315 555 118 274 365 219 502 871 292 205 1410 261 390 189 313 159 164 286 562 114 2528 1649 2163 5412

pilight_debug:



Tempearature 25,2 / Humidity 35 / Channel 2 / ID 124
Code:
11:38:33.748 ->
11:38:33.748 -> time:        299137 ms
11:38:33.748 -> hardware:    ESPiLight
11:38:33.782 -> pulse:        3
11:38:33.782 -> rawlen:        183
11:38:33.782 -> pulselen:    289
11:38:33.782 ->
11:38:33.782 -> Raw code:
11:38:33.782 -> 1939 494 981 492 966 491 984 474 984 488 1959 476 1955 493 1954 495 1938 494 1955 493 1938 495 981 492 965 492 1956 493 1939 494 1954 494 1953 480 979 494 967 491 1956 492 981 476 984 488 968 491 1955 494 1954 478 3905 503 961 496 1952 495 1938 495 1952 497 1950 483 1950 498 978 479 980 492 1954 479 981 492 965 493 1956 492 964 493 982 491 967 491 985 488 1941 492 1956 493 1938 495 1957 491 1953 479 1955 495 977 481 980 491 1956 478 1953 496 1952 495 1938 496 978 493 965 495 1952 494 966 491 983 490 1420 523 1953 498 1951 241 3042 1385 601 286 356 397 166 316 271 91 179 129 155 106 422 333 115 235 125 103 112 92 100 91 155 150 99 146 134 172 336 129 131 485 372 108 229 138 141 136 82 110 120 189 209 739 289 1087 1761 967 122 254 553 979 406 4606 264 667 9844
Code:
11:39:40.757 -> time:        366135 ms
11:39:40.757 -> hardware:    ESPiLight
11:39:40.757 -> pulse:        3
11:39:40.757 -> rawlen:        181
11:39:40.757 -> pulselen:    159
11:39:40.757 ->
11:39:40.757 -> Raw code:
11:39:40.757 -> 1953 479 982 490 984 475 1956 492 982 475 984 489 971 487 986 487 1942 491 1959 490 1957 476 1955 494 1954 493 1940 493 983 491 967 489 1957 493 1941 491 1955 494 1940 492 982 491 967 491 1958 490 969 490 982 490 969 486 1960 491 1942 492 3905 487 979 493 1955 479 1953 494 1954 493 1939 496 1953 494 965 492 980 502 1934 489 982 491 969 488 1959 491 967 490 985 474 983 490 969 488 1959 490 1960 474 1956 493 1954 493 1941 493 1954 494 965 493 981 490 1944 488 1960 490 1941 492 1954 494 969 489 981 492 1943 489 984 490 968 489 1438 518 1960 475 1956 136 4506 952 91 942 155 90 140 190 107 87 177 91 366 378 153 585 253 596 197 843 125 201 89 225 695 159 137 315 555 118 274 365 219 502 871 292 205 1410 261 390 189 313 159 164 286 562 114 2528 1649 2163 5412

Tempearature 25,3 / Humidity 36 / Channel 3 / ID 136
Code:
11:38:41.796 -> time:                    307174 ms
11:38:41.796 -> hardware:          ESPiLight
11:38:41.796 -> pulse:                  2
11:38:41.796 -> rawlen:                               217
11:38:41.796 -> pulselen:            218
11:38:41.796 ->
11:38:41.796 -> Raw code:
11:38:41.796 -> 974 486 1952 488 1951 489 1952 489 1950 488 1952 502 973 486 973 485 1953 488 988 485 976 483 1954 486 989 484 975 483 3914 482 1952 489 984 491 969 487 974 484 1954 501 974 486 973 485 990 483 1956 485 974 485 1954 487 987 486 978 480 975 485 990 483 977 481 1957 485 1953 487 1953 501 1952 489 1949 490 1952 494 963 490 1953 485 1953 502 1953 488 1950 490 1950 489 972 487 987 485 1954 486 974 485 974 500 1954 486 974 485 976 130 4909 90 156 107 85 126 207 198 149 159 137 95 98 81 154 163 83 278 112 222 99 133 180 127 161 94 84 118 414 407 102 104 104 119 1342 410 295 153 115 290 678 93 246 86 128 108 119 425 389 121 511 781 105 87 579 82 101 134 2619 125 84 115 1481 486 178 555 732 911 932 1603 110 3423 587 624 1055 3043 1692 151 674 110 375 106 110 157 215 132 130 81 139 86 168 97 213 171 256 151 249 129 681 500 393 259 204 2985 274 345 107 140 96 140 120 201 89 148 7426
Code:
11:40:00.752 ->
11:40:00.752 -> time:        386137 ms
11:40:00.752 -> hardware:    ESPiLight
11:40:00.752 -> pulse:        7
11:40:00.752 -> rawlen:        173
11:40:00.752 -> pulselen:    280
11:40:00.787 ->
11:40:00.787 -> Raw code:
11:40:00.787 -> 1954 487 1952 488 1952 503 1950 490 1950 490 969 488 972 501 1938 503 1950 490 1951 489 1950 490 970 489 986 487 1951 489 972 487 973 500 1953 488 972 486 974 485 3912 497 1950 492 969 489 970 487 987 487 1951 490 968 491 987 484 976 483 1955 488 972 499 1955 487 971 486 974 486 990 483 975 485 976 498 1954 487 1953 486 1952 488 1952 487 1952 490 1949 489 986 488 971 488 1951 490 1951 491 1948 489 1951 508 966 487 973 486 1954 485 983 491 974 485 1955 485 989 486 973 134 4314 634 340 1130 152 145 290 501 172 159 167 109 213 182 85 135 81 123 95 108 132 161 102 254 108 127 200 244 184 134 94 1143 310 105 191 147 314 373 125 87 495 124 257 124 813 142 2332 1659 1047 115 1486 414 103 731 392 249 397 224 98 303 9529

my protocol File attached.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "../../core/pilight.h"
#include "../../core/common.h"
#include "../../core/dso.h"
#include "../../core/log.h"
#include "../protocol.h"
#include "../../core/binary.h"
#include "../../core/gc.h"
#include "bresser_3ch.h"


#define NORMAL_REPEATS        0
#define PULSE_MULTIPLIER    13
#define MIN_PULSE_LENGTH    500
#define MAX_PULSE_LENGTH    1900
#define AVG_PULSE_LENGTH    1400

#define RAW_LENGTH        74
#define MIN_RAW_LENGTH        90
#define MAX_RAW_LENGTH        300
#define BIT_LENGTH        36
#define SYNC_LENGTH  3900
#define PULSE_FOOTER_LOW  140
#define PULSE_FOOTER_HIGH  
#define SEP_LENGTH   500
#define BIT1_LENGTH  1900
#define BIT0_LENGTH  950
#define RING_BUFFER_SIZE  256
unsigned int syncIndex1 = 0;  // index of the first sync signal
/*
    bresser sensor protocol
    
    found on httpx://github.com/giulio93/Backeng_433mhz_Arduino

    
*/

typedef struct settings_t {
    double id;
    double channel;
    double temp;
    double humi;
    struct settings_t *next;
} settings_t;

static struct settings_t *settings = NULL;

static bool isSync(unsigned int idx) {
 unsigned long t0 = bre->raw[(idx+bre->rawlen-1)%bre->rawlen ];
 unsigned long t1 = bre->raw[idx];

 // on the temperature sensor, the sync signal
 // is roughtly 4.0ms. Accounting for error
 // it should be within 3.0ms and 5.0ms
 if (t0>(SEP_LENGTH-100) && t0<(SEP_LENGTH+100) &&
   t1>(SYNC_LENGTH-1000) && t1<(SYNC_LENGTH+1000)) {
   return true;
 }
 return false;
}


static int validate(void) {
    
     if(bre->rawlen >= MIN_RAW_LENGTH && bre->rawlen <= MAX_RAW_LENGTH) {
        for(unsigned int x=0;x<bre->rawlen-2;x=(x+1)%bre->rawlen ) {
            //if(bre->raw[x] < MIN_PULSE_LENGTH || bre->raw[x] > MAX_PULSE_LENGTH){return -1;}
            if (isSync(x)) {
                syncIndex1 = (x+1) %bre->rawlen;
                if (bre->rawlen - syncIndex1  >= 74 )
                {
                    return 0;
                }
            }
        }
        
    }
    return -1;
}

static void createMessage(int *binary, int id, int channel, double temperature, double humidity, int battery) {
    int i = 0;
    char binaryCh[BIT_LENGTH];
    bre->message = json_mkobject();
    if(binary != NULL) {
           for(i=0;i<BIT_LENGTH;i++) {
                if(binary[i] == 0) {
                    binaryCh[i] = '0';
                } else {
                    binaryCh[i] = '1';
                }
           }
           binaryCh[BIT_LENGTH] = '\0';
           json_append_member(bre->message, "binary", json_mkstring(binaryCh));
       }
    json_append_member(bre->message, "id", json_mknumber(id, 0));
    json_append_member(bre->message, "channel", json_mknumber(channel +1, 0));
    json_append_member(bre->message, "temperature", json_mknumber(temperature/10, 1));
    json_append_member(bre->message, "humidity", json_mknumber(humidity, 1));
    json_append_member(bre->message, "battery", json_mknumber(battery, 0));
    
    bre->txrpt = NORMAL_REPEATS;
}

static void parseCode(void) {
    int i = 0, c=0, x = 0, binary[BIT_LENGTH];
    int id = 0, battery = 0, channel = 0;;
    double temperature = 0.0, humidity = 0.0;
    double humi_offset = 0.0, temp_offset = 0.0;
    
    if(syncIndex1==0 && bre->rawlen - syncIndex1  >= 74){
        logprintf(LOG_ERR, "bre: parsecode - invalid parameter passed %d", bre->rawlen);
        return;
    }
    
    for(unsigned int i=syncIndex1,c =0; i<syncIndex1+BIT_LENGTH*2; i=(i+2)%bre->rawlen,c++) {
        unsigned long t0 = bre->raw[i], t1 = bre->raw[(i+1)%bre->rawlen];
          if (t0>(SEP_LENGTH-100) && t0<(SEP_LENGTH+100)) {
             //Bit 1 stay up around 1.9ms
            if (t1>(BIT1_LENGTH-100) && t1<(BIT1_LENGTH+100)) {
            
              binary[c] = 1;
            }
            //Bit 1 stay up around 0.95ms
            else if (t1>(BIT0_LENGTH-100) && t1<(BIT0_LENGTH+100)) {
              binary[c] = 0;
            }
            else {
              return;
            }
          }
        
    }
    
    //01110000 10100000 01110110 11110011 0010SYNC  11.8C 50%
   //                           1111 <== Celsius/ Fahrenheit Flag

    id = binToDecRev(binary, 0, 7);
    battery = binary[8];
    channel = binToDecRev(binary, 10, 11);
    temperature = binToSignedRev(binary, 12, 23);
    //01110000 10100000 01110110 11110011 0010SYNC  11.8C 50%
   //                               0011 0010<== Humidity
    humidity = binToDecRev(binary, 28, 35);

    struct settings_t *tmp = settings;
    while(tmp) {
        if(fabs(tmp->id-id) < EPSILON) {
            humi_offset = tmp->humi;
            temp_offset = tmp->temp;
            break;
        }
        tmp = tmp->next;
    }

    temperature += temp_offset;
    humidity += humi_offset;
    createMessage(binary, id, channel, temperature, humidity, battery);
}



static int checkValues(struct JsonNode *jvalues) {
    struct JsonNode *jid = NULL;

    if((jid = json_find_member(jvalues, "id"))) {
        struct settings_t *snode = NULL;
        struct JsonNode *jchild = NULL;
        struct JsonNode *jchild1 = NULL;
        double channel = -1, id = -1;
        int match = 0;

        jchild = json_first_child(jid);
        while(jchild) {
            jchild1 = json_first_child(jchild);
            while(jchild1) {
                    if(strcmp(jchild1->key, "channel") == 0) {
                    channel = jchild1->number_;
                }
                if(strcmp(jchild1->key, "id") == 0) {
                    id = jchild1->number_;
                }
                jchild1 = jchild1->next;
            }
            jchild = jchild->next;
        }

        struct settings_t *tmp = settings;
        while(tmp) {
            if(fabs(tmp->id-id) < EPSILON) {
                match = 1;
                break;
            }
            tmp = tmp->next;
        }

        if(match == 0) {
            if((snode = MALLOC(sizeof(struct settings_t))) == NULL) {
                fprintf(stderr, "out of memory\n");
                exit(EXIT_FAILURE);
            }
            snode->id = id;
            snode->channel = channel;
            snode->temp = 0;
            snode->humi = 0;

            json_find_number(jvalues, "temperature-offset", &snode->temp);
            json_find_number(jvalues, "humidity-offset", &snode->humi);

            snode->next = settings;
            settings = snode;
        }
    }
    return 0;
}



static void gc(void) {
    struct settings_t *tmp = NULL;
    while(settings) {
        tmp = settings;
        settings = settings->next;
        FREE(tmp);
    }
    if(settings != NULL) {
        FREE(settings);
    }
}

#if !defined(MODULE) && !defined(_WIN32)
__attribute__((weak))
#endif
void bresser3chInit(void) {
    protocol_register(&bre);
    protocol_set_id(bre, "bre");
    protocol_device_add(bre, "bre", "bresser Thermo-/Hygro-Sensor 3CH");
    bre->devtype = WEATHER;
    bre->hwtype = RF433;
    bre->txrpt = NORMAL_REPEATS;
    bre->maxgaplen = AVG_PULSE_LENGTH*PULSE_DIV;
    bre->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
    bre->minrawlen = MIN_RAW_LENGTH;
    bre->maxrawlen = MAX_RAW_LENGTH;

    options_add(&bre->options, 't', "temperature", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
    options_add(&bre->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "[0-9]");
    options_add(&bre->options, 'c', "channel", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "[0-9]");
    options_add(&bre->options, 'h', "humidity", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "[0-9]");
    options_add(&bre->options, 'b', "battery", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[01]$");

    options_add(&bre->options, 0, "temperature-offset", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "[0-9]");
    options_add(&bre->options, 0, "humidity-offset", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "[0-9]");
    options_add(&bre->options, 0, "temperature-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)2, "[0-9]");
    options_add(&bre->options, 0, "humidity-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)2, "[0-9]");
    options_add(&bre->options, 0, "show-humidity", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
    options_add(&bre->options, 0, "show-temperature", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
    options_add(&bre->options, 0, "show-battery", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");

    bre->parseCode=&parseCode;
    bre->checkValues=&checkValues;
    bre->validate=&validate;
    bre->gc=&gc;
}

#if defined(MODULE) && !defined(_WIN32)
void compatibility(struct module_t *module) {
    module->name = "bre";
    module->version = "1.0";
    module->reqversion = "6.0";
    module->reqcommit = "84";
}

void init(void) {
    bresser3chInit();
}
#endif
I am a German native speaker 
 
Reply
#13
Super! Can you make this into a PR on github?
 
Reply
#14
(02-14-2019, 10:57 AM)curlymo Wrote: Super! Can you make this into a PR on github?

I will do that.
I am a German native speaker 
 
Reply
  


Possibly Related Threads...
Thread Author Replies Views Last Post
  [Partially Supported] TFA / Conrad Weather Yves 184 7,581 03-31-2019, 05:22 PM
Last Post: curlymo
  Weather Station Globaltronics GT-WT-01 Prutsky 13 6,476 04-09-2018, 07:34 PM
Last Post: NevelS
  1byone Motion Sensors MorfelPi 4 1,432 01-30-2018, 10:42 PM
Last Post: maui
  Weather Underground "wunderground" humidity wimThoelke 6 1,272 10-23-2017, 09:44 PM
Last Post: wimThoelke
  Bresser weatherstation thekk 2 2,027 10-15-2016, 03:07 PM
Last Post: wo_rasp
  Weather Sensor NC-7345-675 OllRo 7 2,840 03-29-2016, 04:01 PM
Last Post: LukaNoah
  RF Wireless no brand Temp Sensors DonBernos 1 2,274 01-07-2016, 06:21 PM
Last Post: DonBernos
  Mebus 06181 weather station stefanroellin 0 1,518 12-27-2015, 06:36 PM
Last Post: stefanroellin
  GPIO Weather koos147 0 1,453 04-01-2015, 08:28 PM
Last Post: koos147
  Weather Underground API gustav... 21 8,739 03-28-2015, 05:46 PM
Last Post: curlymo

Forum Jump:


Browsing: 1 Guest(s)