Added ESPilight libs
This commit is contained in:
1 parent
0e743a0e33
commit
d2c3373b8e
138 files changed
+18414
No files matched your search
Executable
+587
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
ESPiLight - pilight 433.92 MHz protocols library for Arduino
|
||||
Copyright (c) 2016 Puuu. All right reserved.
|
||||
|
||||
Project home: https://github.com/puuu/espilight/
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with library. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <ESPiLight.h>
|
||||
#include "tools/aprintf.h"
|
||||
|
||||
// ESP32 doesn't define ICACHE_RAM_ATTR
|
||||
#ifndef ICACHE_RAM_ATTR
|
||||
#define ICACHE_RAM_ATTR IRAM_ATTR
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define Debug(x) Serial.print(x)
|
||||
#define DebugLn(x) Serial.println(x)
|
||||
#else
|
||||
#define Debug(x)
|
||||
#define DebugLn(x)
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "pilight/libs/pilight/protocols/protocol.h"
|
||||
}
|
||||
protocols_t *protocols = nullptr;
|
||||
protocols_t *used_protocols = nullptr;
|
||||
|
||||
volatile PulseTrain_t ESPiLight::_pulseTrains[RECEIVER_BUFFER_SIZE];
|
||||
bool ESPiLight::_enabledReceiver;
|
||||
volatile uint8_t ESPiLight::_actualPulseTrain = 0;
|
||||
uint8_t ESPiLight::_avaiablePulseTrain = 0;
|
||||
volatile unsigned long ESPiLight::_lastChange =
|
||||
0; // Timestamp of previous edge
|
||||
volatile uint8_t ESPiLight::_nrpulses = 0;
|
||||
int16_t ESPiLight::_interrupt = NOT_AN_INTERRUPT;
|
||||
|
||||
uint8_t ESPiLight::minrawlen = 5;
|
||||
uint8_t ESPiLight::maxrawlen = MAXPULSESTREAMLENGTH;
|
||||
uint16_t ESPiLight::mingaplen = 5100;
|
||||
uint16_t ESPiLight::maxgaplen = 10000;
|
||||
|
||||
static void fire_callback(protocol_t *protocol, ESPiLightCallBack callback);
|
||||
|
||||
static protocols_t *get_protocols() {
|
||||
if (protocols == nullptr) {
|
||||
ESPiLight::setErrorOutput(Serial);
|
||||
protocol_init();
|
||||
}
|
||||
return protocols;
|
||||
}
|
||||
|
||||
static protocols_t *get_used_protocols() {
|
||||
if (used_protocols == nullptr) {
|
||||
used_protocols = get_protocols();
|
||||
}
|
||||
return used_protocols;
|
||||
}
|
||||
|
||||
void ESPiLight::initReceiver(byte inputPin) {
|
||||
int16_t interrupt = digitalPinToInterrupt(inputPin);
|
||||
if (_interrupt == interrupt) {
|
||||
return;
|
||||
}
|
||||
if (_interrupt >= 0) {
|
||||
detachInterrupt((uint8_t)_interrupt);
|
||||
}
|
||||
_interrupt = interrupt;
|
||||
|
||||
resetReceiver();
|
||||
enableReceiver();
|
||||
|
||||
if (interrupt >= 0) {
|
||||
attachInterrupt((uint8_t)interrupt, interruptHandler, CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ESPiLight::receivePulseTrain(uint16_t *pulses) {
|
||||
uint8_t length = nextPulseTrainLength();
|
||||
|
||||
if (length > 0) {
|
||||
volatile PulseTrain_t &pulseTrain = _pulseTrains[_avaiablePulseTrain];
|
||||
_avaiablePulseTrain = (_avaiablePulseTrain + 1) % RECEIVER_BUFFER_SIZE;
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
pulses[i] = pulseTrain.pulses[i];
|
||||
}
|
||||
pulseTrain.length = 0;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
uint8_t ESPiLight::nextPulseTrainLength() {
|
||||
return _pulseTrains[_avaiablePulseTrain].length;
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR ESPiLight::interruptHandler() {
|
||||
if (!_enabledReceiver) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long now = micros();
|
||||
unsigned int duration = 0;
|
||||
|
||||
volatile PulseTrain_t &pulseTrain = _pulseTrains[_actualPulseTrain];
|
||||
volatile uint16_t *codes = pulseTrain.pulses;
|
||||
|
||||
if (pulseTrain.length == 0) {
|
||||
duration = now - _lastChange;
|
||||
/* We first do some filtering (same as pilight BPF) */
|
||||
if (duration > MIN_PULSELENGTH) {
|
||||
if (duration < MAX_PULSELENGTH) {
|
||||
/* All codes are buffered */
|
||||
codes[_nrpulses] = (uint16_t)duration;
|
||||
_nrpulses = (uint8_t)((_nrpulses + 1) % MAXPULSESTREAMLENGTH);
|
||||
/* Let's match footers */
|
||||
if (duration > mingaplen) {
|
||||
// Debug('g');
|
||||
/* Only match minimal length pulse streams */
|
||||
if (_nrpulses >= minrawlen && _nrpulses <= maxrawlen) {
|
||||
// Debug(_nrpulses);
|
||||
// Debug('l');
|
||||
pulseTrain.length = _nrpulses;
|
||||
_actualPulseTrain = (_actualPulseTrain + 1) % RECEIVER_BUFFER_SIZE;
|
||||
}
|
||||
_nrpulses = 0;
|
||||
}
|
||||
}
|
||||
_lastChange = now;
|
||||
}
|
||||
} else {
|
||||
Debug("_!_");
|
||||
}
|
||||
}
|
||||
|
||||
void ESPiLight::resetReceiver() {
|
||||
for (unsigned int i = 0; i < RECEIVER_BUFFER_SIZE; i++) {
|
||||
_pulseTrains[i].length = 0;
|
||||
}
|
||||
_avaiablePulseTrain = 0;
|
||||
_actualPulseTrain = 0;
|
||||
_nrpulses = 0;
|
||||
}
|
||||
|
||||
void ESPiLight::enableReceiver() { _enabledReceiver = true; }
|
||||
|
||||
void ESPiLight::disableReceiver() { _enabledReceiver = false; }
|
||||
|
||||
void ESPiLight::loop() {
|
||||
int length = 0;
|
||||
uint16_t pulses[MAXPULSESTREAMLENGTH];
|
||||
|
||||
length = receivePulseTrain(pulses);
|
||||
|
||||
if (length > 0) {
|
||||
/*
|
||||
Debug("RAW (");
|
||||
Debug(length);
|
||||
Debug("): ");
|
||||
for(int i=0;i<length;i++) {
|
||||
Debug(pulses[i]);
|
||||
Debug(' ');
|
||||
}
|
||||
DebugLn();
|
||||
*/
|
||||
parsePulseTrain(pulses, (uint8_t)length);
|
||||
}
|
||||
}
|
||||
|
||||
ESPiLight::ESPiLight(int8_t outputPin) {
|
||||
_outputPin = outputPin;
|
||||
_callback = nullptr;
|
||||
_rawCallback = nullptr;
|
||||
_echoEnabled = false;
|
||||
|
||||
if (_outputPin >= 0) {
|
||||
pinMode((uint8_t)_outputPin, OUTPUT);
|
||||
digitalWrite((uint8_t)_outputPin, LOW);
|
||||
}
|
||||
|
||||
get_protocols();
|
||||
}
|
||||
|
||||
void ESPiLight::setCallback(ESPiLightCallBack callback) {
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
void ESPiLight::setPulseTrainCallBack(PulseTrainCallBack rawCallback) {
|
||||
_rawCallback = rawCallback;
|
||||
}
|
||||
|
||||
void ESPiLight::sendPulseTrain(const uint16_t *pulses, size_t length,
|
||||
size_t repeats) {
|
||||
if (_outputPin >= 0) {
|
||||
bool receiverState = _enabledReceiver;
|
||||
_enabledReceiver = (_echoEnabled && receiverState);
|
||||
for (unsigned int r = 0; r < repeats; r++) {
|
||||
for (unsigned int i = 0; i < length; i += 2) {
|
||||
digitalWrite((uint8_t)_outputPin, HIGH);
|
||||
delayMicroseconds(pulses[i]);
|
||||
digitalWrite((uint8_t)_outputPin, LOW);
|
||||
if (i + 1 < length) {
|
||||
delayMicroseconds(pulses[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
digitalWrite((uint8_t)_outputPin, LOW);
|
||||
_enabledReceiver = receiverState;
|
||||
}
|
||||
}
|
||||
|
||||
int ESPiLight::send(const String &protocol, const String &json,
|
||||
size_t repeats) {
|
||||
if (_outputPin < 0) {
|
||||
DebugLn("No output pin set, cannot send");
|
||||
return ERROR_NO_OUTPUT_PIN;
|
||||
}
|
||||
int length = 0;
|
||||
uint16_t pulses[MAXPULSESTREAMLENGTH];
|
||||
|
||||
length = createPulseTrain(pulses, protocol, json);
|
||||
if (length > 0) {
|
||||
/*
|
||||
DebugLn();
|
||||
Debug("send: ");
|
||||
Debug(length);
|
||||
Debug(" pulses (");
|
||||
Debug(protocol);
|
||||
Debug(", ");
|
||||
Debug(content);
|
||||
DebugLn(")");
|
||||
*/
|
||||
sendPulseTrain(pulses, (unsigned)length, repeats);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
int ESPiLight::createPulseTrain(uint16_t *pulses, const String &protocol_id,
|
||||
const String &content) {
|
||||
protocol_t *protocol = nullptr;
|
||||
protocols_t *pnode = get_used_protocols();
|
||||
JsonNode *message;
|
||||
|
||||
Debug("piLightCreatePulseTrain: ");
|
||||
|
||||
if (!json_validate(content.c_str())) {
|
||||
Debug("invalid json: ");
|
||||
DebugLn(content);
|
||||
return ERROR_INVALID_JSON;
|
||||
}
|
||||
|
||||
while (pnode != nullptr) {
|
||||
protocol = pnode->listener;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
if ((protocol->createCode != nullptr) && (protocol_id == protocol->id) &&
|
||||
(protocol->maxrawlen <= MAXPULSESTREAMLENGTH)) {
|
||||
#pragma GCC diagnostic pop
|
||||
Debug("protocol: ");
|
||||
Debug(protocol->id);
|
||||
|
||||
protocol->rawlen = 0;
|
||||
protocol->raw = pulses;
|
||||
message = json_decode(content.c_str());
|
||||
int return_value = protocol->createCode(message);
|
||||
json_delete(message);
|
||||
// delete message created by createCode()
|
||||
json_delete(protocol->message);
|
||||
protocol->message = nullptr;
|
||||
|
||||
if (return_value == EXIT_SUCCESS) {
|
||||
DebugLn(" create Code succeded.");
|
||||
return protocol->rawlen;
|
||||
} else {
|
||||
DebugLn(" create Code failed.");
|
||||
return ERROR_INVALID_PILIGHT_MSG;
|
||||
}
|
||||
}
|
||||
pnode = pnode->next;
|
||||
}
|
||||
return ERROR_UNAVAILABLE_PROTOCOL;
|
||||
}
|
||||
|
||||
size_t ESPiLight::parsePulseTrain(uint16_t *pulses, uint8_t length) {
|
||||
size_t matches = 0;
|
||||
protocol_t *protocol = nullptr;
|
||||
protocols_t *pnode = get_used_protocols();
|
||||
|
||||
// DebugLn("piLightParsePulseTrain start");
|
||||
while ((pnode != nullptr) && (_callback != nullptr)) {
|
||||
protocol = pnode->listener;
|
||||
|
||||
if (protocol->parseCode != nullptr && protocol->validate != nullptr) {
|
||||
protocol->raw = pulses;
|
||||
protocol->rawlen = length;
|
||||
|
||||
if (protocol->validate() == 0) {
|
||||
Debug("pulses: ");
|
||||
Debug(length);
|
||||
Debug(" possible protocol: ");
|
||||
DebugLn(protocol->id);
|
||||
|
||||
if (protocol->first > 0) {
|
||||
protocol->first = protocol->second;
|
||||
}
|
||||
protocol->second = micros();
|
||||
if (protocol->first == 0) {
|
||||
protocol->first = protocol->second;
|
||||
}
|
||||
|
||||
/* Reset # of repeats after a certain delay */
|
||||
if ((protocol->second - protocol->first) > 500000) {
|
||||
protocol->repeats = 0;
|
||||
}
|
||||
|
||||
protocol->message = nullptr;
|
||||
protocol->parseCode();
|
||||
if (protocol->message != nullptr) {
|
||||
matches++;
|
||||
protocol->repeats++;
|
||||
|
||||
fire_callback(protocol, _callback);
|
||||
|
||||
json_delete(protocol->message);
|
||||
protocol->message = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
pnode = pnode->next;
|
||||
}
|
||||
if (_rawCallback != nullptr) {
|
||||
(_rawCallback)(pulses, length);
|
||||
}
|
||||
|
||||
// Debug("piLightParsePulseTrain end. matches: ");
|
||||
// DebugLn(matches);
|
||||
return matches;
|
||||
}
|
||||
|
||||
static void fire_callback(protocol_t *protocol, ESPiLightCallBack callback) {
|
||||
PilightRepeatStatus_t status = FIRST;
|
||||
char *content = json_encode(protocol->message);
|
||||
String deviceId = "";
|
||||
double itmp;
|
||||
char *stmp;
|
||||
|
||||
if ((protocol->repeats <= 1) || (protocol->old_content == nullptr)) {
|
||||
status = FIRST;
|
||||
json_free(protocol->old_content);
|
||||
protocol->old_content = content;
|
||||
} else if (protocol->repeats < 100) {
|
||||
if (strcmp(content, protocol->old_content) == 0) {
|
||||
protocol->repeats += 100;
|
||||
status = VALID;
|
||||
} else {
|
||||
status = INVALID;
|
||||
}
|
||||
json_free(protocol->old_content);
|
||||
protocol->old_content = content;
|
||||
} else {
|
||||
status = KNOWN;
|
||||
json_free(content);
|
||||
}
|
||||
if (json_find_number(protocol->message, "id", &itmp) == 0) {
|
||||
deviceId = String((int)round(itmp));
|
||||
} else if (json_find_string(protocol->message, "id", &stmp) == 0) {
|
||||
deviceId = String(stmp);
|
||||
};
|
||||
(callback)(String(protocol->id), String(protocol->old_content), status,
|
||||
protocol->repeats, deviceId);
|
||||
}
|
||||
|
||||
String ESPiLight::pulseTrainToString(const uint16_t *codes, size_t length) {
|
||||
bool match = false;
|
||||
int diff = 0;
|
||||
|
||||
uint8_t nrpulses = 0; // number of pulse types
|
||||
uint16_t plstypes[MAX_PULSE_TYPES] = {};
|
||||
|
||||
String data("");
|
||||
data.reserve(6 + length);
|
||||
data += "c:";
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
match = false;
|
||||
for (uint8_t j = 0; j < MAX_PULSE_TYPES; j++) {
|
||||
// We device these numbers by 10 to normalize them a bit
|
||||
diff = (plstypes[j] / 50) - (codes[i] / 50);
|
||||
if ((diff >= -2) && (diff <= 2)) {
|
||||
// Write numbers
|
||||
data += (char)('0' + ((char)j));
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
plstypes[nrpulses++] = codes[i];
|
||||
data += (char)('0' + ((char)(nrpulses - 1)));
|
||||
if (nrpulses >= MAX_PULSE_TYPES) {
|
||||
DebugLn("too many pulse types");
|
||||
return String("");
|
||||
}
|
||||
}
|
||||
}
|
||||
data += ";p:";
|
||||
for (uint8_t i = 0; i < nrpulses; i++) {
|
||||
data += plstypes[i];
|
||||
if (i + 1 < nrpulses) {
|
||||
data += ',';
|
||||
}
|
||||
}
|
||||
data += '@';
|
||||
return data;
|
||||
}
|
||||
|
||||
int ESPiLight::stringToPulseTrain(const String &data, uint16_t *codes,
|
||||
size_t maxlength) {
|
||||
unsigned int length = 0; // length of pulse train
|
||||
unsigned int nrpulses = 0; // number of pulse types
|
||||
uint16_t plstypes[MAX_PULSE_TYPES] = {};
|
||||
|
||||
// validate data string
|
||||
int scode = data.indexOf('c') + 2;
|
||||
if (scode < 0 || (unsigned)scode > data.length()) {
|
||||
DebugLn("'c' not found in data string, or has no data");
|
||||
return ERROR_INVALID_PULSETRAIN_MSG_C;
|
||||
}
|
||||
int spulse = data.indexOf('p') + 2;
|
||||
if (spulse < 0 || (unsigned)spulse > data.length()) {
|
||||
DebugLn("'p' not found in data string, or has no data");
|
||||
return ERROR_INVALID_PULSETRAIN_MSG_P;
|
||||
}
|
||||
// parsing pulse types
|
||||
unsigned int start = (unsigned)spulse;
|
||||
int end = data.indexOf(',', start);
|
||||
while (end > 0) {
|
||||
plstypes[nrpulses++] =
|
||||
(uint16_t)data.substring(start, (unsigned)end).toInt();
|
||||
start = (unsigned)end + 1;
|
||||
end = data.indexOf(',', start);
|
||||
}
|
||||
end = data.indexOf(';', start);
|
||||
if (end < 0) {
|
||||
end = data.indexOf('@', start);
|
||||
}
|
||||
if (end < 0) {
|
||||
DebugLn("';' or '@' not found in data string");
|
||||
return ERROR_INVALID_PULSETRAIN_MSG_END;
|
||||
}
|
||||
plstypes[nrpulses++] = (uint16_t)data.substring(start, (unsigned)end).toInt();
|
||||
// parsing pulses
|
||||
int pulse_index = 0;
|
||||
for (unsigned int i = (unsigned)scode; i < data.length(); i++) {
|
||||
if ((data[i] == ';') || (data[i] == '@')) break;
|
||||
if (i >= maxlength) break;
|
||||
pulse_index = data[i] - '0';
|
||||
if ((pulse_index < 0) || ((unsigned)pulse_index >= nrpulses)) {
|
||||
DebugLn("Pulse type not defined");
|
||||
return ERROR_INVALID_PULSETRAIN_MSG_TYPE;
|
||||
}
|
||||
codes[length++] = plstypes[pulse_index];
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
static protocols_t *find_proto(const char *name) {
|
||||
protocols_t *pnode = get_protocols();
|
||||
while (pnode != nullptr) {
|
||||
if (strcmp(name, pnode->listener->id) == 0) {
|
||||
return pnode;
|
||||
}
|
||||
pnode = pnode->next;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ESPiLight::limitProtocols(const String &protos) {
|
||||
if (!json_validate(protos.c_str())) {
|
||||
DebugLn("Protocol limit argument is not a valid json message!");
|
||||
return;
|
||||
}
|
||||
JsonNode *message = json_decode(protos.c_str());
|
||||
|
||||
if (message->tag != JSON_ARRAY) {
|
||||
DebugLn("Protocol limit argument is not a json array!");
|
||||
json_delete(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_used_protocols() != get_protocols()) {
|
||||
protocols_t *pnode = get_used_protocols();
|
||||
while (pnode != nullptr) {
|
||||
protocols_t *tmp = pnode;
|
||||
pnode = pnode->next;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
used_protocols = nullptr;
|
||||
JsonNode *curr = message->children.head;
|
||||
unsigned int proto_count = 0;
|
||||
|
||||
while (curr != nullptr) {
|
||||
if (!curr->tag == JSON_STRING) {
|
||||
DebugLn("Element is not a String");
|
||||
curr = curr->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
protocols_t *templ = find_proto(curr->string_);
|
||||
if (templ == nullptr) {
|
||||
Debug("Protocol not found: ");
|
||||
DebugLn(curr->string_);
|
||||
curr = curr->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
protocols_t *new_node = new protocols_t;
|
||||
new_node->listener = templ->listener;
|
||||
new_node->next = used_protocols;
|
||||
used_protocols = new_node;
|
||||
|
||||
Debug("activated protocol ");
|
||||
DebugLn(templ->listener->id);
|
||||
proto_count++;
|
||||
|
||||
if (curr == message->children.tail) {
|
||||
break;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
json_delete(message);
|
||||
}
|
||||
|
||||
static String protocols_to_array(protocols_t *pnode) {
|
||||
protocols_t *tmp = pnode;
|
||||
size_t needed_len = 2; // []
|
||||
while (tmp != nullptr) {
|
||||
needed_len += strlen(tmp->listener->id) + 3; // "xx",
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
String ret;
|
||||
ret.reserve(needed_len);
|
||||
|
||||
ret += '[';
|
||||
|
||||
bool first = true;
|
||||
while (pnode != nullptr) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
ret += ",";
|
||||
}
|
||||
ret += '"';
|
||||
ret += pnode->listener->id;
|
||||
ret += '"';
|
||||
pnode = pnode->next;
|
||||
}
|
||||
ret += "]";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
String ESPiLight::availableProtocols() {
|
||||
return protocols_to_array(get_protocols());
|
||||
}
|
||||
|
||||
String ESPiLight::enabledProtocols() {
|
||||
return protocols_to_array(get_used_protocols());
|
||||
}
|
||||
|
||||
void ESPiLight::setEchoEnabled(bool enabled) { _echoEnabled = enabled; }
|
||||
|
||||
void ESPiLight::setErrorOutput(Print &output) { set_aprintf_output(&output); }
|
||||
Executable
+195
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
ESPiLight - pilight 433.92 MHz protocols library for Arduino
|
||||
Copyright (c) 2016 Puuu. All right reserved.
|
||||
|
||||
Project home: https://github.com/puuu/espilight/
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with library. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef ESPILIGHT_H
|
||||
#define ESPILIGHT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
#define RECEIVER_BUFFER_SIZE 10
|
||||
|
||||
#define MIN_PULSELENGTH 80
|
||||
#define MAX_PULSELENGTH 16000
|
||||
#define MAXPULSESTREAMLENGTH 255
|
||||
|
||||
#define MAX_PULSE_TYPES 16
|
||||
|
||||
enum PilightRepeatStatus_t { FIRST, INVALID, VALID, KNOWN };
|
||||
|
||||
typedef struct PulseTrain_t {
|
||||
uint16_t pulses[MAXPULSESTREAMLENGTH];
|
||||
uint8_t length;
|
||||
} PulseTrain_t;
|
||||
|
||||
typedef std::function<void(const String &protocol, const String &message,
|
||||
int status, size_t repeats, const String &deviceID)>
|
||||
ESPiLightCallBack;
|
||||
typedef std::function<void(const uint16_t *pulses, size_t length)>
|
||||
PulseTrainCallBack;
|
||||
|
||||
class ESPiLight {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
ESPiLight(int8_t outputPin);
|
||||
|
||||
/**
|
||||
* Transmit pulse train
|
||||
*/
|
||||
void sendPulseTrain(const uint16_t *pulses, size_t length,
|
||||
size_t repeats = 10);
|
||||
|
||||
/**
|
||||
* Transmit Pilight json message
|
||||
*/
|
||||
int send(const String &protocol, const String &json, size_t repeats = 10);
|
||||
|
||||
/**
|
||||
* Parse pulse train and fire callback
|
||||
*/
|
||||
size_t parsePulseTrain(uint16_t *pulses, uint8_t length);
|
||||
|
||||
/**
|
||||
* Process receiver queue and fire callback
|
||||
*/
|
||||
void loop();
|
||||
|
||||
void setCallback(ESPiLightCallBack callback);
|
||||
void setPulseTrainCallBack(PulseTrainCallBack rawCallback);
|
||||
|
||||
/**
|
||||
* If set to true, the receiver will temporarely be disabled when sending.
|
||||
*/
|
||||
void setEchoEnabled(bool enabled);
|
||||
|
||||
/**
|
||||
* Initialise receiver
|
||||
*/
|
||||
static void initReceiver(byte inputPin);
|
||||
|
||||
/**
|
||||
* Get last received PulseTrain.
|
||||
* Returns: length of PulseTrain or 0 if not avaiable
|
||||
*/
|
||||
static uint8_t receivePulseTrain(uint16_t *pulses);
|
||||
|
||||
/**
|
||||
* Check if new PulseTrain avaiable.
|
||||
* Returns: 0 if no new PulseTrain avaiable
|
||||
*/
|
||||
static uint8_t nextPulseTrainLength();
|
||||
|
||||
/**
|
||||
* Enable Receiver. No need to call enableReceiver() after initReceiver().
|
||||
*/
|
||||
static void enableReceiver();
|
||||
|
||||
/**
|
||||
* Disable decoding. You can re-enable decoding by calling enableReceiver();
|
||||
*/
|
||||
static void disableReceiver();
|
||||
|
||||
/**
|
||||
* interruptHandler is called on every change in the input
|
||||
* signal. If RcPilight::initReceiver is called with interrupt <0,
|
||||
* you have to call interruptHandler() yourself. (Or use
|
||||
* InterruptChain)
|
||||
*/
|
||||
static void interruptHandler();
|
||||
|
||||
/**
|
||||
* Limit the available protocols.
|
||||
*
|
||||
* This gets a json array of the protocol names that should be activated.
|
||||
* If the array is empty, the filter gets reset.
|
||||
*/
|
||||
static void limitProtocols(const String &protos);
|
||||
|
||||
/**
|
||||
* Return a json array containing all the available protocols.
|
||||
*/
|
||||
static String availableProtocols();
|
||||
|
||||
/**
|
||||
* Return an json array containing all the currently enabled protocols
|
||||
*/
|
||||
static String enabledProtocols();
|
||||
|
||||
/**
|
||||
* Set pilight error output Print class (default is Serial)
|
||||
*/
|
||||
static void setErrorOutput(Print &output);
|
||||
|
||||
static uint8_t minrawlen;
|
||||
static uint8_t maxrawlen;
|
||||
static uint16_t mingaplen;
|
||||
static uint16_t maxgaplen;
|
||||
|
||||
static String pulseTrainToString(const uint16_t *pulses, size_t length);
|
||||
static int stringToPulseTrain(const String &data, uint16_t *pulses,
|
||||
size_t maxlength);
|
||||
|
||||
static int createPulseTrain(uint16_t *pulses, const String &protocol_id,
|
||||
const String &json);
|
||||
|
||||
/**
|
||||
* Error return codes for send() and createPulseTrain()
|
||||
*/
|
||||
static const int ERROR_UNAVAILABLE_PROTOCOL = 0;
|
||||
static const int ERROR_INVALID_PILIGHT_MSG = -1;
|
||||
static const int ERROR_INVALID_JSON = -2;
|
||||
static const int ERROR_NO_OUTPUT_PIN = -3;
|
||||
|
||||
/**
|
||||
* Error return codes for stringToPulseTrain()
|
||||
*/
|
||||
static const int ERROR_INVALID_PULSETRAIN_MSG_C = -1;
|
||||
static const int ERROR_INVALID_PULSETRAIN_MSG_P = -2;
|
||||
static const int ERROR_INVALID_PULSETRAIN_MSG_END = -3;
|
||||
static const int ERROR_INVALID_PULSETRAIN_MSG_TYPE = -4;
|
||||
|
||||
private:
|
||||
ESPiLightCallBack _callback;
|
||||
PulseTrainCallBack _rawCallback;
|
||||
int8_t _outputPin;
|
||||
bool _echoEnabled;
|
||||
|
||||
/**
|
||||
* Quasi-reset. Called when the current edge is too long or short.
|
||||
* reset "promotes" the current edge as being the first edge of a new
|
||||
* sequence.
|
||||
*/
|
||||
static void resetReceiver();
|
||||
|
||||
/**
|
||||
* Internal functions
|
||||
*/
|
||||
static bool _enabledReceiver; // If true, monitoring and decoding is
|
||||
// enabled. If false, interruptHandler will
|
||||
// return immediately.
|
||||
static volatile PulseTrain_t _pulseTrains[];
|
||||
static volatile uint8_t _actualPulseTrain;
|
||||
static uint8_t _avaiablePulseTrain;
|
||||
static volatile unsigned long _lastChange; // Timestamp of previous edge
|
||||
static volatile uint8_t _nrpulses;
|
||||
static int16_t _interrupt;
|
||||
};
|
||||
|
||||
#endif
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright (C) 2013 - 2016 CurlyMo
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "binary.h"
|
||||
|
||||
/*
|
||||
* Macros to help convertion of a value from and to bits.
|
||||
* The value-variable passed to VALUE_TO_BITS_MSB_FIRST()
|
||||
* and VALUE_TO_BITS_LSB_FIRST() MUST be an unsigned type!
|
||||
* Macros have side effects to almost all variables passed!
|
||||
*/
|
||||
|
||||
#define BITS_LSB_FIRST_TO_VALUE(bits, s, e, result) \
|
||||
unsigned long long mask = 1; \
|
||||
result = 0; \
|
||||
for(; s<=e; mask <<= 1) \
|
||||
if(bits[s++] != 0) \
|
||||
result |= mask
|
||||
|
||||
#define BITS_MSB_FIRST_TO_VALUE(bits, s, e, result) \
|
||||
unsigned long long mask = 1; \
|
||||
result = 0; \
|
||||
e++; \
|
||||
for(; e > 0 && s<e; mask <<= 1) \
|
||||
if(bits[--e] != 0) \
|
||||
result |= mask
|
||||
|
||||
#define VALUE_TO_BITS_MSB_FIRST(value, bits, length) \
|
||||
unsigned long long mask = value; \
|
||||
do bits++; while (mask >>= 1); \
|
||||
int *start = bits; \
|
||||
do *--start = value & 1; while (value >>= 1); \
|
||||
length = bits - start
|
||||
|
||||
|
||||
#define VALUE_TO_BITS_LSB_FIRST(value, bits, length) \
|
||||
int *start = bits; \
|
||||
do *bits++ = value & 1; while (value >>= 1); \
|
||||
length = bits - start
|
||||
|
||||
/*
|
||||
* Invocation of above macros for various types:
|
||||
* Again:
|
||||
* The value-variable passed to VALUE_TO_BITS_MSB_FIRST()
|
||||
* and VALUE_TO_BITS_LSB_FIRST() MUST be an unsigned type!
|
||||
*/
|
||||
int binToDecRev(const int *binary, int s, int e) { // 0<=s<=e, binary[s(msb) .. e(lsb)]
|
||||
int result;
|
||||
BITS_MSB_FIRST_TO_VALUE(binary, s, e, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int binToDec(const int *binary, int s, int e) { // 0<=s<=e, binary[s(lsb) .. e(msb)]
|
||||
int result;
|
||||
BITS_LSB_FIRST_TO_VALUE(binary, s, e, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int decToBin(int dec, int *binary) { // stores dec as binary[msb .. lsb] and return index of lsb
|
||||
unsigned int n = (unsigned int) dec;
|
||||
int len;
|
||||
VALUE_TO_BITS_MSB_FIRST(n, binary, len);
|
||||
return len - 1; // return index, not count.
|
||||
}
|
||||
|
||||
int decToBinRev(int dec, int *binary) { // stores dec as binary[lsb .. msb] and return index of msb
|
||||
unsigned int n = (unsigned int) dec;
|
||||
int len;
|
||||
VALUE_TO_BITS_LSB_FIRST(n, binary, len);
|
||||
return len - 1; // return index, not count.
|
||||
}
|
||||
|
||||
unsigned long long binToDecRevUl(const int *binary, unsigned int s, unsigned int e) {
|
||||
unsigned long long result = 0;
|
||||
BITS_MSB_FIRST_TO_VALUE(binary, s, e, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long long binToDecUl(const int *binary, unsigned int s, unsigned int e) {
|
||||
unsigned long long result;
|
||||
BITS_LSB_FIRST_TO_VALUE(binary, s, e, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int decToBinUl(unsigned long long n, int *binary) {
|
||||
int len;
|
||||
VALUE_TO_BITS_MSB_FIRST(n, binary, len);
|
||||
return len - 1; // return index, not count.
|
||||
}
|
||||
|
||||
int decToBinRevUl(unsigned long long n, int *binary) {
|
||||
int len;
|
||||
VALUE_TO_BITS_LSB_FIRST(n, binary, len);
|
||||
return len - 1; // return index, not count.
|
||||
}
|
||||
|
||||
int binToSignedRev(const int *binary, int s, int e) { // 0<=s<=e, binary[s(msb) .. e(lsb)]
|
||||
int result = binToDecRev(binary, s, e);
|
||||
if (binary[s]) {
|
||||
result -= 1<<(e-s+1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int binToSigned(const int *binary, int s, int e) { // 0<=s<=e, binary[s(lsb) .. e(msb)]
|
||||
int result = binToDec(binary, s, e);
|
||||
if (binary[e]) {
|
||||
result -= 1<<(e-s+1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (C) 2013 - 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _BINARY_H_
|
||||
#define _BINARY_H_
|
||||
|
||||
/*
|
||||
* Convert "bits" to the corresponding integer value.
|
||||
* The difference between binToDecRev[Ul]() and binToDec[Ul]() is where the most and where the least
|
||||
* significant bit is located (at index position s or e).
|
||||
* @param binary The bits to convert, each represented by an int in a buffer (non-zero = "1").
|
||||
* @param s, e Start+End index in the buffer of "bits". 0<=s<=e. e-s < sizeof(int)*8
|
||||
* @return int The converted value.
|
||||
*/
|
||||
int binToDecRev(const int *binary, int s, int e); // 0<=s<=e, binary[s(msb) .. e(lsb)]
|
||||
int binToDec(const int *binary, int s, int e); // 0<=s<=e, binary[s(lsb) .. e(msb)]
|
||||
|
||||
/*
|
||||
* Convert an integer value to its bits, stored in a buffer of ints.
|
||||
* The difference of decToBinRev() and decToBin() is if Most or Least Significant bit is generated first.
|
||||
* IMPORTANT: binToDec() devToBin() use the "Rev"/"non-Rev" in opposit meaning: A buffer generated
|
||||
* using the "Rev" function must be read by the "non-Rev" function to produce the original value. :-(
|
||||
* @param dec The number to convert.
|
||||
* @param binary The buffer of int where to store the "bits" (0 and 1).
|
||||
* @return int The index of the last bit generated (0 if one bit was generated).
|
||||
*/
|
||||
int decToBinRev(int dec, int *binary); // stores dec as binary[lsb .. msb] and return index of msb
|
||||
int decToBin(int dec, int *binary); // stores dec as binary[msb .. lsb] and return index of lsb
|
||||
|
||||
/*
|
||||
* Dito for unsigned long long values.
|
||||
*/
|
||||
unsigned long long binToDecRevUl(const int *binary, unsigned int s, unsigned int e);
|
||||
unsigned long long binToDecUl(const int *binary, unsigned int s, unsigned int e);
|
||||
int decToBinUl(unsigned long long n, int *binary);
|
||||
int decToBinRevUl(unsigned long long n, int *binary);
|
||||
|
||||
/*
|
||||
* Convert "bits" to the corresponding signed integer value.
|
||||
* The difference between binToSignedRev() and binToSigned() is where the most and where the least
|
||||
* significant bit is located (at index position s or e).
|
||||
* @param binary The bits to convert, each represented by an int in a buffer (non-zero = "1").
|
||||
* @param s, e Start+End index in the buffer of "bits". 0<=s<=e. e-s < sizeof(int)*8
|
||||
* @return signed int The converted value.
|
||||
*
|
||||
* Examples:
|
||||
* binToSignedRev((int[]){0,1,1,1, 1,1,1,1}, 0, 7) == 127
|
||||
* binToSignedRev((int[]){0,1,1,1, 1,1,1,0}, 0, 7) == 126
|
||||
* binToSignedRev((int[]){0,0,0,0, 0,0,1,0}, 0, 7) == 2
|
||||
* binToSignedRev((int[]){0,0,0,0, 0,0,0,1}, 0, 7) == 1
|
||||
* binToSignedRev((int[]){0,0,0,0, 0,0,0,0}, 0, 7) == 0
|
||||
* binToSignedRev((int[]){1,1,1,1, 1,1,1,1}, 0, 7) == -1
|
||||
* binToSignedRev((int[]){1,1,1,1, 1,1,1,0}, 0, 7) == -2
|
||||
* binToSignedRev((int[]){1,0,0,0, 0,0,1,0}, 0, 7) == -126
|
||||
* binToSignedRev((int[]){1,0,0,0, 0,0,0,1}, 0, 7) == -127
|
||||
* binToSignedRev((int[]){1,0,0,0, 0,0,0,0}, 0, 7) == -128
|
||||
* binToSignedRev((int[]){1,0, 0,1,1,1, 0,0}, 2, 5) == 7
|
||||
* binToSignedRev((int[]){1,0, 1,1,1,0, 0,0}, 2, 5) == -2
|
||||
*
|
||||
* binToSigned((int[]){1,1,1,1, 1,1,1,0}, 0, 7) == 127
|
||||
* binToSigned((int[]){0,1,1,1, 1,1,1,0}, 0, 7) == 126
|
||||
* binToSigned((int[]){0,1,0,0, 0,0,0,0}, 0, 7) == 2
|
||||
* binToSigned((int[]){1,0,0,0, 0,0,0,0}, 0, 7) == 1
|
||||
* binToSigned((int[]){0,0,0,0, 0,0,0,0}, 0, 7) == 0
|
||||
* binToSigned((int[]){1,1,1,1, 1,1,1,1}, 0, 7) == -1
|
||||
* binToSigned((int[]){0,1,1,1, 1,1,1,1}, 0, 7) == -2
|
||||
* binToSigned((int[]){0,1,0,0, 0,0,0,1}, 0, 7) == -126
|
||||
* binToSigned((int[]){1,0,0,0, 0,0,0,1}, 0, 7) == -127
|
||||
* binToSigned((int[]){0,0,0,0, 0,0,0,1}, 0, 7) == -128
|
||||
* binToSigned((int[]){1,0, 1,1,1,0, 0,0}, 2, 5) == 7
|
||||
* binToSigned((int[]){1,0, 0,1,1,1, 0,0}, 2, 5) == -2
|
||||
*/
|
||||
int binToSignedRev(const int *binary, int s, int e); // 0<=s<=e, binary[s(msb) .. e(lsb)]
|
||||
int binToSigned(const int *binary, int s, int e); // 0<=s<=e, binary[s(lsb) .. e(msb)]
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
/*dummy*/
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _DSO_H_
|
||||
#define _DSO_H_
|
||||
|
||||
typedef struct dso_t {
|
||||
void *handle;
|
||||
char *name;
|
||||
ssize_t size;
|
||||
struct dso_t *next;
|
||||
} dso_t;
|
||||
|
||||
typedef struct module_t {
|
||||
const char *name;
|
||||
const char *version;
|
||||
const char *reqversion;
|
||||
const char *reqcommit;
|
||||
} module_t;
|
||||
|
||||
struct dso_t *dso;
|
||||
|
||||
void *dso_load(char *object);
|
||||
int dso_gc(void);
|
||||
void *dso_function(void *handle, const char *name);
|
||||
|
||||
#endif
|
||||
+1
@@ -0,0 +1 @@
|
||||
/*dummy*/
|
||||
+1439
File diff suppressed because it is too large.
Load diff
+124
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright (C) 2013 - 2014 CurlyMo (curlymoo1@gmail.com)
|
||||
2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CCAN_JSON_H
|
||||
#define CCAN_JSON_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define JSON_NULL 0x01
|
||||
#define JSON_BOOL 0x01 << 1
|
||||
#define JSON_STRING 0x01 << 2
|
||||
#define JSON_NUMBER 0x01 << 3
|
||||
#define JSON_ARRAY 0x01 << 4
|
||||
#define JSON_OBJECT 0x01 << 5
|
||||
|
||||
#define JsonTag int
|
||||
|
||||
typedef struct JsonNode JsonNode;
|
||||
|
||||
struct JsonNode
|
||||
{
|
||||
/* only if parent is an object or array (NULL otherwise) */
|
||||
JsonNode *parent;
|
||||
JsonNode *prev, *next;
|
||||
|
||||
/* only if parent is an object (NULL otherwise) */
|
||||
char *key; /* Must be valid UTF-8. */
|
||||
|
||||
JsonTag tag;
|
||||
union {
|
||||
/* JSON_BOOL */
|
||||
bool bool_;
|
||||
|
||||
/* JSON_STRING */
|
||||
char *string_; /* Must be valid UTF-8. */
|
||||
|
||||
/* JSON_NUMBER */
|
||||
double number_;
|
||||
|
||||
/* JSON_ARRAY */
|
||||
/* JSON_OBJECT */
|
||||
struct {
|
||||
JsonNode *head, *tail;
|
||||
} children;
|
||||
};
|
||||
int decimals_;
|
||||
};
|
||||
|
||||
/*** Encoding, decoding, and validation ***/
|
||||
|
||||
JsonNode *json_decode (const char *json);
|
||||
char *json_encode (const JsonNode *node);
|
||||
char *json_encode_string (const char *str);
|
||||
char *json_stringify (const JsonNode *node, const char *space);
|
||||
void json_delete (JsonNode *node);
|
||||
|
||||
bool json_validate (const char *json);
|
||||
|
||||
/*** Lookup and traversal ***/
|
||||
|
||||
JsonNode *json_find_element (JsonNode *array, int index);
|
||||
JsonNode *json_find_member (JsonNode *object, const char *key);
|
||||
|
||||
JsonNode *json_first_child (const JsonNode *node);
|
||||
|
||||
#define json_foreach(i, object_or_array) \
|
||||
for ((i) = json_first_child(object_or_array); \
|
||||
(i) != NULL; \
|
||||
(i) = (i)->next)
|
||||
|
||||
/*** Construction and manipulation ***/
|
||||
|
||||
JsonNode *json_mknull(void);
|
||||
JsonNode *json_mkbool(bool b);
|
||||
JsonNode *json_mkstring(const char *s);
|
||||
JsonNode *json_mknumber(double n, int decimals);
|
||||
JsonNode *json_mkarray(void);
|
||||
JsonNode *json_mkobject(void);
|
||||
|
||||
void json_append_element(JsonNode *array, JsonNode *element);
|
||||
void json_prepend_element(JsonNode *array, JsonNode *element);
|
||||
void json_append_member(JsonNode *object, const char *key, JsonNode *value);
|
||||
void json_prepend_member(JsonNode *object, const char *key, JsonNode *value);
|
||||
|
||||
void json_remove_from_parent(JsonNode *node);
|
||||
|
||||
void json_free(void *a);
|
||||
|
||||
/*** Debugging ***/
|
||||
|
||||
/*
|
||||
* Look for structure and encoding problems in a JsonNode or its descendents.
|
||||
*
|
||||
* If a problem is detected, return false, writing a description of the problem
|
||||
* to errmsg (unless errmsg is NULL).
|
||||
*/
|
||||
bool json_check(const JsonNode *node, char errmsg[256]);
|
||||
|
||||
int json_find_number(JsonNode *object, const char *name, double *out);
|
||||
int json_find_string(JsonNode *object, const char *name, char **out);
|
||||
|
||||
#endif
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
ESPiLight - pilight 433.92 MHz protocols library for Arduino
|
||||
Copyright (c) 2016 Puuu. All right reserved.
|
||||
|
||||
Project home: https://github.com/puuu/espilight/
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with library. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _LOG_H_
|
||||
#define _LOG_H_
|
||||
|
||||
#define LOG_EMERG 0
|
||||
#define LOG_ALERT 1
|
||||
#define LOG_CRIT 2
|
||||
#define LOG_ERR 3
|
||||
#define LOG_WARNING 4
|
||||
#define LOG_NOTICE 5
|
||||
#define LOG_INFO 6
|
||||
#define LOG_DEBUG 7
|
||||
|
||||
#define LOG_STACK 255
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define logprintf(prio, args...) {printf("pilight(%d): ", prio);printf(args);printf("\n");}
|
||||
|
||||
#endif
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (C) 2013 - 2016 CurlyMo
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef _MEM_H_
|
||||
#define _MEM_H_
|
||||
|
||||
#define OUT_OF_MEMORY fprintf(stderr, "out of memory in %s #%d\n", __FILE__, __LINE__),exit(EXIT_FAILURE);
|
||||
|
||||
int xfree(void);
|
||||
void memtrack(void);
|
||||
|
||||
void *__malloc(unsigned long, const char *, int);
|
||||
void *__realloc(void *, unsigned long, const char *, int);
|
||||
void *__calloc(unsigned long a, unsigned long b, const char *, int);
|
||||
void __free(void *, const char *, int);
|
||||
/*
|
||||
* Windows already has a _strdup, libpcap uses __strdup
|
||||
*/
|
||||
char *___strdup(char *, const char *, int);
|
||||
|
||||
// #define MALLOC(a) __malloc(a, __FILE__, __LINE__)
|
||||
// #define REALLOC(a, b) __realloc(a, b, __FILE__, __LINE__)
|
||||
// #define CALLOC(a, b) __calloc(a, b, __FILE__, __LINE__)
|
||||
// #define STRDUP(a) ___strdup(a, __FILE__, __LINE__)
|
||||
// #define FREE(a) __free((void *)(a), __FILE__, __LINE__),(a)=NULL
|
||||
|
||||
#define MALLOC malloc
|
||||
#define REALLOC realloc
|
||||
#define CALLOC calloc
|
||||
#define STRDUP strdup
|
||||
#define FREE(a) free((void *)(a)),(a)=NULL
|
||||
|
||||
#define _MALLOC malloc
|
||||
#define _REALLOC realloc
|
||||
#define _CALLOC calloc
|
||||
#define _STRDUP strdup
|
||||
#define _FREE free
|
||||
|
||||
#endif
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
ESPiLight - pilight 433.92 MHz protocols library for Arduino
|
||||
Copyright (c) 2016 Puuu. All right reserved.
|
||||
|
||||
Project home: https://github.com/puuu/espilight/
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with library. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PILIGHT_H_
|
||||
#define _PILIGHT_H_
|
||||
|
||||
//#include "defines.h"
|
||||
#define PULSE_DIV 34
|
||||
#define EPSILON 0.00001
|
||||
|
||||
#include "mem.h"
|
||||
#include "../../../../tools/aprintf.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "alecto_ws1700.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 20
|
||||
#define MIN_PULSE_LENGTH 261
|
||||
#define AVG_PULSE_LENGTH 266
|
||||
#define MAX_PULSE_LENGTH 280
|
||||
#define RAW_LENGTH 74
|
||||
|
||||
typedef struct settings_t {
|
||||
double id;
|
||||
double temp;
|
||||
double humi;
|
||||
struct settings_t *next;
|
||||
} settings_t;
|
||||
|
||||
static struct settings_t *settings = NULL;
|
||||
|
||||
static int validate(void) {
|
||||
if(alecto_ws1700->rawlen == RAW_LENGTH) {
|
||||
if(alecto_ws1700->raw[alecto_ws1700->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
alecto_ws1700->raw[alecto_ws1700->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, binary[RAW_LENGTH/2];
|
||||
int id = 0, battery = 0, header = 0;
|
||||
double humi_offset = 0.0, temp_offset = 0.0;
|
||||
double temperature = 0.0, humidity = 0.0;
|
||||
|
||||
if(alecto_ws1700->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "alecto_ws1700: parsecode - invalid parameter passed %d", alecto_ws1700->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=1;x<alecto_ws1700->rawlen-1;x+=2) {
|
||||
if(alecto_ws1700->raw[x] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
header = binToDecRev(binary, 0, 3);
|
||||
if (header != 5) {
|
||||
return;
|
||||
}
|
||||
id = binToDecRev(binary, 4, 11);
|
||||
battery = binary[12];
|
||||
temperature = (double)binToSignedRev(binary, 16, 27);
|
||||
humidity = (double)binToDecRev(binary, 28, 35);
|
||||
|
||||
temperature /= 10;
|
||||
|
||||
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;
|
||||
|
||||
alecto_ws1700->message = json_mkobject();
|
||||
json_append_member(alecto_ws1700->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(alecto_ws1700->message, "temperature", json_mknumber(temperature, 1));
|
||||
json_append_member(alecto_ws1700->message, "humidity", json_mknumber(humidity, 1));
|
||||
json_append_member(alecto_ws1700->message, "battery", json_mknumber(battery, 0));
|
||||
}
|
||||
|
||||
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 id = -1;
|
||||
int match = 0;
|
||||
|
||||
jchild = json_first_child(jid);
|
||||
while(jchild) {
|
||||
jchild1 = json_first_child(jchild);
|
||||
while(jchild1) {
|
||||
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->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 alectoWS1700Init(void) {
|
||||
|
||||
protocol_register(&alecto_ws1700);
|
||||
protocol_set_id(alecto_ws1700, "alecto_ws1700");
|
||||
protocol_device_add(alecto_ws1700, "alecto_ws1700", "Alecto WS1700 Weather Stations");
|
||||
protocol_device_add(alecto_ws1700, "iboutique", "iBoutique Weather Stations");
|
||||
alecto_ws1700->devtype = WEATHER;
|
||||
alecto_ws1700->hwtype = RF433;
|
||||
alecto_ws1700->minrawlen = RAW_LENGTH;
|
||||
alecto_ws1700->maxrawlen = RAW_LENGTH;
|
||||
alecto_ws1700->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
alecto_ws1700->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&alecto_ws1700->options, 't', "temperature", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
options_add(&alecto_ws1700->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "[0-9]");
|
||||
options_add(&alecto_ws1700->options, 'h', "humidity", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "[0-9]");
|
||||
options_add(&alecto_ws1700->options, 'b', "battery", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[01]$");
|
||||
|
||||
// options_add(&alecto_ws1700->options, 0, "decimals", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_ws1700->options, 0, "temperature-offset", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "[0-9]");
|
||||
options_add(&alecto_ws1700->options, 0, "humidity-offset", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "[0-9]");
|
||||
options_add(&alecto_ws1700->options, 0, "temperature-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_ws1700->options, 0, "humidity-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_ws1700->options, 0, "show-humidity", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
options_add(&alecto_ws1700->options, 0, "show-temperature", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
options_add(&alecto_ws1700->options, 0, "show-battery", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
|
||||
alecto_ws1700->parseCode=&parseCode;
|
||||
alecto_ws1700->checkValues=&checkValues;
|
||||
alecto_ws1700->validate=&validate;
|
||||
alecto_ws1700->gc=&gc;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "alecto_ws1700";
|
||||
module->version = "2.5";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
alectoWS1700Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_WS1700_H_
|
||||
#define _PROTOCOL_WS1700_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *alecto_ws1700;
|
||||
void alectoWS1700Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "alecto_wsd17.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 14
|
||||
#define MIN_PULSE_LENGTH 265
|
||||
#define AVG_PULSE_LENGTH 270
|
||||
#define MAX_PULSE_LENGTH 275
|
||||
#define RAW_LENGTH 74
|
||||
|
||||
typedef struct settings_t {
|
||||
double id;
|
||||
double temp;
|
||||
struct settings_t *next;
|
||||
} settings_t;
|
||||
|
||||
static struct settings_t *settings = NULL;
|
||||
|
||||
static int validate(void) {
|
||||
if(alecto_wsd17->rawlen == RAW_LENGTH) {
|
||||
if(alecto_wsd17->raw[alecto_wsd17->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
alecto_wsd17->raw[alecto_wsd17->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, id = 0, binary[RAW_LENGTH/2];
|
||||
double temp_offset = 0.0, temperature = 0.0;
|
||||
|
||||
if(alecto_wsd17->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "alecto_wsd17: parsecode - invalid parameter passed %d", alecto_wsd17->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=1;x<alecto_wsd17->rawlen-1;x+=2) {
|
||||
if(alecto_wsd17->raw[x] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
id = binToDecRev(binary, 0, 11);
|
||||
temperature = binToDecRev(binary, 16, 27);
|
||||
|
||||
struct settings_t *tmp = settings;
|
||||
while(tmp) {
|
||||
if(fabs(tmp->id-id) < EPSILON) {
|
||||
temp_offset = tmp->temp;
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
temperature += temp_offset;
|
||||
|
||||
alecto_wsd17->message = json_mkobject();
|
||||
json_append_member(alecto_wsd17->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(alecto_wsd17->message, "temperature", json_mknumber(temperature/10, 1));
|
||||
}
|
||||
|
||||
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 id = -1;
|
||||
int match = 0;
|
||||
|
||||
jchild = json_first_child(jid);
|
||||
while(jchild) {
|
||||
jchild1 = json_first_child(jchild);
|
||||
while(jchild1) {
|
||||
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->temp = 0;
|
||||
|
||||
json_find_number(jvalues, "temperature-offset", &snode->temp);
|
||||
|
||||
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 alectoWSD17Init(void) {
|
||||
protocol_register(&alecto_wsd17);
|
||||
protocol_set_id(alecto_wsd17, "alecto_wsd17");
|
||||
protocol_device_add(alecto_wsd17, "alecto_wsd17", "Alecto WSD-17 Weather Stations");
|
||||
alecto_wsd17->devtype = WEATHER;
|
||||
alecto_wsd17->hwtype = RF433;
|
||||
alecto_wsd17->minrawlen = RAW_LENGTH;
|
||||
alecto_wsd17->maxrawlen = RAW_LENGTH;
|
||||
alecto_wsd17->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
alecto_wsd17->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&alecto_wsd17->options, 't', "temperature", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
options_add(&alecto_wsd17->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "[0-9]");
|
||||
|
||||
// options_add(&alecto_wsd17->options, 0, "decimals", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_wsd17->options, 0, "temperature-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_wsd17->options, 0, "temperature-offset", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "[0-9]");
|
||||
options_add(&alecto_wsd17->options, 0, "show-temperature", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
|
||||
alecto_wsd17->parseCode=&parseCode;
|
||||
alecto_wsd17->checkValues=&checkValues;
|
||||
alecto_wsd17->validate=&validate;
|
||||
alecto_wsd17->gc=&gc;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "alecto_wsd17";
|
||||
module->version = "1.1";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
alectoWSD17Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ALECTO_WSD17_H_
|
||||
#define _PROTOCOL_ALECTO_WSD17_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *alecto_wsd17;
|
||||
void alectoWSD17Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & Tommybear1979
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "alecto_wx500.h"
|
||||
//
|
||||
// Protocol characteristics: SYNC bit: 526/8942, Logical 0: 526/1578, Logical 1: 526/3419
|
||||
//
|
||||
#define PULSE_MULTIPLIER 16
|
||||
#define MIN_PULSE_LENGTH 235
|
||||
#define AVG_PULSE_LENGTH 255
|
||||
#define MAX_PULSE_LENGTH 275
|
||||
#define ZERO_PULSE 2104
|
||||
#define ONE_PULSE 3945
|
||||
#define AVG_PULSE (ZERO_PULSE+ONE_PULSE)/2
|
||||
#define RAW_LENGTH 74
|
||||
|
||||
typedef struct settings_t {
|
||||
double id;
|
||||
double temp;
|
||||
double humi;
|
||||
struct settings_t *next;
|
||||
} settings_t;
|
||||
|
||||
static struct settings_t *settings = NULL;
|
||||
|
||||
static int validate(void) {
|
||||
if(alecto_wx500->rawlen == RAW_LENGTH) {
|
||||
if(alecto_wx500->raw[alecto_wx500->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
alecto_wx500->raw[alecto_wx500->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, type = 0, id = 0, binary[RAW_LENGTH/2];
|
||||
double temp_offset = 0.0, humi_offset = 0.0;
|
||||
double humidity = 0.0, temperature = 0.0;
|
||||
int winddir = 0, windavg = 0, windgust = 0;
|
||||
int /*rain = 0, */battery = 0;
|
||||
int n0 = 0, n1 = 0, n2 = 0, n3 = 0;
|
||||
int n4 = 0, n5 = 0, n6 = 0, n7 = 0, n8 = 0;
|
||||
int checksum = 1;
|
||||
|
||||
if(alecto_wx500->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "alecto_wx500: parsecode - invalid parameter passed %d", alecto_wx500->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=1;x<alecto_wx500->rawlen;x+=2) {
|
||||
if(alecto_wx500->raw[x] > AVG_PULSE) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
n8=binToDec(binary, 32, 36);
|
||||
n7=binToDec(binary, 28, 31);
|
||||
n6=binToDec(binary, 24, 27);
|
||||
n5=binToDec(binary, 20, 23);
|
||||
n4=binToDec(binary, 16, 19);
|
||||
n3=binToDec(binary, 12, 15);
|
||||
n2=binToDec(binary, 8, 11);
|
||||
n1=binToDec(binary, 4, 7);
|
||||
n0=binToDec(binary, 0, 3);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if((n2 & 0x6) != 0x6) {
|
||||
type = 0x1;
|
||||
checksum = (0xf-n0-n1-n2-n3-n4-n5-n6-n7) & 0xf;
|
||||
if(n8 != checksum) {
|
||||
type=0x5;
|
||||
return;
|
||||
}
|
||||
//Wind average * 0.2
|
||||
} else if(n3 == 0x1) {
|
||||
type = 0x2;
|
||||
checksum = (0xf-n0-n1-n2-n3-n4-n5-n6-n7) & 0xf;
|
||||
if(n8 != checksum){
|
||||
type=0x5;
|
||||
return;
|
||||
}
|
||||
//Wind direction & gust
|
||||
} else if((n3 & 0x7) == 0x7) {
|
||||
type = 0x3;
|
||||
checksum = (0xf-n0-n1-n2-n3-n4-n5-n6-n7) & 0xf;
|
||||
if(n8 != checksum) {
|
||||
type=0x5;
|
||||
return;
|
||||
}
|
||||
//Rain
|
||||
} else if(n3 == 0x3) {
|
||||
type = 0x4;
|
||||
checksum = (0x7+n0+n1+n2+n3+n4+n5+n6+n7) & 0xf;
|
||||
if(n8 != checksum){
|
||||
type = 0x5;
|
||||
return;
|
||||
}
|
||||
//Catch
|
||||
} else {
|
||||
type = 0x5;
|
||||
return;
|
||||
}
|
||||
|
||||
alecto_wx500->message = json_mkobject();
|
||||
switch(type) {
|
||||
case 1:
|
||||
id = binToDec(binary, 0, 7);
|
||||
temperature = (double)(binToSigned(binary, 12, 23)) / 10.0;
|
||||
humidity = (binToDec(binary, 28, 31) * 10) + binToDec(binary, 24,27);
|
||||
battery = !binary[8];
|
||||
|
||||
temperature += temp_offset;
|
||||
humidity += humi_offset;
|
||||
|
||||
json_append_member(alecto_wx500->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(alecto_wx500->message, "temperature", json_mknumber(temperature, 1));
|
||||
json_append_member(alecto_wx500->message, "humidity", json_mknumber(humidity, 1));
|
||||
json_append_member(alecto_wx500->message, "battery", json_mknumber(battery, 0));
|
||||
break;
|
||||
case 2:
|
||||
id = binToDec(binary, 0, 7);
|
||||
windavg = binToDec(binary, 24, 31) * 2;
|
||||
battery = !binary[8];
|
||||
|
||||
json_append_member(alecto_wx500->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(alecto_wx500->message, "windavg", json_mknumber((double)windavg/10, 1));
|
||||
json_append_member(alecto_wx500->message, "battery", json_mknumber(battery, 0));
|
||||
break;
|
||||
case 3:
|
||||
id = binToDec(binary, 0, 7);
|
||||
winddir = binToDec(binary, 15, 23);
|
||||
windgust = binToDec(binary, 24, 31) * 2;
|
||||
battery = !binary[8];
|
||||
|
||||
json_append_member(alecto_wx500->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(alecto_wx500->message, "winddir", json_mknumber((double)winddir, 0));
|
||||
json_append_member(alecto_wx500->message, "windgust", json_mknumber((double)windgust/10, 1));
|
||||
json_append_member(alecto_wx500->message, "battery", json_mknumber(battery, 0));
|
||||
break;
|
||||
case 4:
|
||||
id = binToDec(binary, 0, 7);
|
||||
/*rain = binToDec(binary, 16, 30) * 5;*/
|
||||
battery = !binary[8];
|
||||
//json_append_member(alecto_wx500->message, "rain", json_mknumber((double)rain/10, 1));
|
||||
json_append_member(alecto_wx500->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(alecto_wx500->message, "battery", json_mknumber(battery, 0));
|
||||
break;
|
||||
default:
|
||||
type=0x5;
|
||||
json_delete(alecto_wx500->message);
|
||||
alecto_wx500->message = NULL;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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 id = -1;
|
||||
int match = 0;
|
||||
|
||||
jchild = json_first_child(jid);
|
||||
while(jchild) {
|
||||
jchild1 = json_first_child(jchild);
|
||||
while(jchild1) {
|
||||
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->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 alectoWX500Init(void) {
|
||||
|
||||
protocol_register(&alecto_wx500);
|
||||
protocol_set_id(alecto_wx500, "alecto_wx500");
|
||||
protocol_device_add(alecto_wx500, "alecto_wx500", "Alecto WX500 Weather Stations");
|
||||
protocol_device_add(alecto_wx500, "auriol_h13726", "Auriol H13726 Weather Stations");
|
||||
protocol_device_add(alecto_wx500, "ventus_wsxxx", "Ventus WSXXX Weather Stations");
|
||||
protocol_device_add(alecto_wx500, "hama_ews1500", "Hama EWS1500 Weather Stations");
|
||||
protocol_device_add(alecto_wx500, "meteoscan_w1XX", "Meteoscan W1XXX Weather Stations");
|
||||
protocol_device_add(alecto_wx500, "balance_rf_ws105", "Balance RF-WS105 Weather Stations");
|
||||
alecto_wx500->devtype = WEATHER;
|
||||
alecto_wx500->hwtype = RF433;
|
||||
alecto_wx500->minrawlen = RAW_LENGTH;
|
||||
alecto_wx500->maxrawlen = RAW_LENGTH;
|
||||
alecto_wx500->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
alecto_wx500->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&alecto_wx500->options, 't', "temperature", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
options_add(&alecto_wx500->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "[0-9]");
|
||||
options_add(&alecto_wx500->options, 'b', "battery", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "[0-9]");
|
||||
options_add(&alecto_wx500->options, 'h', "humidity", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
options_add(&alecto_wx500->options, 'w', "windavg", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
options_add(&alecto_wx500->options, 'd', "winddir", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
options_add(&alecto_wx500->options, 'g', "windgust", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
//options_add(&alecto_wx500->options, 'r', "rain", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
|
||||
// options_add(&alecto_wx500->options, 0, "decimals", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_wx500->options, 0, "temperature-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_wx500->options, 0, "humidity-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_wx500->options, 0, "wind-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&alecto_wx500->options, 0, "humidity-offset", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "[0-9]");
|
||||
options_add(&alecto_wx500->options, 0, "temperature-offset", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "[0-9]");
|
||||
options_add(&alecto_wx500->options, 0, "show-humidity", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
options_add(&alecto_wx500->options, 0, "show-temperature", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
options_add(&alecto_wx500->options, 0, "show-battery", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
options_add(&alecto_wx500->options, 0, "show-wind", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
//options_add(&alecto_wx500->options, 0, "show-rain", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
alecto_wx500->parseCode=&parseCode;
|
||||
alecto_wx500->checkValues=&checkValues;
|
||||
alecto_wx500->validate=&validate;
|
||||
alecto_wx500->gc=&gc;
|
||||
}
|
||||
|
||||
#ifdef MODULAR
|
||||
void compatibility(const char **version, const char **commit) {
|
||||
module->name = "alecto_wx500";
|
||||
module->version = "1.2";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
alectoWX500Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & Tommybear1979
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ALECTO_WX500_H_
|
||||
#define _PROTOCOL_ALECTO_WX500_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *alecto_wx500;
|
||||
void alectoWX500Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & lvdp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "arctech_contact.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 4
|
||||
#define MIN_PULSE_LENGTH 250
|
||||
#define MAX_PULSE_LENGTH 320
|
||||
#define AVG_PULSE_LENGTH 300
|
||||
#define MIN_RAW_LENGTH 132
|
||||
#define MAX_RAW_LENGTH 148
|
||||
#define RAW_LENGTH 148
|
||||
|
||||
static int validate(void) {
|
||||
if(arctech_contact->rawlen == MIN_RAW_LENGTH || arctech_contact->rawlen == MAX_RAW_LENGTH) {
|
||||
if(arctech_contact->raw[arctech_contact->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_contact->raw[arctech_contact->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_contact->raw[1] >= AVG_PULSE_LENGTH*(PULSE_MULTIPLIER*2)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all) {
|
||||
arctech_contact->message = json_mkobject();
|
||||
json_append_member(arctech_contact->message, "id", json_mknumber(id, 0));
|
||||
if(all == 1) {
|
||||
json_append_member(arctech_contact->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(arctech_contact->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
|
||||
if(state == 1) {
|
||||
json_append_member(arctech_contact->message, "state", json_mkstring("opened"));
|
||||
} else {
|
||||
json_append_member(arctech_contact->message, "state", json_mkstring("closed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[MAX_RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(arctech_contact->rawlen>MAX_RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "arctech_contact: parsecode - invalid parameter passed %d", arctech_contact->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<arctech_contact->rawlen;x+=4) {
|
||||
if(arctech_contact->raw[x+3] > AVG_PULSE_LENGTH*PULSE_MULTIPLIER) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int unit = binToDecRev(binary, 28, 31);
|
||||
int state = binary[27];
|
||||
int all = binary[26];
|
||||
int id = binToDecRev(binary, 0, 25);
|
||||
|
||||
createMessage(id, unit, state, all);
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void arctechContactInit(void) {
|
||||
|
||||
protocol_register(&arctech_contact);
|
||||
protocol_set_id(arctech_contact, "arctech_contact");
|
||||
protocol_device_add(arctech_contact, "kaku_contact", "KlikAanKlikUit Contact Sensor");
|
||||
protocol_device_add(arctech_contact, "dio_contact", "D-IO Contact Sensor");
|
||||
|
||||
arctech_contact->devtype = CONTACT;
|
||||
arctech_contact->hwtype = RF433;
|
||||
arctech_contact->minrawlen = MIN_RAW_LENGTH;
|
||||
arctech_contact->maxrawlen = MAX_RAW_LENGTH;
|
||||
arctech_contact->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
arctech_contact->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&arctech_contact->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_contact->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,7}|[1-5][0-9]{7}|6([0-6][0-9]{6}|7(0[0-9]{5}|10([0-7][0-9]{3}|8([0-7][0-9]{2}|8([0-5][0-9]|6[0-3]))))))$");
|
||||
options_add(&arctech_contact->options, 't', "opened", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_contact->options, 'f', "closed", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&arctech_contact->options, 'a', "all", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
arctech_contact->parseCode=&parseCode;
|
||||
arctech_contact->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "arctech_contact";
|
||||
module->version = "2.2";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "38";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
arctechContactInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & ldvp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ARCTECH_CONTACT_H_
|
||||
#define _PROTOCOL_ARCTECH_CONTACT_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *arctech_contact;
|
||||
void arctechContactInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "arctech_dimmer.h"
|
||||
|
||||
#define LEARN_REPEATS 40
|
||||
#define NORMAL_REPEATS 10
|
||||
#define PULSE_MULTIPLIER 4
|
||||
#define MIN_PULSE_LENGTH 250
|
||||
#define MAX_PULSE_LENGTH 320
|
||||
#define AVG_PULSE_LENGTH 300
|
||||
#define RAW_LENGTH 148
|
||||
|
||||
static int validate(void) {
|
||||
if(arctech_dimmer->rawlen == RAW_LENGTH) {
|
||||
if(arctech_dimmer->raw[arctech_dimmer->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_dimmer->raw[arctech_dimmer->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_dimmer->raw[1] >= AVG_PULSE_LENGTH*(PULSE_MULTIPLIER*2)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all, int dimlevel, int learn) {
|
||||
arctech_dimmer->message = json_mkobject();
|
||||
json_append_member(arctech_dimmer->message, "id", json_mknumber(id, 0));
|
||||
|
||||
if(all == 1) {
|
||||
json_append_member(arctech_dimmer->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(arctech_dimmer->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
|
||||
if(dimlevel == 0) {
|
||||
state = 0;
|
||||
} else if(dimlevel > 0) {
|
||||
state = 1;
|
||||
json_append_member(arctech_dimmer->message, "dimlevel", json_mknumber(dimlevel, 0));
|
||||
}
|
||||
|
||||
if(state == 1) {
|
||||
json_append_member(arctech_dimmer->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(arctech_dimmer->message, "state", json_mkstring("off"));
|
||||
}
|
||||
|
||||
if(learn == 1) {
|
||||
arctech_dimmer->txrpt = LEARN_REPEATS;
|
||||
} else {
|
||||
arctech_dimmer->txrpt = NORMAL_REPEATS;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(arctech_dimmer->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "arctech_dimmer: parsecode - invalid parameter passed %d", arctech_dimmer->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<arctech_dimmer->rawlen;x+=4) {
|
||||
if(arctech_dimmer->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int dimlevel = binToDecRev(binary, 32, 35);
|
||||
int unit = binToDecRev(binary, 28, 31);
|
||||
int state = binary[27];
|
||||
int all = binary[26];
|
||||
int id = binToDecRev(binary, 0, 25);
|
||||
|
||||
createMessage(id, unit, state, all, dimlevel, 0);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_dimmer->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_dimmer->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
arctech_dimmer->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
arctech_dimmer->raw[i+3]=(AVG_PULSE_LENGTH*PULSE_MULTIPLIER);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_dimmer->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_dimmer->raw[i+1]=(AVG_PULSE_LENGTH*PULSE_MULTIPLIER);
|
||||
arctech_dimmer->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
arctech_dimmer->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(2,147);
|
||||
}
|
||||
|
||||
static void createStart(void) {
|
||||
arctech_dimmer->raw[0]=AVG_PULSE_LENGTH;
|
||||
arctech_dimmer->raw[1]=(10*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBin(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=((length-i)+1)*4;
|
||||
createHigh(106-x, 106-(x-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createAll(int all) {
|
||||
if(all == 1) {
|
||||
createHigh(106, 109);
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createHigh(110, 113);
|
||||
} else if(state == -1) {
|
||||
arctech_dimmer->raw[110]=(AVG_PULSE_LENGTH);
|
||||
arctech_dimmer->raw[111]=(AVG_PULSE_LENGTH);
|
||||
arctech_dimmer->raw[112]=(AVG_PULSE_LENGTH);
|
||||
arctech_dimmer->raw[113]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBin(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=((length-i)+1)*4;
|
||||
createHigh(130-x, 130-(x-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createDimlevel(int dimlevel) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBin(dimlevel, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=((length-i)+1)*4;
|
||||
createHigh(146-x, 146-(x-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
arctech_dimmer->raw[147]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int checkValues(struct JsonNode *code) {
|
||||
int dimlevel = -1;
|
||||
int max = 15;
|
||||
int min = 0;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "dimlevel-maximum", &itmp) == 0)
|
||||
max = (int)round(itmp);
|
||||
if(json_find_number(code, "dimlevel-minimum", &itmp) == 0)
|
||||
min = (int)round(itmp);
|
||||
if(json_find_number(code, "dimlevel", &itmp) == 0)
|
||||
dimlevel = (int)round(itmp);
|
||||
|
||||
if(min > max) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(dimlevel != -1) {
|
||||
if(dimlevel < min || dimlevel > max) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
int all = 0;
|
||||
int dimlevel = -1;
|
||||
int learn = -1;
|
||||
int max = 15;
|
||||
int min = 0;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "dimlevel-maximum", &itmp) == 0)
|
||||
max = (int)round(itmp);
|
||||
if(json_find_number(code, "dimlevel-minimum", &itmp) == 0)
|
||||
min = (int)round(itmp);
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "dimlevel", &itmp) == 0)
|
||||
dimlevel = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if(json_find_number(code, "learn", &itmp) == 0)
|
||||
learn = 1;
|
||||
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(all > 0 && learn > -1) {
|
||||
logprintf(LOG_ERR, "arctech_dimmer: all and learn cannot be combined");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id == -1 || (unit == -1 && all == 0) || (dimlevel == -1 && state == -1)) {
|
||||
logprintf(LOG_ERR, "arctech_dimmer: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 67108863 || id < 1) {
|
||||
logprintf(LOG_ERR, "arctech_dimmer: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((unit > 15 || unit < 0) && all == 0) {
|
||||
logprintf(LOG_ERR, "arctech_dimmer: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(dimlevel != -1 && (dimlevel > max || dimlevel < min) ) {
|
||||
logprintf(LOG_ERR, "arctech_dimmer: invalid dimlevel range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(dimlevel >= 0 && state == 0) {
|
||||
logprintf(LOG_ERR, "arctech_dimmer: dimlevel and off state cannot be combined");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(unit == -1 && all == 1) {
|
||||
unit = 0;
|
||||
}
|
||||
if(dimlevel >= 0) {
|
||||
state = -1;
|
||||
}
|
||||
createMessage(id, unit, state, all, dimlevel, learn);
|
||||
createStart();
|
||||
clearCode();
|
||||
createId(id);
|
||||
createAll(all);
|
||||
createState(state);
|
||||
createUnit(unit);
|
||||
if(dimlevel > -1) {
|
||||
createDimlevel(dimlevel);
|
||||
}
|
||||
createFooter();
|
||||
arctech_dimmer->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -a --all\t\t\tsend command to all devices with this id\n");
|
||||
printf("\t -d --dimlevel=dimlevel\t\tsend a specific dimlevel\n");
|
||||
printf("\t -l --learn\t\t\tsend multiple streams so dimmer can learn\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void arctechDimmerInit(void) {
|
||||
|
||||
protocol_register(&arctech_dimmer);
|
||||
protocol_set_id(arctech_dimmer, "arctech_dimmer");
|
||||
protocol_device_add(arctech_dimmer, "kaku_dimmer", "KlikAanKlikUit Dimmers");
|
||||
arctech_dimmer->devtype = DIMMER;
|
||||
arctech_dimmer->hwtype = RF433;
|
||||
arctech_dimmer->txrpt = NORMAL_REPEATS;
|
||||
arctech_dimmer->minrawlen = RAW_LENGTH;
|
||||
arctech_dimmer->maxrawlen = RAW_LENGTH;
|
||||
arctech_dimmer->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
arctech_dimmer->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&arctech_dimmer->options, 'd', "dimlevel", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_dimmer->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_dimmer->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,7}|[1-5][0-9]{7}|6([0-6][0-9]{6}|7(0[0-9]{5}|10([0-7][0-9]{3}|8([0-7][0-9]{2}|8([0-5][0-9]|6[0-3]))))))$");
|
||||
options_add(&arctech_dimmer->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_dimmer->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_dimmer->options, 'a', "all", OPTION_OPT_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&arctech_dimmer->options, 'l', "learn", OPTION_NO_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&arctech_dimmer->options, 0, "dimlevel-minimum", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_dimmer->options, 0, "dimlevel-maximum", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)15, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_dimmer->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&arctech_dimmer->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
arctech_dimmer->parseCode=&parseCode;
|
||||
arctech_dimmer->createCode=&createCode;
|
||||
arctech_dimmer->printHelp=&printHelp;
|
||||
arctech_dimmer->checkValues=&checkValues;
|
||||
arctech_dimmer->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "arctech_dimmer";
|
||||
module->version = "3.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
arctechDimmerInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ARCTECH_DIMMER_H_
|
||||
#define _PROTOCOL_ARCTECH_DIMMER_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *arctech_dimmer;
|
||||
void arctechDimmerInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & lvdp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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 "arctech_dusk.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 250
|
||||
#define MAX_PULSE_LENGTH 282
|
||||
#define AVG_PULSE_LENGTH 277
|
||||
#define RAW_LENGTH 132
|
||||
|
||||
static int validate(void) {
|
||||
if(arctech_dusk->rawlen == RAW_LENGTH) {
|
||||
if(arctech_dusk->raw[arctech_dusk->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_dusk->raw[arctech_dusk->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_dusk->raw[1] >= AVG_PULSE_LENGTH*(PULSE_MULTIPLIER*3)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all) {
|
||||
arctech_dusk->message = json_mkobject();
|
||||
json_append_member(arctech_dusk->message, "id", json_mknumber(id, 0));
|
||||
if(all == 1) {
|
||||
json_append_member(arctech_dusk->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(arctech_dusk->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
|
||||
if(state == 1) {
|
||||
json_append_member(arctech_dusk->message, "state", json_mkstring("dusk"));
|
||||
} else {
|
||||
json_append_member(arctech_dusk->message, "state", json_mkstring("dawn"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(arctech_dusk->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "arctech_dusk: parsecode - invalid parameter passed %d", arctech_dusk->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<arctech_dusk->rawlen;x+=4) {
|
||||
if(arctech_dusk->raw[x+3] > AVG_PULSE_LENGTH*PULSE_MULTIPLIER) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int unit = binToDecRev(binary, 28, 31);
|
||||
int state = binary[27];
|
||||
int all = binary[26];
|
||||
int id = binToDecRev(binary, 0, 25);
|
||||
|
||||
createMessage(id, unit, state, all);
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void arctechDuskInit(void) {
|
||||
|
||||
protocol_register(&arctech_dusk);
|
||||
protocol_set_id(arctech_dusk, "arctech_dusk");
|
||||
protocol_device_add(arctech_dusk, "kaku_dusk", "KlikAanKlikUit Dusk Sensor");
|
||||
arctech_dusk->devtype = DUSK;
|
||||
arctech_dusk->hwtype = RF433;
|
||||
arctech_dusk->minrawlen = RAW_LENGTH;
|
||||
arctech_dusk->maxrawlen = RAW_LENGTH;
|
||||
arctech_dusk->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
arctech_dusk->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&arctech_dusk->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_dusk->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,7}|[1-5][0-9]{7}|6([0-6][0-9]{6}|7(0[0-9]{5}|10([0-7][0-9]{3}|8([0-7][0-9]{2}|8([0-5][0-9]|6[0-3]))))))$");
|
||||
options_add(&arctech_dusk->options, 't', "dusk", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_dusk->options, 'f', "dawn", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
arctech_dusk->parseCode=&parseCode;
|
||||
arctech_dusk->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "arctech_dusk";
|
||||
module->version = "2.2";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
arctechDuskInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & ldvp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ARCTECH_DUSK_H_
|
||||
#define _PROTOCOL_ARCTECH_DUSK_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *arctech_dusk;
|
||||
void arctechDuskInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & lvdp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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 "arctech_motion.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 250
|
||||
#define MAX_PULSE_LENGTH 284
|
||||
#define AVG_PULSE_LENGTH 279
|
||||
#define RAW_LENGTH 132
|
||||
|
||||
static int validate(void) {
|
||||
if(arctech_motion->rawlen == RAW_LENGTH) {
|
||||
if(arctech_motion->raw[arctech_motion->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_motion->raw[arctech_motion->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_motion->raw[1] >= AVG_PULSE_LENGTH*(PULSE_MULTIPLIER*3)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all) {
|
||||
arctech_motion->message = json_mkobject();
|
||||
json_append_member(arctech_motion->message, "id", json_mknumber(id, 0));
|
||||
if(all == 1) {
|
||||
json_append_member(arctech_motion->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(arctech_motion->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
|
||||
if(state == 1) {
|
||||
json_append_member(arctech_motion->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(arctech_motion->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(arctech_motion->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "arctech_motion: parsecode - invalid parameter passed %d", arctech_motion->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<arctech_motion->rawlen;x+=4) {
|
||||
if(arctech_motion->raw[x+3] > AVG_PULSE_LENGTH*PULSE_MULTIPLIER) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int unit = binToDecRev(binary, 28, 31);
|
||||
int state = binary[27];
|
||||
int all = binary[26];
|
||||
int id = binToDecRev(binary, 0, 25);
|
||||
|
||||
createMessage(id, unit, state, all);
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void arctechMotionInit(void) {
|
||||
|
||||
protocol_register(&arctech_motion);
|
||||
protocol_set_id(arctech_motion, "arctech_motion");
|
||||
protocol_device_add(arctech_motion, "kaku_motion", "KlikAanKlikUit Motion Sensor");
|
||||
arctech_motion->devtype = MOTION;
|
||||
arctech_motion->hwtype = RF433;
|
||||
arctech_motion->minrawlen = RAW_LENGTH;
|
||||
arctech_motion->maxrawlen = RAW_LENGTH;
|
||||
arctech_motion->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
arctech_motion->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&arctech_motion->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_motion->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,7}|[1-5][0-9]{7}|6([0-6][0-9]{6}|7(0[0-9]{5}|10([0-7][0-9]{3}|8([0-7][0-9]{2}|8([0-5][0-9]|6[0-3]))))))$");
|
||||
options_add(&arctech_motion->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_motion->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
arctech_motion->parseCode=&parseCode;
|
||||
arctech_motion->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "arctech_motion";
|
||||
module->version = "2.2";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
arctechMotionInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & lvdp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ARCTECH_MOTION_H_
|
||||
#define _PROTOCOL_ARCTECH_MOTION_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *arctech_motion;
|
||||
void arctechMotionInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "arctech_screen.h"
|
||||
|
||||
#define LEARN_REPEATS 40
|
||||
#define NORMAL_REPEATS 10
|
||||
#define PULSE_MULTIPLIER 5
|
||||
#define MIN_PULSE_LENGTH 250
|
||||
#define MAX_PULSE_LENGTH 320
|
||||
#define AVG_PULSE_LENGTH 300
|
||||
#define RAW_LENGTH 132
|
||||
|
||||
static int validate(void) {
|
||||
if(arctech_screen->rawlen == RAW_LENGTH) {
|
||||
if(arctech_screen->raw[arctech_screen->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_screen->raw[arctech_screen->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_screen->raw[1] >= AVG_PULSE_LENGTH*(PULSE_MULTIPLIER*1.5)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all, int learn) {
|
||||
arctech_screen->message = json_mkobject();
|
||||
json_append_member(arctech_screen->message, "id", json_mknumber(id, 0));
|
||||
if(all == 1) {
|
||||
json_append_member(arctech_screen->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(arctech_screen->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
|
||||
if(state == 1) {
|
||||
json_append_member(arctech_screen->message, "state", json_mkstring("up"));
|
||||
} else {
|
||||
json_append_member(arctech_screen->message, "state", json_mkstring("down"));
|
||||
}
|
||||
|
||||
if(learn == 1) {
|
||||
arctech_screen->txrpt = LEARN_REPEATS;
|
||||
} else {
|
||||
arctech_screen->txrpt = NORMAL_REPEATS;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(arctech_screen->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "arctech_screen: parsecode - invalid parameter passed %d", arctech_screen->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<arctech_screen->rawlen;x+=4) {
|
||||
if(arctech_screen->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int unit = binToDecRev(binary, 28, 31);
|
||||
int state = binary[27];
|
||||
int all = binary[26];
|
||||
int id = binToDecRev(binary, 0, 25);
|
||||
|
||||
createMessage(id, unit, state, all, 0);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_screen->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_screen->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
arctech_screen->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(2, 132);
|
||||
}
|
||||
|
||||
static void createStart(void) {
|
||||
arctech_screen->raw[0]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen->raw[1]=(9*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBin(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=((length-i)+1)*4;
|
||||
createHigh(106-x, 106-(x-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createAll(int all) {
|
||||
if(all == 1) {
|
||||
createHigh(106, 109);
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createHigh(110, 113);
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBin(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=((length-i)+1)*4;
|
||||
createHigh(130-x, 130-(x-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
arctech_screen->raw[131]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
int all = 0;
|
||||
int learn = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if(json_find_number(code, "down", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "up", &itmp) == 0)
|
||||
state=1;
|
||||
if(json_find_number(code, "learn", &itmp) == 0)
|
||||
learn = 1;
|
||||
|
||||
if(all > 0 && learn > -1) {
|
||||
logprintf(LOG_ERR, "arctech_screen: all and learn cannot be combined");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id == -1 || (unit == -1 && all == 0) || state == -1) {
|
||||
logprintf(LOG_ERR, "arctech_screen: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 67108863 || id < 1) {
|
||||
logprintf(LOG_ERR, "arctech_screen: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((unit > 15 || unit < 0) && all == 0) {
|
||||
logprintf(LOG_ERR, "arctech_screen: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(unit == -1 && all == 1) {
|
||||
unit = 0;
|
||||
}
|
||||
createMessage(id, unit, state, all, learn);
|
||||
createStart();
|
||||
clearCode();
|
||||
createId(id);
|
||||
createAll(all);
|
||||
createState(state);
|
||||
createUnit(unit);
|
||||
createFooter();
|
||||
arctech_screen->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --up\t\t\tsend an up signal\n");
|
||||
printf("\t -f --down\t\t\tsend an down signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -a --all\t\t\tsend command to all devices with this id\n");
|
||||
printf("\t -l --learn\t\t\tsend multiple streams so screen can learn\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void arctechScreenInit(void) {
|
||||
|
||||
protocol_register(&arctech_screen);
|
||||
protocol_set_id(arctech_screen, "arctech_screen");
|
||||
protocol_device_add(arctech_screen, "kaku_screen", "KlikAanKlikUit Screens");
|
||||
protocol_device_add(arctech_screen, "dio_screen", "DI-O Screens");
|
||||
arctech_screen->devtype = SCREEN;
|
||||
arctech_screen->hwtype = RF433;
|
||||
arctech_screen->txrpt = NORMAL_REPEATS;
|
||||
arctech_screen->minrawlen = RAW_LENGTH;
|
||||
arctech_screen->maxrawlen = RAW_LENGTH;
|
||||
arctech_screen->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
arctech_screen->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&arctech_screen->options, 't', "up", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_screen->options, 'f', "down", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_screen->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_screen->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,7}|[1-5][0-9]{7}|6([0-6][0-9]{6}|7(0[0-9]{5}|10([0-7][0-9]{3}|8([0-7][0-9]{2}|8([0-5][0-9]|6[0-3]))))))$");
|
||||
options_add(&arctech_screen->options, 'a', "all", OPTION_OPT_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&arctech_screen->options, 'l', "learn", OPTION_NO_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&arctech_screen->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&arctech_screen->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
arctech_screen->parseCode=&parseCode;
|
||||
arctech_screen->createCode=&createCode;
|
||||
arctech_screen->printHelp=&printHelp;
|
||||
arctech_screen->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "arctech_screen";
|
||||
module->version = "3.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
arctechScreenInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ARCTECH_SCREEN_H_
|
||||
#define _PROTOCOL_ARCTECH_SCREEN_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *arctech_screen;
|
||||
void arctechScreenInit(void);
|
||||
|
||||
#endif
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "arctech_screen_old.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 310
|
||||
#define MAX_PULSE_LENGTH 350
|
||||
#define AVG_PULSE_LENGTH 335
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(arctech_screen_old->rawlen == RAW_LENGTH) {
|
||||
if(arctech_screen_old->raw[arctech_screen_old->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_screen_old->raw[arctech_screen_old->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state) {
|
||||
arctech_screen_old->message = json_mkobject();
|
||||
json_append_member(arctech_screen_old->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(arctech_screen_old->message, "unit", json_mknumber(unit, 0));
|
||||
if(state == 1)
|
||||
json_append_member(arctech_screen_old->message, "state", json_mkstring("up"));
|
||||
else
|
||||
json_append_member(arctech_screen_old->message, "state", json_mkstring("down"));
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
int len = (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2));
|
||||
|
||||
if(arctech_screen_old->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "arctech_screen_old: parsecode - invalid parameter passed %d", arctech_screen_old->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<arctech_screen_old->rawlen-2;x+=4) {
|
||||
if(arctech_screen_old->raw[x+3] > len) {
|
||||
binary[i++] = 0;
|
||||
} else {
|
||||
binary[i++] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int unit = binToDec(binary, 0, 3);
|
||||
int state = binary[11];
|
||||
int id = binToDec(binary, 4, 8);
|
||||
createMessage(id, unit, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_screen_old->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen_old->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
arctech_screen_old->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
arctech_screen_old->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_screen_old->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen_old->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
arctech_screen_old->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen_old->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHigh(0,35);
|
||||
createLow(36,47);
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createLow(x, x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createLow(16+x, 16+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createHigh(44,47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
arctech_screen_old->raw[48]=(AVG_PULSE_LENGTH);
|
||||
arctech_screen_old->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "down", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "up", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(id == -1 || unit == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "arctech_screen_old: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 31 || id < 0) {
|
||||
logprintf(LOG_ERR, "arctech_screen_old: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 15 || unit < 0) {
|
||||
logprintf(LOG_ERR, "arctech_screen_old: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, unit, state);
|
||||
clearCode();
|
||||
createUnit(unit);
|
||||
createId(id);
|
||||
createState(state);
|
||||
createFooter();
|
||||
arctech_screen_old->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --up\t\t\tsend an up signal\n");
|
||||
printf("\t -f --down\t\t\tsend an down signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void arctechScreenOldInit(void) {
|
||||
|
||||
protocol_register(&arctech_screen_old);
|
||||
protocol_set_id(arctech_screen_old, "arctech_screen_old");
|
||||
protocol_device_add(arctech_screen_old, "kaku_screen_old", "Old KlikAanKlikUit Screens");
|
||||
arctech_screen_old->devtype = SCREEN;
|
||||
arctech_screen_old->hwtype = RF433;
|
||||
arctech_screen_old->minrawlen = RAW_LENGTH;
|
||||
arctech_screen_old->maxrawlen = RAW_LENGTH;
|
||||
arctech_screen_old->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
arctech_screen_old->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&arctech_screen_old->options, 't', "up", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_screen_old->options, 'f', "down", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_screen_old->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_screen_old->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
|
||||
options_add(&arctech_screen_old->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&arctech_screen_old->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
arctech_screen_old->parseCode=&parseCode;
|
||||
arctech_screen_old->createCode=&createCode;
|
||||
arctech_screen_old->printHelp=&printHelp;
|
||||
arctech_screen_old->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "arctech_screen_old";
|
||||
module->version = "2.5";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
arctechScreenOldInit();
|
||||
}
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ARCTECH_SCREEN_OLD_H_
|
||||
#define _PROTOCOL_ARCTECH_SCREEN_OLD_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *arctech_screen_old;
|
||||
void arctechScreenOldInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "arctech_switch.h"
|
||||
|
||||
#define LEARN_REPEATS 40
|
||||
#define NORMAL_REPEATS 10
|
||||
#define PULSE_MULTIPLIER 4
|
||||
#define MIN_PULSE_LENGTH 250
|
||||
#define MAX_PULSE_LENGTH 320
|
||||
#define AVG_PULSE_LENGTH 315
|
||||
#define RAW_LENGTH 132
|
||||
|
||||
static int validate(void) {
|
||||
if(arctech_switch->rawlen == RAW_LENGTH) {
|
||||
if(arctech_switch->raw[arctech_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_switch->raw[arctech_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_switch->raw[1] >= AVG_PULSE_LENGTH*(PULSE_MULTIPLIER*1.5)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all, int learn) {
|
||||
arctech_switch->message = json_mkobject();
|
||||
|
||||
json_append_member(arctech_switch->message, "id", json_mknumber(id, 0));
|
||||
|
||||
if(all == 1) {
|
||||
json_append_member(arctech_switch->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(arctech_switch->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
|
||||
if(state == 1) {
|
||||
json_append_member(arctech_switch->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(arctech_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
|
||||
if(learn == 1) {
|
||||
arctech_switch->txrpt = LEARN_REPEATS;
|
||||
} else {
|
||||
arctech_switch->txrpt = NORMAL_REPEATS;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(arctech_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "arctech_switch: parsecode - invalid parameter passed %d", arctech_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<arctech_switch->rawlen;x+=4) {
|
||||
if(arctech_switch->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int unit = binToDecRev(binary, 28, 31);
|
||||
int state = binary[27];
|
||||
int all = binary[26];
|
||||
int id = binToDecRev(binary, 0, 25);
|
||||
|
||||
createMessage(id, unit, state, all, 0);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch->raw[i+3]=(AVG_PULSE_LENGTH*PULSE_MULTIPLIER);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch->raw[i+1]=(AVG_PULSE_LENGTH*PULSE_MULTIPLIER);
|
||||
arctech_switch->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(2, 131);
|
||||
}
|
||||
|
||||
static void createStart(void) {
|
||||
arctech_switch->raw[0]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch->raw[1]=(9*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBin(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=((length-i)+1)*4;
|
||||
createHigh(106-x, 106-(x-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createAll(int all) {
|
||||
if(all == 1) {
|
||||
createHigh(106, 109);
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createHigh(110, 113);
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBin(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=((length-i)+1)*4;
|
||||
createHigh(130-x, 130-(x-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
arctech_switch->raw[131]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
int all = 0;
|
||||
int learn = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
if(json_find_number(code, "learn", &itmp) == 0)
|
||||
learn = 1;
|
||||
|
||||
if(all > 0 && learn > -1) {
|
||||
logprintf(LOG_ERR, "arctech_switch: all and learn cannot be combined");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id == -1 || (unit == -1 && all == 0) || state == -1) {
|
||||
logprintf(LOG_ERR, "arctech_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 67108863 || id < 1) {
|
||||
logprintf(LOG_ERR, "arctech_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((unit > 15 || unit < 0) && all == 0) {
|
||||
logprintf(LOG_ERR, "arctech_switch: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(unit == -1 && all == 1) {
|
||||
unit = 0;
|
||||
}
|
||||
createMessage(id, unit, state, all, learn);
|
||||
createStart();
|
||||
clearCode();
|
||||
createId(id);
|
||||
createAll(all);
|
||||
createState(state);
|
||||
createUnit(unit);
|
||||
createFooter();
|
||||
arctech_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -a --all\t\t\tsend command to all devices with this id\n");
|
||||
printf("\t -l --learn\t\t\tsend multiple streams so switch can learn\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void arctechSwitchInit(void) {
|
||||
protocol_register(&arctech_switch);
|
||||
protocol_set_id(arctech_switch, "arctech_switch");
|
||||
protocol_device_add(arctech_switch, "kaku_switch", "KlikAanKlikUit Switches");
|
||||
protocol_device_add(arctech_switch, "dio_switch", "D-IO Switches");
|
||||
protocol_device_add(arctech_switch, "nexa_switch", "Nexa Switches");
|
||||
protocol_device_add(arctech_switch, "coco_switch", "CoCo Technologies Switches");
|
||||
protocol_device_add(arctech_switch, "intertechno_switch", "Intertechno Switches");
|
||||
arctech_switch->devtype = SWITCH;
|
||||
arctech_switch->hwtype = RF433;
|
||||
arctech_switch->txrpt = NORMAL_REPEATS;
|
||||
arctech_switch->minrawlen = RAW_LENGTH;
|
||||
arctech_switch->maxrawlen = RAW_LENGTH;
|
||||
arctech_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
arctech_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&arctech_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_switch->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,7}|[1-5][0-9]{7}|6([0-6][0-9]{6}|7(0[0-9]{5}|10([0-7][0-9]{3}|8([0-7][0-9]{2}|8([0-5][0-9]|6[0-3]))))))$");
|
||||
options_add(&arctech_switch->options, 'a', "all", OPTION_OPT_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&arctech_switch->options, 'l', "learn", OPTION_NO_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&arctech_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&arctech_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
arctech_switch->parseCode=&parseCode;
|
||||
arctech_switch->createCode=&createCode;
|
||||
arctech_switch->printHelp=&printHelp;
|
||||
arctech_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "arctech_switch";
|
||||
module->version = "3.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
arctechSwitchInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ARCTECH_SWITCH_H_
|
||||
#define _PROTOCOL_ARCTECH_SWITCH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *arctech_switch;
|
||||
void arctechSwitchInit(void);
|
||||
|
||||
#endif
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "arctech_switch_old.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 310
|
||||
#define MAX_PULSE_LENGTH 405
|
||||
#define AVG_PULSE_LENGTH 335
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(arctech_switch_old->rawlen == RAW_LENGTH) {
|
||||
if(arctech_switch_old->raw[arctech_switch_old->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
arctech_switch_old->raw[arctech_switch_old->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state) {
|
||||
arctech_switch_old->message = json_mkobject();
|
||||
json_append_member(arctech_switch_old->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(arctech_switch_old->message, "unit", json_mknumber(unit, 0));
|
||||
if(state == 1)
|
||||
json_append_member(arctech_switch_old->message, "state", json_mkstring("on"));
|
||||
else
|
||||
json_append_member(arctech_switch_old->message, "state", json_mkstring("off"));
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
int len = (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2));
|
||||
|
||||
if(arctech_switch_old->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "arctech_switch_old: parsecode - invalid parameter passed %d", arctech_switch_old->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<arctech_switch_old->rawlen-3;x+=4) {
|
||||
// valid telegrams must consist of 0110 and 1001 blocks
|
||||
int low_high = 0;
|
||||
if(arctech_switch_old->raw[x] > len) {
|
||||
low_high |= 1;
|
||||
}
|
||||
if(arctech_switch_old->raw[x+1] > len) {
|
||||
low_high |= 2;
|
||||
}
|
||||
if(arctech_switch_old->raw[x+2] > len) {
|
||||
low_high |= 4;
|
||||
}
|
||||
if(arctech_switch_old->raw[x+3] > len) {
|
||||
low_high |= 8;
|
||||
}
|
||||
switch(low_high) {
|
||||
case 6:
|
||||
binary[i++] = 1;
|
||||
break;
|
||||
case 10:
|
||||
binary[i++] = 0;
|
||||
break;
|
||||
default:
|
||||
return; // invalid telegram
|
||||
}
|
||||
}
|
||||
|
||||
int unit = binToDec(binary, 0, 3);
|
||||
int state = binary[11];
|
||||
int id = binToDec(binary, 4, 8);
|
||||
createMessage(id, unit, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_switch_old->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch_old->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
arctech_switch_old->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
arctech_switch_old->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
arctech_switch_old->raw[i]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch_old->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
arctech_switch_old->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch_old->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHigh(0,35);
|
||||
createLow(36,47);
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createLow(x, x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createLow(16+x, 16+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createHigh(44,47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
arctech_switch_old->raw[48]=(AVG_PULSE_LENGTH);
|
||||
arctech_switch_old->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(id == -1 || unit == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "arctech_switch_old: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 31 || id < 0) {
|
||||
logprintf(LOG_ERR, "arctech_switch_old: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 15 || unit < 0) {
|
||||
logprintf(LOG_ERR, "arctech_switch_old: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, unit, state);
|
||||
clearCode();
|
||||
createUnit(unit);
|
||||
createId(id);
|
||||
createState(state);
|
||||
createFooter();
|
||||
arctech_switch_old->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void arctechSwitchOldInit(void) {
|
||||
|
||||
protocol_register(&arctech_switch_old);
|
||||
protocol_set_id(arctech_switch_old, "arctech_switch_old");
|
||||
protocol_device_add(arctech_switch_old, "kaku_switch_old", "Old KlikAanKlikUit Switches");
|
||||
protocol_device_add(arctech_switch_old, "cogex", "Cogex Switches");
|
||||
protocol_device_add(arctech_switch_old, "intertechno_old", "Old Intertechno Switches");
|
||||
protocol_device_add(arctech_switch_old, "byebyestandby", "Bye Bye Standby Switches");
|
||||
protocol_device_add(arctech_switch_old, "duwi", "Düwi Terminal Switches");
|
||||
arctech_switch_old->devtype = SWITCH;
|
||||
arctech_switch_old->hwtype = RF433;
|
||||
arctech_switch_old->minrawlen = RAW_LENGTH;
|
||||
arctech_switch_old->maxrawlen = RAW_LENGTH;
|
||||
arctech_switch_old->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
arctech_switch_old->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&arctech_switch_old->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_switch_old->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&arctech_switch_old->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[1][0-5])$");
|
||||
options_add(&arctech_switch_old->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
|
||||
options_add(&arctech_switch_old->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&arctech_switch_old->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
arctech_switch_old->parseCode=&parseCode;
|
||||
arctech_switch_old->createCode=&createCode;
|
||||
arctech_switch_old->printHelp=&printHelp;
|
||||
arctech_switch_old->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "arctech_switch_old";
|
||||
module->version = "2.5";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
arctechSwitchOldInit();
|
||||
}
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ARCTECH_SWITCH_OLD_H_
|
||||
#define _PROTOCOL_ARCTECH_SWITCH_OLD_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *arctech_switch_old;
|
||||
void arctechSwitchOldInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
Copyright (C) 2014 Bram1337 & CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "auriol.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 13
|
||||
#define MIN_PULSE_LENGTH 264
|
||||
#define MAX_PULSE_LENGTH 274
|
||||
#define AVG_PULSE_LENGTH 269
|
||||
#define RAW_LENGTH 66
|
||||
|
||||
typedef struct settings_t {
|
||||
double id;
|
||||
double temp;
|
||||
struct settings_t *next;
|
||||
} settings_t;
|
||||
|
||||
static struct settings_t *settings = NULL;
|
||||
|
||||
static int validate(void) {
|
||||
if(auriol->rawlen == RAW_LENGTH) {
|
||||
if(auriol->raw[auriol->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
auriol->raw[auriol->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, binary[RAW_LENGTH/2];
|
||||
int channel = 0, id = 0, battery = 0;
|
||||
double temp_offset = 0.0, temperature = 0.0;
|
||||
|
||||
if(auriol->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "auriol: parsecode - invalid parameter passed %d", auriol->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=1;x<auriol->rawlen-2;x+=2) {
|
||||
if(auriol->raw[x] > AVG_PULSE_LENGTH*PULSE_MULTIPLIER) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
id = binToDecRev(binary, 0, 7);
|
||||
battery = binary[8];
|
||||
channel = 1 + binToDecRev(binary, 10, 11); // channel as id
|
||||
temperature = (double)binToSignedRev(binary, 12, 23)/10;
|
||||
// checksum = (double)binToDecRev(binary, 24, 31); been unable to deciper it
|
||||
struct settings_t *tmp = settings;
|
||||
while(tmp) {
|
||||
if(fabs(tmp->id-id) < EPSILON) {
|
||||
temp_offset = tmp->temp;
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
temperature += temp_offset;
|
||||
|
||||
if(channel != 4) {
|
||||
auriol->message = json_mkobject();
|
||||
json_append_member(auriol->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(auriol->message, "temperature", json_mknumber(temperature, 1));
|
||||
json_append_member(auriol->message, "battery", json_mknumber(battery, 0));
|
||||
json_append_member(auriol->message, "channel", json_mknumber(channel, 0));
|
||||
}
|
||||
}
|
||||
|
||||
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 id = -1;
|
||||
int match = 0;
|
||||
|
||||
jchild = json_first_child(jid);
|
||||
while(jchild) {
|
||||
jchild1 = json_first_child(jchild);
|
||||
while(jchild1) {
|
||||
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->temp = 0;
|
||||
|
||||
json_find_number(jvalues, "temperature-offset", &snode->temp);
|
||||
|
||||
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 auriolInit(void) {
|
||||
|
||||
protocol_register(&auriol);
|
||||
protocol_set_id(auriol, "auriol");
|
||||
protocol_device_add(auriol, "auriol", "Auriol Weather Stations");
|
||||
auriol->devtype = WEATHER;
|
||||
auriol->hwtype = RF433;
|
||||
auriol->minrawlen = RAW_LENGTH;
|
||||
auriol->maxrawlen = RAW_LENGTH;
|
||||
auriol->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
auriol->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&auriol->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "[0-9]");
|
||||
options_add(&auriol->options, 'c', "channel", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "[1-3]");
|
||||
options_add(&auriol->options, 't', "temperature", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,3}$");
|
||||
options_add(&auriol->options, 'b', "battery", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[01]$");
|
||||
|
||||
// options_add(&auriol->options, 0, "decimals", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&auriol->options, 0, "temperature-offset", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)0, "[0-9]");
|
||||
options_add(&auriol->options, 0, "temperature-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "[0-9]");
|
||||
options_add(&auriol->options, 0, "show-temperature", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
options_add(&auriol->options, 0, "show-battery", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
|
||||
auriol->parseCode=&parseCode;
|
||||
auriol->checkValues=&checkValues;
|
||||
auriol->validate=&validate;
|
||||
auriol->gc=&gc;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "auriol";
|
||||
module->version = "2.3";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
auriolInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 Bram1337 & CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_AURIOL_H_
|
||||
#define _PROTOCOL_AURIOL_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *auriol;
|
||||
void auriolInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo-rasp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "beamish_switch.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 4
|
||||
#define NORMAL_REPEATS 10
|
||||
#define MIN_PULSE_LENGTH 318
|
||||
#define MAX_PULSE_LENGTH 328
|
||||
#define AVG_PULSE_LENGTH 323
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int map[7] = {0, 192, 48, 12, 3, 15, 195};
|
||||
|
||||
static int validate(void) {
|
||||
if(beamish_switch->rawlen == RAW_LENGTH) {
|
||||
if(beamish_switch->raw[beamish_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
beamish_switch->raw[beamish_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all) {
|
||||
beamish_switch->message = json_mkobject();
|
||||
json_append_member(beamish_switch->message, "id", json_mknumber(id, 0));
|
||||
if(all == 1) {
|
||||
json_append_member(beamish_switch->message, "all", json_mknumber(1, 0));
|
||||
} else {
|
||||
json_append_member(beamish_switch->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
if(state == 0) {
|
||||
json_append_member(beamish_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
if(state == 1) {
|
||||
json_append_member(beamish_switch->message, "state", json_mkstring("on"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, y = 0, binary[RAW_LENGTH/2];
|
||||
int id = -1, state = -1, unit = -1, all = 0, code = 0;
|
||||
|
||||
if(beamish_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "beamish_switch: parsecode - invalid parameter passed %d", beamish_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<beamish_switch->rawlen;x+=2) {
|
||||
if(beamish_switch->raw[x] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
id = binToDecRev(binary, 0, 15);
|
||||
code = binToDecRev(binary, 16, 23);
|
||||
|
||||
for(y=0;y<7;y++) {
|
||||
if(map[y] == code) {
|
||||
unit = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(unit == 5) {
|
||||
state = 1;
|
||||
all = 1;
|
||||
}
|
||||
if(unit == 6) {
|
||||
state = 0;
|
||||
all = 1;
|
||||
}
|
||||
|
||||
createMessage(id, unit, state, all);
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
beamish_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
beamish_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
beamish_switch->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
beamish_switch->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHigh(0,47);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createLow(31-(x+1), 31-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createLow(47-(x+1), 47-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
beamish_switch->raw[48]=(AVG_PULSE_LENGTH);
|
||||
beamish_switch->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
int all = 0;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = 1;
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(id == -1 || (unit == -1 && all == 0) || (state == -1 && all == 1)) {
|
||||
logprintf(LOG_ERR, "beamish_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 65535 || id < 1) {
|
||||
logprintf(LOG_ERR, "beamish_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((unit > 4 || unit < 1) && all == 0) {
|
||||
logprintf(LOG_ERR, "beamish_switch: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(all == 1 && state == 1)
|
||||
unit = 5;
|
||||
if(all == 1 && state == 0)
|
||||
unit = 6;
|
||||
|
||||
createMessage(id, unit, state, all);
|
||||
clearCode();
|
||||
createId(id);
|
||||
unit = map[unit];
|
||||
createUnit(unit);
|
||||
createFooter();
|
||||
beamish_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -a --all\t\t\tsend command to all devices with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void beamishSwitchInit(void) {
|
||||
|
||||
protocol_register(&beamish_switch);
|
||||
protocol_set_id(beamish_switch, "beamish_switch");
|
||||
protocol_device_add(beamish_switch, "beamish_switch", "beamish_switch Switches");
|
||||
beamish_switch->devtype = SWITCH;
|
||||
beamish_switch->hwtype = RF433;
|
||||
beamish_switch->txrpt = NORMAL_REPEATS;
|
||||
beamish_switch->minrawlen = RAW_LENGTH;
|
||||
beamish_switch->maxrawlen = RAW_LENGTH;
|
||||
beamish_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
beamish_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&beamish_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&beamish_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&beamish_switch->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([1-4])$");
|
||||
options_add(&beamish_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$");
|
||||
options_add(&beamish_switch->options, 'a', "all", OPTION_NO_VALUE, 0, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&beamish_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&beamish_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
beamish_switch->parseCode=&parseCode;
|
||||
beamish_switch->createCode=&createCode;
|
||||
beamish_switch->printHelp=&printHelp;
|
||||
beamish_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "beamish_switch";
|
||||
module->version = "1.2";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
beamishSwitchInit();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo-rasp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_BEAMISH_SWITCH_H_
|
||||
#define _PROTOCOL_BEAMISH_SWITCH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *beamish_switch;
|
||||
void beamishSwitchInit(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "clarus.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 160
|
||||
#define MAX_PULSE_LENGTH 200
|
||||
#define AVG_PULSE_LENGTH 180
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(clarus_switch->rawlen == RAW_LENGTH) {
|
||||
if(clarus_switch->raw[clarus_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
clarus_switch->raw[clarus_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(const char *id, int unit, int state) {
|
||||
clarus_switch->message = json_mkobject();
|
||||
json_append_member(clarus_switch->message, "id", json_mkstring(id));
|
||||
json_append_member(clarus_switch->message, "unit", json_mknumber(unit, 0));
|
||||
if(state == 2)
|
||||
json_append_member(clarus_switch->message, "state", json_mkstring("on"));
|
||||
else
|
||||
json_append_member(clarus_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, z = 65, binary[RAW_LENGTH/4];
|
||||
char id[3];
|
||||
|
||||
if(clarus_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "clarus_switch: parsecode - invalid parameter passed %d", clarus_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert the one's and zero's into binary */
|
||||
for(x=0;x<clarus_switch->rawlen-2;x+=4) {
|
||||
if(clarus_switch->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4]=1;
|
||||
} else if(clarus_switch->raw[x+0] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4]=2;
|
||||
} else {
|
||||
binary[x/4]=0;
|
||||
}
|
||||
}
|
||||
|
||||
for(x=9;x>=5;--x) {
|
||||
if(binary[x] == 2) {
|
||||
break;
|
||||
}
|
||||
z++;
|
||||
}
|
||||
|
||||
int unit = binToDecRev(binary, 0, 5);
|
||||
int state = binary[11];
|
||||
int y = binToDecRev(binary, 6, 9);
|
||||
sprintf(&id[0], "%c%d", z, y);
|
||||
|
||||
createMessage(id, unit, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
clarus_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createMed(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
clarus_switch->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
clarus_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(0,47);
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(23-(x+3), 23-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createId(const char *id) {
|
||||
int l = ((int)(id[0]))-65;
|
||||
int y = atoi(&id[1]);
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(y, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
x=i*4;
|
||||
if(binary[i]==1) {
|
||||
createHigh(39-(x+3), 39-x);
|
||||
}
|
||||
}
|
||||
x=(l*4);
|
||||
createMed(39-(x+3), 39-x);
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createMed(40,43);
|
||||
createHigh(44,47);
|
||||
} else {
|
||||
createHigh(40,43);
|
||||
createMed(44,47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
clarus_switch->raw[48]=(AVG_PULSE_LENGTH);
|
||||
clarus_switch->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
const char *id = NULL;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
double itmp;
|
||||
char *stmp;
|
||||
|
||||
if(json_find_string(code, "id", &stmp) == 0)
|
||||
id = stmp;
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
|
||||
if(id == NULL || unit == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "clarus_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if((int)(id[0]) < 65 || (int)(id[0]) > 70) {
|
||||
logprintf(LOG_ERR, "clarus_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(atoi(&id[1]) < 0 || atoi(&id[1]) > 31) {
|
||||
logprintf(LOG_ERR, "clarus_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 63 || unit < 0) {
|
||||
logprintf(LOG_ERR, "clarus_switch: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, unit, ((state == 2 || state == 1) ? 2 : 0));
|
||||
clearCode();
|
||||
createUnit(unit);
|
||||
createId(id);
|
||||
createState(state);
|
||||
createFooter();
|
||||
clarus_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void clarusSwitchInit(void) {
|
||||
|
||||
protocol_register(&clarus_switch);
|
||||
protocol_set_id(clarus_switch, "clarus_switch");
|
||||
protocol_device_add(clarus_switch, "clarus_switch", "Clarus Switches");
|
||||
clarus_switch->devtype = SWITCH;
|
||||
clarus_switch->hwtype = RF433;
|
||||
clarus_switch->minrawlen = RAW_LENGTH;
|
||||
clarus_switch->maxrawlen = RAW_LENGTH;
|
||||
clarus_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
clarus_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&clarus_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&clarus_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&clarus_switch->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]|[1-5][0-9]|6[0-3])$");
|
||||
options_add(&clarus_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_STRING, NULL, "^[ABCDEF](3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
|
||||
options_add(&clarus_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&clarus_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
clarus_switch->parseCode=&parseCode;
|
||||
clarus_switch->createCode=&createCode;
|
||||
clarus_switch->printHelp=&printHelp;
|
||||
clarus_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "clarus_switch";
|
||||
module->version = "2.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
clarusSwitchInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_CLARUS_H_
|
||||
#define _PROTOCOL_CLARUS_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *clarus_switch;
|
||||
void clarusSwitchInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "cleverwatts.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 4
|
||||
#define MIN_PULSE_LENGTH 265
|
||||
#define MAX_PULSE_LENGTH 274
|
||||
#define AVG_PULSE_LENGTH 269
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(cleverwatts->rawlen == RAW_LENGTH) {
|
||||
if(cleverwatts->raw[cleverwatts->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
cleverwatts->raw[cleverwatts->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all) {
|
||||
cleverwatts->message = json_mkobject();
|
||||
json_append_member(cleverwatts->message, "id", json_mknumber(id, 0));
|
||||
if(all == 0) {
|
||||
json_append_member(cleverwatts->message, "all", json_mknumber(1, 0));
|
||||
} else {
|
||||
json_append_member(cleverwatts->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
if(state == 0)
|
||||
json_append_member(cleverwatts->message, "state", json_mkstring("on"));
|
||||
else
|
||||
json_append_member(cleverwatts->message, "state", json_mkstring("off"));
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, binary[RAW_LENGTH/2];
|
||||
int id = 0, state = 0, unit = 0, all = 0;
|
||||
|
||||
if(cleverwatts->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "cleverwatts: parsecode - invalid parameter passed %d", cleverwatts->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=1;x<cleverwatts->rawlen-1;x+=2) {
|
||||
if(cleverwatts->raw[x] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
id = binToDecRev(binary, 0, 19);
|
||||
state = binary[20];
|
||||
unit = binToDecRev(binary, 21, 22);
|
||||
all = binary[23];
|
||||
|
||||
createMessage(id, unit, state, all);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
cleverwatts->raw[i]=(AVG_PULSE_LENGTH);
|
||||
cleverwatts->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
cleverwatts->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
cleverwatts->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHigh(0,47);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createLow(39-(x+1), 39-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createAll(int all) {
|
||||
if(all == 0) {
|
||||
createLow(46, 47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createLow(40, 41);
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createLow(45-(x+1), 45-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
cleverwatts->raw[48]=(AVG_PULSE_LENGTH);
|
||||
cleverwatts->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
int all = 0;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=1;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=0;
|
||||
|
||||
if(id == -1 || (unit == -1 && all == 0) || state == -1) {
|
||||
logprintf(LOG_ERR, "cleverwatts: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 1048575 || id < 1) {
|
||||
logprintf(LOG_ERR, "cleverwatts: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((unit > 3 || unit < 0) && all == 0) {
|
||||
logprintf(LOG_ERR, "cleverwatts: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(unit == -1 && all == 1) {
|
||||
unit = 3;
|
||||
}
|
||||
createMessage(id, unit, state, all ^ 1);
|
||||
clearCode();
|
||||
createId(id);
|
||||
createState(state);
|
||||
createUnit(unit);
|
||||
createAll(all);
|
||||
createFooter();
|
||||
cleverwatts->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -a --all\t\t\tsend command to all devices with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void cleverwattsInit(void) {
|
||||
|
||||
protocol_register(&cleverwatts);
|
||||
protocol_set_id(cleverwatts, "cleverwatts");
|
||||
protocol_device_add(cleverwatts, "cleverwatts", "Cleverwatts Switches");
|
||||
cleverwatts->devtype = SWITCH;
|
||||
cleverwatts->hwtype = RF433;
|
||||
cleverwatts->minrawlen = RAW_LENGTH;
|
||||
cleverwatts->maxrawlen = RAW_LENGTH;
|
||||
cleverwatts->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
cleverwatts->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&cleverwatts->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&cleverwatts->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&cleverwatts->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-3])$");
|
||||
options_add(&cleverwatts->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,6}|10([0-3][0-9]{4}|4([0-7][0-9]{3}|8([0-4][0-9]{2}|5([0-6][0-9]|7[0-5])))))$");
|
||||
options_add(&cleverwatts->options, 'a', "all", OPTION_OPT_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&cleverwatts->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&cleverwatts->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
cleverwatts->parseCode=&parseCode;
|
||||
cleverwatts->createCode=&createCode;
|
||||
cleverwatts->printHelp=&printHelp;
|
||||
cleverwatts->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "cleverwatts";
|
||||
module->version = "1.1";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
cleverwattsInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_CLEVERWATTS_H_
|
||||
#define _PROTOCOL_CLEVERWATTS_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *cleverwatts;
|
||||
void cleverwattsInit(void);
|
||||
|
||||
#endif
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & Bram1337
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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 "conrad_rsl_contact.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 5
|
||||
#define MIN_PULSE_LENGTH 185
|
||||
#define MAX_PULSE_LENGTH 195
|
||||
#define AVG_PULSE_LENGTH 190
|
||||
#define RAW_LENGTH 66
|
||||
|
||||
static int validate(void) {
|
||||
if(conrad_rsl_contact->rawlen == RAW_LENGTH) {
|
||||
if(conrad_rsl_contact->raw[conrad_rsl_contact->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
conrad_rsl_contact->raw[conrad_rsl_contact->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int state) {
|
||||
conrad_rsl_contact->message = json_mkobject();
|
||||
json_append_member(conrad_rsl_contact->message, "id", json_mknumber(id, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(conrad_rsl_contact->message, "state", json_mkstring("opened"));
|
||||
} else {
|
||||
json_append_member(conrad_rsl_contact->message, "state", json_mkstring("closed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, binary[RAW_LENGTH/2];
|
||||
|
||||
if(conrad_rsl_contact->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "conrad_rsl_contact: parsecode - invalid parameter passed %d", conrad_rsl_contact->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert the one's and zero's into binary */
|
||||
for(x=0; x<conrad_rsl_contact->rawlen; x+=2) {
|
||||
if(conrad_rsl_contact->raw[x+1] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/2]=1;
|
||||
} else {
|
||||
binary[x/2]=0;
|
||||
}
|
||||
}
|
||||
|
||||
int id = binToDecRev(binary, 6, 31);
|
||||
int check = binToDecRev(binary, 0, 3);
|
||||
int check1 = binary[32];
|
||||
int state = binary[4];
|
||||
|
||||
if(check == 5 && check1 == 1) {
|
||||
createMessage(id, state);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void conradRSLContactInit(void) {
|
||||
|
||||
protocol_register(&conrad_rsl_contact);
|
||||
protocol_set_id(conrad_rsl_contact, "conrad_rsl_contact");
|
||||
protocol_device_add(conrad_rsl_contact, "conrad_rsl_contact", "Conrad RSL Contact Sensor");
|
||||
conrad_rsl_contact->devtype = CONTACT;
|
||||
conrad_rsl_contact->hwtype = RF433;
|
||||
conrad_rsl_contact->minrawlen = RAW_LENGTH;
|
||||
conrad_rsl_contact->maxrawlen = RAW_LENGTH;
|
||||
conrad_rsl_contact->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
conrad_rsl_contact->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&conrad_rsl_contact->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(([0-9]|([1-9][0-9])|([1-9][0-9]{2})|([1-9][0-9]{3})|([1-9][0-9]{4})|([1-9][0-9]{5})|([1-9][0-9]{6})|((6710886[0-3])|(671088[0-5][0-9])|(67108[0-7][0-9]{2})|(6710[0-7][0-9]{3})|(671[0--1][0-9]{4})|(670[0-9]{5})|(6[0-6][0-9]{6})|(0[0-5][0-9]{7}))))$");
|
||||
options_add(&conrad_rsl_contact->options, 't', "opened", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&conrad_rsl_contact->options, 'f', "closed", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
conrad_rsl_contact->parseCode=&parseCode;
|
||||
conrad_rsl_contact->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "conrad_rsl_contact";
|
||||
module->version = "2.3";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
conradRSLContactInit();
|
||||
}
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & Bram1337
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_CONRAD_RSL_CN_H_
|
||||
#define _PROTOCOL_CONRAD_RSL_CN_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *conrad_rsl_contact;
|
||||
void conradRSLContactInit(void);
|
||||
|
||||
#endif
|
||||
+316
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & Bram1337
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "conrad_rsl_switch.h"
|
||||
|
||||
#define LEARN_REPEATS 40
|
||||
#define NORMAL_REPEATS 10
|
||||
#define PULSE_MULTIPLIER 6
|
||||
#define MIN_PULSE_LENGTH 190
|
||||
#define MAX_PULSE_LENGTH 210
|
||||
#define AVG_PULSE_LENGTH 200
|
||||
#define RAW_LENGTH 66
|
||||
|
||||
static int codes[5][4][2];
|
||||
|
||||
static int validate(void) {
|
||||
if(conrad_rsl_switch->rawlen == RAW_LENGTH) {
|
||||
if(conrad_rsl_switch->raw[conrad_rsl_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
conrad_rsl_switch->raw[conrad_rsl_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int learn) {
|
||||
conrad_rsl_switch->message = json_mkobject();
|
||||
|
||||
if(id == 4) {
|
||||
json_append_member(conrad_rsl_switch->message, "all", json_mknumber(1, 0));
|
||||
} else {
|
||||
json_append_member(conrad_rsl_switch->message, "id", json_mknumber(id+1, 0));
|
||||
}
|
||||
json_append_member(conrad_rsl_switch->message, "unit", json_mknumber(unit+1, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(conrad_rsl_switch->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(conrad_rsl_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
if(learn == 1) {
|
||||
conrad_rsl_switch->txrpt = LEARN_REPEATS;
|
||||
} else {
|
||||
conrad_rsl_switch->txrpt = NORMAL_REPEATS;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, binary[RAW_LENGTH/2];
|
||||
int id = 0, unit = 0, state = 0;
|
||||
|
||||
if(conrad_rsl_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "conrad_rsl_switch: parsecode - invalid parameter passed %d", conrad_rsl_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert the one's and zero's into binary */
|
||||
for(x=0;x<conrad_rsl_switch->rawlen;x+=2) {
|
||||
if(conrad_rsl_switch->raw[x+1] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/2]=0;
|
||||
} else {
|
||||
binary[x/2]=1;
|
||||
}
|
||||
}
|
||||
|
||||
int check = binToDecRev(binary, 0, 7);
|
||||
int match = 0;
|
||||
for(id=0;id<5;id++) {
|
||||
for(unit=0;unit<4;unit++) {
|
||||
if(codes[id][unit][0] == check) {
|
||||
state = 0;
|
||||
match = 1;
|
||||
}
|
||||
if(codes[id][unit][1] == check) {
|
||||
state = 1;
|
||||
match = 1;
|
||||
}
|
||||
if(match) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(match) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
createMessage(id, unit, state, 0);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
conrad_rsl_switch->raw[i]=((PULSE_MULTIPLIER+1)*AVG_PULSE_LENGTH);
|
||||
conrad_rsl_switch->raw[i+1]=AVG_PULSE_LENGTH*3;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
conrad_rsl_switch->raw[i]=AVG_PULSE_LENGTH*3;
|
||||
conrad_rsl_switch->raw[i+1]=((PULSE_MULTIPLIER+1)*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
int i = 0, x = 0;
|
||||
createHigh(0,65);
|
||||
// for(i=0;i<65;i+=2) {
|
||||
// x=i*2;
|
||||
// createHigh(x,x+1);
|
||||
// }
|
||||
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
|
||||
length = decToBinRev(23876, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
x=i*2;
|
||||
if(binary[i]==1) {
|
||||
createLow(x+16, x+16+1);
|
||||
} else {
|
||||
createHigh(x+16, x+16+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createId(int id, int unit, int state) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
int code = codes[id][unit][state];
|
||||
|
||||
length = decToBin(code, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
x=i*2;
|
||||
if(binary[i]==1) {
|
||||
createLow(x, x+1);
|
||||
} else {
|
||||
createHigh(x, x+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
conrad_rsl_switch->raw[64]=(AVG_PULSE_LENGTH*3);
|
||||
conrad_rsl_switch->raw[65]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int state = -1;
|
||||
int unit = -1;
|
||||
int all = 0;
|
||||
int learn = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = 1;
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
if(json_find_number(code, "learn", &itmp) == 0)
|
||||
learn = 1;
|
||||
|
||||
if(unit == -1 || (id == -1 && all == 0) || state == -1) {
|
||||
logprintf(LOG_ERR, "conrad_rsl_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if((id > 5 || id < 0) && all == 0) {
|
||||
logprintf(LOG_ERR, "conrad_rsl_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 5 || unit < 0) {
|
||||
logprintf(LOG_ERR, "conrad_rsl_switch: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(all == 1) {
|
||||
id = 5;
|
||||
}
|
||||
id -= 1;
|
||||
unit -= 1;
|
||||
createMessage(id, unit, state, learn);
|
||||
clearCode();
|
||||
createId(id, unit, state);
|
||||
createFooter();
|
||||
conrad_rsl_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -i --id=id\tcontrol a device with this id\n");
|
||||
printf("\t -i --unit=unit\tcontrol a device with this unit\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -a --all\t\t\tsend an all signal\n");
|
||||
printf("\t -l --learn\t\t\tsend multiple streams so switch can learn\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void conradRSLSwitchInit(void) {
|
||||
|
||||
memset(codes, 0, 33);
|
||||
codes[0][0][0] = 190;
|
||||
codes[0][0][1] = 182;
|
||||
codes[0][1][0] = 129;
|
||||
codes[0][1][1] = 142;
|
||||
codes[0][2][0] = 174;
|
||||
codes[0][2][1] = 166;
|
||||
codes[0][3][0] = 158;
|
||||
codes[0][3][1] = 150;
|
||||
|
||||
codes[1][0][0] = 181;
|
||||
codes[1][0][1] = 185;
|
||||
codes[1][1][0] = 141;
|
||||
codes[1][1][1] = 133;
|
||||
codes[1][2][0] = 165;
|
||||
codes[1][2][1] = 169;
|
||||
codes[1][3][0] = 149;
|
||||
codes[1][3][1] = 153;
|
||||
|
||||
codes[2][0][0] = 184;
|
||||
codes[2][0][1] = 176;
|
||||
codes[2][1][0] = 132;
|
||||
codes[2][1][1] = 136;
|
||||
codes[2][2][0] = 168;
|
||||
codes[2][2][1] = 160;
|
||||
codes[2][3][0] = 152;
|
||||
codes[2][3][1] = 144;
|
||||
|
||||
codes[3][0][0] = 178;
|
||||
codes[3][0][1] = 188;
|
||||
codes[3][1][0] = 138;
|
||||
codes[3][1][1] = 130;
|
||||
codes[3][2][0] = 162;
|
||||
codes[3][2][1] = 172;
|
||||
codes[3][3][0] = 146;
|
||||
codes[3][3][1] = 156;
|
||||
|
||||
codes[4][0][0] = 163;
|
||||
codes[4][0][1] = 147;
|
||||
|
||||
protocol_register(&conrad_rsl_switch);
|
||||
protocol_set_id(conrad_rsl_switch, "conrad_rsl_switch");
|
||||
protocol_device_add(conrad_rsl_switch, "conrad_rsl_switch", "Conrad RSL Switches");
|
||||
conrad_rsl_switch->devtype = SWITCH;
|
||||
conrad_rsl_switch->hwtype = RF433;
|
||||
conrad_rsl_switch->txrpt = NORMAL_REPEATS;
|
||||
conrad_rsl_switch->minrawlen = RAW_LENGTH;
|
||||
conrad_rsl_switch->maxrawlen = RAW_LENGTH;
|
||||
conrad_rsl_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
conrad_rsl_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&conrad_rsl_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^[1-4]$");
|
||||
options_add(&conrad_rsl_switch->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^[1-4]$");
|
||||
options_add(&conrad_rsl_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&conrad_rsl_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&conrad_rsl_switch->options, 'a', "all", OPTION_OPT_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&conrad_rsl_switch->options, 'l', "learn", OPTION_NO_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&conrad_rsl_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&conrad_rsl_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
conrad_rsl_switch->parseCode=&parseCode;
|
||||
conrad_rsl_switch->createCode=&createCode;
|
||||
conrad_rsl_switch->printHelp=&printHelp;
|
||||
conrad_rsl_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "conrad_rsl_switch";
|
||||
module->version = "2.3";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
conradRSLSwitchInit();
|
||||
}
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & Bram1337
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_CONRAD_RSL_SW_H_
|
||||
#define _PROTOCOL_CONRAD_RSL_SW_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *conrad_rsl_switch;
|
||||
void conradRSLSwitchInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMo & Rafael
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "../../core/binary.h"
|
||||
#include "../../core/gc.h"
|
||||
#include "../protocol.h"
|
||||
#include "daycom.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 4
|
||||
#define MIN_PULSE_LENGTH 280
|
||||
#define MAX_PULSE_LENGTH 296
|
||||
#define AVG_PULSE_LENGTH 284
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(daycom->rawlen == RAW_LENGTH) {
|
||||
if(daycom->raw[daycom->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
daycom->raw[daycom->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int systemcode, int unit, int state) {
|
||||
daycom->message = json_mkobject();
|
||||
json_append_member(daycom->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(daycom->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(daycom->message, "unit", json_mknumber(unit, 0));
|
||||
if(state == 0) {
|
||||
json_append_member(daycom->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(daycom->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/2], x = 0, i = 0;
|
||||
int id = -1, state = -1, unit = -1, systemcode = -1;
|
||||
|
||||
if(daycom->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "daycom: parsecode - invalid parameter passed %d", daycom->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<daycom->rawlen;x+=2) {
|
||||
if(daycom->raw[x] > AVG_PULSE_LENGTH*(PULSE_MULTIPLIER/2)) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
id = binToDecRev(binary, 0, 5);
|
||||
systemcode = binToDecRev(binary, 6, 19);
|
||||
unit = binToDecRev(binary, 21, 23 );
|
||||
state = binary[20];
|
||||
createMessage(id, systemcode, unit, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
for(i=s;i<=e;i+=2) {
|
||||
daycom->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
daycom->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
for(i=s;i<=e;i+=2) {
|
||||
daycom->raw[i]=(AVG_PULSE_LENGTH);
|
||||
daycom->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHigh(0,47);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createLow(11-(x+1), 11-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(systemcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createLow(39-(x+1), 39-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createLow(47-(x+1), 47-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createLow(40, 41);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void createFooter(void) {
|
||||
daycom->raw[48]=(AVG_PULSE_LENGTH);
|
||||
daycom->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(JsonNode *code) {
|
||||
int id = -1;
|
||||
int systemcode = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=1;
|
||||
if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=0;
|
||||
|
||||
if(id == -1 || systemcode == -1 || unit == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "daycom: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 63 || id < 0) {
|
||||
logprintf(LOG_ERR, "daycom: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 16999 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "daycom: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 7 || unit < 0) {
|
||||
logprintf(LOG_ERR, "daycom: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, systemcode, unit, state);
|
||||
clearCode();
|
||||
createId(id);
|
||||
createSystemCode(systemcode);
|
||||
createState(state);
|
||||
createUnit(unit);
|
||||
createFooter();
|
||||
daycom->rawlen = RAW_LENGTH;
|
||||
state = 0;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -s --systemcode=systemcode\t\t\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --unitcode=unitcode\t\t\tcontrol a device with this unitcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
|
||||
void daycomInit(void) {
|
||||
protocol_register(&daycom);
|
||||
protocol_set_id(daycom, "daycom");
|
||||
protocol_device_add(daycom, "daycom", "Daycom switches");
|
||||
daycom->devtype = SWITCH;
|
||||
daycom->hwtype = RF433;
|
||||
daycom->minrawlen = RAW_LENGTH;
|
||||
daycom->maxrawlen = RAW_LENGTH;
|
||||
daycom->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
daycom->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&daycom->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&daycom->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&daycom->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-7])$");
|
||||
options_add(&daycom->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,4}|1[0-6][0-9]{3})$");
|
||||
options_add(&daycom->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^[0-6]?[0-9]$");
|
||||
|
||||
options_add(&daycom->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
daycom->parseCode=&parseCode;
|
||||
daycom->createCode=&createCode;
|
||||
daycom->printHelp=&printHelp;
|
||||
daycom->validate=&validate;
|
||||
}
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "daycom";
|
||||
module->version = "1.1";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "187";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
daycomInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMo & Rafael
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_DAYCOM_H_
|
||||
#define _PROTOCOL_DAYCOM_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *daycom;
|
||||
void daycomInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "ehome.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 277
|
||||
#define MAX_PULSE_LENGTH 287
|
||||
#define AVG_PULSE_LENGTH 282
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(ehome->rawlen == RAW_LENGTH) {
|
||||
if(ehome->raw[ehome->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
ehome->raw[ehome->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int state) {
|
||||
ehome->message = json_mkobject();
|
||||
json_append_member(ehome->message, "id", json_mknumber(id, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(ehome->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(ehome->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, binary[RAW_LENGTH/4];
|
||||
|
||||
if(ehome->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "ehome: parsecode - invalid parameter passed %d", ehome->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(i=0;i<ehome->rawlen-2;i+=4) {
|
||||
if(ehome->raw[i+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i/4]=1;
|
||||
} else {
|
||||
binary[i/4]=0;
|
||||
}
|
||||
}
|
||||
|
||||
int id = binToDec(binary, 1, 3);
|
||||
int state = binary[0];
|
||||
|
||||
createMessage(id, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
ehome->raw[i]=AVG_PULSE_LENGTH;
|
||||
ehome->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
ehome->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
ehome->raw[i+3]=AVG_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createMed(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
ehome->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
ehome->raw[i+1]=AVG_PULSE_LENGTH;
|
||||
ehome->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
ehome->raw[i+3]=AVG_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
ehome->raw[i]=AVG_PULSE_LENGTH;
|
||||
ehome->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
ehome->raw[i+2]=AVG_PULSE_LENGTH;
|
||||
ehome->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(0,47);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(4+x, 4+(x+3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createMed(0, 3);
|
||||
} else {
|
||||
createHigh(0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
ehome->raw[48]=(AVG_PULSE_LENGTH);
|
||||
ehome->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(id == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "ehome: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 7 || id < 0) {
|
||||
logprintf(LOG_ERR, "ehome: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, state);
|
||||
clearCode();
|
||||
createId(id);
|
||||
createState(state);
|
||||
createFooter();
|
||||
ehome->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void ehomeInit(void) {
|
||||
|
||||
protocol_register(&ehome);
|
||||
protocol_set_id(ehome, "ehome");
|
||||
protocol_device_add(ehome, "ehome", "eHome Switches");
|
||||
ehome->devtype = SWITCH;
|
||||
ehome->hwtype = RF433;
|
||||
ehome->minrawlen = RAW_LENGTH;
|
||||
ehome->maxrawlen = RAW_LENGTH;
|
||||
ehome->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
ehome->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&ehome->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-4])$");
|
||||
options_add(&ehome->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&ehome->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&ehome->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&ehome->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
ehome->parseCode=&parseCode;
|
||||
ehome->createCode=&createCode;
|
||||
ehome->printHelp=&printHelp;
|
||||
ehome->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "ehome";
|
||||
module->version = "1.1";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
ehomeInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_EHOME_H_
|
||||
#define _PROTOCOL_EHOME_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *ehome;
|
||||
void ehomeInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "elro_300_switch.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 4
|
||||
#define MIN_PULSE_LENGTH 297
|
||||
#define MAX_PULSE_LENGTH 307
|
||||
#define AVG_PULSE_LENGTH 302
|
||||
#define RAW_LENGTH 116
|
||||
|
||||
static int validate(void) {
|
||||
if(elro_300_switch->rawlen == RAW_LENGTH) {
|
||||
if(elro_300_switch->raw[elro_300_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
elro_300_switch->raw[elro_300_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates as System message informing the daemon about a received or created message
|
||||
*
|
||||
* systemcode : integer number, the 32 bit system code
|
||||
* unitcode : unit being adressed, integer number
|
||||
* state : either 2 (off) or 1 (on)
|
||||
* group : if 1 this affects a whole group of devices
|
||||
*/
|
||||
static void createMessage(unsigned long long systemcode, int unitcode, int state, int group) {
|
||||
elro_300_switch->message = json_mkobject();
|
||||
//aka address
|
||||
json_append_member(elro_300_switch->message, "systemcode", json_mknumber((double)systemcode, 0));
|
||||
//toggle all or just one unit
|
||||
if(group == 1) {
|
||||
json_append_member(elro_300_switch->message, "all", json_mknumber(group, 0));
|
||||
} else {
|
||||
json_append_member(elro_300_switch->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
}
|
||||
//aka command
|
||||
if(state == 1) {
|
||||
json_append_member(elro_300_switch->message, "state", json_mkstring("on"));
|
||||
}
|
||||
else if(state == 2) {
|
||||
json_append_member(elro_300_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main method when reading a received code
|
||||
* Decodes the received stream
|
||||
*
|
||||
*/
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, binary[RAW_LENGTH/2];
|
||||
|
||||
if(elro_300_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "elro_300_switch: parsecode - invalid parameter passed %d", elro_300_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
//utilize the "code" field
|
||||
//at this point the code field holds translated "0" and "1" codes from the received pulses
|
||||
//this means that we have to combine these ourselves into meaningful values in groups of 2
|
||||
|
||||
for(i=0; i < elro_300_switch->rawlen; i++) {
|
||||
if(elro_300_switch->raw[i] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
if(i&1) {
|
||||
binary[x++] = 1;
|
||||
} else {
|
||||
return; // even pulse lengths must be low
|
||||
}
|
||||
} else if(i&1) {
|
||||
binary[x++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//chunked code now contains "groups of 2" codes for us to handle.
|
||||
unsigned long long systemcode = binToDecRevUl(binary, 11, 42);
|
||||
int groupcode = binToDec(binary, 43, 46);
|
||||
int groupcode2 = binToDec(binary, 49, 50);
|
||||
int unitcode = binToDec(binary, 51, 56);
|
||||
int state = binToDec(binary, 47, 48);
|
||||
int groupRes = 0;
|
||||
|
||||
if(groupcode == 13 && groupcode2 == 2) {
|
||||
groupRes = 0;
|
||||
} else if(groupcode == 3 && groupcode2 == 3) {
|
||||
groupRes = 1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if(state < 1 || state > 2) {
|
||||
return;
|
||||
} else {
|
||||
createMessage(systemcode, unitcode, state, groupRes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a number of "low" entries (302 302). Note that each entry requires 2 raw positions
|
||||
* so e-s should be a multiple of 2
|
||||
* s : start position in the raw code (inclusive)
|
||||
* e : end position in the raw code (inclusive)
|
||||
*/
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
elro_300_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
elro_300_switch->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a number of "high" entries (302 1028). Note that each entry requires 2 raw positions
|
||||
* so e-s should be a multiple of 2
|
||||
* s : start position in the raw code (inclusive)
|
||||
* e : end position in the raw code (inclusive)
|
||||
*/
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
elro_300_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
elro_300_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This simply clears the full length of the code to be all "zeroes" (LOW entries)
|
||||
*/
|
||||
static void elro300ClearCode(void) {
|
||||
createLow(0,116);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the passed number
|
||||
* converts it into raw and inserts them into the raw code at the appropriate position
|
||||
*
|
||||
* systemcode : unsigned integer number, the 32 bit system code
|
||||
*/
|
||||
static void createSystemCode(unsigned long long systemcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
length = decToBinRevUl(systemcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[(length)-i]==1) {
|
||||
x=i*2;
|
||||
createHigh(22+x, 22+x+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the passed number converts it into raw and inserts it into the raw code at the appropriate position
|
||||
*
|
||||
* unitcode : integer number, id of the unit to control
|
||||
*/
|
||||
static void createUnitCode(int unitcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unitcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createHigh(102+x, 102+x+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the passed number converts it into raw and inserts it into the raw code at the appropriate position
|
||||
*
|
||||
* state : integer number, state value to set. can be either 1 (on) or 2 (off)
|
||||
*/
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createHigh(94, 95);
|
||||
createLow(96, 97);
|
||||
}
|
||||
else {
|
||||
createLow(94, 95);
|
||||
createHigh(96, 97);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the first group code portions to the appropriate raw values.
|
||||
* Fro grouped mode this is the equivalent to 1100 and 11, for non-grouped mode 1011 and 01
|
||||
*
|
||||
* group : integer value, 1 means grouped enabled, 0 means disabled
|
||||
*/
|
||||
static void createGroupCode(int group) {
|
||||
if(group == 1) {
|
||||
createHigh(86, 89);
|
||||
createLow(90, 93);
|
||||
createHigh(98, 101);
|
||||
} else {
|
||||
createHigh(86, 87);
|
||||
createLow(88, 89);
|
||||
createHigh(90, 93);
|
||||
createLow(98, 99);
|
||||
createHigh(100, 101);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the (as far as is known) fixed message preamble
|
||||
* First eleven words are the preamble
|
||||
*/
|
||||
static void createPreamble(void) {
|
||||
createHigh(0,3);
|
||||
createLow(4,9);
|
||||
createHigh(10,17);
|
||||
createLow(18,21);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the message trailer (one HIGH) into the raw message
|
||||
*/
|
||||
static void createFooter(void) {
|
||||
elro_300_switch->raw[114]=(AVG_PULSE_LENGTH);
|
||||
elro_300_switch->raw[115]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main method for creating a message based on daemon-passed values in the elro_300_switch protocol.
|
||||
* code : JSON Message containing the received parameters to use for message creation
|
||||
*
|
||||
* returns : EXIT_SUCCESS or EXIT_FAILURE on obvious occasions
|
||||
*/
|
||||
static int createCode(struct JsonNode *code) {
|
||||
unsigned long long systemcode = 0;
|
||||
int unitcode = -1;
|
||||
int group = 0;
|
||||
int state = -1;
|
||||
double itmp;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0) {
|
||||
systemcode = (unsigned long long)itmp;
|
||||
}
|
||||
if(json_find_number(code, "unitcode", &itmp) == 0) {
|
||||
unitcode = (int)round(itmp);
|
||||
}
|
||||
if(json_find_number(code, "all", &itmp) == 0) {
|
||||
group = 1;
|
||||
//on the reference remote, group toggles always used a unit code of 56.
|
||||
//for that reason we are enforcing that here
|
||||
unitcode = 56;
|
||||
}
|
||||
|
||||
if(json_find_number(code, "off", &itmp) == 0) {
|
||||
state=2;
|
||||
}
|
||||
else if(json_find_number(code, "on", &itmp) == 0) {
|
||||
state=1;
|
||||
}
|
||||
|
||||
if(systemcode == 0 || unitcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "elro_300_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 4294967295u || unitcode > 99 || unitcode < 0) {
|
||||
logprintf(LOG_ERR, "elro_300_switch: values out of valid range");
|
||||
} else {
|
||||
createMessage(systemcode, unitcode, state, group);
|
||||
elro300ClearCode();
|
||||
createPreamble();
|
||||
createSystemCode(systemcode);
|
||||
createGroupCode(group);
|
||||
createState(state);
|
||||
createUnitCode(unitcode);
|
||||
createFooter();
|
||||
elro_300_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs help messages directly to the current output target (probably the console)
|
||||
*/
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -a --all\t\t\ttoggle switching all devices on or off\n");
|
||||
printf("\t -u --unitcode=unitcode\t\tcontrol a device with this unitcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Main Init method called to init the protocol and register its functions with pilight
|
||||
*/
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void elro300SwitchInit(void) {
|
||||
|
||||
protocol_register(&elro_300_switch);
|
||||
protocol_set_id(elro_300_switch, "elro_300_switch");
|
||||
protocol_device_add(elro_300_switch, "elro_300_switch", "Elro 300 Series Switches");
|
||||
elro_300_switch->devtype = SWITCH;
|
||||
elro_300_switch->hwtype = RF433;
|
||||
elro_300_switch->minrawlen = RAW_LENGTH;
|
||||
elro_300_switch->maxrawlen = RAW_LENGTH;
|
||||
elro_300_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
elro_300_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&elro_300_switch->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1,9}|[1-3][0-9]{9}|4([01][0-9]{8}|2([0-8][0-9]{7}|9([0-3][0-9]{6}|4([0-8][0-9]{5}|9([0-5][0-9]{4}|6([0-6][0-9]{3}|7([01][0-9]{2}|2([0-8][0-9]|9[0-4])))))))))$");
|
||||
options_add(&elro_300_switch->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^[0-9]{1,2}$");
|
||||
options_add(&elro_300_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&elro_300_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&elro_300_switch->options, 'a', "all", OPTION_OPT_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&elro_300_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&elro_300_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
|
||||
elro_300_switch->parseCode=&parseCode;
|
||||
elro_300_switch->createCode=&createCode;
|
||||
elro_300_switch->printHelp=&printHelp;
|
||||
elro_300_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "elro_300_switch";
|
||||
module->version = "2.3";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
elro300SwitchInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ELRO_300_SWITCH_H_
|
||||
#define _PROTOCOL_ELRO_300_SWITCH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *elro_300_switch;
|
||||
void elro300SwitchInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "elro_400_switch.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 291
|
||||
#define MAX_PULSE_LENGTH 301
|
||||
#define AVG_PULSE_LENGTH 296
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(elro_400_switch->rawlen == RAW_LENGTH) {
|
||||
if(elro_400_switch->raw[elro_400_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
elro_400_switch->raw[elro_400_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int unitcode, int state) {
|
||||
elro_400_switch->message = json_mkobject();
|
||||
json_append_member(elro_400_switch->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(elro_400_switch->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(elro_400_switch->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(elro_400_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, i = 0, binary[RAW_LENGTH/4];
|
||||
|
||||
if(elro_400_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "elro_400_switch: parsecode - invalid parameter passed %d", elro_400_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<elro_400_switch->rawlen-2;x+=4) {
|
||||
if(elro_400_switch->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 0;
|
||||
} else {
|
||||
binary[i++] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int systemcode = binToDecRev(binary, 0, 4);
|
||||
int unitcode = binToDecRev(binary, 5, 9);
|
||||
int state = binary[11];
|
||||
createMessage(systemcode, unitcode, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
elro_400_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
elro_400_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
elro_400_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
elro_400_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
elro_400_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
elro_400_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
elro_400_switch->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
elro_400_switch->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
static void clearCode(void) {
|
||||
createHigh(0,47);
|
||||
}
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(systemcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createLow(19-(x+3), 19-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnitCode(int unitcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unitcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createLow(39-(x+3), 39-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createLow(44, 47);
|
||||
createLow(40, 43);
|
||||
} else {
|
||||
createLow(40, 43);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
elro_400_switch->raw[48]=(AVG_PULSE_LENGTH);
|
||||
elro_400_switch->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int systemcode = -1;
|
||||
int unitcode = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "unitcode", &itmp) == 0)
|
||||
unitcode = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(systemcode == -1 || unitcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "elro_400_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 31 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "elro_400_switch: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unitcode > 31 || unitcode < 0) {
|
||||
logprintf(LOG_ERR, "elro_400_switch: invalid unitcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
clearCode();
|
||||
createSystemCode(systemcode);
|
||||
createUnitCode(unitcode);
|
||||
createState(state);
|
||||
createFooter();
|
||||
elro_400_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --unitcode=unitcode\t\tcontrol a device with this unitcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void elro400SwitchInit(void) {
|
||||
|
||||
protocol_register(&elro_400_switch);
|
||||
protocol_set_id(elro_400_switch, "elro_400_switch");
|
||||
protocol_device_add(elro_400_switch, "elro_400_switch", "Elro 400 Series Switches");
|
||||
elro_400_switch->devtype = SWITCH;
|
||||
elro_400_switch->hwtype = RF433;
|
||||
elro_400_switch->minrawlen = RAW_LENGTH;
|
||||
elro_400_switch->maxrawlen = RAW_LENGTH;
|
||||
elro_400_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
elro_400_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&elro_400_switch->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&elro_400_switch->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&elro_400_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&elro_400_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&elro_400_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&elro_400_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
elro_400_switch->parseCode=&parseCode;
|
||||
elro_400_switch->createCode=&createCode;
|
||||
elro_400_switch->printHelp=&printHelp;
|
||||
elro_400_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "elro_400_switch";
|
||||
module->version = "2.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
elro400SwitchInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ELRO_400_SWITCH_H_
|
||||
#define _PROTOCOL_ELRO_400_SWITCH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *elro_400_switch;
|
||||
void elro400SwitchInit(void);
|
||||
|
||||
#endif
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "elro_800_contact.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 283
|
||||
#define MAX_PULSE_LENGTH 305
|
||||
#define AVG_PULSE_LENGTH 300
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(elro_800_contact->rawlen == RAW_LENGTH) {
|
||||
if(elro_800_contact->raw[elro_800_contact->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
elro_800_contact->raw[elro_800_contact->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int unitcode, int state) {
|
||||
elro_800_contact->message = json_mkobject();
|
||||
json_append_member(elro_800_contact->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(elro_800_contact->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
if(state == 0) {
|
||||
json_append_member(elro_800_contact->message, "state", json_mkstring("opened"));
|
||||
} else {
|
||||
json_append_member(elro_800_contact->message, "state", json_mkstring("closed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(elro_800_contact->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "elro_800_contact: parsecode - invalid parameter passed %d", elro_800_contact->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<elro_800_contact->rawlen-2;x+=4) {
|
||||
if(elro_800_contact->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int systemcode = binToDec(binary, 0, 4);
|
||||
int unitcode = binToDec(binary, 5, 9);
|
||||
int state = binary[11];
|
||||
createMessage(systemcode, unitcode, state);
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void elro800ContactInit(void) {
|
||||
|
||||
protocol_register(&elro_800_contact);
|
||||
protocol_set_id(elro_800_contact, "elro_800_contact");
|
||||
protocol_device_add(elro_800_contact, "elro_800_contact", "Elro Series 800 Contact");
|
||||
elro_800_contact->devtype = CONTACT;
|
||||
elro_800_contact->hwtype = RF433;
|
||||
elro_800_contact->minrawlen = RAW_LENGTH;
|
||||
elro_800_contact->maxrawlen = RAW_LENGTH;
|
||||
elro_800_contact->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
elro_800_contact->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&elro_800_contact->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&elro_800_contact->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&elro_800_contact->options, 't', "opened", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&elro_800_contact->options, 'f', "closed", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
elro_800_contact->parseCode=&parseCode;
|
||||
elro_800_contact->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "elro_800_contact";
|
||||
module->version = "2.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
elro800ContactInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ELRO_800_CONTACT_H_
|
||||
#define _PROTOCOL_ELRO_800_CONTACT_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *elro_800_contact;
|
||||
void elro800ContactInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "elro_800_switch.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 274
|
||||
#define MAX_PULSE_LENGTH 320
|
||||
#define AVG_PULSE_LENGTH 300
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(elro_800_switch->rawlen == RAW_LENGTH) {
|
||||
if(elro_800_switch->raw[elro_800_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
elro_800_switch->raw[elro_800_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int unitcode, int state) {
|
||||
elro_800_switch->message = json_mkobject();
|
||||
json_append_member(elro_800_switch->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(elro_800_switch->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
if(state == 0) {
|
||||
json_append_member(elro_800_switch->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(elro_800_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0;
|
||||
|
||||
if(elro_800_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "elro_800_switch: parsecode - invalid parameter passed %d", elro_800_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<elro_800_switch->rawlen-2;x+=4) {
|
||||
if(elro_800_switch->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4] = 1;
|
||||
} else {
|
||||
binary[x/4] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int systemcode = binToDec(binary, 0, 4);
|
||||
int unitcode = binToDec(binary, 5, 9);
|
||||
int check = binary[10];
|
||||
int state = binary[11];
|
||||
|
||||
// second part of systemcode based on Med
|
||||
for(x=0;x<=16;x+=4) {
|
||||
if(elro_800_switch->raw[x+0] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4] = 1;
|
||||
} else {
|
||||
binary[x/4] = 0;
|
||||
}
|
||||
}
|
||||
int systemcode2 = binToDec(binary, 0, 4);
|
||||
|
||||
systemcode |= (systemcode2<<5);
|
||||
|
||||
if(check != state) {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
elro_800_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createMed(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
elro_800_switch->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
elro_800_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
static void clearCode(void) {
|
||||
createLow(0,47);
|
||||
}
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(systemcode & 0x1F, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(x, x+3);
|
||||
}
|
||||
}
|
||||
|
||||
length = decToBinRev((systemcode>>5) & 0x1F, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createMed(x, x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnitCode(int unitcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unitcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(20+x, 20+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createHigh(44, 47);
|
||||
} else {
|
||||
createHigh(40, 43);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
elro_800_switch->raw[48]=(AVG_PULSE_LENGTH);
|
||||
elro_800_switch->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int systemcode = -1;
|
||||
int unitcode = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "unitcode", &itmp) == 0)
|
||||
unitcode = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=1;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=0;
|
||||
|
||||
if(systemcode == -1 || unitcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "elro_800_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 1023 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "elro_800_switch: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unitcode > 31 || unitcode < 0) {
|
||||
logprintf(LOG_ERR, "elro_800_switch: invalid unitcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
clearCode();
|
||||
createSystemCode(systemcode);
|
||||
createUnitCode(unitcode);
|
||||
createState(state);
|
||||
createFooter();
|
||||
elro_800_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --unitcode=unitcode\t\tcontrol a device with this unitcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void elro800SwitchInit(void) {
|
||||
|
||||
protocol_register(&elro_800_switch);
|
||||
protocol_set_id(elro_800_switch, "elro_800_switch");
|
||||
protocol_device_add(elro_800_switch, "elro_800_switch", "Elro 800 series Switches");
|
||||
protocol_device_add(elro_800_switch, "brennenstuhl", "Brennenstuhl Comfort");
|
||||
protocol_device_add(elro_800_switch, "maxitronic", "Maxi-Tronic FUNK-LIGHT switches");
|
||||
elro_800_switch->devtype = SWITCH;
|
||||
elro_800_switch->hwtype = RF433;
|
||||
elro_800_switch->minrawlen = RAW_LENGTH;
|
||||
elro_800_switch->maxrawlen = RAW_LENGTH;
|
||||
elro_800_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
elro_800_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&elro_800_switch->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^102[0-3]|10[01][0-9]|[0-9]{1,3}$");
|
||||
options_add(&elro_800_switch->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&elro_800_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&elro_800_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&elro_800_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&elro_800_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
elro_800_switch->parseCode=&parseCode;
|
||||
elro_800_switch->createCode=&createCode;
|
||||
elro_800_switch->printHelp=&printHelp;
|
||||
elro_800_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "elro_800_switch";
|
||||
module->version = "2.5";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
elro800SwitchInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_ELRO_800_SWITCH_H_
|
||||
#define _PROTOCOL_ELRO_800_SWITCH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *elro_800_switch;
|
||||
void elro800SwitchInit(void);
|
||||
|
||||
#endif
|
||||
+368
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
Copyright (C) 2015 woutput
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "eurodomest_switch.h"
|
||||
|
||||
// Timing from http://forum.pilight.org/attachment.php?aid=595
|
||||
|
||||
// Increase this value to be more robust, but also create more false positives
|
||||
#define PEAK_TO_PEAK_JITTER 200
|
||||
|
||||
// About 2/3 of the jitter appears to make the pulses longer instead of shorter
|
||||
// The same jitter appears on every pulse type (as may be expected)
|
||||
|
||||
// Short pulse timing
|
||||
#define MIN_SHORT_PULSE_LENGTH (AVG_SHORT_PULSE_LENGTH - 0.333 * PEAK_TO_PEAK_JITTER)
|
||||
#define AVG_SHORT_PULSE_LENGTH 280
|
||||
#define MAX_SHORT_PULSE_LENGTH (AVG_SHORT_PULSE_LENGTH + 0.667 * PEAK_TO_PEAK_JITTER)
|
||||
|
||||
// Medium pulse timing
|
||||
#define MIN_MEDIUM_PULSE_LENGTH (AVG_MEDIUM_PULSE_LENGTH - 0.333 * PEAK_TO_PEAK_JITTER)
|
||||
#define AVG_MEDIUM_PULSE_LENGTH 868
|
||||
#define MAX_MEDIUM_PULSE_LENGTH (AVG_MEDIUM_PULSE_LENGTH + 0.667 * PEAK_TO_PEAK_JITTER)
|
||||
|
||||
// Long pulse timing
|
||||
#define MIN_LONG_PULSE_LENGTH (AVG_LONG_PULSE_LENGTH - 0.333 * PEAK_TO_PEAK_JITTER)
|
||||
#define AVG_LONG_PULSE_LENGTH 9660
|
||||
#define MAX_LONG_PULSE_LENGTH (AVG_LONG_PULSE_LENGTH + 0.667 * PEAK_TO_PEAK_JITTER)
|
||||
|
||||
#define RAW_LENGTH 50
|
||||
// Two pulses per bit, last two pulses are footer
|
||||
#define BINARY_LENGTH 24
|
||||
|
||||
#define LEARN_REPEATS 40
|
||||
#define NORMAL_REPEATS 10
|
||||
|
||||
static int validate(void) {
|
||||
if (eurodomest_switch->rawlen == RAW_LENGTH) {
|
||||
if (eurodomest_switch->raw[eurodomest_switch->rawlen - 1] >= MIN_LONG_PULSE_LENGTH &&
|
||||
eurodomest_switch->raw[eurodomest_switch->rawlen - 1] <= MAX_LONG_PULSE_LENGTH) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state, int all, int learn) {
|
||||
eurodomest_switch->message = json_mkobject();
|
||||
|
||||
json_append_member(eurodomest_switch->message, "id", json_mknumber(id, 0));
|
||||
|
||||
if (all == 1) {
|
||||
json_append_member(eurodomest_switch->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(eurodomest_switch->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
|
||||
if (state == 1) {
|
||||
json_append_member(eurodomest_switch->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(eurodomest_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
|
||||
if (learn == 1) {
|
||||
eurodomest_switch->txrpt = LEARN_REPEATS;
|
||||
} else {
|
||||
eurodomest_switch->txrpt = NORMAL_REPEATS;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[BINARY_LENGTH], x = 0, i = 0;
|
||||
|
||||
for (x = 0; x < eurodomest_switch->rawlen - 2; x += 2) {
|
||||
if ((eurodomest_switch->raw[x] >= MIN_MEDIUM_PULSE_LENGTH) &&
|
||||
(eurodomest_switch->raw[x] <= MAX_MEDIUM_PULSE_LENGTH) &&
|
||||
(eurodomest_switch->raw[x + 1] >= MIN_SHORT_PULSE_LENGTH) &&
|
||||
(eurodomest_switch->raw[x + 1] <= MAX_SHORT_PULSE_LENGTH)) {
|
||||
binary[i++] = 0;
|
||||
} else if ((eurodomest_switch->raw[x] >= MIN_SHORT_PULSE_LENGTH) &&
|
||||
(eurodomest_switch->raw[x] <= MAX_SHORT_PULSE_LENGTH) &&
|
||||
(eurodomest_switch->raw[x + 1] >= MIN_MEDIUM_PULSE_LENGTH) &&
|
||||
(eurodomest_switch->raw[x + 1] <= MAX_MEDIUM_PULSE_LENGTH)) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
return; // decoding failed, return without creating message
|
||||
}
|
||||
}
|
||||
|
||||
// The last 4 bits contain the unit, state and all information
|
||||
|
||||
int unit = 0;
|
||||
int all = 0;
|
||||
int state = 0;
|
||||
|
||||
if (binary[20] == 0 && binary[21] == 0 && binary[22] == 0 && binary[23] == 0) {
|
||||
unit = 1;
|
||||
all = 0;
|
||||
state = 1; // on
|
||||
} else if (binary[20] == 0 && binary[21] == 0 && binary[22] == 0 && binary[23] == 1) {
|
||||
unit = 1;
|
||||
all = 0;
|
||||
state = 0; // off
|
||||
} else if (binary[20] == 0 && binary[21] == 0 && binary[22] == 1 && binary[23] == 1) {
|
||||
unit = 2;
|
||||
all = 0;
|
||||
state = 0; // off
|
||||
} else if (binary[20] == 0 && binary[21] == 0 && binary[22] == 1 && binary[23] == 0) {
|
||||
unit = 2;
|
||||
all = 0;
|
||||
state = 1; // on
|
||||
} else if (binary[20] == 0 && binary[21] == 1 && binary[22] == 0 && binary[23] == 1) {
|
||||
unit = 3;
|
||||
all = 0;
|
||||
state = 0; // off
|
||||
} else if (binary[20] == 0 && binary[21] == 1 && binary[22] == 0 && binary[23] == 0) {
|
||||
unit = 3;
|
||||
all = 0;
|
||||
state = 1; // on
|
||||
} else if (binary[20] == 1 && binary[21] == 0 && binary[22] == 0 && binary[23] == 1) {
|
||||
unit = 4;
|
||||
all = 0;
|
||||
state = 0; // off
|
||||
} else if (binary[20] == 1 && binary[21] == 0 && binary[22] == 0 && binary[23] == 0) {
|
||||
unit = 4;
|
||||
all = 0;
|
||||
state = 1; // on
|
||||
} else if (binary[20] == 1 && binary[21] == 1 && binary[22] == 1 && binary[23] == 0) {
|
||||
unit = 0; // not used, all = 1
|
||||
all = 1;
|
||||
state = 0; // off
|
||||
} else if (binary[20] == 1 && binary[21] == 1 && binary[22] == 0 && binary[23] == 1) {
|
||||
unit = 0; // not used, all = 1
|
||||
all = 1;
|
||||
state = 1; // on
|
||||
} else {
|
||||
return; // decoding failed, return without creating message
|
||||
}
|
||||
|
||||
int id = binToDec(binary, 0, 19);
|
||||
createMessage(id, unit, state, all, 0);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for (i = s; i <= e; i += 2) { // medium - short
|
||||
eurodomest_switch->raw[i] = AVG_MEDIUM_PULSE_LENGTH;
|
||||
eurodomest_switch->raw[i + 1] = AVG_SHORT_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for (i = s; i <= e; i += 2) { // short - medium
|
||||
eurodomest_switch->raw[i] = AVG_SHORT_PULSE_LENGTH;
|
||||
eurodomest_switch->raw[i + 1] = AVG_MEDIUM_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i = 0, x = 0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for (i = 0; i <= length; i++) {
|
||||
if (binary[i] == 0) {
|
||||
x = i * 2;
|
||||
createLow(x, x+1);
|
||||
} else { //so binary[i] == 1
|
||||
x = i * 2;
|
||||
createHigh(x, x + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int createUnitAndStateAndAll(int unit, int state, int all) {
|
||||
if (unit == 1 && state == 0 && all == 0) {
|
||||
createLow(40, 41);
|
||||
createLow(42, 43);
|
||||
createLow(44, 45);
|
||||
createHigh(46, 47);
|
||||
} else if (unit == 1 && state == 1 && all == 0) {
|
||||
createLow(40, 41);
|
||||
createLow(42, 43);
|
||||
createLow(44, 45);
|
||||
createLow(46, 47);
|
||||
} else if (unit == 2 && state == 0 && all == 0) {
|
||||
createLow(40, 41);
|
||||
createLow(42, 43);
|
||||
createHigh(44, 45);
|
||||
createHigh(46, 47);
|
||||
} else if (unit == 2 && state == 1 && all == 0) {
|
||||
createLow(40, 41);
|
||||
createLow(42, 43);
|
||||
createHigh(44, 45);
|
||||
createLow(46, 47);
|
||||
} else if (unit == 3 && state == 0 && all == 0) {
|
||||
createLow(40, 41);
|
||||
createHigh(42, 43);
|
||||
createLow(44, 45);
|
||||
createHigh(46, 47);
|
||||
} else if (unit == 3 && state == 1 && all == 0) {
|
||||
createLow(40, 41);
|
||||
createHigh(42, 43);
|
||||
createLow(44, 45);
|
||||
createLow(46, 47);
|
||||
} else if (unit == 4 && state == 0 && all == 0) {
|
||||
createHigh(40, 41);
|
||||
createLow(42, 43);
|
||||
createLow(44, 45);
|
||||
createHigh(46, 47);
|
||||
} else if (unit == 4 && state == 1 && all == 0) {
|
||||
createHigh(40, 41);
|
||||
createLow(42, 43);
|
||||
createLow(44, 45);
|
||||
createLow(46, 47);
|
||||
} else if (unit == 0 && state == 0 && all == 1) {
|
||||
createHigh(40, 41);
|
||||
createHigh(42, 43);
|
||||
createHigh(44, 45);
|
||||
createLow(46, 47);
|
||||
} else if (unit == 0 && state == 1 && all == 1) {
|
||||
createHigh(40, 41);
|
||||
createHigh(42, 43);
|
||||
createLow(44, 45);
|
||||
createHigh(46, 47);
|
||||
} else {
|
||||
logprintf(LOG_ERR, "eurodomest_switch: incorrect combination of arguments");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
eurodomest_switch->raw[48] = AVG_SHORT_PULSE_LENGTH;
|
||||
eurodomest_switch->raw[49] = AVG_LONG_PULSE_LENGTH;
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
int all = 0;
|
||||
int learn = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if (json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if (json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if (json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if (json_find_number(code, "off", &itmp) == 0)
|
||||
state = 0;
|
||||
else if (json_find_number(code, "on", &itmp) == 0)
|
||||
state = 1;
|
||||
if (json_find_number(code, "learn", &itmp) == 0)
|
||||
learn = 1;
|
||||
|
||||
if (all > 0 && learn > -1) {
|
||||
logprintf(LOG_ERR, "eurodomest_switch: all and learn cannot be combined");
|
||||
return EXIT_FAILURE;
|
||||
} else if (id == -1 || (unit == -1 && all == 0) || state == -1) {
|
||||
logprintf(LOG_ERR, "eurodomest_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if (id > 1048575 || id < 0) {
|
||||
logprintf(LOG_ERR, "eurodomest_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if ((unit > 4 || unit < 1) && all == 0) {
|
||||
logprintf(LOG_ERR, "eurodomest_switch: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if (unit == -1 && all == 1) {
|
||||
unit = 0;
|
||||
}
|
||||
createMessage(id, unit, state, all, learn);
|
||||
createId(id);
|
||||
if (createUnitAndStateAndAll(unit, state, all) == EXIT_FAILURE)
|
||||
return EXIT_FAILURE;
|
||||
createFooter();
|
||||
eurodomest_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -a --all\t\t\tsend command to all devices with this id\n");
|
||||
printf("\t -l --learn\t\t\tsend multiple streams so switch can learn\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void eurodomestSwitchInit(void) {
|
||||
|
||||
protocol_register(&eurodomest_switch);
|
||||
protocol_set_id(eurodomest_switch, "eurodomest_switch");
|
||||
protocol_device_add(eurodomest_switch, "eurodomest_switch", "Eurodomest Switches");
|
||||
eurodomest_switch->devtype = SWITCH;
|
||||
eurodomest_switch->hwtype = RF433;
|
||||
eurodomest_switch->minrawlen = RAW_LENGTH;
|
||||
eurodomest_switch->maxrawlen = RAW_LENGTH;
|
||||
eurodomest_switch->maxgaplen = MAX_LONG_PULSE_LENGTH;
|
||||
eurodomest_switch->mingaplen = MIN_LONG_PULSE_LENGTH;
|
||||
|
||||
options_add(&eurodomest_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&eurodomest_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&eurodomest_switch->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([1-4])$");
|
||||
options_add(&eurodomest_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]{1}|[0-9]{2}|[0-9]{3}|[0-9]{4}|[0-9]{5}|[0-9]{6}|[0-9]{7})$");
|
||||
options_add(&eurodomest_switch->options, 'a', "all", OPTION_OPT_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&eurodomest_switch->options, 'l', "learn", OPTION_NO_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&eurodomest_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]$");
|
||||
options_add(&eurodomest_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]$");
|
||||
|
||||
eurodomest_switch->parseCode = &parseCode;
|
||||
eurodomest_switch->createCode = &createCode;
|
||||
eurodomest_switch->printHelp = &printHelp;
|
||||
eurodomest_switch->validate = &validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "eurodomest_switch";
|
||||
module->version = "1.0";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
eurodomestSwitchInit();
|
||||
}
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2015 woutput
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_EURODOMEST_SWITCH_H_
|
||||
#define _PROTOCOL_EURODOMEST_SWITCH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *eurodomest_switch;
|
||||
void eurodomestSwitchInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMo and Meloen
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "ev1527.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 5
|
||||
#define MIN_PULSE_LENGTH 251
|
||||
#define MAX_PULSE_LENGTH 311
|
||||
#define AVG_PULSE_LENGTH 256
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(ev1527->rawlen == RAW_LENGTH) {
|
||||
if(ev1527->raw[ev1527->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
ev1527->raw[ev1527->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int unitcode, int state) {
|
||||
ev1527->message = json_mkobject();
|
||||
json_append_member(ev1527->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
if(state == 0) {
|
||||
json_append_member(ev1527->message, "state", json_mkstring("opened"));
|
||||
} else {
|
||||
json_append_member(ev1527->message, "state", json_mkstring("closed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/2], x = 0, i = 0;
|
||||
|
||||
if(ev1527->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "ev1527: parsecode - invalid parameter passed %d", ev1527->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<ev1527->rawlen-2;x+=2) {
|
||||
if(ev1527->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int unitcode = binToDec(binary, 0, 19);
|
||||
int state = binary[20];
|
||||
createMessage(unitcode, state);
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void ev1527Init(void) {
|
||||
|
||||
protocol_register(&ev1527);
|
||||
protocol_set_id(ev1527, "ev1527");
|
||||
protocol_device_add(ev1527, "ev1527", "ev1527 contact sensor");
|
||||
ev1527->devtype = CONTACT;
|
||||
ev1527->hwtype = RF433;
|
||||
ev1527->minrawlen = RAW_LENGTH;
|
||||
ev1527->maxrawlen = RAW_LENGTH;
|
||||
ev1527->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
ev1527->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&ev1527->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(104857[0-5]|10485[0-6][0-9]|1048[0-4][0-9][0-9]|104[0-7][0-9]{3}|10[0-3][0-9]{4}|0?[0-9]{1,6})$");
|
||||
options_add(&ev1527->options, 't', "opened", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&ev1527->options, 'f', "closed", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
ev1527->parseCode=&parseCode;
|
||||
ev1527->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "ev1527";
|
||||
module->version = "1.2";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
ev1527Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_EV1527_H_
|
||||
#define _PROTOCOL_EV1527_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *ev1527;
|
||||
void ev1527Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
|
||||
Copyright (C) 2015 CurlyMo & Meloen
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "../../core/binary.h"
|
||||
#include "../../core/gc.h"
|
||||
#include "../protocol.h"
|
||||
#include "heitech.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 270
|
||||
#define MAX_PULSE_LENGTH 290
|
||||
#define AVG_PULSE_LENGTH 280
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(heitech->rawlen == RAW_LENGTH) {
|
||||
if(heitech->raw[heitech->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
heitech->raw[heitech->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int unitcode, int state) {
|
||||
heitech->message = json_mkobject();
|
||||
json_append_member(heitech->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(heitech->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
|
||||
if(state == 0) {
|
||||
json_append_member(heitech->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(heitech->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, binary[RAW_LENGTH/4];
|
||||
|
||||
if(heitech->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "heitech: parsecode - invalid parameter passed %d", heitech->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<heitech->rawlen-2;x+=4) {
|
||||
if(heitech->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4]=1;
|
||||
} else {
|
||||
binary[x/4]=0;
|
||||
}
|
||||
}
|
||||
|
||||
int systemcode = binToDec(binary, 0, 4);
|
||||
int unitcode = binToDec(binary, 5, 9);
|
||||
int check = binary[10];
|
||||
int state = binary[11];
|
||||
|
||||
if(check != state) {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
heitech->raw[i]=AVG_PULSE_LENGTH;
|
||||
heitech->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
heitech->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
heitech->raw[i+3]=AVG_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
heitech->raw[i]=AVG_PULSE_LENGTH;
|
||||
heitech->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
heitech->raw[i+2]=AVG_PULSE_LENGTH;
|
||||
heitech->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(0,47);
|
||||
}
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(systemcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(x, x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnitCode(int unitcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unitcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(20+x, 20+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createHigh(44, 47);
|
||||
} else {
|
||||
createHigh(40, 43);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
heitech->raw[48]=(AVG_PULSE_LENGTH);
|
||||
heitech->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
static int createCode(JsonNode *code) {
|
||||
int systemcode = -1;
|
||||
int unitcode = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "unitcode", &itmp) == 0)
|
||||
unitcode = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=1;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=0;
|
||||
|
||||
if(systemcode == -1 || unitcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "heitech: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 31 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "heitech: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unitcode > 31 || unitcode < 0) {
|
||||
logprintf(LOG_ERR, "heitech: invalid unitcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
clearCode();
|
||||
createSystemCode(systemcode);
|
||||
createUnitCode(unitcode);
|
||||
createState(state);
|
||||
createFooter();
|
||||
heitech->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --unitcode=unitcode\t\tcontrol a device with this unitcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void heitechInit(void) {
|
||||
|
||||
protocol_register(&heitech);
|
||||
protocol_set_id(heitech, "heitech");
|
||||
protocol_device_add(heitech, "heitech", "Heitech series Switches");
|
||||
heitech->devtype = SWITCH;
|
||||
heitech->hwtype = RF433;
|
||||
heitech->minrawlen = RAW_LENGTH;
|
||||
heitech->maxrawlen = RAW_LENGTH;
|
||||
heitech->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
heitech->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&heitech->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&heitech->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&heitech->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&heitech->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&heitech->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
heitech->parseCode=&parseCode;
|
||||
heitech->createCode=&createCode;
|
||||
heitech->printHelp=&printHelp;
|
||||
heitech->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "heitech";
|
||||
module->version = "1.1";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "187";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
heitechInit();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMo & meloen
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_HEITECH_H_
|
||||
#define _PROTOCOL_HEITECH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *heitech;
|
||||
void heitechInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
Copyright (C) 2013 Bram1337 & CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "impuls.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 130
|
||||
#define MAX_PULSE_LENGTH 170
|
||||
#define AVG_PULSE_LENGTH 150
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(impuls->rawlen == RAW_LENGTH) {
|
||||
if(impuls->raw[impuls->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
impuls->raw[impuls->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int programcode, int state) {
|
||||
impuls->message = json_mkobject();
|
||||
json_append_member(impuls->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(impuls->message, "programcode", json_mknumber(programcode, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(impuls->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(impuls->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, binary[RAW_LENGTH/4];
|
||||
|
||||
if(impuls->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "impuls: parsecode - invalid parameter passed %d", impuls->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert the one's and zero's into binary */
|
||||
for(x=0;x<impuls->rawlen-2;x+=4) {
|
||||
if(impuls->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2)) ||
|
||||
impuls->raw[x+0] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4]=1;
|
||||
} else {
|
||||
binary[x/4]=0;
|
||||
}
|
||||
}
|
||||
|
||||
int systemcode = binToDec(binary, 0, 4);
|
||||
int programcode = binToDec(binary, 5, 9);
|
||||
int check = binary[10];
|
||||
int state = binary[11];
|
||||
|
||||
if(check != state) {
|
||||
createMessage(systemcode, programcode, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
impuls->raw[i]=AVG_PULSE_LENGTH;
|
||||
impuls->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
impuls->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
impuls->raw[i+3]=AVG_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createMed(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
impuls->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
impuls->raw[i+1]=AVG_PULSE_LENGTH;
|
||||
impuls->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
impuls->raw[i+3]=AVG_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
impuls->raw[i]=AVG_PULSE_LENGTH;
|
||||
impuls->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
impuls->raw[i+2]=AVG_PULSE_LENGTH;
|
||||
impuls->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(0,47);
|
||||
}
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(systemcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createMed(x, x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createProgramCode(int programcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(programcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(20+x, 20+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createHigh(40, 43);
|
||||
} else {
|
||||
createHigh(44, 47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
impuls->raw[48]=(AVG_PULSE_LENGTH);
|
||||
impuls->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int systemcode = -1;
|
||||
int programcode = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "programcode", &itmp) == 0)
|
||||
programcode = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(systemcode == -1 || programcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "impuls: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 31 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "impuls: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(programcode > 31 || programcode < 0) {
|
||||
logprintf(LOG_ERR, "impuls: invalid programcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(systemcode, programcode, state);
|
||||
clearCode();
|
||||
createSystemCode(systemcode);
|
||||
createProgramCode(programcode);
|
||||
createState(state);
|
||||
createFooter();
|
||||
impuls->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --programcode=programcode\tcontrol a device with this programcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void impulsInit(void) {
|
||||
|
||||
protocol_register(&impuls);
|
||||
protocol_set_id(impuls, "impuls");
|
||||
protocol_device_add(impuls, "impuls", "Impuls Switches");
|
||||
impuls->devtype = SWITCH;
|
||||
impuls->hwtype = RF433;
|
||||
impuls->minrawlen = RAW_LENGTH;
|
||||
impuls->maxrawlen = RAW_LENGTH;
|
||||
impuls->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
impuls->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&impuls->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&impuls->options, 'u', "programcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&impuls->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&impuls->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&impuls->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&impuls->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
impuls->parseCode=&parseCode;
|
||||
impuls->createCode=&createCode;
|
||||
impuls->printHelp=&printHelp;
|
||||
impuls->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "impuls";
|
||||
module->version = "2.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
impulsInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 Bram1337 & CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_IMPULS_H_
|
||||
#define _PROTOCOL_IMPULS_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *impuls;
|
||||
void impulsInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
Copyright (C) 2017 Oleksii Serdiuk
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include "livolo_switch.h"
|
||||
|
||||
#include "../../core/binary.h"
|
||||
#include "../../core/log.h"
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
# include "../../core/dso.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
// Based on the protocol description from
|
||||
// http://platenspeler.github.io/DeveloperGuide/433Transmitters/433messaging.html
|
||||
// with timing adjustments, based on sniffing the remote I own
|
||||
|
||||
#define REPEATS 120
|
||||
#define PULSE_LENGTH 170
|
||||
#define MIN_RAW_LENGTH 24
|
||||
#define MAX_RAW_LENGTH 47
|
||||
|
||||
#define ID_BITS 16
|
||||
#define UNIT_BITS 7
|
||||
|
||||
static int createHeader() {
|
||||
livolo_switch->raw[0] = PULSE_LENGTH*3.5;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int createLow(int i) {
|
||||
livolo_switch->raw[i] = PULSE_LENGTH;
|
||||
livolo_switch->raw[i+1] = PULSE_LENGTH;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int createHigh(int i) {
|
||||
livolo_switch->raw[i] = PULSE_LENGTH*2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int createBits(int value, int start, int length) {
|
||||
int binary[255];
|
||||
int l = 0;
|
||||
int i = 0, x = start;
|
||||
|
||||
l = decToBin(value, binary);
|
||||
// Pad with zeroes
|
||||
for(i=0;i<length-1-l;i++) {
|
||||
x += createLow(x);
|
||||
};
|
||||
for(i=0;i<=l;i++) {
|
||||
if(binary[i] == 1) {
|
||||
x += createHigh(x);
|
||||
} else {
|
||||
x += createLow(x);
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static int createKeycode(int key) {
|
||||
switch(key) {
|
||||
case 0:
|
||||
// "Off" key
|
||||
return 106;
|
||||
case 1:
|
||||
return 0;
|
||||
case 2:
|
||||
return 96;
|
||||
case 3:
|
||||
return 120;
|
||||
case 4:
|
||||
return 24;
|
||||
case 5:
|
||||
return 80;
|
||||
case 6:
|
||||
return 48;
|
||||
case 7:
|
||||
return 108;
|
||||
case 8:
|
||||
return 12;
|
||||
case 9:
|
||||
return 72;
|
||||
case 10:
|
||||
return 40;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void createMessage(int id, int key, int off) {
|
||||
livolo_switch->message = json_mkobject();
|
||||
|
||||
json_append_member(livolo_switch->message, "id", json_mknumber(id, 0));
|
||||
|
||||
if(off == 1) {
|
||||
json_append_member(livolo_switch->message, "off", json_mknumber(off, 0));
|
||||
} else {
|
||||
json_append_member(livolo_switch->message, "key", json_mknumber(key, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static int createCode(JsonNode *code) {
|
||||
int id = -1;
|
||||
int key = -1;
|
||||
int off = 0;
|
||||
int x = 0;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "key", &itmp) == 0)
|
||||
key = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0) {
|
||||
off = 1;
|
||||
key = 0;
|
||||
}
|
||||
|
||||
if(off > 0 && key > 0) {
|
||||
logprintf(LOG_ERR, "livolo_switch: off and key cannot be combined");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id == -1 || (key == -1 && off == 0)) {
|
||||
logprintf(LOG_ERR, "livolo_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id < 0 || id > 65535) {
|
||||
logprintf(LOG_ERR, "livolo_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((key < 1 || key > 10) && off == 0) {
|
||||
logprintf(LOG_ERR, "livolo_switch: invalid key range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, key, off);
|
||||
|
||||
x = createHeader();
|
||||
x = createBits(id, x, ID_BITS);
|
||||
x = createBits(createKeycode(key), x, UNIT_BITS);
|
||||
livolo_switch->rawlen = x;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -i --id=id\t\t\tsend with id of the remote (0..65535)\n");
|
||||
printf("\t -n --key=number\t\t\tsend with key number on the remote (1..10)\n");
|
||||
printf("\t -f --off\t\t\tsend turn off code for the remote\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void livoloSwitchInit(void) {
|
||||
protocol_register(&livolo_switch);
|
||||
protocol_set_id(livolo_switch, "livolo_switch");
|
||||
protocol_device_add(livolo_switch, "livolo_switch", "Livolo Switches");
|
||||
livolo_switch->devtype = SWITCH;
|
||||
livolo_switch->hwtype = RF433;
|
||||
livolo_switch->txrpt = REPEATS;
|
||||
livolo_switch->minrawlen = MIN_RAW_LENGTH;
|
||||
livolo_switch->maxrawlen = MAX_RAW_LENGTH;
|
||||
|
||||
options_add(&livolo_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL,
|
||||
// 16 bits: 0..65535
|
||||
"^([0-5]?[0-9]{1,4}|(6[0-4][0-9]{3})|(65[0-4][0-9]{2})|(655[0-2][0-9])|(6553[0-5]))$");
|
||||
options_add(&livolo_switch->options, 'n', "key", OPTION_OPT_VALUE, DEVICES_ID, JSON_NUMBER, NULL,
|
||||
// 7 its: 0..127
|
||||
"^(([0-9]{1,2})|(1[0-1][0-9])|(12[0-7]))$");
|
||||
options_add(&livolo_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&livolo_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, NULL, "^[01]$");
|
||||
options_add(&livolo_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, NULL, "^[01]$");
|
||||
|
||||
livolo_switch->createCode=&createCode;
|
||||
livolo_switch->printHelp=&printHelp;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "livolo_switch";
|
||||
module->version = "0.1";
|
||||
module->reqversion = "7.0";
|
||||
module->reqcommit = NULL;
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
livoloSwitchInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2017 Oleksii Serdiuk
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_LIVOLO_SWITCH_H_
|
||||
#define _PROTOCOL_LIVOLO_SWITCH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *livolo_switch;
|
||||
void livoloSwitchInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMo, Meloen and Scarala
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "logilink_switch.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 279
|
||||
#define MAX_PULSE_LENGTH 289
|
||||
#define AVG_PULSE_LENGTH 284
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(logilink_switch->rawlen == RAW_LENGTH) {
|
||||
if(logilink_switch->raw[logilink_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
logilink_switch->raw[logilink_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int unitcode, int state) {
|
||||
logilink_switch->message = json_mkobject();
|
||||
json_append_member(logilink_switch->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(logilink_switch->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
if(state == 0) {
|
||||
json_append_member(logilink_switch->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(logilink_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, binary[RAW_LENGTH/2];
|
||||
int systemcode = 0, state = 0, unitcode = 0;
|
||||
|
||||
if(logilink_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "logilink_switch: parsecode - invalid parameter passed %d", logilink_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<logilink_switch->rawlen-1;x+=2) {
|
||||
if(logilink_switch->raw[x] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
systemcode = binToDecRev(binary, 0, 19);
|
||||
state = binary[20];
|
||||
unitcode = binToDecRev(binary, 21, 23);
|
||||
|
||||
createMessage(systemcode, unitcode, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i = 0;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
logilink_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
logilink_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i = 0;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
logilink_switch->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
logilink_switch->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(0, logilink_switch->rawlen-2);
|
||||
}
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
int binary[255];
|
||||
int length=0;
|
||||
int i = 0, x = 38;
|
||||
|
||||
length = decToBin(systemcode, binary);
|
||||
for(i=length;i>=0;i--) {
|
||||
if(binary[i] == 1) {
|
||||
createHigh(x, x+1);
|
||||
}
|
||||
|
||||
x -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnitCode(int unitcode) {
|
||||
switch(unitcode) {
|
||||
case 7:
|
||||
createHigh(42, 47); // Button 1
|
||||
break;
|
||||
case 3:
|
||||
createLow(42, 43); // Button 2
|
||||
createHigh(44, 47);
|
||||
break;
|
||||
case 5:
|
||||
createHigh(42, 43); // Button 3
|
||||
createLow(44, 45);
|
||||
createHigh(46, 47);
|
||||
break;
|
||||
case 6:
|
||||
createHigh(42, 45); // Button 4
|
||||
createLow(46, 47);
|
||||
break;
|
||||
case 0:
|
||||
createLow(42, 47); // Button ALL OFF
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createLow(40, 41);
|
||||
} else {
|
||||
createHigh(40, 41);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
logilink_switch->raw[48]=(AVG_PULSE_LENGTH);
|
||||
logilink_switch->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int systemcode = -1;
|
||||
int unitcode = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "unitcode", &itmp) == 0)
|
||||
unitcode = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=1;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=0;
|
||||
|
||||
if(systemcode == -1 || unitcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "logilink_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 2097151 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "logilink_switch: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unitcode > 7 || unitcode < 0) {
|
||||
logprintf(LOG_ERR, "logilink_switch: invalid unitcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
clearCode();
|
||||
createSystemCode(systemcode);
|
||||
createUnitCode(unitcode);
|
||||
createState(state);
|
||||
createFooter();
|
||||
logilink_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --unitcode=unitcode\t\tcontrol a device with this unitcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
|
||||
void logilinkSwitchInit(void) {
|
||||
protocol_register(&logilink_switch);
|
||||
protocol_set_id(logilink_switch, "logilink_switch");
|
||||
protocol_device_add(logilink_switch, "logilink_switch", "Logilink Switches");
|
||||
logilink_switch->devtype = SWITCH;
|
||||
logilink_switch->hwtype = RF433;
|
||||
logilink_switch->minrawlen = RAW_LENGTH;
|
||||
logilink_switch->maxrawlen = RAW_LENGTH;
|
||||
logilink_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
logilink_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&logilink_switch->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&logilink_switch->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^[0-7]$");
|
||||
options_add(&logilink_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&logilink_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&logilink_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&logilink_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
logilink_switch->parseCode=&parseCode;
|
||||
logilink_switch->createCode=&createCode;
|
||||
logilink_switch->printHelp=&printHelp;
|
||||
logilink_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "logilink_sitch";
|
||||
module->version = "1.1";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
logilinkSwitchInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMo, Meloen and Scarala
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_LOGILINK_SWITCH_H_
|
||||
#define _PROTOCOL_LOGILINK_SWITCH_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *logilink_switch;
|
||||
void logilinkSwitchInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "mumbi.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 307
|
||||
#define MAX_PULSE_LENGTH 317
|
||||
#define AVG_PULSE_LENGTH 312
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(mumbi->rawlen == RAW_LENGTH) {
|
||||
if(mumbi->raw[mumbi->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
mumbi->raw[mumbi->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int unitcode, int state) {
|
||||
mumbi->message = json_mkobject();
|
||||
json_append_member(mumbi->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(mumbi->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(mumbi->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(mumbi->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(mumbi->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "mumbi: parsecode - invalid parameter passed %d", mumbi->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<mumbi->rawlen-2;x+=4) {
|
||||
if(mumbi->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int systemcode = binToDec(binary, 0, 4);
|
||||
int unitcode = binToDec(binary, 5, 9);
|
||||
int state = binary[11];
|
||||
if(unitcode > 0) {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
mumbi->raw[i]=(AVG_PULSE_LENGTH);
|
||||
mumbi->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
mumbi->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
mumbi->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
mumbi->raw[i]=(AVG_PULSE_LENGTH);
|
||||
mumbi->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
mumbi->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
mumbi->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
static void clearCode(void) {
|
||||
createLow(0,47);
|
||||
}
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(systemcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(x, x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnitCode(int unitcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unitcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(20+x, 20+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createHigh(44, 47);
|
||||
} else {
|
||||
createHigh(40, 43);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
mumbi->raw[48]=(AVG_PULSE_LENGTH);
|
||||
mumbi->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int systemcode = -1;
|
||||
int unitcode = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "unitcode", &itmp) == 0)
|
||||
unitcode = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(systemcode == -1 || unitcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "mumbi: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 31 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "mumbi: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unitcode > 31 || unitcode < 0) {
|
||||
logprintf(LOG_ERR, "mumbi: invalid unitcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
clearCode();
|
||||
createSystemCode(systemcode);
|
||||
createUnitCode(unitcode);
|
||||
createState(state);
|
||||
createFooter();
|
||||
mumbi->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --unitcode=unitcode\t\tcontrol a device with this unitcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void mumbiInit(void) {
|
||||
|
||||
protocol_register(&mumbi);
|
||||
protocol_set_id(mumbi, "mumbi");
|
||||
protocol_device_add(mumbi, "mumbi", "Mumbi Switches");
|
||||
mumbi->devtype = SWITCH;
|
||||
mumbi->hwtype = RF433;
|
||||
mumbi->minrawlen = RAW_LENGTH;
|
||||
mumbi->maxrawlen = RAW_LENGTH;
|
||||
mumbi->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
mumbi->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&mumbi->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&mumbi->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&mumbi->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&mumbi->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&mumbi->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&mumbi->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
mumbi->parseCode=&parseCode;
|
||||
mumbi->createCode=&createCode;
|
||||
mumbi->printHelp=&printHelp;
|
||||
mumbi->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "mumbi";
|
||||
module->version = "2.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
mumbiInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_MUMBI_H_
|
||||
#define _PROTOCOL_MUMBI_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *mumbi;
|
||||
void mumbiInit(void);
|
||||
|
||||
#endif
|
||||
+246
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo_rasp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "ninjablocks_weather.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 2
|
||||
#define MIN_PULSE_LENGTH 2115
|
||||
#define MAX_PULSE_LENGTH 2125
|
||||
#define AVG_PULSE_LENGTH 2120
|
||||
#define MIN_RAW_LENGTH 41
|
||||
#define MAX_RAW_LENGTH 70
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
#define PULSE_NINJA_WEATHER_SHORT 1000
|
||||
#define PULSE_NINJA_WEATHER_LONG 2000
|
||||
#define PULSE_NINJA_WEATHER_FOOTER AVG_PULSE_LENGTH // 72080/PULSE_DIV
|
||||
#define PULSE_NINJA_WEATHER_LOWER 750 // SHORT*0,75
|
||||
#define PULSE_NINJA_WEATHER_UPPER 1250 // SHORT * 1,25
|
||||
|
||||
typedef struct settings_t {
|
||||
double id;
|
||||
double unit;
|
||||
double temp;
|
||||
double humi;
|
||||
struct settings_t *next;
|
||||
} settings_t;
|
||||
|
||||
static struct settings_t *settings = NULL;
|
||||
|
||||
static int validate(void) {
|
||||
if(ninjablocks_weather->rawlen >= MIN_RAW_LENGTH && ninjablocks_weather->rawlen <= MAX_RAW_LENGTH) {
|
||||
if(ninjablocks_weather->raw[ninjablocks_weather->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
ninjablocks_weather->raw[ninjablocks_weather->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, double temperature, double humidity) {
|
||||
ninjablocks_weather->message = json_mkobject();
|
||||
json_append_member(ninjablocks_weather->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(ninjablocks_weather->message, "unit", json_mknumber(unit, 0));
|
||||
json_append_member(ninjablocks_weather->message, "temperature", json_mknumber(temperature/100, 2));
|
||||
json_append_member(ninjablocks_weather->message, "humidity", json_mknumber(humidity, 0));
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, pRaw = 0, binary[MAX_RAW_LENGTH/2];
|
||||
int iParity = 1, iParityData = -1; // init for even parity
|
||||
int iHeaderSync = 12; // 1100
|
||||
int iDataSync = 6; // 110
|
||||
double temp_offset = 0.0;
|
||||
double humi_offset = 0.0;
|
||||
|
||||
if(ninjablocks_weather->rawlen>MAX_RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "ninjablocks_weather: parsecode - invalid parameter passed %d", ninjablocks_weather->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
// Decode Biphase Mark Coded Differential Manchester (BMCDM) pulse stream into binary
|
||||
for(x=0; x<=(MAX_RAW_LENGTH/2); x++) {
|
||||
if(ninjablocks_weather->raw[pRaw] > PULSE_NINJA_WEATHER_LOWER &&
|
||||
ninjablocks_weather->raw[pRaw] < PULSE_NINJA_WEATHER_UPPER) {
|
||||
binary[x] = 1;
|
||||
iParityData = iParity;
|
||||
iParity = -iParity;
|
||||
pRaw++;
|
||||
} else {
|
||||
binary[x] = 0;
|
||||
}
|
||||
pRaw++;
|
||||
}
|
||||
if(iParityData < 0) {
|
||||
iParityData = 0;
|
||||
}
|
||||
|
||||
// Binary record: 0-3 sync0, 4-7 unit, 8-9 id, 10-12 sync1, 13-19 humidity, 20-34 temperature, 35 even par, 36 footer
|
||||
int headerSync = binToDecRev(binary, 0,3);
|
||||
int unit = binToDecRev(binary, 4,7);
|
||||
int id = binToDecRev(binary, 8,9);
|
||||
int dataSync = binToDecRev(binary, 10,12);
|
||||
double humidity = binToDecRev(binary, 13,19); // %
|
||||
double temperature = binToDecRev(binary, 20,34);
|
||||
// ((temp * (100 / 128)) - 5000) * 10 °C, 2 digits
|
||||
temperature = ((int)((double)(temperature * 0.78125)) - 5000);
|
||||
|
||||
struct settings_t *tmp = settings;
|
||||
while(tmp) {
|
||||
if(fabs(tmp->id-id) < EPSILON && fabs(tmp->unit-unit) < EPSILON) {
|
||||
humi_offset = tmp->humi;
|
||||
temp_offset = tmp->temp;
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
temperature += temp_offset;
|
||||
humidity += humi_offset;
|
||||
|
||||
if(iParityData == 0 && (iHeaderSync == headerSync || dataSync == iDataSync)) {
|
||||
createMessage(id, unit, temperature, humidity);
|
||||
}
|
||||
}
|
||||
|
||||
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 unit = -1, id = -1;
|
||||
int match = 0;
|
||||
|
||||
jchild = json_first_child(jid);
|
||||
while(jchild) {
|
||||
jchild1 = json_first_child(jchild);
|
||||
while(jchild1) {
|
||||
if(strcmp(jchild1->key, "unit") == 0) {
|
||||
unit = 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 && fabs(tmp->unit-unit) < 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->unit = unit;
|
||||
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 ninjablocksWeatherInit(void) {
|
||||
|
||||
protocol_register(&ninjablocks_weather);
|
||||
protocol_set_id(ninjablocks_weather, "ninjablocks_weather");
|
||||
protocol_device_add(ninjablocks_weather, "ninjablocks_weather", "Ninjablocks Weather Sensors");
|
||||
ninjablocks_weather->devtype = WEATHER;
|
||||
ninjablocks_weather->hwtype = RF433;
|
||||
ninjablocks_weather->minrawlen = MIN_RAW_LENGTH;
|
||||
ninjablocks_weather->maxrawlen = MAX_RAW_LENGTH;
|
||||
ninjablocks_weather->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
ninjablocks_weather->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
// sync-id[4]; Homecode[4], Channel Code[2], Sync[3], Humidity[7], Temperature[15], Footer [1]
|
||||
options_add(&ninjablocks_weather->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]|1[0-5])$");
|
||||
options_add(&ninjablocks_weather->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-3])$");
|
||||
options_add(&ninjablocks_weather->options, 't', "temperature", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,5}$");
|
||||
options_add(&ninjablocks_weather->options, 'h', "humidity", OPTION_HAS_VALUE, DEVICES_VALUE, JSON_NUMBER, NULL, "^[0-9]{1,5}$");
|
||||
|
||||
// options_add(&ninjablocks_weather->options, 0, "decimals", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, (void *)2, "[0-9]");
|
||||
options_add(&ninjablocks_weather->options, 0, "temperature-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)2, "[0-9]");
|
||||
options_add(&ninjablocks_weather->options, 0, "humidity-decimals", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)2, "[0-9]");
|
||||
options_add(&ninjablocks_weather->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&ninjablocks_weather->options, 0, "show-humidity", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
options_add(&ninjablocks_weather->options, 0, "show-temperature", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)1, "^[10]{1}$");
|
||||
|
||||
ninjablocks_weather->parseCode=&parseCode;
|
||||
ninjablocks_weather->checkValues=&checkValues;
|
||||
ninjablocks_weather->validate=&validate;
|
||||
ninjablocks_weather->gc=&gc;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "ninjablocks_weather";
|
||||
module->version = "1.2";
|
||||
module->reqversion = "7.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
ninjablocksWeatherInit();
|
||||
}
|
||||
#endif
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo-rasp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_NINJABLOCKS_WEATHER_H_
|
||||
#define _PROTOCOL_NINJABLOCKS_WEATHER_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *ninjablocks_weather;
|
||||
void ninjablocksWeatherInit(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "pollin.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 296
|
||||
#define MAX_PULSE_LENGTH 306
|
||||
#define AVG_PULSE_LENGTH 301
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(pollin->rawlen == RAW_LENGTH) {
|
||||
if(pollin->raw[pollin->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
pollin->raw[pollin->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int unitcode, int state) {
|
||||
pollin->message = json_mkobject();
|
||||
json_append_member(pollin->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(pollin->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
if(state == 0) {
|
||||
json_append_member(pollin->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(pollin->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(pollin->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "pollin: parsecode - invalid parameter passed %d", pollin->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<pollin->rawlen-2;x+=4) {
|
||||
if(pollin->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int systemcode = binToDec(binary, 0, 4);
|
||||
int unitcode = binToDec(binary, 5, 9);
|
||||
int state = binary[11];
|
||||
createMessage(systemcode, unitcode, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
pollin->raw[i]=(AVG_PULSE_LENGTH);
|
||||
pollin->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
pollin->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
pollin->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
pollin->raw[i]=(AVG_PULSE_LENGTH);
|
||||
pollin->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
pollin->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
pollin->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
static void clearCode(void) {
|
||||
createLow(0,47);
|
||||
}
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(systemcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(x, x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnitCode(int unitcode) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unitcode, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(20+x, 20+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createHigh(44, 47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
pollin->raw[48]=(AVG_PULSE_LENGTH);
|
||||
pollin->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int systemcode = -1;
|
||||
int unitcode = -1;
|
||||
int state = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "unitcode", &itmp) == 0)
|
||||
unitcode = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=1;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=0;
|
||||
|
||||
if(systemcode == -1 || unitcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "pollin: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 31 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "pollin: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unitcode > 31 || unitcode < 0) {
|
||||
logprintf(LOG_ERR, "pollin: invalid unitcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(systemcode, unitcode, state);
|
||||
clearCode();
|
||||
createSystemCode(systemcode);
|
||||
createUnitCode(unitcode);
|
||||
createState(state);
|
||||
createFooter();
|
||||
pollin->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --unitcode=unitcode\t\tcontrol a device with this unitcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void pollinInit(void) {
|
||||
|
||||
protocol_register(&pollin);
|
||||
protocol_set_id(pollin, "pollin");
|
||||
protocol_device_add(pollin, "pollin", "Pollin Switches");
|
||||
pollin->devtype = SWITCH;
|
||||
pollin->hwtype = RF433;
|
||||
pollin->minrawlen = RAW_LENGTH;
|
||||
pollin->maxrawlen = RAW_LENGTH;
|
||||
pollin->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
pollin->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&pollin->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&pollin->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&pollin->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&pollin->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&pollin->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&pollin->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
pollin->parseCode=&parseCode;
|
||||
pollin->createCode=&createCode;
|
||||
pollin->printHelp=&printHelp;
|
||||
pollin->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "pollin";
|
||||
module->version = "2.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
pollinInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_POLLIN_H_
|
||||
#define _PROTOCOL_POLLIN_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *pollin;
|
||||
void pollinInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMo & wo_rasp & RvW
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/* Protocol quigg_gt1000 is an implementation of a protocol for the Quigg GT-FSI-08 switches
|
||||
with GT-1000 remote. It is believed that they are compatible with the Lidl and Brennenstuhl outlets
|
||||
RvW, jan 2015
|
||||
This implementation mimics the GT-1000 remote control with extensions
|
||||
These switches listen to the next command string of 24 bit:
|
||||
|-|0-----------4|5---------20|21------24|
|
||||
|S| group-id[4] | random[16] |unit-id[4]|
|
||||
|-|-------------|------------|----------|
|
||||
where:
|
||||
S=Start, a short high pulse of 350 us followed by a low of 2350 us
|
||||
group-id[4]= 4 logic bits for the group-id code, range 0..15
|
||||
unit-id[4]= 4 bits for the unit code for switches 1..4. Two different coding schemes are used
|
||||
random[16]= a 16 bit sequence where no bits seems to have a specific function. Each action
|
||||
for each switch uses 4 codes (40 in total for one group-id) that are transmitted in a rolling sequence by the RC
|
||||
Although codes are reused within a single group, for the sake of code simplicity and readability
|
||||
this implementation will not use this fact. So we will implement a table with 16*40 = 640 "random" codes
|
||||
|
||||
A logic bit is encoded by the position of the high to low transition in the 1540 us bit window.
|
||||
A logic 1 therefore is encoded by a mark(high) of 1100 us followed by a space(low) of 440 us.
|
||||
A logic 0 is encoded by a mark of 330 us followed by a space of 1210 us
|
||||
|
||||
The total message consists of 24 bit + start pulse, and has therefore a duration 39660 us
|
||||
There is no space between the repetition of a message, so the next message immediately follows the previous message
|
||||
|
||||
To program a switch the RC uses a second type of start pulse with a mark(high) of 3000us and a space(low) of 7300us
|
||||
In order to be able to program switches from pilight, this implementation mimics this behavior by
|
||||
transmitting two normal code sequences followed by a program sequence with this long start pulse.
|
||||
This implies that the complete message in fact consists of 75 bits and a short footer.
|
||||
*/
|
||||
|
||||
#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 "quigg_gt1000.h"
|
||||
|
||||
/* define the basic protocol Mark-Space pulse width and other values*/
|
||||
#define START_MARK 350
|
||||
#define START_SPACE 2340
|
||||
#define PROG_MARK 3000
|
||||
#define PROG_SPACE 7300
|
||||
#define SHORT_MARK 330
|
||||
#define LONG_SPACE 1210
|
||||
#define LONG_MARK 1100
|
||||
#define SHORT_SPACE 440
|
||||
#define FOOTER_MARK 200
|
||||
|
||||
#define LEARN_REPEATS 40
|
||||
#define NORMAL_REPEATS 10
|
||||
#define PULSE_MULTIPLIER 2
|
||||
#define MIN_PULSE_LENGTH 320
|
||||
#define MAX_PULSE_LENGTH 340
|
||||
#define AVG_PULSE_LENGTH 330
|
||||
#define RAW_LENGTH 151
|
||||
#define BIN_LENGTH 24
|
||||
/*
|
||||
// Support Rx
|
||||
static int validate(void) {
|
||||
if(quigg_gt1000->rawlen == RAW_LENGTH) {
|
||||
if(quigg_gt1000->raw[0] >= (int)(START_MARK*0.9) &&
|
||||
quigg_gt1000->raw[0] <= (int)(START_MARK*1.1) &&
|
||||
quigg_gt1000->raw[1] >= (int)(START_SPACE*0.9) &&
|
||||
quigg_gt1000->raw[1] <= (int)(START_SPACE*1.1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
int codetab[16][40] = {
|
||||
/* the next table contains the random codes (bits 4..19) of the 4 code sequences for
|
||||
* each off-on action for each switch 0..3 in each group-id 0..15.
|
||||
* For each group-id a separate array is created where de codes are stored in the next order:
|
||||
* off-codes 0..3 for switch 0, on-codes 0..3 for switch 0,
|
||||
* off-codes 0..3 for switch 1, on-codes 0..3 for switch 1,
|
||||
* off-codes 0..3 for switch 2, on-codes 0..3 for switch 2,
|
||||
* off-codes 0..3 for switch 3, on-codes 0..3 for switch 3,
|
||||
* off-codes 0..3 for all, on-codes 0..3 for all
|
||||
* If a code is unknown 0 is substituted, f.e. for group-id 0 no codes are known, so all 40 values are 0
|
||||
*/
|
||||
/* code 0 */
|
||||
{ 0xBB42,0x4301,0x00F9,0x8EBA, 0xE4C3,0x1924,0x6CDB,0x9D57,
|
||||
0x00F9,0x4301,0x00F9,0x8EBA, 0x9D57,0xE4C3,0x6CDB,0x1924,
|
||||
0x8EBA,0x00F9,0x4301,0xBB42, 0x1924,0xE4C3,0x6CDB,0x9D57,
|
||||
0xE4C3,0x1924,0x9D57,0x6CDB, 0x8EBA,0xBB42,0x4301,0x00F9,
|
||||
0xE4C3,0x1924,0x9D57,0x6CDB, 0x4301,0x00F9,0x8EBA,0xBB42 },
|
||||
/* code 1 */
|
||||
{ 0x616A,0xCF71,0x7AE2,0xB639, 0xF59B,0xE923,0x14C4,0x32A7,
|
||||
0x616A,0xB639,0xCF71,0x7AE2, 0x14C4,0x32A7,0xF59B,0xE923,
|
||||
0xCF71,0x616A,0x7AE2,0xB639, 0xE923,0xF59B,0x14C4,0x32A7,
|
||||
0x14C4,0xE923,0xF59B,0x32A7, 0x7AE2,0x616A,0xCF71,0xB639,
|
||||
0x14C4,0xE923,0xF59B,0x32A7, 0x7AE2,0x616A,0xB639,0xCF71 },
|
||||
/* code 2 */
|
||||
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 },
|
||||
/* code 3 */
|
||||
{ 0x32D7,0x7D4B,0x9482,0xC818, 0x067A,0x2901,0xB1B6,0xEA35,
|
||||
0x5B5C,0x6364,0x85F9,0xFEED, 0x1FA0,0x4CCF,0xA793,0xD02E,
|
||||
0x067A,0x2901,0xB1B6,0xEA35, 0x32D7,0x7D4B,0x9482,0xC818,
|
||||
0x1FA0,0x4CCF,0xA793,0xD02E, 0x5B5C,0x6364,0x85F9,0xFEED,
|
||||
0x067A,0x2901,0xB1B6,0xEA35, 0x32D7,0x7D4B,0x9482,0xC818 },
|
||||
/* code 4 */
|
||||
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 },
|
||||
/* code 5 */
|
||||
{ 0x23C2,0x71A1,0x88DA,0xDC19, 0x1FBB,0x39E4,0xA743,0xFE77,
|
||||
0x23C2,0x71A1,0x88DA,0xDC19, 0x1FBB,0x39E4,0xA743,0xFE77,
|
||||
0x23C2,0x71A1,0x88DA,0xDC19, 0x1FBB,0x39E4,0xA743,0xFE77,
|
||||
0x1FBB,0x39E4,0xA743,0xFE77, 0x23C2,0x71A1,0x88DA,0xDC19,
|
||||
0x1FBB,0x39E4,0xA743,0xFE77, 0x23C2,0x71A1,0x88DA,0xDC19 },
|
||||
/* code 6 */
|
||||
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 },
|
||||
/* code 7 */
|
||||
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 },
|
||||
/* code 8 */
|
||||
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 },
|
||||
/* code 9 */
|
||||
{ 0x1B1A,0x27D9,0x75C1,0xC0A2, 0x02FB,0x3D03,0x6EE7,0xB974,
|
||||
0x1B1A,0x27D9,0x75C1,0xC0A2, 0x02FB,0x3D03,0x6EE7,0xB974,
|
||||
0x1B1A,0x27D9,0x75C1,0xC0A2, 0x02FB,0x3D03,0x6EE7,0xB974,
|
||||
0x02FB,0x3D03,0x6EE7,0xB974, 0x1B1A,0x27D9,0x75C1,0xC0A2,
|
||||
0x02FB,0x3D03,0x6EE7,0xB974, 0x1B1A,0x27D9,0x75C1,0xC0A2 },
|
||||
/* code 10 */
|
||||
{ 0x9E98,0xC2AB,0xE057,0xF4F2, 0x460A,0x6971,0x77E6,0xBB25,
|
||||
0x0CBD,0x1589,0x51C4,0x8FDC, 0x2313,0x386F,0xAD3E,0xDA40,
|
||||
0x460A,0x6971,0x77E6,0xBB25, 0x9E98,0xC2AB,0xE057,0xF4F2,
|
||||
0x2313,0x386F,0xAD3E,0xDA40, 0x0CBD,0x1589,0x51C4,0x8FDC,
|
||||
0x460A,0x6971,0x77E6,0xBB25, 0x9E98,0xC2AB,0xE057,0xF4F2 },
|
||||
/* code 11 */
|
||||
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 },
|
||||
/* code 12 */
|
||||
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 },
|
||||
/* code 13 */
|
||||
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 },
|
||||
/* code 14 */
|
||||
{ 0xE692,0x98F8,0x577B,0xABB7, 0x0AD6,0xBDA1,0xC465,0x6F4A,
|
||||
0xF234,0x89EC,0x2519,0x715D, 0x1383,0xDC2F,0x40CE,0x3E00,
|
||||
0x0AD6,0xBDA1,0xC465,0x6F4A, 0xE692,0x98F8,0x577B,0xABB7,
|
||||
0x1383,0xDC2F,0x40CE,0x3E00, 0xF234,0x89EC,0x2519,0x715D,
|
||||
0x0AD6,0xBDA1,0xC465,0x6F4A, 0xE692,0x98F8,0x577B,0xABB7 },
|
||||
/* code 15 */
|
||||
{ 0x1067,0x3D02,0x9B1B,0, 0x2636,0x6C81,0xE5B5,0xF1FA,
|
||||
0x432D,0x54CC,0x8A79,0xC7D4, 0x7290,0xA85F,0xDFEE,0,
|
||||
0x2636,0x6C81,0xE5B5,0xF1FA, 0x1067,0x3D02,0x9B1B,0,
|
||||
0x7290,0xA85F,0xDFEE,0, 0x432D,0x54CC,0x8A79,0xC7D4,
|
||||
0x2636,0x6C81,0xE5B5,0xF1FA, 0x1067,0x3D02,0x9B1B,0 }
|
||||
};
|
||||
|
||||
int unittab[2][5] = {
|
||||
/* This table defines the coding of the unit-id or switch-id. Two coding schemes are used
|
||||
* I call them first and second generation switches. They encode the unit-id in a different way.
|
||||
*/
|
||||
/* first gen group-id = 1, 5, 9, 12 */
|
||||
{ 0x0, 0x4, 0xC, 0x2, 0xA }, /* these are 1st gen switch-codes for switch 0..3 and all */
|
||||
/* second gen all other */
|
||||
{ 0xC, 0x5, 0xE, 0x7, 0x2 } /* 2nd gen switch-codes */
|
||||
};
|
||||
|
||||
int gentab[16] =
|
||||
/* This table defines the switch generation for each group-id
|
||||
* A 0 at location x means group-id x belongs to first generation, and a 1 means second generation
|
||||
*/
|
||||
/* for now only group-id 1,5,9 and 12 are first generation */
|
||||
{0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1};
|
||||
|
||||
#define NRSUPERMASK 0x07
|
||||
#define NRSUPERCODES (NRSUPERMASK+1) /* we will use 8 on and 8 off supercodes */
|
||||
/* make sure the number of Supercodes is always a power of 2, i.e. 2,4,8,16 ... */
|
||||
int supercodes[2*NRSUPERCODES] = {
|
||||
/* since with supercodes group-id's are irrelevant, the codes consist of the first 20 bits of the code sequence */
|
||||
/* OFF codes */
|
||||
0x0F000,0x1F006,0x4F00E,0x5F016,0x8F01E,0x9F026,0xCF02E,0xDF02F,
|
||||
/* ON codes */
|
||||
0x0F005,0x1F008,0x4F015,0x5F018,0x8F025,0x9F028,0xCF02C,0xDF03C };
|
||||
|
||||
char bincode[BIN_LENGTH+1];
|
||||
|
||||
static void createMessage(int id, int unit, int state, int seq, int learn) {
|
||||
int i = 0;
|
||||
|
||||
for(i=0;i<BIN_LENGTH;i++) {
|
||||
bincode[i] = bincode[i] | 0x30; /* convert bin 0,1 into char 0,1 */
|
||||
}
|
||||
|
||||
bincode[BIN_LENGTH] = '\0'; /* end of string */
|
||||
|
||||
quigg_gt1000->message = json_mkobject();
|
||||
json_append_member(quigg_gt1000->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(quigg_gt1000->message, "unit", json_mknumber(unit, 0));
|
||||
json_append_member(quigg_gt1000->message, "seq", json_mknumber(seq, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(quigg_gt1000->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(quigg_gt1000->message, "state", json_mkstring("off"));
|
||||
}
|
||||
json_append_member(quigg_gt1000->message, "code", json_mkstring(bincode));
|
||||
}
|
||||
|
||||
static int fillLow(int idx) {
|
||||
/* fill in the mark-space code for a logic Low = short pulse*/
|
||||
quigg_gt1000->raw[idx++] = SHORT_MARK;
|
||||
quigg_gt1000->raw[idx++] = LONG_SPACE;
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int fillHigh(int idx) {
|
||||
/* fill in the mark-space code for a logic High = long pulse*/
|
||||
quigg_gt1000->raw[idx++] = LONG_MARK;
|
||||
quigg_gt1000->raw[idx++] = SHORT_SPACE;
|
||||
return idx;
|
||||
}
|
||||
|
||||
static void numtoBin(int idx, int num, int len) {
|
||||
/* fill in bits idx to idx+len-1 for number, msb first */
|
||||
for(len--;len>=0;len--) {
|
||||
bincode[idx+len] = (num & 1); /* value is lsb num */
|
||||
num = num>>1; /* shift number 1 place to right, so 2th bit becomes lsb */
|
||||
}
|
||||
}
|
||||
|
||||
static int fillRawCode(void) {
|
||||
/* convert binary code in bincode[] to raw Mark-Space combis for this protocol */
|
||||
/* the complete RawCode consist of <startpulse><bincode><startpulse><bincode><progpulse><bincode><footer> */
|
||||
|
||||
int idx = 0; /* the index into the raw matrix, starting with 0 */
|
||||
int cnt = 0;
|
||||
|
||||
quigg_gt1000->raw[idx++] = START_MARK; /* always start with start pulse */
|
||||
quigg_gt1000->raw[idx++] = START_SPACE;
|
||||
for(cnt=0;cnt<BIN_LENGTH; cnt++) {
|
||||
idx = (bincode[cnt]==1) ? fillHigh(idx) : fillLow(idx);
|
||||
}
|
||||
|
||||
quigg_gt1000->raw[idx++] = START_MARK; /* start second sequence*/
|
||||
quigg_gt1000->raw[idx++] = START_SPACE;
|
||||
for(cnt=0;cnt<BIN_LENGTH; cnt++) {
|
||||
idx = (bincode[cnt]==1) ? fillHigh(idx) : fillLow(idx);
|
||||
}
|
||||
|
||||
quigg_gt1000->raw[idx++] = PROG_MARK; /* program sequence */
|
||||
quigg_gt1000->raw[idx++] = PROG_SPACE;
|
||||
for(cnt=0;cnt<BIN_LENGTH;cnt++) {
|
||||
idx = (bincode[cnt]==1) ? fillHigh(idx) : fillLow(idx);
|
||||
}
|
||||
|
||||
quigg_gt1000->raw[idx++] = FOOTER_MARK;
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int fillBinCode(int id, int unit, int state, int codeseq) {
|
||||
int genindex = 0, rcodeindex = 0;
|
||||
|
||||
/* encode id */
|
||||
numtoBin(0, id, 4); /* first 4 bits [0..3] is id-code */
|
||||
|
||||
/* encode the right random code, depends on id, state and unit, state=0,1 */
|
||||
rcodeindex= 8*unit + 4*state; /*calculate second index into codetab*/
|
||||
if(codetab[id][rcodeindex + codeseq] == 0) { /* no random code available? */
|
||||
/* then try first index */
|
||||
if(codetab[id][rcodeindex] == 0) { /* and no first code available? */
|
||||
logprintf(LOG_ERR, "quiggGT1000: no random code available for this switch action");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
logprintf(LOG_WARNING, "quiggGT1000: seq#%d not available for this switch action, using #0 instead", codeseq);
|
||||
codeseq = 0;
|
||||
}
|
||||
}
|
||||
/* now we have an index for a valid random code, so put it in our codetab starting at position 4 */
|
||||
numtoBin(4, codetab[id][rcodeindex + codeseq], 16);
|
||||
|
||||
/* encode the unit part of the command */
|
||||
/* key1..4 represents unit0..3, encoding depends on generation */
|
||||
/* master key results in unit=4, encoding depends on generation */
|
||||
genindex = gentab[id]; /* get 0 or 1 depending on generation of group-id */
|
||||
numtoBin(20, unittab[genindex][unit], 4); /* get unit-id from tab and encode starting at pos 20 */
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void fillSuperBinCode(int state, int codeseq) {
|
||||
/* encode the right random supercode, depends on state=0,1 and codeseq*/
|
||||
numtoBin(0, supercodes[NRSUPERCODES * state + codeseq], 20);
|
||||
|
||||
/* encode the unit part of the command, is always 1000 or 8 */
|
||||
numtoBin(20, 8, 4);
|
||||
}
|
||||
|
||||
|
||||
static int createCode(JsonNode *code) { // function to create the raw code
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int all = 0;
|
||||
int super = 0;
|
||||
int state = -1;
|
||||
int seq = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "num", &itmp) == 0)
|
||||
seq = (int)round(itmp);
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if(json_find_number(code, "super", &itmp) == 0)
|
||||
super = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(seq == -1) {/* no seqnr was given, a random seqnr will be used */
|
||||
srand((unsigned int)time (0)); /* seed the random generator with current time */
|
||||
seq = rand() & ((super == 1)? NRSUPERMASK:0x03); /* use last bits of random number */
|
||||
}
|
||||
|
||||
if((id == -1 && super==0) || (unit == -1 && all==0 && super==0) || state == -1) {
|
||||
logprintf(LOG_ERR, "quigg_gt1000: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if((id >15 || id < 0) && super == 0) {
|
||||
logprintf(LOG_ERR, "quigg_gt1000: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((unit > 3 || unit < 0) && all == 0 && super == 0){
|
||||
logprintf(LOG_ERR, "quigg_gt1000: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(((seq > 3 || seq < 0) && super == 0) || ((seq >= NRSUPERCODES || seq < 0) && super != 0)) {
|
||||
logprintf(LOG_ERR, "quigg_gt1000: invalid optional seq number");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(all == 1) { /* all overrides unit selection */
|
||||
unit = 4;
|
||||
}
|
||||
/* first create binary command string */
|
||||
if(super == 1) { /* do we want supercodes? */
|
||||
/* for supercodes we use a non-existend id and unit */
|
||||
id = 16; /* this does only influence the CreateMessage and not the bin code generation */
|
||||
unit = 5;
|
||||
fillSuperBinCode(state, seq); /*create binary supercode string */
|
||||
} else if(fillBinCode(id, unit, state, seq) != EXIT_SUCCESS) {
|
||||
return EXIT_FAILURE; /* failure because no codeseq was available */
|
||||
}
|
||||
|
||||
/* and now convert binary to Mark-Space combis */
|
||||
if(fillRawCode() != RAW_LENGTH) {
|
||||
/* this Error should never occur. It indicates a wrong raw protocol length or misaligned fill */
|
||||
logprintf(LOG_ERR, "quigg_gt1000: raw index not correct %d %d",quigg_gt1000->rawlen,fillRawCode);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
quigg_gt1000->rawlen = RAW_LENGTH;
|
||||
createMessage(id, unit, state, seq, 0);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) { // print help for this protocol (send -p <name> -H)
|
||||
printf("\t -t --on\tsend an on signal\n");
|
||||
printf("\t -f --off\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\tcontrol a device with this unit code [0..3]\n");
|
||||
printf("\t -i --id=id\tcontrol a device with this id [0..15] \n");
|
||||
printf("\t -a --all\tcontrol all devices with this id\n");
|
||||
printf("\t -s --super\tcontrol all devices regardless of id\n");
|
||||
printf("\t -n --num\toptional use random (super)code sequence num 0..3 (%d)\n", NRSUPERCODES-1);
|
||||
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void quiggGT1000Init(void) {
|
||||
protocol_register(&quigg_gt1000);
|
||||
protocol_set_id(quigg_gt1000, "quigg_gt1000");
|
||||
protocol_device_add(quigg_gt1000, "quigg_gt1000", "Quigg GT-1000 protocol");
|
||||
quigg_gt1000->devtype = SWITCH;
|
||||
quigg_gt1000->hwtype = RF433;
|
||||
quigg_gt1000->txrpt = NORMAL_REPEATS;
|
||||
quigg_gt1000->minrawlen = RAW_LENGTH;
|
||||
quigg_gt1000->maxrawlen = RAW_LENGTH;
|
||||
quigg_gt1000->maxgaplen = (int)PROG_SPACE*1.1;
|
||||
quigg_gt1000->mingaplen = (int)PROG_SPACE*0.9;
|
||||
|
||||
options_add(&quigg_gt1000->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&quigg_gt1000->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&quigg_gt1000->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-5])$");
|
||||
options_add(&quigg_gt1000->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(1[0-6]|[0-9])$");
|
||||
options_add(&quigg_gt1000->options, 'a', "all", OPTION_NO_VALUE, DEVICES_SETTING, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&quigg_gt1000->options, 's', "super", OPTION_NO_VALUE, DEVICES_SETTING, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&quigg_gt1000->options, 'n', "num", OPTION_HAS_VALUE, DEVICES_SETTING, JSON_NUMBER, NULL, "^([0-3])$");
|
||||
|
||||
options_add(&quigg_gt1000->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&quigg_gt1000->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
quigg_gt1000->printHelp = &printHelp;
|
||||
quigg_gt1000->createCode = &createCode;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "quigg_gt1000";
|
||||
module->version = "1.0";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
quiggGT1000Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo_rasp & RvW
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/* Protocol quigg_gt1000 is an implementation of a protocol for the Quigg GT-FSI-08 switches
|
||||
with GT-1000 remote. It is believed that they are compatible with the Lidl and Brennenstuhl outlets
|
||||
RvW, jan 2015
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_QUIGG_GT1000_H_
|
||||
#define _PROTOCOL_QUIGG_GT1000_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *quigg_gt1000;
|
||||
void quiggGT1000Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo_rasp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "quigg_gt7000.h"
|
||||
|
||||
#define PULSE_QUIGG_SHORT 700
|
||||
#define PULSE_QUIGG_LONG 1400
|
||||
#define PULSE_QUIGG_FOOTER 81000
|
||||
#define PULSE_QUIGG_50 PULSE_QUIGG_SHORT+(PULSE_QUIGG_LONG-PULSE_QUIGG_SHORT)/2
|
||||
|
||||
#define LEARN_REPEATS 4
|
||||
#define NORMAL_REPEATS 4
|
||||
#define PULSE_MULTIPLIER 2
|
||||
#define AVG_PULSE_LENGTH PULSE_QUIGG_SHORT
|
||||
#define MIN_PULSE_LENGTH AVG_PULSE_LENGTH-80
|
||||
#define MAX_PULSE_LENGTH AVG_PULSE_LENGTH+260
|
||||
#define RAW_LENGTH 42
|
||||
|
||||
static int validate(void) {
|
||||
if(quigg_gt7000->rawlen == RAW_LENGTH) {
|
||||
if(quigg_gt7000->raw[quigg_gt7000->rawlen-1] >= (int)(PULSE_QUIGG_FOOTER*0.9) &&
|
||||
quigg_gt7000->raw[quigg_gt7000->rawlen-1] <= (int)(PULSE_QUIGG_FOOTER*1.1) &&
|
||||
quigg_gt7000->raw[0] >= MIN_PULSE_LENGTH &&
|
||||
quigg_gt7000->raw[0] <= MAX_PULSE_LENGTH) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int state, int unit, int all, int learn) {
|
||||
quigg_gt7000->message = json_mkobject();
|
||||
json_append_member(quigg_gt7000->message, "id", json_mknumber(id, 0));
|
||||
if(all == 1) {
|
||||
json_append_member(quigg_gt7000->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(quigg_gt7000->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
|
||||
if(state == 1) {
|
||||
json_append_member(quigg_gt7000->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(quigg_gt7000->message, "state", json_mkstring("off"));
|
||||
}
|
||||
|
||||
if(learn == 1) {
|
||||
quigg_gt7000->txrpt = LEARN_REPEATS;
|
||||
} else {
|
||||
quigg_gt7000->txrpt = NORMAL_REPEATS;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/2], x = 0, dec_unit[4] = {0, 3, 1, 2};
|
||||
int iParity=1, iParityData=-1; // init for even parity
|
||||
|
||||
if(quigg_gt7000->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "quigg_gt7000: parsecode - invalid parameter passed %d", quigg_gt7000->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0; x<quigg_gt7000->rawlen-1; x+=2) {
|
||||
if(quigg_gt7000->raw[x+1] > PULSE_QUIGG_50) {
|
||||
binary[x/2] = 1;
|
||||
if((x / 2) > 11 && (x / 2) < 19) {
|
||||
iParityData = iParity;
|
||||
iParity = -iParity;
|
||||
}
|
||||
} else {
|
||||
binary[x/2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(iParityData < 0)
|
||||
iParityData=0;
|
||||
|
||||
int id = binToDecRev(binary, 0, 11);
|
||||
int unit = binToDecRev(binary, 12, 13);
|
||||
int all = binToDecRev(binary, 14, 14);
|
||||
int state = binToDecRev(binary, 15, 15);
|
||||
int dimm = binToDecRev(binary, 16, 16);
|
||||
int parity = binToDecRev(binary, 19, 19);
|
||||
int learn = 0;
|
||||
|
||||
unit = dec_unit[unit];
|
||||
|
||||
if((dimm == 1) && (state == 1)) {
|
||||
dimm = 2;
|
||||
}
|
||||
|
||||
if (iParityData == parity && dimm < 1) {
|
||||
createMessage(id, state, unit, all, learn);
|
||||
}
|
||||
}
|
||||
|
||||
static void createZero(int s, int e) {
|
||||
int i;
|
||||
for(i=s;i<=e;i+=2) {
|
||||
quigg_gt7000->raw[i] = PULSE_QUIGG_SHORT;
|
||||
quigg_gt7000->raw[i+1] = PULSE_QUIGG_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
static void createOne(int s, int e) {
|
||||
int i;
|
||||
for(i=s;i<=e;i+=2) {
|
||||
quigg_gt7000->raw[i] = PULSE_QUIGG_LONG;
|
||||
quigg_gt7000->raw[i+1] = PULSE_QUIGG_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHeader(void) {
|
||||
quigg_gt7000->raw[0] = PULSE_QUIGG_SHORT;
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
quigg_gt7000->raw[quigg_gt7000->rawlen-1] = PULSE_QUIGG_FOOTER;
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHeader();
|
||||
createZero(1, quigg_gt7000->rawlen-3);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[16], length = 0, i = 0, x = 23;
|
||||
|
||||
length = decToBin(id, binary);
|
||||
for(i=length;i>=0;i--) {
|
||||
if(binary[i] == 1) {
|
||||
createOne(x, x+1);
|
||||
}
|
||||
x = x-2;
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
switch (unit) {
|
||||
case 0:
|
||||
createZero(25, 30); // 1st row
|
||||
break;
|
||||
case 1:
|
||||
createOne(25, 26); // 2nd row
|
||||
createOne(37, 38); // needs to be set
|
||||
break;
|
||||
case 2:
|
||||
createOne(25, 28); // 3rd row
|
||||
createOne(37, 38); // needs to be set
|
||||
break;
|
||||
case 3:
|
||||
createOne(27, 28); // 4th row
|
||||
break;
|
||||
case 4:
|
||||
createOne(25, 30); // 6th row MASTER (all)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createOne(31, 32); //on
|
||||
}
|
||||
}
|
||||
|
||||
static void createParity(void) {
|
||||
int i, p = 1; // init even parity, without system ID
|
||||
for(i=25;i<=37;i+=2) {
|
||||
if(quigg_gt7000->raw[i] == PULSE_QUIGG_LONG) {
|
||||
p = -p;
|
||||
}
|
||||
}
|
||||
if(p == -1) {
|
||||
createOne(39, 40);
|
||||
}
|
||||
}
|
||||
|
||||
static int createCode(JsonNode *code) {
|
||||
double itmp = -1;
|
||||
int unit = -1, id = -1, learn = -1, state = -1, all = 0;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if(json_find_number(code, "learn", &itmp) == 0)
|
||||
learn = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(id==-1 || (unit==-1 && all==0) || state==-1) {
|
||||
logprintf(LOG_ERR, "quigg_gt7000: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 4095 || id < 0) {
|
||||
logprintf(LOG_ERR, "quigg_gt7000: invalid programm code id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((unit > 3 || unit < 0) && all == 0) {
|
||||
logprintf(LOG_ERR, "quigg_gt7000: invalid button code unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(unit == -1 && all == 1) {
|
||||
unit = 4;
|
||||
}
|
||||
quigg_gt7000->rawlen = RAW_LENGTH;
|
||||
createMessage(id, state, unit, all, learn);
|
||||
clearCode();
|
||||
createId(id);
|
||||
createUnit(unit);
|
||||
createState(state);
|
||||
createParity();
|
||||
createFooter();
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -i --id=id\t\t\tcontrol one or multiple devices with this id\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol the device unit with this code\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal to device\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal to device\n");
|
||||
printf("\t -l --learn\t\t\temulate learning mode of remote control\n");
|
||||
printf("\t -a --id=all\t\t\tcommand to all devices with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void quiggGT7000Init(void) {
|
||||
|
||||
protocol_register(&quigg_gt7000);
|
||||
protocol_set_id(quigg_gt7000, "quigg_gt7000");
|
||||
protocol_device_add(quigg_gt7000, "quigg_gt7000", "Quigg GT-7000 Switches");
|
||||
quigg_gt7000->devtype = SWITCH;
|
||||
quigg_gt7000->hwtype = RF433;
|
||||
quigg_gt7000->txrpt = NORMAL_REPEATS; // SHORT: GT-FSI-04a range: 620... 960
|
||||
quigg_gt7000->minrawlen = RAW_LENGTH;
|
||||
quigg_gt7000->maxrawlen = RAW_LENGTH;
|
||||
quigg_gt7000->maxgaplen = (int)(PULSE_QUIGG_FOOTER*0.9);
|
||||
quigg_gt7000->mingaplen = (int)(PULSE_QUIGG_FOOTER*1.1);
|
||||
|
||||
options_add(&quigg_gt7000->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&quigg_gt7000->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&quigg_gt7000->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-3])$");
|
||||
options_add(&quigg_gt7000->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-3][0-9][0-9][0-9]|40[0-8][0-9]|409[0-5])$");
|
||||
options_add(&quigg_gt7000->options, 'a', "all", OPTION_NO_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&quigg_gt7000->options, 'l', "learn", OPTION_HAS_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&quigg_gt7000->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&quigg_gt7000->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
quigg_gt7000->parseCode=&parseCode;
|
||||
quigg_gt7000->createCode=&createCode;
|
||||
quigg_gt7000->printHelp=&printHelp;
|
||||
quigg_gt7000->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "quigg_gt7000";
|
||||
module->version = "2.2";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
quiggGT7000Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo_rasp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_QUIGG_GT7000_H_
|
||||
#define _PROTOCOL_QUIGG_GT7000_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *quigg_gt7000;
|
||||
void quiggGT7000Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMoo & dominikkarall
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "quigg_gt9000.h"
|
||||
|
||||
#define PULSE_QUIGG_SHORT 500
|
||||
#define PULSE_QUIGG_LONG 1100
|
||||
#define PULSE_QUIGG_FOOTER1 3000
|
||||
#define PULSE_QUIGG_FOOTER2 7000
|
||||
|
||||
#define NORMAL_REPEATS 4
|
||||
#define AVG_PULSE_LENGTH 750
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
/* Encoding details:
|
||||
Bit
|
||||
0-3 First part of systemcode
|
||||
4-19 Encrypted systemcode
|
||||
16-19 ON/OFF statecodes (in encoded state, is also used decoded for systemcode)
|
||||
example based on 1110 firt part systemcode
|
||||
ON2/OFF4 - 0000
|
||||
OFF1/ON3/ONALL - 1000
|
||||
OFF2/ON4 - 0100
|
||||
OFF2/ON4 - 1100
|
||||
OFF1/ON3/ONALL - 0010
|
||||
ON1/OFF3/OFFALL - 1010
|
||||
ON1/OFF3/OFFALL - 0110
|
||||
ON2/OFF4 - 1110
|
||||
ON1/OFF3/OFFALL - 0001
|
||||
OFF2/ON4 - 1001
|
||||
ON1/OFF3/OFFALL - 0101
|
||||
OFF2/ON4 - 1101
|
||||
ON2/OFF4 - 0011
|
||||
OFF1/ON3/ONALL - 1011
|
||||
OFF1/ON3/ONALL - 0111
|
||||
ON2/OFF4 - 1111
|
||||
20-24 Unit
|
||||
25 Footer (3000 7000)
|
||||
*/
|
||||
|
||||
char gt9000_unit_offon_map[16][2][4] = {{{8,2,11,7},{10,6,1,5}}, //unit 0 (untested)
|
||||
{{8,2,11,7},{10,6,1,5}}, //unit 1 (untested)
|
||||
{{8,2,11,7},{10,6,1,5}}, //unit 2 (working)
|
||||
{{8,2,11,7},{10,6,1,5}}, //unit 3
|
||||
{{10,6,1,5},{8,2,11,7}}, //unit 4 (ALL-working)
|
||||
{{10,6,1,5},{8,2,11,7}}, //unit 5 (working)
|
||||
{{10,6,1,5},{8,2,11,7}}, //unit 6 (working)
|
||||
{{10,6,1,5},{8,2,11,7}}, //unit 7
|
||||
{{4,9,12,13},{0,3,14,15}}, //unit 8 (working)
|
||||
{{4,9,12,13},{0,3,14,15}}, //unit 9 (untested)
|
||||
{{4,9,12,13},{0,3,14,15}}, //unit 10
|
||||
{{4,9,12,13},{0,3,14,15}}, //unit 11 (untested)
|
||||
{{0,3,14,15},{4,9,12,13}}, //unit 12 (untested)
|
||||
{{0,3,14,15},{4,9,12,13}}, //unit 13 (untested)
|
||||
{{0,3,14,15},{4,9,12,13}}, //unit 14
|
||||
{{0,3,14,15},{4,9,12,13}}};//unit 15 (untested)
|
||||
char gt9000_unit_offon_map2[16][2][4] = {{{1,2,9,10},{3,4,7,11}}, //unit 0
|
||||
{{1,2,9,10},{3,4,7,11}}, //unit 1 (untested)
|
||||
{{1,2,9,10},{3,4,7,11}}, //unit 2
|
||||
{{1,2,9,10},{3,4,7,11}}, //unit 3
|
||||
{{3,4,7,11},{1,2,9,10}}, //unit 4
|
||||
{{3,4,7,11},{1,2,9,10}}, //unit 5 (ALL-working)
|
||||
{{3,4,7,11},{1,2,9,10}}, //unit 6 (untested)
|
||||
{{3,4,7,11},{1,2,9,10}}, //unit 7 (untested)
|
||||
{{-1,-1,-1,-1},{-1,-1,-1,-1}},
|
||||
{{-1,-1,-1,-1},{-1,-1,-1,-1}},
|
||||
{{-1,-1,-1,-1},{-1,-1,-1,-1}},
|
||||
{{-1,-1,-1,-1},{-1,-1,-1,-1}},
|
||||
{{-1,-1,-1,-1},{-1,-1,-1,-1}},
|
||||
{{-1,-1,-1,-1},{-1,-1,-1,-1}},
|
||||
{{-1,-1,-1,-1},{-1,-1,-1,-1}},
|
||||
{{-1,-1,-1,-1},{-1,-1,-1,-1}}};
|
||||
|
||||
int gt9000_hash[16] = { 0x0, 0x9, 0xF, 0x4, 0xA, 0xD, 0x5, 0xB,
|
||||
0x3, 0x2, 0x1, 0x7, 0xE, 0x6, 0xC, 0x8 };
|
||||
int gt9000_hash2[16] = { 0x0, 0x9, 0x5, 0xF, 0x3, 0x6, 0xC, 0x7,
|
||||
0xE, 0xD, 0x1, 0xB, 0x2, 0xA, 0x4, 0x8 };
|
||||
|
||||
static int isSyscodeType1(int syscodetype) {
|
||||
if(syscodetype & 0x13)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate(void) {
|
||||
if(quigg_gt9000->rawlen == RAW_LENGTH) {
|
||||
if(quigg_gt9000->raw[quigg_gt9000->rawlen-1] >= (int)(PULSE_QUIGG_FOOTER2*0.9) &&
|
||||
quigg_gt9000->raw[quigg_gt9000->rawlen-1] <= (int)(PULSE_QUIGG_FOOTER2*1.1) &&
|
||||
quigg_gt9000->raw[quigg_gt9000->rawlen-2] >= (int)(PULSE_QUIGG_FOOTER1*0.9) &&
|
||||
quigg_gt9000->raw[quigg_gt9000->rawlen-2] <= (int)(PULSE_QUIGG_FOOTER1*1.1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int *binary, int systemcode, int state, int unit) {
|
||||
int i = 0;
|
||||
char binaryCh[RAW_LENGTH/2];
|
||||
quigg_gt9000->message = json_mkobject();
|
||||
if(binary != NULL) {
|
||||
for(i=0;i<RAW_LENGTH/2;i++) {
|
||||
if(binary[i] == 0) {
|
||||
binaryCh[i] = '0';
|
||||
} else {
|
||||
binaryCh[i] = '1';
|
||||
}
|
||||
}
|
||||
binaryCh[RAW_LENGTH/2-1] = '\0';
|
||||
json_append_member(quigg_gt9000->message, "binary", json_mkstring(binaryCh));
|
||||
}
|
||||
json_append_member(quigg_gt9000->message, "id", json_mknumber(systemcode, 0));
|
||||
json_append_member(quigg_gt9000->message, "unit", json_mknumber(unit, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(quigg_gt9000->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(quigg_gt9000->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static int decodePayload(int payload, int index, int syscodetype) {
|
||||
int ret = -1;
|
||||
|
||||
if(isSyscodeType1(syscodetype))
|
||||
ret = payload^gt9000_hash[index];
|
||||
else
|
||||
ret = payload^gt9000_hash2[index];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parseSystemcode(int *binary) {
|
||||
int systemcode1dec = binToDecRev(binary, 0, 3);
|
||||
int systemcode2enc = binToDecRev(binary, 4, 7);
|
||||
int systemcode2dec = 0; //calculate all codes with base syscode2 = 0
|
||||
int systemcode3enc = binToDecRev(binary, 8, 11);
|
||||
int systemcode3dec = decodePayload(systemcode3enc, systemcode2enc, systemcode1dec);
|
||||
int systemcode4enc = binToDecRev(binary, 12, 15);
|
||||
int systemcode4dec = decodePayload(systemcode4enc, systemcode3enc, systemcode1dec);
|
||||
int systemcode5enc = binToDecRev(binary, 16, 19);
|
||||
int systemcode5dec = decodePayload(systemcode5enc, systemcode4enc, systemcode1dec);
|
||||
int systemcode = (systemcode1dec<<16) + (systemcode2dec<<12) + (systemcode3dec<<8) + (systemcode4dec<<4) + systemcode5dec;
|
||||
|
||||
return systemcode;
|
||||
}
|
||||
|
||||
static void pulseToBinary(int *binary) {
|
||||
int x = 0;
|
||||
for(x=0; x<quigg_gt9000->rawlen-1; x+=2) {
|
||||
if(quigg_gt9000->raw[x+1] > AVG_PULSE_LENGTH) {
|
||||
binary[x/2] = 0;
|
||||
} else {
|
||||
binary[x/2] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/2], state = 0;
|
||||
int i = 0;
|
||||
|
||||
pulseToBinary(binary);
|
||||
|
||||
int syscodetype = binToDecRev(binary, 0, 3);
|
||||
int systemcode = parseSystemcode(binary);
|
||||
int statecode = binToDecRev(binary, 16, 19);
|
||||
int unit = binToDec(binary, 20, 23);
|
||||
|
||||
//validate unit & statecode
|
||||
if(isSyscodeType1(syscodetype)) {
|
||||
for(i=0;i<4;i++) {
|
||||
if(statecode == gt9000_unit_offon_map[unit][1][i]) {
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(i=0;i<4;i++) {
|
||||
if(statecode == gt9000_unit_offon_map2[unit][1][i]) {
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createMessage(binary, systemcode, state, unit);
|
||||
}
|
||||
|
||||
static void createZero(int s, int e) {
|
||||
int i;
|
||||
for(i=s;i<=e;i+=2) {
|
||||
quigg_gt9000->raw[i] = PULSE_QUIGG_SHORT;
|
||||
quigg_gt9000->raw[i+1] = PULSE_QUIGG_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
static void createOne(int s, int e) {
|
||||
int i;
|
||||
for(i=s;i<=e;i+=2) {
|
||||
quigg_gt9000->raw[i] = PULSE_QUIGG_LONG;
|
||||
quigg_gt9000->raw[i+1] = PULSE_QUIGG_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
quigg_gt9000->raw[quigg_gt9000->rawlen-2] = PULSE_QUIGG_FOOTER1;
|
||||
quigg_gt9000->raw[quigg_gt9000->rawlen-1] = PULSE_QUIGG_FOOTER2;
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createZero(0, quigg_gt9000->rawlen-3);
|
||||
}
|
||||
|
||||
static void createEncryptedData(int encrypteddata) {
|
||||
int binary[20], length = 0, i = 0, x = 0;
|
||||
|
||||
length = decToBin(encrypteddata, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
x = (i+19-length)*2;
|
||||
if(binary[i] == 1) {
|
||||
createOne(x, x+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[4], length = 0, i = 0, x = 20;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
x = i*2 + 20*2;
|
||||
if(binary[i] == 1) {
|
||||
createOne(x, x+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void initAllCodes(int systemcode, int allcodes[16]) {
|
||||
int i = 0, syscodetype = 0;
|
||||
int systemcode1enc = 0, systemcode2enc = 0, systemcode3enc = 0, systemcode4enc = 0, systemcode5enc = 0;
|
||||
int systemcode1dec = 0, systemcode3dec = 0, systemcode4dec = 0, systemcode5dec = 0;
|
||||
|
||||
syscodetype = (systemcode >> 16) & 0xF;
|
||||
systemcode1dec = (systemcode >> 16) & 0xF;
|
||||
//systemcode2dec is always 0, therefore it is not needed
|
||||
//systemcode2dec = (systemcode >> 12) & 0xF;
|
||||
systemcode3dec = (systemcode >> 8) & 0xF;
|
||||
systemcode4dec = (systemcode >> 4) & 0xF;
|
||||
systemcode5dec = systemcode & 0xF;
|
||||
|
||||
//first 4 bits are not encrypted
|
||||
systemcode1enc = systemcode1dec;
|
||||
|
||||
//encrypt systemcode
|
||||
for(i=0;i<16;i++) {
|
||||
systemcode2enc = i;
|
||||
if(isSyscodeType1(syscodetype)) {
|
||||
systemcode3enc = gt9000_hash[systemcode2enc]^systemcode3dec;
|
||||
systemcode4enc = gt9000_hash[systemcode3enc]^systemcode4dec;
|
||||
systemcode5enc = gt9000_hash[systemcode4enc]^systemcode5dec;
|
||||
} else { //if(systemcodetype == 13 || systemcodetype == 12)
|
||||
systemcode3enc = gt9000_hash2[systemcode2enc]^systemcode3dec;
|
||||
systemcode4enc = gt9000_hash2[systemcode3enc]^systemcode4dec;
|
||||
systemcode5enc = gt9000_hash2[systemcode4enc]^systemcode5dec;
|
||||
}
|
||||
allcodes[systemcode5enc] = (systemcode1enc<<16) + (systemcode2enc<<12) + (systemcode3enc<<8) + (systemcode4enc<<4) + systemcode5enc;
|
||||
}
|
||||
}
|
||||
|
||||
static int createCode(JsonNode *code) {
|
||||
int syscodetype = 0;
|
||||
double itmp = -1;
|
||||
int unit = -1, systemcode = -1, verifysyscode = -1, state = -1, all = 0, statecode = -1;
|
||||
int allcodes[16], binary[RAW_LENGTH/2];
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if((systemcode == -1) || (unit == -1 && all == 0)) {
|
||||
logprintf(LOG_ERR, "quigg_gt9000: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode == -1) {
|
||||
logprintf(LOG_ERR, "quigg_gt9000: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit < 0) {
|
||||
logprintf(LOG_ERR, "quigg_gt9000: invalid unit code range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
quigg_gt9000->rawlen = RAW_LENGTH;
|
||||
//create all 16 codes used by the remote
|
||||
initAllCodes(systemcode, allcodes);
|
||||
//it is possible to use 4 codes per state
|
||||
//we stick to code number 1 in the on/off array
|
||||
syscodetype = (systemcode >> 16) & 0xF;
|
||||
if(isSyscodeType1(syscodetype))
|
||||
statecode = gt9000_unit_offon_map[unit][state][1];
|
||||
else
|
||||
statecode = gt9000_unit_offon_map2[unit][state][1];
|
||||
|
||||
if(statecode==-1) {
|
||||
logprintf(LOG_ERR, "quigg_gt9000: unit %d not supported, try 0-15.", unit);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int encrypteddata = allcodes[statecode];
|
||||
|
||||
clearCode();
|
||||
createEncryptedData(encrypteddata);
|
||||
createUnit(unit);
|
||||
createFooter();
|
||||
|
||||
pulseToBinary(binary);
|
||||
verifysyscode = parseSystemcode(binary);
|
||||
if(verifysyscode != systemcode) {
|
||||
logprintf(LOG_ERR, "quigg_gt9000: invalid id, try %d", verifysyscode);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
createMessage(NULL, systemcode, state, unit);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -u --unit=unit\t\t\tcontrol the device unit with this code\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal to device\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal to device\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol one or multiple devices with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void quiggGT9000Init(void) {
|
||||
|
||||
protocol_register(&quigg_gt9000);
|
||||
protocol_set_id(quigg_gt9000, "quigg_gt9000");
|
||||
protocol_device_add(quigg_gt9000, "quigg_gt9000", "Quigg GT-9000 remote with GT-FSi-06 switches");
|
||||
quigg_gt9000->devtype = SWITCH;
|
||||
quigg_gt9000->hwtype = RF433;
|
||||
quigg_gt9000->txrpt = NORMAL_REPEATS;
|
||||
quigg_gt9000->minrawlen = RAW_LENGTH;
|
||||
quigg_gt9000->maxrawlen = RAW_LENGTH;
|
||||
quigg_gt9000->maxgaplen = (int)(PULSE_QUIGG_FOOTER2*1.1);
|
||||
quigg_gt9000->mingaplen = (int)(PULSE_QUIGG_FOOTER2*0.9);
|
||||
|
||||
options_add(&quigg_gt9000->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&quigg_gt9000->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&quigg_gt9000->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&quigg_gt9000->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
quigg_gt9000->parseCode=&parseCode;
|
||||
quigg_gt9000->createCode=&createCode;
|
||||
quigg_gt9000->printHelp=&printHelp;
|
||||
quigg_gt9000->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "quigg_gt9000";
|
||||
module->version = "1.3";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
quiggGT9000Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2015 CurlyMoo & dominikkarall
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_QUIGG_GT9000_H_
|
||||
#define _PROTOCOL_QUIGG_GT9000_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *quigg_gt9000;
|
||||
void quiggGT9000Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo_rasp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "quigg_screen.h"
|
||||
|
||||
#define PULSE_QUIGG_SCREEN_SHORT 700
|
||||
#define PULSE_QUIGG_SCREEN_LONG 1400
|
||||
#define PULSE_QUIGG_SCREEN_FOOTER 81000
|
||||
#define PULSE_QUIGG_SCREEN_50 PULSE_QUIGG_SCREEN_SHORT+(PULSE_QUIGG_SCREEN_LONG-PULSE_QUIGG_SCREEN_SHORT)/2
|
||||
|
||||
#define LEARN_REPEATS 4
|
||||
#define NORMAL_REPEATS 4
|
||||
#define PULSE_MULTIPLIER 2
|
||||
#define AVG_PULSE_LENGTH PULSE_QUIGG_SCREEN_SHORT
|
||||
#define MIN_PULSE_LENGTH AVG_PULSE_LENGTH-80
|
||||
#define MAX_PULSE_LENGTH AVG_PULSE_LENGTH+260
|
||||
#define RAW_LENGTH 42
|
||||
|
||||
static int validate(void) {
|
||||
if(quigg_screen->rawlen == RAW_LENGTH) {
|
||||
if(quigg_screen->raw[quigg_screen->rawlen-1] >= (int)(PULSE_QUIGG_SCREEN_FOOTER*0.9) &&
|
||||
quigg_screen->raw[quigg_screen->rawlen-1] <= (int)(PULSE_QUIGG_SCREEN_FOOTER*1.1) &&
|
||||
quigg_screen->raw[0] >= MIN_PULSE_LENGTH &&
|
||||
quigg_screen->raw[0] <= MAX_PULSE_LENGTH) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void createMessage(int id, int state, int unit, int all, int learn) {
|
||||
quigg_screen->message = json_mkobject();
|
||||
json_append_member(quigg_screen->message, "id", json_mknumber(id, 0));
|
||||
if(all==1) {
|
||||
json_append_member(quigg_screen->message, "all", json_mknumber(all, 0));
|
||||
} else {
|
||||
json_append_member(quigg_screen->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
if(state==0) {
|
||||
json_append_member(quigg_screen->message, "state", json_mkstring("up"));
|
||||
} else {
|
||||
json_append_member(quigg_screen->message, "state", json_mkstring("down"));
|
||||
}
|
||||
|
||||
if(learn == 1) {
|
||||
quigg_screen->txrpt = LEARN_REPEATS;
|
||||
} else {
|
||||
quigg_screen->txrpt = NORMAL_REPEATS;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/2], x = 0, dec_unit[4] = {0, 3, 1, 2};
|
||||
int iParity = 1, iParityData = -1; // init for even parity
|
||||
int iSwitch = 0;
|
||||
|
||||
if(quigg_screen->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "quigg_screen: parsecode - invalid parameter passed %d", quigg_screen->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
// 42 bytes are the number of raw bytes
|
||||
// Byte 1,2 in raw buffer is the first logical byte, rawlen-3,-2 is the parity bit, rawlen-1 is the footer
|
||||
for(x=0; x<quigg_screen->rawlen-1; x+=2) {
|
||||
if(quigg_screen->raw[x+1] > PULSE_QUIGG_SCREEN_50) {
|
||||
binary[x/2] = 1;
|
||||
if((x / 2) > 11 && (x / 2) < 19) {
|
||||
iParityData = iParity;
|
||||
iParity = -iParity;
|
||||
}
|
||||
} else {
|
||||
binary[x/2] = 0;
|
||||
}
|
||||
}
|
||||
if(iParityData < 0)
|
||||
iParityData=0;
|
||||
|
||||
int id = binToDecRev(binary, 0, 11);
|
||||
int unit = binToDecRev(binary, 12, 13);
|
||||
int all = binToDecRev(binary, 14, 14);
|
||||
int state = binToDecRev(binary, 15, 15);
|
||||
int screen = binToDecRev(binary, 16, 16);
|
||||
int parity = binToDecRev(binary, 19, 19);
|
||||
int learn = 0;
|
||||
|
||||
unit = dec_unit[unit];
|
||||
|
||||
// Prepare dim up/down mode for appropriate handling with createMessage
|
||||
iSwitch = (screen * 2) + state; // 00-turn off 01-turn on 10-dim up 11-dim down
|
||||
|
||||
switch(iSwitch) {
|
||||
case 0:
|
||||
case 1:
|
||||
screen=-1; // mode handled by quigg_GT7000 protocol driver
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if((iParityData == parity) && (screen != -1)) {
|
||||
createMessage(id, state, unit, all, learn);
|
||||
}
|
||||
}
|
||||
|
||||
static void createZero(int s, int e) {
|
||||
int i;
|
||||
for(i=s;i<=e;i+=2) {
|
||||
quigg_screen->raw[i] = PULSE_QUIGG_SCREEN_SHORT;
|
||||
quigg_screen->raw[i+1] = PULSE_QUIGG_SCREEN_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
static void createOne(int s, int e) {
|
||||
int i;
|
||||
for(i=s;i<=e;i+=2) {
|
||||
quigg_screen->raw[i] = PULSE_QUIGG_SCREEN_LONG;
|
||||
quigg_screen->raw[i+1] = PULSE_QUIGG_SCREEN_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHeader(void) {
|
||||
quigg_screen->raw[0] = PULSE_QUIGG_SCREEN_SHORT;
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
quigg_screen->raw[quigg_screen->rawlen-1] = PULSE_QUIGG_SCREEN_FOOTER;
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHeader();
|
||||
createZero(1,quigg_screen->rawlen-3);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[16], length = 0, i = 0, x = 23;
|
||||
|
||||
length = decToBin(id, binary);
|
||||
for(i=length;i>=0;i--) {
|
||||
if(binary[i] == 1) {
|
||||
createOne(x, x+1);
|
||||
}
|
||||
x = x-2;
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
switch (unit) {
|
||||
case 0:
|
||||
createZero(25, 30); // Unit 0 screen
|
||||
createOne(33, 34);
|
||||
createOne(37, 38);
|
||||
break;
|
||||
case 1:
|
||||
createOne(25, 26); // Unit 1 screen
|
||||
createOne(33, 34);
|
||||
break;
|
||||
case 2:
|
||||
createOne(25, 28); // Unit 2 screen
|
||||
createOne(33, 34);
|
||||
break;
|
||||
case 3:
|
||||
createOne(27, 28); // Unit 3 screen
|
||||
createOne(33, 34);
|
||||
createOne(37, 38);
|
||||
break;
|
||||
case 4:
|
||||
createOne(25, 30); // MASTER (all) screen
|
||||
createOne(33, 34);
|
||||
createOne(37, 38);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state==1) {
|
||||
createOne(31, 32); // dim down
|
||||
}
|
||||
}
|
||||
|
||||
static void createParity(void) {
|
||||
int i, p = 1; // init even parity, without system ID
|
||||
for(i=25;i<=37;i+=2) {
|
||||
if(quigg_screen->raw[i] == PULSE_QUIGG_SCREEN_LONG) {
|
||||
p = -p;
|
||||
}
|
||||
}
|
||||
if(p == -1) {
|
||||
createOne(39,40);
|
||||
}
|
||||
}
|
||||
|
||||
static int createCode(JsonNode *code) {
|
||||
double itmp = -1;
|
||||
int unit = -1, id = -1, learn = -1, state = -1, all = 0;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if(json_find_number(code, "learn", &itmp) == 0)
|
||||
learn = (int)round(itmp);
|
||||
if(json_find_number(code, "up", &itmp) == 0)
|
||||
state=0;
|
||||
if(json_find_number(code, "down", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(id==-1 || (unit==-1 && all==0) || state==-1) {
|
||||
logprintf(LOG_ERR, "quigg_screen: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 4095 || id < 0) {
|
||||
logprintf(LOG_ERR, "quigg_screen: invalid system id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if((unit > 3 || unit < 0) && all == 0) {
|
||||
logprintf(LOG_ERR, "quigg_screen: invalid unit code range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if(unit == -1 && all == 1) {
|
||||
unit = 4;
|
||||
}
|
||||
quigg_screen->rawlen = RAW_LENGTH;
|
||||
createMessage(id, state, unit, all, learn);
|
||||
clearCode();
|
||||
createId(id);
|
||||
createUnit(unit);
|
||||
createState(state);
|
||||
createParity();
|
||||
createFooter();
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -i --id=id\t\t\tselect the device units with this system id\n");
|
||||
printf("\t -a --id=all\t\t\tcontrol all devices selected with the system id\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol the individual device unit selected with the system id\n");
|
||||
printf("\t -f --up\t\t\tsend an darken DOWN command to the selected device\n");
|
||||
printf("\t -l --learn\t\t\temulate learning mode of remote control\n");
|
||||
printf("\t -t --down\t\t\tsend an brighten UP command to the selected device\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void quiggScreenInit(void) {
|
||||
|
||||
protocol_register(&quigg_screen);
|
||||
protocol_set_id(quigg_screen, "quigg_screen");
|
||||
protocol_device_add(quigg_screen, "quigg_screen", "Quigg Switch Screen");
|
||||
quigg_screen->devtype = SCREEN;
|
||||
quigg_screen->hwtype = RF433;
|
||||
quigg_screen->txrpt = NORMAL_REPEATS; // SHORT: GT-FSI-04a range: 620... 960
|
||||
quigg_screen->minrawlen = RAW_LENGTH;
|
||||
quigg_screen->maxrawlen = RAW_LENGTH;
|
||||
quigg_screen->maxgaplen = (int)(PULSE_QUIGG_SCREEN_FOOTER*0.9);
|
||||
quigg_screen->mingaplen = (int)(PULSE_QUIGG_SCREEN_FOOTER*1.1);
|
||||
|
||||
options_add(&quigg_screen->options, 't', "up", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&quigg_screen->options, 'f', "down", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&quigg_screen->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-3])$");
|
||||
options_add(&quigg_screen->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-3][0-9][0-9][0-9]|40[0-8][0-9]|409[0-5])$");
|
||||
options_add(&quigg_screen->options, 'a', "all", OPTION_NO_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
options_add(&quigg_screen->options, 'l', "learn", OPTION_HAS_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&quigg_screen->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&quigg_screen->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
quigg_screen->parseCode=&parseCode;
|
||||
quigg_screen->createCode=&createCode;
|
||||
quigg_screen->printHelp=&printHelp;
|
||||
quigg_screen->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "quigg_screen";
|
||||
module->version = "2.2";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
quiggScreenInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & wo_rasp
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_QUIGG_SCREEN_H_
|
||||
#define _PROTOCOL_QUIGG_SCREEN_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *quigg_screen;
|
||||
void quiggScreenInit(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "rc101.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 236
|
||||
#define MAX_PULSE_LENGTH 246
|
||||
#define AVG_PULSE_LENGTH 241
|
||||
#define RAW_LENGTH 66
|
||||
|
||||
static int validate(void) {
|
||||
if(rc101->rawlen == RAW_LENGTH) {
|
||||
if(rc101->raw[rc101->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
rc101->raw[rc101->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int state, int unit, int all) {
|
||||
rc101->message = json_mkobject();
|
||||
json_append_member(rc101->message, "id", json_mknumber(id, 0));
|
||||
if(all == 1) {
|
||||
json_append_member(rc101->message, "all", json_mknumber(1, 0));
|
||||
} else {
|
||||
json_append_member(rc101->message, "unit", json_mknumber(unit, 0));
|
||||
}
|
||||
if(state == 1) {
|
||||
json_append_member(rc101->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(rc101->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int i = 0, x = 0, binary[RAW_LENGTH/2];
|
||||
|
||||
if(rc101->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "rc101: parsecode - invalid parameter passed %d", rc101->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(i=0;i<rc101->rawlen; i+=2) {
|
||||
if(rc101->raw[i] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x++] = 1;
|
||||
} else {
|
||||
binary[x++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int id = binToDec(binary, 0, 19);
|
||||
int state = binary[20];
|
||||
int unit = 7-binToDec(binary, 21, 23);
|
||||
int all = 0;
|
||||
if(unit == 7 && state == 1) {
|
||||
all = 1;
|
||||
state = 0;
|
||||
}
|
||||
if(unit == 6 && state == 0) {
|
||||
all = 1;
|
||||
state = 1;
|
||||
}
|
||||
createMessage(id, state, unit, all);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
rc101->raw[i]=AVG_PULSE_LENGTH;
|
||||
rc101->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=2) {
|
||||
rc101->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rc101->raw[i+1]=AVG_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(0, 63);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createHigh(x, x+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(7-unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*2;
|
||||
createHigh(42+x, 42+x+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createHigh(40, 41);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
rc101->raw[64]=(AVG_PULSE_LENGTH);
|
||||
rc101->raw[65]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int state = -1;
|
||||
int unit = -1;
|
||||
int all = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
if(json_find_number(code, "all", &itmp) == 0)
|
||||
all = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(all == 1 && state == 1) {
|
||||
unit = 6;
|
||||
state = 0;
|
||||
}
|
||||
if(all == 1 && state == 0) {
|
||||
unit = 7;
|
||||
state = 1;
|
||||
}
|
||||
|
||||
if(id == -1 || state == -1 || unit == -1) {
|
||||
logprintf(LOG_ERR, "rc101: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 1048575 || id < 0) {
|
||||
logprintf(LOG_ERR, "rc101: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 4 || unit < 0) {
|
||||
createMessage(id, state, unit, all);
|
||||
clearCode();
|
||||
createId(id);
|
||||
createState(state);
|
||||
if(unit > -1) {
|
||||
createUnit(unit);
|
||||
}
|
||||
createFooter();
|
||||
rc101->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -a --all\t\t\tsend command to all devices with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void rc101Init(void) {
|
||||
|
||||
protocol_register(&rc101);
|
||||
protocol_set_id(rc101, "rc101");
|
||||
protocol_device_add(rc101, "rc101", "rc101 Switches");
|
||||
protocol_device_add(rc101, "rc102", "rc102 Switches");
|
||||
rc101->devtype = SWITCH;
|
||||
rc101->hwtype = RF433;
|
||||
rc101->minrawlen = RAW_LENGTH;
|
||||
rc101->maxrawlen = RAW_LENGTH;
|
||||
rc101->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
rc101->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&rc101->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-4])$");
|
||||
options_add(&rc101->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-4])$");
|
||||
options_add(&rc101->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rc101->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rc101->options, 'a', "all", OPTION_OPT_VALUE, DEVICES_OPTIONAL, JSON_NUMBER, NULL, NULL);
|
||||
|
||||
options_add(&rc101->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&rc101->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
rc101->parseCode=&parseCode;
|
||||
rc101->createCode=&createCode;
|
||||
rc101->printHelp=&printHelp;
|
||||
rc101->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "rc101";
|
||||
module->version = "1.1";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
rc101Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_RC101_H_
|
||||
#define _PROTOCOL_RC101_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *rc101;
|
||||
void rc101Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & neevedr
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "rev_v1.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 314
|
||||
#define MAX_PULSE_LENGTH 324
|
||||
#define AVG_PULSE_LENGTH 319
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(rev1_switch->rawlen == RAW_LENGTH) {
|
||||
if(rev1_switch->raw[rev1_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
rev1_switch->raw[rev1_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(char *id, int unit, int state) {
|
||||
rev1_switch->message = json_mkobject();
|
||||
json_append_member(rev1_switch->message, "id", json_mkstring(id));
|
||||
json_append_member(rev1_switch->message, "unit", json_mknumber(unit, 0));
|
||||
if(state == 1)
|
||||
json_append_member(rev1_switch->message, "state", json_mkstring("off"));
|
||||
else
|
||||
json_append_member(rev1_switch->message, "state", json_mkstring("on"));
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, z = 65, binary[RAW_LENGTH/4];
|
||||
char id[3];
|
||||
|
||||
if(rev1_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "rev1_switch: parsecode - invalid parameter passed %d", rev1_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert the one's and zero's into binary */
|
||||
for(x=0;x<rev1_switch->rawlen-2;x+=4) {
|
||||
if(rev1_switch->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4]=1;
|
||||
} else if(rev1_switch->raw[x+0] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4]=2;
|
||||
} else {
|
||||
binary[x/4]=0;
|
||||
}
|
||||
}
|
||||
|
||||
for(x=9;x>=5;--x) {
|
||||
if(binary[x] == 2) {
|
||||
break;
|
||||
}
|
||||
z++;
|
||||
}
|
||||
|
||||
int unit = binToDecRev(binary, 0, 5);
|
||||
int state = binary[10];
|
||||
int y = binToDecRev(binary, 6, 9);
|
||||
sprintf(&id[0], "%c%d", z, y);
|
||||
|
||||
createMessage(id, unit, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rev1_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createMed(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rev1_switch->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rev1_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createMed(0,4);
|
||||
createLow(4,47);
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(23-(x+3), 23-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createId(char *id) {
|
||||
int l = ((int)(id[0]))-65;
|
||||
int y = atoi(&id[1]);
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(y, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
x=i*4;
|
||||
if(binary[i]==1) {
|
||||
createHigh(39-(x+3), 39-x);
|
||||
}
|
||||
}
|
||||
x=(l*4);
|
||||
createMed(39-(x+3), 39-x);
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createMed(40,43);
|
||||
createHigh(44,47);
|
||||
} else {
|
||||
createHigh(40,43);
|
||||
createMed(44,47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
rev1_switch->raw[48]=(AVG_PULSE_LENGTH);
|
||||
rev1_switch->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
char id[3] = {'\0'};
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
double itmp = -1;
|
||||
char *stmp;
|
||||
|
||||
strcpy(id, "-1");
|
||||
|
||||
if(json_find_string(code, "id", &stmp) == 0)
|
||||
strcpy(id, stmp);
|
||||
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
|
||||
if(strcmp(id, "-1") == 0 || unit == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "rev1_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if((int)(id[0]) < 65 || (int)(id[0]) > 70) {
|
||||
logprintf(LOG_ERR, "rev1_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(atoi(&id[1]) < 0 || atoi(&id[1]) > 31) {
|
||||
logprintf(LOG_ERR, "rev1_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 63 || unit < 0) {
|
||||
logprintf(LOG_ERR, "rev1_switch: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, unit, state);
|
||||
clearCode();
|
||||
createUnit(unit);
|
||||
createId(id);
|
||||
createState(state);
|
||||
createFooter();
|
||||
rev1_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void rev1Init(void) {
|
||||
|
||||
protocol_register(&rev1_switch);
|
||||
protocol_set_id(rev1_switch, "rev1_switch");
|
||||
protocol_device_add(rev1_switch, "rev1_switch", "Rev Switches v1");
|
||||
rev1_switch->devtype = SWITCH;
|
||||
rev1_switch->hwtype = RF433;
|
||||
rev1_switch->minrawlen = RAW_LENGTH;
|
||||
rev1_switch->maxrawlen = RAW_LENGTH;
|
||||
rev1_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
rev1_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&rev1_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rev1_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rev1_switch->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]|[1-5][0-9]|6[0-3])$");
|
||||
options_add(&rev1_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_STRING, NULL, "^[ABCDEF](3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
|
||||
options_add(&rev1_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&rev1_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
rev1_switch->parseCode=&parseCode;
|
||||
rev1_switch->createCode=&createCode;
|
||||
rev1_switch->printHelp=&printHelp;
|
||||
rev1_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "rev1_switch";
|
||||
module->version = "0.14";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
rev1Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & neevedr
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_REV1_H_
|
||||
#define _PROTOCOL_REV1_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *rev1_switch;
|
||||
void rev1Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & neevedr
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "rev_v2.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 167
|
||||
#define MAX_PULSE_LENGTH 263
|
||||
#define AVG_PULSE_LENGTH 258
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(rev2_switch->rawlen == RAW_LENGTH) {
|
||||
if(rev2_switch->raw[rev2_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
rev2_switch->raw[rev2_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(char *id, int unit, int state) {
|
||||
rev2_switch->message = json_mkobject();
|
||||
json_append_member(rev2_switch->message, "id", json_mkstring(id));
|
||||
json_append_member(rev2_switch->message, "unit", json_mknumber(unit, 0));
|
||||
if(state == 2)
|
||||
json_append_member(rev2_switch->message, "state", json_mkstring("on"));
|
||||
else
|
||||
json_append_member(rev2_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, z = 65, binary[RAW_LENGTH/4];
|
||||
char id[3];
|
||||
|
||||
if(rev2_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "rev2_switch: parsecode - invalid parameter passed %d", rev2_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert the one's and zero's into binary */
|
||||
for(x=0;x<rev2_switch->rawlen-2;x+=4) {
|
||||
if(rev2_switch->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4]=1;
|
||||
} else if(rev2_switch->raw[x+0] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[x/4]=2;
|
||||
} else {
|
||||
binary[x/4]=0;
|
||||
}
|
||||
}
|
||||
|
||||
for(x=9;x>=5;--x) {
|
||||
if(binary[x] == 2) {
|
||||
break;
|
||||
}
|
||||
z++;
|
||||
}
|
||||
|
||||
int unit = binToDecRev(binary, 0, 5);
|
||||
int state = binary[11];
|
||||
int y = binToDecRev(binary, 6, 9);
|
||||
sprintf(&id[0], "%c%d", z, y);
|
||||
|
||||
createMessage(id, unit, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rev2_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createMed(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rev2_switch->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+1]=(AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rev2_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createMed(0,4);
|
||||
createLow(4,47);
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(23-(x+3), 23-x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createId(char *id) {
|
||||
int l = ((int)(id[0]))-65;
|
||||
int y = atoi(&id[1]);
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(y, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
x=i*4;
|
||||
if(binary[i]==1) {
|
||||
createHigh(39-(x+3), 39-x);
|
||||
}
|
||||
}
|
||||
x=(l*4);
|
||||
createMed(39-(x+3), 39-x);
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createMed(40,43);
|
||||
createHigh(44,47);
|
||||
} else {
|
||||
createHigh(40,43);
|
||||
createMed(44,47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
rev2_switch->raw[48]=(AVG_PULSE_LENGTH);
|
||||
rev2_switch->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
char id[3] = {'\0'};
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
double itmp = -1;
|
||||
char *stmp;
|
||||
|
||||
strcpy(id, "-1");
|
||||
|
||||
if(json_find_string(code, "id", &stmp) == 0)
|
||||
strcpy(id, stmp);
|
||||
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
|
||||
if(strcmp(id, "-1") == 0 || unit == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "rev2_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if((int)(id[0]) < 65 || (int)(id[0]) > 70) {
|
||||
logprintf(LOG_ERR, "rev2_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(atoi(&id[1]) < 0 || atoi(&id[1]) > 31) {
|
||||
logprintf(LOG_ERR, "rev2_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 63 || unit < 0) {
|
||||
logprintf(LOG_ERR, "rev2_switch: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, unit, ((state == 2 || state == 1) ? 2 : 0));
|
||||
clearCode();
|
||||
createUnit(unit);
|
||||
createId(id);
|
||||
createState(state);
|
||||
createFooter();
|
||||
rev2_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void rev2Init(void) {
|
||||
|
||||
protocol_register(&rev2_switch);
|
||||
protocol_set_id(rev2_switch, "rev2_switch");
|
||||
protocol_device_add(rev2_switch, "rev2_switch", "Rev Switches v2");
|
||||
rev2_switch->devtype = SWITCH;
|
||||
rev2_switch->hwtype = RF433;
|
||||
rev2_switch->minrawlen = RAW_LENGTH;
|
||||
rev2_switch->maxrawlen = RAW_LENGTH;
|
||||
rev2_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
rev2_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&rev2_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rev2_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rev2_switch->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]|[1-5][0-9]|6[0-3])$");
|
||||
options_add(&rev2_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_STRING, NULL, "^[ABCDEF](3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
|
||||
options_add(&rev2_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&rev2_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
rev2_switch->parseCode=&parseCode;
|
||||
rev2_switch->createCode=&createCode;
|
||||
rev2_switch->printHelp=&printHelp;
|
||||
rev2_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "rev2_switch";
|
||||
module->version = "0.14";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
rev2Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & neevedr
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_REV2_H_
|
||||
#define _PROTOCOL_REV2_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *rev2_switch;
|
||||
void rev2Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & easy12
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "rev_v3.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 253
|
||||
#define MAX_PULSE_LENGTH 269
|
||||
#define AVG_PULSE_LENGTH 264
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(rev3_switch->rawlen == RAW_LENGTH) {
|
||||
if(rev3_switch->raw[rev3_switch->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
rev3_switch->raw[rev3_switch->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int unit, int state) {
|
||||
rev3_switch->message = json_mkobject();
|
||||
json_append_member(rev3_switch->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(rev3_switch->message, "unit", json_mknumber(unit, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(rev3_switch->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(rev3_switch->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, i = 0, binary[RAW_LENGTH/4];
|
||||
|
||||
if(rev3_switch->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "rev3_switch: parsecode - invalid parameter passed %d", rev3_switch->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert the one's and zero's into binary */
|
||||
for(x=0;x<rev3_switch->rawlen-2;x+=4) {
|
||||
if(rev3_switch->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int unit = binToDec(binary, 6, 9);
|
||||
int state = binary[11];
|
||||
int id = binToDec(binary, 0, 5);
|
||||
|
||||
createMessage(id, unit, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rev3_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
rev3_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev3_switch->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev3_switch->raw[i+3]=(AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rev3_switch->raw[i]=(AVG_PULSE_LENGTH);
|
||||
rev3_switch->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rev3_switch->raw[i+2]=(AVG_PULSE_LENGTH);
|
||||
rev3_switch->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHigh(0,3);
|
||||
createLow(4,47);
|
||||
}
|
||||
|
||||
static void createUnit(int unit) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(unit, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createHigh(24+x, 24+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
x=i*4;
|
||||
if(binary[i]==1) {
|
||||
createHigh(x, x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createHigh(40,43);
|
||||
createLow(44,47);
|
||||
} else {
|
||||
createLow(40,43);
|
||||
createHigh(44,47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
rev3_switch->raw[48]=(AVG_PULSE_LENGTH);
|
||||
rev3_switch->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
int state = -1;
|
||||
double itmp = -1;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(json_find_number(code, "unit", &itmp) == 0)
|
||||
unit = (int)round(itmp);
|
||||
|
||||
if(id == -1 || unit == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "rev3_switch: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 63 || id < 0) {
|
||||
logprintf(LOG_ERR, "rev3_switch: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(unit > 15 || unit < 0) {
|
||||
logprintf(LOG_ERR, "rev3_switch: invalid unit range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, unit, state);
|
||||
clearCode();
|
||||
createUnit(unit);
|
||||
createId(id);
|
||||
createState(state);
|
||||
createFooter();
|
||||
rev3_switch->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
printf("\t -u --unit=unit\t\t\tcontrol a device with this unit code\n");
|
||||
printf("\t -i --id=id\t\t\tcontrol a device with this id\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void rev3Init(void) {
|
||||
|
||||
protocol_register(&rev3_switch);
|
||||
protocol_set_id(rev3_switch, "rev3_switch");
|
||||
protocol_device_add(rev3_switch, "rev3_switch", "Rev Switches v3");
|
||||
rev3_switch->devtype = SWITCH;
|
||||
rev3_switch->hwtype = RF433;
|
||||
rev3_switch->minrawlen = RAW_LENGTH;
|
||||
rev3_switch->maxrawlen = RAW_LENGTH;
|
||||
rev3_switch->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
rev3_switch->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&rev3_switch->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rev3_switch->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rev3_switch->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-9]|[1][0-5])$");
|
||||
options_add(&rev3_switch->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(6[0123]|[12345][0-9]|[0-9]{1})$");
|
||||
|
||||
options_add(&rev3_switch->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&rev3_switch->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
rev3_switch->parseCode=&parseCode;
|
||||
rev3_switch->createCode=&createCode;
|
||||
rev3_switch->printHelp=&printHelp;
|
||||
rev3_switch->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "rev3_switch";
|
||||
module->version = "0.14";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
rev3Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & easy12
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_REV3_H_
|
||||
#define _PROTOCOL_REV3_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *rev3_switch;
|
||||
void rev3Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & Bram1337 & kirichkov
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "rsl366.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 375
|
||||
#define MAX_PULSE_LENGTH 395
|
||||
#define AVG_PULSE_LENGTH 480
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(rsl366->rawlen == RAW_LENGTH) {
|
||||
if(rsl366->raw[rsl366->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
rsl366->raw[rsl366->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV) &&
|
||||
rsl366->raw[rsl366->rawlen-3] <= (AVG_PULSE_LENGTH*PULSE_MULTIPLIER) &&
|
||||
rsl366->raw[rsl366->rawlen-7] <= (AVG_PULSE_LENGTH*PULSE_MULTIPLIER) &&
|
||||
rsl366->raw[rsl366->rawlen-11] <= (AVG_PULSE_LENGTH*PULSE_MULTIPLIER)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int programcode, int state) {
|
||||
rsl366->message = json_mkobject();
|
||||
json_append_member(rsl366->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(rsl366->message, "programcode", json_mknumber(programcode, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(rsl366->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(rsl366->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int x = 0, i = 0, binary[RAW_LENGTH/4];
|
||||
|
||||
if(rsl366->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "rsl366: parsecode - invalid parameter passed %d", rsl366->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert the one's and zero's into binary */
|
||||
for(x=3;x<rsl366->rawlen;x+=4) {
|
||||
if(rsl366->raw[x] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++]=1;
|
||||
} else {
|
||||
binary[i++]=0;
|
||||
}
|
||||
}
|
||||
|
||||
//Check if there is a valid systemcode
|
||||
if((binary[0]+binary[1]+binary[2]+binary[3]) > 1)
|
||||
return;
|
||||
|
||||
//Get systemcode: 1000=>1, 0100=>2, 0010=>3, 0001=>4
|
||||
int systemcode = 0;
|
||||
for(i=0;i<4;i++) {
|
||||
if(binary[i] == 1)
|
||||
systemcode = i+1;
|
||||
}
|
||||
|
||||
//Check if there is a valid programcode
|
||||
if((binary[4]+binary[5]+binary[6]+binary[7]) > 1)
|
||||
return;
|
||||
|
||||
//Get programcode: 1000=>1, 0100=>2, 0010=>3, 0001=>4
|
||||
int programcode = 0;
|
||||
for(i=4;i<8;i++) {
|
||||
if(binary[i] == 1)
|
||||
programcode = i-3;
|
||||
}
|
||||
|
||||
//Check if a system and programcode was found
|
||||
if(systemcode == 0 || programcode == 0)
|
||||
return;
|
||||
|
||||
// There seems to be no check and binary[10] is always a low
|
||||
int state = binary[11]^1;
|
||||
|
||||
createMessage(systemcode, programcode, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rsl366->raw[i]=AVG_PULSE_LENGTH;
|
||||
rsl366->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rsl366->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rsl366->raw[i+3]=AVG_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
rsl366->raw[i]=AVG_PULSE_LENGTH;
|
||||
rsl366->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
rsl366->raw[i+2]=AVG_PULSE_LENGTH;
|
||||
rsl366->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createLow(0,47);
|
||||
}
|
||||
|
||||
static void createSystemCode(int systemcode) {
|
||||
createHigh((systemcode-1)*4, (systemcode-1)*4+3);
|
||||
}
|
||||
|
||||
static void createProgramCode(int programcode) {
|
||||
createHigh(16+(programcode-1)*4, 16+(programcode-1)*4+3);
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 0) {
|
||||
createHigh(44, 47);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
rsl366->raw[48]=(AVG_PULSE_LENGTH);
|
||||
rsl366->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int systemcode = -1;
|
||||
int programcode = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "systemcode", &itmp) == 0)
|
||||
systemcode = (int)round(itmp);
|
||||
if(json_find_number(code, "programcode", &itmp) == 0)
|
||||
programcode = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(systemcode == -1 || programcode == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "rsl366: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(systemcode > 4 || systemcode < 0) {
|
||||
logprintf(LOG_ERR, "rsl366: invalid systemcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else if(programcode > 4 || programcode < 0) {
|
||||
logprintf(LOG_ERR, "rsl366: invalid programcode range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(systemcode, programcode, state);
|
||||
clearCode();
|
||||
createSystemCode(systemcode);
|
||||
createProgramCode(programcode);
|
||||
createState(state);
|
||||
createFooter();
|
||||
rsl366->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -s --systemcode=systemcode\tcontrol a device with this systemcode\n");
|
||||
printf("\t -u --programcode=programcode\tcontrol a device with this programcode\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void rsl366Init(void) {
|
||||
|
||||
protocol_register(&rsl366);
|
||||
protocol_set_id(rsl366, "rsl366");
|
||||
protocol_device_add(rsl366, "rsl366", "RSL366 Switches");
|
||||
protocol_device_add(rsl366, "promax", "Pro MAX Switches");
|
||||
rsl366->devtype = SWITCH;
|
||||
rsl366->hwtype = RF433;
|
||||
rsl366->minrawlen = RAW_LENGTH;
|
||||
rsl366->maxrawlen = RAW_LENGTH;
|
||||
rsl366->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
rsl366->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&rsl366->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([1234]{1})$");
|
||||
options_add(&rsl366->options, 'u', "programcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([1234]{1})$");
|
||||
options_add(&rsl366->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&rsl366->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&rsl366->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&rsl366->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
rsl366->parseCode=&parseCode;
|
||||
rsl366->createCode=&createCode;
|
||||
rsl366->printHelp=&printHelp;
|
||||
rsl366->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "rsl366";
|
||||
module->version = "2.7";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
rsl366Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo & Bram1337 & kirichkov
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_RSL366_H_
|
||||
#define _PROTOCOL_RSL366_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *rsl366;
|
||||
void rsl366Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "sc2262.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 427
|
||||
#define MAX_PULSE_LENGTH 444
|
||||
#define AVG_PULSE_LENGTH 432
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(sc2262->rawlen == RAW_LENGTH) {
|
||||
if(sc2262->raw[sc2262->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
sc2262->raw[sc2262->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int systemcode, int unitcode, int state) {
|
||||
sc2262->message = json_mkobject();
|
||||
json_append_member(sc2262->message, "systemcode", json_mknumber(systemcode, 0));
|
||||
json_append_member(sc2262->message, "unitcode", json_mknumber(unitcode, 0));
|
||||
if(state == 0) {
|
||||
json_append_member(sc2262->message, "state", json_mkstring("opened"));
|
||||
} else {
|
||||
json_append_member(sc2262->message, "state", json_mkstring("closed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(sc2262->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "sc2262: parsecode - invalid parameter passed %d", sc2262->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<sc2262->rawlen-2;x+=4) {
|
||||
if(sc2262->raw[x+3] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int systemcode = binToDec(binary, 0, 4);
|
||||
int unitcode = binToDec(binary, 5, 9);
|
||||
int state = binary[11];
|
||||
createMessage(systemcode, unitcode, state);
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void sc2262Init(void) {
|
||||
|
||||
protocol_register(&sc2262);
|
||||
protocol_set_id(sc2262, "sc2262");
|
||||
protocol_device_add(sc2262, "sc2262", "sc2262 contact sensor");
|
||||
sc2262->devtype = CONTACT;
|
||||
sc2262->hwtype = RF433;
|
||||
sc2262->minrawlen = RAW_LENGTH;
|
||||
sc2262->maxrawlen = RAW_LENGTH;
|
||||
sc2262->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
sc2262->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&sc2262->options, 's', "systemcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&sc2262->options, 'u', "unitcode", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(3[012]?|[012][0-9]|[0-9]{1})$");
|
||||
options_add(&sc2262->options, 't', "opened", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&sc2262->options, 'f', "closed", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
sc2262->parseCode=&parseCode;
|
||||
sc2262->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "sc2262";
|
||||
module->version = "2.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
sc2262Init();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_SC2262_H_
|
||||
#define _PROTOCOL_SC2262_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *sc2262;
|
||||
void sc2262Init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "secudo_smoke.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 2
|
||||
#define MIN_PULSE_LENGTH 292
|
||||
#define MAX_PULSE_LENGTH 332
|
||||
#define AVG_PULSE_LENGTH 312
|
||||
#define RAW_LENGTH 26
|
||||
|
||||
static int validate(void) {
|
||||
if(secudo_smoke->rawlen == RAW_LENGTH) {
|
||||
if(secudo_smoke->raw[secudo_smoke->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
secudo_smoke->raw[secudo_smoke->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/2];
|
||||
int id = 0;
|
||||
int x = 0, i = 0;
|
||||
|
||||
int len = (AVG_PULSE_LENGTH*(PULSE_MULTIPLIER+1)) / 2;
|
||||
|
||||
if(secudo_smoke->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "secudo_smoke: parsecode - invalid parameter passed %d", secudo_smoke->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=1;x<secudo_smoke->rawlen-2;x+=2) {
|
||||
if(secudo_smoke->raw[x] > len) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
id = binToDec(binary, 0, 9);
|
||||
id = (~id) & 1023;
|
||||
|
||||
secudo_smoke->message = json_mkobject();
|
||||
json_append_member(secudo_smoke->message, "id", json_mknumber(id, 0));
|
||||
json_append_member(secudo_smoke->message, "state", json_mkstring("alarm"));
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void secudoSmokeInit(void) {
|
||||
protocol_register(&secudo_smoke);
|
||||
protocol_set_id(secudo_smoke, "secudo_smoke_sensor");
|
||||
protocol_device_add(secudo_smoke, "secudo_smoke_sensor", "Secudo/FlammEx smoke sensor");
|
||||
secudo_smoke->devtype = ALARM;
|
||||
secudo_smoke->hwtype = RF433;
|
||||
secudo_smoke->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
secudo_smoke->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
secudo_smoke->minrawlen = 26;
|
||||
secudo_smoke->maxrawlen = 26;
|
||||
|
||||
options_add(&secudo_smoke->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^[0-9]{1-4}$");
|
||||
options_add(&secudo_smoke->options, 't', "alarm", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
secudo_smoke->parseCode=&parseCode;
|
||||
secudo_smoke->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "secudo_smoke_sensor";
|
||||
module->version = "1.1";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "38";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
secudoSmokeInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2014 CurlyMo
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_SECUDO_SMOKE_H_
|
||||
#define _PROTOCOL_SECUDO_SMOKE_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *secudo_smoke;
|
||||
void secudoSmokeInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & Bram1337
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#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 "selectremote.h"
|
||||
|
||||
#define PULSE_MULTIPLIER 3
|
||||
#define MIN_PULSE_LENGTH 391
|
||||
#define MAX_PULSE_LENGTH 401
|
||||
#define AVG_PULSE_LENGTH 396
|
||||
#define RAW_LENGTH 50
|
||||
|
||||
static int validate(void) {
|
||||
if(selectremote->rawlen == RAW_LENGTH) {
|
||||
if(selectremote->raw[selectremote->rawlen-1] >= (MIN_PULSE_LENGTH*PULSE_DIV) &&
|
||||
selectremote->raw[selectremote->rawlen-1] <= (MAX_PULSE_LENGTH*PULSE_DIV)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void createMessage(int id, int state) {
|
||||
selectremote->message = json_mkobject();
|
||||
json_append_member(selectremote->message, "id", json_mknumber(id, 0));
|
||||
if(state == 1) {
|
||||
json_append_member(selectremote->message, "state", json_mkstring("on"));
|
||||
} else {
|
||||
json_append_member(selectremote->message, "state", json_mkstring("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCode(void) {
|
||||
int binary[RAW_LENGTH/4], x = 0, i = 0;
|
||||
|
||||
if(selectremote->rawlen>RAW_LENGTH) {
|
||||
logprintf(LOG_ERR, "selectremote: parsecode - invalid parameter passed %d", selectremote->rawlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<selectremote->rawlen-2;x+=4) {
|
||||
if(selectremote->raw[x] > (int)((double)AVG_PULSE_LENGTH*((double)PULSE_MULTIPLIER/2))) {
|
||||
binary[i++] = 1;
|
||||
} else {
|
||||
binary[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int id = 7-binToDec(binary, 1, 3);
|
||||
int state = binary[8];
|
||||
|
||||
createMessage(id, state);
|
||||
}
|
||||
|
||||
static void createLow(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
selectremote->raw[i]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
selectremote->raw[i+1]=AVG_PULSE_LENGTH;
|
||||
selectremote->raw[i+2]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
selectremote->raw[i+3]=AVG_PULSE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void createHigh(int s, int e) {
|
||||
int i;
|
||||
|
||||
for(i=s;i<=e;i+=4) {
|
||||
selectremote->raw[i]=AVG_PULSE_LENGTH;
|
||||
selectremote->raw[i+1]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
selectremote->raw[i+2]=AVG_PULSE_LENGTH;
|
||||
selectremote->raw[i+3]=(PULSE_MULTIPLIER*AVG_PULSE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearCode(void) {
|
||||
createHigh(0,47);
|
||||
}
|
||||
|
||||
static void createId(int id) {
|
||||
int binary[255];
|
||||
int length = 0;
|
||||
int i=0, x=0;
|
||||
|
||||
id = 7-id;
|
||||
length = decToBinRev(id, binary);
|
||||
for(i=0;i<=length;i++) {
|
||||
if(binary[i]==1) {
|
||||
x=i*4;
|
||||
createLow(4+x, 4+x+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createState(int state) {
|
||||
if(state == 1) {
|
||||
createLow(32, 35);
|
||||
}
|
||||
}
|
||||
|
||||
static void createFooter(void) {
|
||||
selectremote->raw[48]=(AVG_PULSE_LENGTH);
|
||||
selectremote->raw[49]=(PULSE_DIV*AVG_PULSE_LENGTH);
|
||||
}
|
||||
|
||||
static int createCode(struct JsonNode *code) {
|
||||
int id = -1;
|
||||
int state = -1;
|
||||
double itmp = 0;
|
||||
|
||||
if(json_find_number(code, "id", &itmp) == 0)
|
||||
id = (int)round(itmp);
|
||||
if(json_find_number(code, "off", &itmp) == 0)
|
||||
state=0;
|
||||
else if(json_find_number(code, "on", &itmp) == 0)
|
||||
state=1;
|
||||
|
||||
if(id == -1 || state == -1) {
|
||||
logprintf(LOG_ERR, "selectremote: insufficient number of arguments");
|
||||
return EXIT_FAILURE;
|
||||
} else if(id > 7 || id < 0) {
|
||||
logprintf(LOG_ERR, "selectremote: invalid id range");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
createMessage(id, state);
|
||||
clearCode();
|
||||
createId(id);
|
||||
createState(state);
|
||||
createFooter();
|
||||
selectremote->rawlen = RAW_LENGTH;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void printHelp(void) {
|
||||
printf("\t -i --id=systemcode\tcontrol a device with this id\n");
|
||||
printf("\t -t --on\t\t\tsend an on signal\n");
|
||||
printf("\t -f --off\t\t\tsend an off signal\n");
|
||||
}
|
||||
|
||||
#if !defined(MODULE) && !defined(_WIN32)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
void selectremoteInit(void) {
|
||||
|
||||
protocol_register(&selectremote);
|
||||
protocol_set_id(selectremote, "selectremote");
|
||||
protocol_device_add(selectremote, "selectremote", "SelectRemote Switches");
|
||||
selectremote->devtype = SWITCH;
|
||||
selectremote->hwtype = RF433;
|
||||
selectremote->minrawlen = RAW_LENGTH;
|
||||
selectremote->maxrawlen = RAW_LENGTH;
|
||||
selectremote->maxgaplen = MAX_PULSE_LENGTH*PULSE_DIV;
|
||||
selectremote->mingaplen = MIN_PULSE_LENGTH*PULSE_DIV;
|
||||
|
||||
options_add(&selectremote->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^[0-7]$");
|
||||
options_add(&selectremote->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
options_add(&selectremote->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
|
||||
|
||||
options_add(&selectremote->options, 0, "readonly", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
options_add(&selectremote->options, 0, "confirm", OPTION_HAS_VALUE, GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");
|
||||
|
||||
selectremote->parseCode=&parseCode;
|
||||
selectremote->createCode=&createCode;
|
||||
selectremote->printHelp=&printHelp;
|
||||
selectremote->validate=&validate;
|
||||
}
|
||||
|
||||
#if defined(MODULE) && !defined(_WIN32)
|
||||
void compatibility(struct module_t *module) {
|
||||
module->name = "selectremote";
|
||||
module->version = "2.4";
|
||||
module->reqversion = "6.0";
|
||||
module->reqcommit = "84";
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
selectremoteInit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2013 CurlyMo & Bram1337
|
||||
|
||||
This file is part of pilight.
|
||||
|
||||
pilight 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 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pilight. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_SELECTREMOTE_H_
|
||||
#define _PROTOCOL_SELECTREMOTE_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
|
||||
struct protocol_t *selectremote;
|
||||
void selectremoteInit(void);
|
||||
|
||||
#endif
|
||||
Loaded 100 of 138 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user