Added support for rain and wind sensors (Oregon Scientific) in telldus-core

This commit is contained in:
Stefan Persson 2013-09-02 16:28:39 +02:00
parent 668dd99ac2
commit 35028b1c82
6 changed files with 291 additions and 6 deletions

View file

@ -73,6 +73,16 @@
* The sensor can report the temperature.
* @def TELLSTICK_HUMIDITY
* The sensor can report the humidity.
* @def TELLSTICK_RAINRATE
* The sensor can report rain fall rate.
* @def TELLSTICK_RAINTOTAL
* The sensor can report total rain fall.
* @def TELLSTICK_WINDDIRECTION
* The sensor can report wind direction.
* @def TELLSTICK_WINDAVERAGE
* The sensor can report average wind speed.
* @def TELLSTICK_WINDGUST
* The sensor can report gust wind speed.
*
**//* @} */
@ -255,8 +265,10 @@
* @param id
* The unique id for the sensor.
* @param dataType
* The type that @a value is. Can be one of @ref TELLSTICK_TEMPERATURE or
* @ref TELLSTICK_HUMIDITY.
* The type that @a value is. Can be one of @ref TELLSTICK_TEMPERATURE,
* @ref TELLSTICK_HUMIDITY, @ref TELLSTICK_RAINTOTAL,
* @ref TELLSTICK_RAINRATE, @ref TELLSTICK_WINDDIRECTION,
* @ref TELLSTICK_WINDAVERAGE or @ref TELLSTICK_WINDGUST.
* @param value
* A human readable string of the data.
* @param timestamp
@ -1135,8 +1147,10 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen,
* @param[in] id
* The id of the sensor.
* @param[in] dataType
* Which sensor value to retrive (one of @ref TELLSTICK_TEMPERATURE or @ref
* TELLSTICK_HUMIDITY).
* Which sensor value to retrive (one of @ref TELLSTICK_TEMPERATURE,
* @ref TELLSTICK_HUMIDITY, @ref TELLSTICK_RAINTOTAL,
* @ref TELLSTICK_RAINRATE, @ref TELLSTICK_WINDDIRECTION,
* @ref TELLSTICK_WINDAVERAGE or @ref TELLSTICK_WINDGUST.
* @param[out] value
* A by ref string where the value will be placed.
* @param[in] len

View file

@ -118,6 +118,11 @@ extern "C" {
// Sensor value types
#define TELLSTICK_TEMPERATURE 1
#define TELLSTICK_HUMIDITY 2
#define TELLSTICK_RAINRATE 4
#define TELLSTICK_RAINTOTAL 8
#define TELLSTICK_WINDDIRECTION 16
#define TELLSTICK_WINDAVERAGE 32
#define TELLSTICK_WINDGUST 64
// Error codes
#define TELLSTICK_SUCCESS 0

View file

@ -722,6 +722,11 @@ void DeviceManager::handleSensorMessage(const ControllerMessage &msg) {
setSensorValueAndSignal("temp", TELLSTICK_TEMPERATURE, sensor, msg, t);
setSensorValueAndSignal("humidity", TELLSTICK_HUMIDITY, sensor, msg, t);
setSensorValueAndSignal("rainrate", TELLSTICK_RAINRATE, sensor, msg, t);
setSensorValueAndSignal("raintotal", TELLSTICK_RAINTOTAL, sensor, msg, t);
setSensorValueAndSignal("winddirection", TELLSTICK_WINDDIRECTION, sensor, msg, t);
setSensorValueAndSignal("windaverage", TELLSTICK_WINDAVERAGE, sensor, msg, t);
setSensorValueAndSignal("windgust", TELLSTICK_WINDGUST, sensor, msg, t);
}
void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const {

View file

@ -21,6 +21,10 @@ std::string ProtocolOregon::decodeData(const ControllerMessage &dataMsg) {
return decode1A2D(data);
} else if (model.compare(L"0xF824") == 0) {
return decodeF824(data);
} else if (model.compare(L"0x1984") == 0 || model.compare(L"0x1994") == 0) {
return decode1984(data, model);
} else if (model.compare(L"0x2914") == 0) {
return decode2914(data);
}
return "";
@ -73,6 +77,71 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) {
return retString.str();
}
std::string ProtocolOregon::decode1984(const std::string &data, const std::wstring &model) {
//wind
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t crcCheck = value & 0xF; //PROBABLY crc
value >>= 4;
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t avg1 = value & 0xF;
value >>= 4;
uint8_t avg2 = value & 0xF;
value >>= 4;
uint8_t avg3 = value & 0xF;
value >>= 4;
uint8_t gust1 = value & 0xF;
value >>= 4;
uint8_t gust2 = value & 0xF;
value >>= 4;
uint8_t gust3 = value & 0xF;
value >>= 4;
uint8_t unknown1 = value & 0xF;
value >>= 4;
uint8_t unknown2 = value & 0xF;
value >>= 4;
uint8_t direction = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; //PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += unknown1 + unknown2 + avg1 + avg2 + avg3 + gust1 + gust2 + gust3 + direction + battery + channel;
if (model.compare(L"0x1984") == 0) {
checksum += 0x1 + 0x9 + 0x8 + 0x4;
}
else {
checksum += 0x1 + 0x9 + 0x9 + 0x4;
}
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){
//checksum error
return "";
}
double avg = ((avg1 * 100) + (avg2 * 10) + avg3)/10.0;
double gust = ((gust1 * 100) + (gust2 * 10) + gust3)/10.0;
float directiondegree = 22.5 * direction;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:1984;id:" << static_cast<int>(rollingcode)
<< ";winddirection:" << directiondegree
<< ";windaverage:" << std::fixed << std::setprecision(1) << avg
<< ";windgust:" << std::fixed << std::setprecision(1) << gust << ";";
return retString.str();
}
std::string ProtocolOregon::decode1A2D(const std::string &data) {
uint64_t value = TelldusCore::hexTo64l(data);
// checksum2 not used yet
@ -128,6 +197,60 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) {
return retString.str();
}
std::string ProtocolOregon::decode2914(const std::string &data) {
//rain
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t totRain1 = value & 0xF;
value >>= 4;
uint8_t totRain2 = value & 0xF;
value >>= 4;
uint8_t totRain3 = value & 0xF;
value >>= 4;
uint8_t totRain4 = value & 0xF;
value >>= 4;
uint8_t totRain5 = value & 0xF;
value >>= 4;
uint8_t totRain6 = value & 0xF;
value >>= 4;
uint8_t rainRate1 = value & 0xF;
value >>= 4;
uint8_t rainRate2 = value & 0xF;
value >>= 4;
uint8_t rainRate3 = value & 0xF;
value >>= 4;
uint8_t rainRate4 = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; //PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += totRain1 + totRain2 + totRain3 + totRain4 + totRain5 + totRain6 + rainRate1 + rainRate2 + rainRate3 + rainRate4 + battery + channel + 0x2 + 0x9 + 0x1 + 0x4;
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){
//checksum error
return "";
}
double totRain = ((totRain1 * 100000) + (totRain2 * 10000) + (totRain3 * 1000) + (totRain4 * 100) + (totRain5 * 10) + totRain6)/1000.0*25.4;
double rainRate = ((rainRate1 * 1000) + (rainRate2 * 100) + (rainRate3 * 10) + rainRate4)/100.0*25.4;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:2914;id:" << static_cast<int>(rollingcode)
<< ";raintotal:" << std::fixed << std::setprecision(1) << totRain
<< ";rainrate:" << std::fixed << std::setprecision(1) << rainRate << ";";
return retString.str();
}
std::string ProtocolOregon::decodeF824(const std::string &data) {
uint64_t value = TelldusCore::hexTo64l(data);

View file

@ -19,6 +19,8 @@ protected:
static std::string decodeEA4C(const std::string &data);
static std::string decode1A2D(const std::string &data);
static std::string decodeF824(const std::string &data);
static std::string decode1984(const std::string &data, const std::wstring &model);
static std::string decode2914(const std::string &data);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_

View file

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctime>
#include <sstream>
#include "../client/telldus-core.h"
#ifdef _WINDOWS
@ -140,13 +141,27 @@ int list_devices() {
int sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes);
if(sensorStatus == 0){
printf("\n\nSENSORS:\n\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "LAST UPDATED");
printf("\n\nSENSORS:\n\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\t%-20s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "RAIN", "WIND", "LAST UPDATED");
}
while(sensorStatus == 0){
char tempvalue[DATA_LENGTH];
tempvalue[0] = 0;
char humidityvalue[DATA_LENGTH];
humidityvalue[0] = 0;
char windvalue[DATA_LENGTH];
windvalue[0] = 0;
char winddirectionvalue[DATA_LENGTH];
winddirectionvalue[0] = 0;
char windaveragevalue[DATA_LENGTH];
windaveragevalue[0] = 0;
char windgustvalue[DATA_LENGTH];
windgustvalue[0] = 0;
char rainvalue[DATA_LENGTH];
rainvalue[0] = 0;
char raintotvalue[DATA_LENGTH];
raintotvalue[0] = 0;
char rainratevalue[DATA_LENGTH];
rainratevalue[0] = 0;
char timeBuf[80];
timeBuf[0] = 0;
time_t timestamp = 0;
@ -162,7 +177,98 @@ int list_devices() {
strcat(humidityvalue, "%");
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
}
printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf);
if (dataTypes & TELLSTICK_RAINRATE) {
tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINRATE, rainratevalue, DATA_LENGTH, (int *)&timestamp);
strcat(rainratevalue, " mm/h, ");
strcat(rainvalue, rainratevalue);
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
}
if (dataTypes & TELLSTICK_RAINTOTAL) {
tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINTOTAL, raintotvalue, DATA_LENGTH, (int *)&timestamp);
//TODO detta blir väl fel, kan väl hamna i andra ordningar, eller hur?
strcat(raintotvalue, " mm");
strcat(rainvalue, raintotvalue);
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
}
if (dataTypes & TELLSTICK_WINDDIRECTION) {
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDDIRECTION, winddirectionvalue, DATA_LENGTH, (int *)&timestamp);
//TODO or use charToInteger in common?
std::stringstream inputstream;
inputstream << winddirectionvalue;
int direction;
inputstream >> direction;
direction = direction / 22.5;
std::string directionabbrev = "N";
switch (direction) {
case 1:
directionabbrev = "NNE";
break;
case 2:
directionabbrev = "NE";
break;
case 3:
directionabbrev = "ENE";
break;
case 4:
directionabbrev = "E";
break;
case 5:
directionabbrev = "ESE";
break;
case 6:
directionabbrev = "SE";
break;
case 7:
directionabbrev = "SSE";
break;
case 8:
directionabbrev = "S";
break;
case 9:
directionabbrev = "SSW";
break;
case 10:
directionabbrev = "SW";
break;
case 11:
directionabbrev = "WSW";
break;
case 12:
directionabbrev = "W";
break;
case 13:
directionabbrev = "WNW";
break;
case 14:
directionabbrev = "NW";
break;
case 15:
directionabbrev = "NNW";
break;
}
strcat(windvalue, directionabbrev.c_str());
strcat(windvalue, ", ");
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
}
if (dataTypes & TELLSTICK_WINDAVERAGE) {
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDAVERAGE, windaveragevalue, DATA_LENGTH, (int *)&timestamp);
strcat(windaveragevalue, " m/s (");
strcat(windvalue, windaveragevalue);
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
}
if (dataTypes & TELLSTICK_WINDGUST) {
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDGUST, windgustvalue, DATA_LENGTH, (int *)&timestamp);
strcat(windgustvalue, " m/s) ");
strcat(windvalue, windgustvalue);
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
}
printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\t%-20s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, rainvalue, windvalue, timeBuf);
sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes);
}
@ -209,6 +315,36 @@ int list_kv_sensors() {
printf("\thumidity=%s", humidityvalue);
}
if (dataTypes & TELLSTICK_WINDDIRECTION) {
char winddirectionvalue[DATA_LENGTH];
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDDIRECTION, winddirectionvalue, DATA_LENGTH, (int *)&timestamp);
printf("\twinddirection=%s", winddirectionvalue);
}
if (dataTypes & TELLSTICK_WINDAVERAGE) {
char windaveragevalue[DATA_LENGTH];
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDAVERAGE, windaveragevalue, DATA_LENGTH, (int *)&timestamp);
printf("\twindaverage=%s", windaveragevalue);
}
if (dataTypes & TELLSTICK_WINDGUST) {
char windgustvalue[DATA_LENGTH];
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDGUST, windgustvalue, DATA_LENGTH, (int *)&timestamp);
printf("\twindgust=%s", windgustvalue);
}
if (dataTypes & TELLSTICK_RAINRATE) {
char rainratevalue[DATA_LENGTH];
tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINRATE, rainratevalue, DATA_LENGTH, (int *)&timestamp);
printf("\trainrate=%s", rainratevalue);
}
if (dataTypes & TELLSTICK_RAINTOTAL) {
char raintotalvalue[DATA_LENGTH];
tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINTOTAL, raintotalvalue, DATA_LENGTH, (int *)&timestamp);
printf("\traintotal=%s", raintotalvalue);
}
if (dataTypes & (TELLSTICK_TEMPERATURE | TELLSTICK_HUMIDITY)) {
/* timestamp has been set, print time & age */
/* (age is more useful on e.g. embedded systems