Added support for rain and wind sensors (Oregon Scientific) in telldus-core
This commit is contained in:
parent
668dd99ac2
commit
35028b1c82
6 changed files with 291 additions and 6 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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(×tamp));
|
||||
}
|
||||
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 *)×tamp);
|
||||
strcat(rainratevalue, " mm/h, ");
|
||||
strcat(rainvalue, rainratevalue);
|
||||
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
|
||||
}
|
||||
|
||||
if (dataTypes & TELLSTICK_RAINTOTAL) {
|
||||
tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINTOTAL, raintotvalue, DATA_LENGTH, (int *)×tamp);
|
||||
//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(×tamp));
|
||||
}
|
||||
|
||||
if (dataTypes & TELLSTICK_WINDDIRECTION) {
|
||||
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDDIRECTION, winddirectionvalue, DATA_LENGTH, (int *)×tamp);
|
||||
//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(×tamp));
|
||||
}
|
||||
|
||||
if (dataTypes & TELLSTICK_WINDAVERAGE) {
|
||||
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDAVERAGE, windaveragevalue, DATA_LENGTH, (int *)×tamp);
|
||||
strcat(windaveragevalue, " m/s (");
|
||||
strcat(windvalue, windaveragevalue);
|
||||
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
|
||||
}
|
||||
|
||||
if (dataTypes & TELLSTICK_WINDGUST) {
|
||||
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDGUST, windgustvalue, DATA_LENGTH, (int *)×tamp);
|
||||
strcat(windgustvalue, " m/s) ");
|
||||
strcat(windvalue, windgustvalue);
|
||||
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
|
||||
}
|
||||
|
||||
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 *)×tamp);
|
||||
printf("\twinddirection=%s", winddirectionvalue);
|
||||
}
|
||||
|
||||
if (dataTypes & TELLSTICK_WINDAVERAGE) {
|
||||
char windaveragevalue[DATA_LENGTH];
|
||||
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDAVERAGE, windaveragevalue, DATA_LENGTH, (int *)×tamp);
|
||||
printf("\twindaverage=%s", windaveragevalue);
|
||||
}
|
||||
|
||||
if (dataTypes & TELLSTICK_WINDGUST) {
|
||||
char windgustvalue[DATA_LENGTH];
|
||||
tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDGUST, windgustvalue, DATA_LENGTH, (int *)×tamp);
|
||||
printf("\twindgust=%s", windgustvalue);
|
||||
}
|
||||
|
||||
if (dataTypes & TELLSTICK_RAINRATE) {
|
||||
char rainratevalue[DATA_LENGTH];
|
||||
tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINRATE, rainratevalue, DATA_LENGTH, (int *)×tamp);
|
||||
printf("\trainrate=%s", rainratevalue);
|
||||
}
|
||||
|
||||
if (dataTypes & TELLSTICK_RAINTOTAL) {
|
||||
char raintotalvalue[DATA_LENGTH];
|
||||
tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINTOTAL, raintotalvalue, DATA_LENGTH, (int *)×tamp);
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue