Added ESPilight libs

This commit is contained in:
Paul committed 2018-09-21 18:02:15 +01:00
1 parent 0e743a0e33
commit d2c3373b8e
138 files changed
+18414

No files matched your search

+587
View File
@@ -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); }
+195
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
/*dummy*/
+42
View File
@@ -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
View File
@@ -0,0 +1 @@
/*dummy*/
File diff suppressed because it is too large. Load diff
+124
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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