Compare commits

...

No commits in common. "BUILD-18" and "master" have entirely different histories.

910 changed files with 128788 additions and 35253 deletions

View file

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="lib" path="libs/dom4j-1.6.1.jar" sourcepath="C:/Users/Ziver/Documents/Programmering/Java/libs/dom4j-1.6.1/src"/>
<classpathentry exported="true" kind="lib" path="libs/javassist.jar" sourcepath="C:/Users/Ziver/Documents/Programmering/Java/libs/javassist-3.12.GA"/>
<classpathentry kind="lib" path="libs/junit-benchmarks-0.7.0.jar"/>
<classpathentry kind="lib" path="libs/mysql-connector-java-5.1.36-bin.jar"/>
<classpathentry kind="lib" path="libs/servlet-api.jar"/>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<classpathentry exported="true" kind="lib" path="libs/commons-fileupload-1.2.1.jar" sourcepath="C:/Users/Ziver/Documents/Programmering/Java/libs/commons/commons-fileupload-1.2.1-sources.jar"/>
<classpathentry exported="true" kind="lib" path="libs/commons-io-1.4.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v7.0"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="libs/sqlite-jdbc-3.7.2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

5
.gitattributes vendored Normal file
View file

@ -0,0 +1,5 @@
# Github language stats file
external/* linguist-vendored
lib/* linguist-vendored
*.css linguist-vendored
*.js linguist-vendored

16
.gitignore vendored Executable file → Normal file
View file

@ -1,2 +1,14 @@
Zutil.jar
/build/
# Configuration and dependencies
/hal.conf
/hal.db*
/lib/zutil-*
/recordings/
# Runtime files
/screenlog.0*
/OZW_Log.txt
# Build and Ide files
build
.gradle
.idea

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "arduino/lib/NexaControl"]
path = arduino/lib/NexaControl
url = https://github.com/dcollin/NexaControl.git

View file

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ZUtil</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.jem.beaninfo.BeanInfoNature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
</projectDescription>

35
Jenkinsfile vendored Normal file
View file

@ -0,0 +1,35 @@
// Jenkinsfile (Pipeline Script)
node {
// Configure environment
env.JAVA_HOME = tool name: 'jdk-11'
env.REPO_URL = "repo.koc.se/hal.git" //scm.getUserRemoteConfigs()[0].getUrl()
env.BUILD_NAME = "BUILD-${env.BUILD_ID}"
checkout scm
stage('Build') {
sh './gradlew clean'
sh './gradlew build'
}
stage('Test') {
try {
sh './gradlew test'
} finally {
junit testResults: '**/build/test-results/test/*.xml'
}
}
stage('Package') {
sh './gradlew distZip'
archiveArtifacts artifacts: 'build/distributions/Hal.zip', fingerprint: true
// Tag artifact
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'f8e5f6c6-4adb-4ab2-bb5d-1c8535dff491',
usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
sh "git tag ${env.BUILD_NAME}"
sh "git push 'https://${USERNAME}:${PASSWORD}@${env.REPO_URL}' ${env.BUILD_NAME}"
}
}
}

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015 Ziver Koc
Copyright (c) 2016-2025 Daniel Collin, Ziver Koc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -9,13 +9,13 @@ 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 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.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

104
README.md Normal file
View file

@ -0,0 +1,104 @@
# Hal
Hal is a home automation hub with sensor statistics with the functionality to
share that data between friends. It has been developed to be very extensible so future
Sensors and other input devices can be supported.
Features:
- **Map**, Set up a house map with sensors and events mapped on a floorplan
- **Triggers and Actions**, IFTTT type functionality
- **Power;Challenge**, Sync power or sensor usage between friends to challenge each other to lower the power usage
- **[Google Assistant Integration](plugins/hal-assistant-google/READNME.md)**
Currently supported devices:
- **Network Scanner**, IP scanner to detect devices on local network
- **NUT**, Linux UPS daemon
- **Tellstick**, Supported devices:
- NexaSelfLearning
- Oregon0x1A2D
- **Raspberry Pi**, GPIO connected sensors
- **[Zigbee](plugins/hal-zigbee/README.md)**
- Temperature Sensors
- Humidity Sensors
- Pressure Sensors
- OnnOff Devices
- **Google Assistant**
- **MQTT Devices**
Under development (Not ready to be used yet)
- **Z-Wave**
The project is currently in alpha state, and as such things will change and break continuously.
### Screenshots
![Week Graph](screenshot_01.jpg)
![Home Map](screenshot_02.jpg)
![Sensor Overview](screenshot_03.jpg)
![Event Overview](screenshot_04.jpg)
## Installing
To run the Hal server you first need to clone the git repository and then run the
gradle command to build and run the server:
```
./gradlew run
```
Check `hal.conf.example` for available configuration options.
By default, HAL server will be listening to http://localhost:8080.
## Running the tests
The current test coverage is greatly lacking, but to run the available JUnit
test-cases run:
```
./gradlew test
```
## Architecture
```
HalAbstractControlerManager
|
| HalAbstractController
| |
| | HalAbstractDevice
| | |
.-----------. .------------. .--------.
| | | | | |
| | | | ----> | Device |
| | | | | |
| | ----> | Controller | '--------'
| | | | .--------.
| | | | | |
| Manager | | | ----> | Device |
| | | | | |
| | '------------' '--------'
| | .------------. .--------.
| | | | | |
| | ----> | Controller | ----> | Device |
| | | | | |
'-----------' '------------' '--------'
```
## Authors
* **Daniel Collin**
* **Ziver Koc**
## License
This project is licensed under the MIT License - see the
[LICENSE.txt](LICENSE.txt) file for details
## Acknowledgments
* Tellstick, for open-sourcing their code

View file

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library" scope="TEST">
<library name="JUnit4">
<CLASSES>
<root url="jar://$APPLICATION_HOME_DIR$/lib/junit-4.12.jar!/" />
<root url="jar://$APPLICATION_HOME_DIR$/lib/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="lib">
<CLASSES>
<root url="file://$MODULE_DIR$/lib" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$MODULE_DIR$/lib" />
</SOURCES>
<jarDirectory url="file://$MODULE_DIR$/lib" recursive="false" />
<jarDirectory url="file://$MODULE_DIR$/lib" recursive="false" type="SOURCES" />
</library>
</orderEntry>
</component>
</module>

View file

@ -0,0 +1,72 @@
#include "usart.h"
#include "rf.h"
#include "buffer.h"
#include "config.h"
/*
* Timer2 interrupt in 16kHz. Samples the RF Rx data pin
*/
ISR(TIMER2_COMPA_vect) {
if ( !IS_RADIO_RECIEVER_ON() ) { //if no Radio Rx should be performed
return;
}
uint8_t bit = RX_PIN_READ();
//will store "lows" on even buffer addresses and "highs" on odd buffer addresses
if ( ( ((uintptr_t)bufferWriteP) & 0x1 ) != bit ) { //compare the bit and the buffer pointer address. true if one is odd and one is even.
//step the buffer pointer
if ( bufferWriteP+1 > RF_rxBufferEndP ) {
*RF_rxBufferStartP = 1; //reset the next data point before going there
bufferWriteP = RF_rxBufferStartP;
} else {
*(bufferWriteP+1) = 1; //reset the next data point before going there
++bufferWriteP;
}
} else {
if ( *bufferWriteP < 255 ) { //Do not step the value if it already is 255 (max value)
++(*bufferWriteP); //step the buffer value
}
}
};//end timer2 interrupt
void setup() {
Serial.begin(9600);
setupPins();
//setup timer2 interrupt at 16kHz for RF sampling
cli(); //stop interrupts
TCCR2A = 0; // set entire TCCR2A register to 0
TCCR2B = 0; // same for TCCR2B
TCNT2 = 0; //initialize counter value to 0
OCR2A = 124; // = ( (16000000Hz) / (16000Hz*8prescaler) ) - 1 (must be <256)
TCCR2A |= (1 << WGM21); // turn on CTC mode
TCCR2B |= (1 << CS21); // Set CS21 bit for 8 prescaler
TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt
sei(); //allow interrupts
//reset buffer just to be sure
for (uint8_t* p = RF_rxBufferStartP; p <= RF_rxBufferEndP; ++p) {
*p = 0;
}
Serial.println(F("+V2"));
ACTIVATE_RADIO_RECEIVER();
};//end setup
void loop() {
//Receive and execute command over serial
parseSerialForCommand();
//Receive signal over air and send it over serial
parseRadioRXBuffer();
};//end loop

View file

@ -0,0 +1,115 @@
#include "archtech.h"
#include "buffer.h"
/*******************************************************************************
--ARCHTECH PROTOCOL SPECIFICATION--
----SIGNAL----
A signal consists of a PREAMBLE, DATA and an POSTAMBLE.
Each signal is sent 4 times in a row to increase the delivery success rate.
----PREAMBLE----
send high for 250 microseconds
send low for 2,500 microseconds
----DATA----
26 bits of transmitter id
1 bit indicating if the on/off bit is targeting a group
1 bit indicating "on" or "off"
4 bits indicating the targeted unit/channel/device
4 bits indicating a absolute dim level (optional)
Total: 32 or 36 bits depending if absolute dimming is used
Each real bit in the data field is sent over air as a pair of two inverted bits.
real bit bits over air
1 = "10"
0 = "01"
Over air a "1"(one) is sent as:
send high for 250 microseconds
send low for 1,250 microseconds
Over air a "0"(zero) is sent as:
send high for 250 microseconds
send low for 250 microseconds
----POSTAMBLE----
send high for 250 microseconds
send low for 10,000 microseconds
*******************************************************************************/
#define ARCHTECH_SHORT_MIN 2
#define ARCHTECH_SHORT_MAX 7
#define ARCHTECH_LONG_MIN 17
#define ARCHTECH_LONG_MAX 27
#define ARCHTECH_PREAMP_MIN 40
#define ARCHTECH_PREAMP_MAX 48
#define IS_SHORT(b) ( ARCHTECH_SHORT_MIN <= b && b <= ARCHTECH_SHORT_MAX )
#define IS_LONG(b) ( ARCHTECH_LONG_MIN <= b && b <= ARCHTECH_LONG_MAX )
#define IS_PREAMP_LONG(b) ( ARCHTECH_PREAMP_MIN <= b && b <= ARCHTECH_PREAMP_MAX )
#define IS_ONE(b1,b2,b3,b4) ( IS_SHORT(b1) && IS_LONG(b2) && IS_SHORT(b3) && IS_SHORT(b4) )
#define IS_ZERO(b1,b2,b3,b4) ( IS_SHORT(b1) && IS_SHORT(b2) && IS_SHORT(b3) && IS_LONG(b4) )
#define IS_PREAMP(b1,b2) ( IS_SHORT(b1) && IS_PREAMP_LONG(b2) )
bool parseArctechSelfLearning(uint8_t* bufStartP, uint8_t* bufEndP) { //start points to a "high" buffer byte, end points to a "low" buffer byte
uint64_t data = 0;
bool dimValuePresent;
uint8_t b1,b2,b3,b4;
//parse preamp
b1 = *bufStartP;
stepBufferPointer(&bufStartP);
b2 = *bufStartP;
stepBufferPointer(&bufStartP);
if (!IS_PREAMP(b1, b2)){
return false;
}
//parse data
uint16_t dataBitsInBuffer = (calculateBufferPointerDistance(bufStartP, bufEndP)-2) / 4; //each bit is representd by 4 high/low
if (dataBitsInBuffer == 32) {
dimValuePresent = false;
} else if (dataBitsInBuffer == 36){
dimValuePresent = true;
} else {
return false;
}
for (uint8_t i = 0; i < dataBitsInBuffer; ++i) {
b1 = *bufStartP; //no of high
stepBufferPointer(&bufStartP);
b2 = *bufStartP; //no of low
stepBufferPointer(&bufStartP);
b3 = *bufStartP; //no of high
stepBufferPointer(&bufStartP);
b4 = *bufStartP; //no of low
stepBufferPointer(&bufStartP);
if (IS_ONE(b1,b2,b3,b4)) { //"one" is sent over air
data <<= 1; //shift in a zero
data |= 0x1; //add one
} else if (IS_ZERO(b1,b2,b3,b4)) { //"zero" is sent over air
data <<= 1; //shift in a zero
} else {
return false;
}
}
//data parsed - send event over serial
Serial.print(F("+Wclass:command;protocol:arctech;model:selflearning;data:0x"));
uint8_t hexToSend = (dimValuePresent ? 9 : 8);
for (int8_t i = hexToSend - 1; i >= 0; --i) {
Serial.print( (byte)((data >> (4 * i)) & 0x0F), HEX);
}
Serial.println(F(";"));
return true;
}; //end parseArctechSelfLearning

View file

@ -0,0 +1,8 @@
#ifndef ARCHTECH_H
#define ARCHTECH_H
#include "Arduino.h"
bool parseArctechSelfLearning(uint8_t* bufStartP, uint8_t* bufEndP);
#endif //ARCHTECH_H

View file

@ -0,0 +1,6 @@
#include "buffer.h"
uint8_t RF_rxBuffer[512]; //must have and even number of elements
uint8_t* RF_rxBufferStartP = &RF_rxBuffer[0];
uint8_t* RF_rxBufferEndP = &RF_rxBuffer[511];
volatile uint8_t* bufferWriteP = RF_rxBufferStartP;

View file

@ -0,0 +1,31 @@
#ifndef BUFFER_H
#define BUFFER_H
#include "Arduino.h"
extern uint8_t RF_rxBuffer[512]; //must have and even number of elements
extern uint8_t* RF_rxBufferStartP;
extern uint8_t* RF_rxBufferEndP;
extern volatile uint8_t* bufferWriteP;
inline uint16_t calculateBufferPointerDistance(uint8_t* bufStartP, uint8_t* bufEndP) {
if (bufStartP <= bufEndP) {
return bufEndP - bufStartP + 1;
} else {
return (RF_rxBufferEndP - bufStartP) + (bufEndP - RF_rxBufferStartP) + 2;
}
}; //end calculateBufferPointerDistance
inline uint8_t* getNextBufferPointer(uint8_t* p) {
if ( p + 1 > RF_rxBufferEndP) {
return RF_rxBufferStartP;
} else {
return p + 1;
}
}; //end getNextBufferPointer
inline void stepBufferPointer(uint8_t** p) {
*p = getNextBufferPointer(*p);
}; //end stepBufferPointer
#endif //BUFFER_H

View file

@ -0,0 +1,25 @@
#ifndef CONFIG_H
#define CONFIG_H
#include "Arduino.h"
/*
* RX PIN = 7
* TX PIN = 8
*/
inline void setupPins(){
pinMode(7, INPUT);
pinMode(8, OUTPUT);
};
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
//pin7 = PD7 = port D, bit 8
#define RX_PIN_READ() ( digitalRead(7) ) // optimized "digitalRead(7)"
//pin8 = PB0 = port B, bit 1
#define TX_PIN_LOW() ( PORTB &= 0b01111111 ) // optimized "digitalWrite(8, LOW)"
#define TX_PIN_HIGH() ( PORTB |= 0b10000000 ) // optimized "digitalWrite(8, HIGH)"
#else
#unsupported architecture
#endif
#endif //CONFIG_H

View file

@ -0,0 +1,210 @@
#include "oregonV2.1.h"
#include "buffer.h"
/*******************************************************************************
--OREGON v2.1 PROTOCOL SPECIFICATION--
----SIGNAL----
A signal consists of a PREAMBLE, DATA and an POSTAMBLE.
Each signal is sent 2 times in a row to increase the delivery success rate.
Between the two times there is a "low" pause of 8192us.
----PREAMBLE----
send 16 "1"(ones) over the air
----DATA----
16 bits of sensor type
XX bits of data (where XX <= 64)
The length XX depends on the sensor type. I.e. 0x1A2D => XX=56
Over air a "1"(one) is sent as:
send high for 512 microseconds
send low for 1024 microseconds
send high for 512 microseconds
Over air a "0"(zero) is sent as:
send low for 512 microseconds
send high for 1024 microseconds
send low for 512 microseconds
----POSTAMBLE----
send 8 "0"(zeros) over the air
*******************************************************************************/
#define SMALL_PULSE(x) ( 4<=x && x<=13 )
#define BIG_PULSE(x) ( 12<=x && x<=22 )
#define MORE_DATA_NEEDED -1
#define INVALID_DATA -2
enum {
PARSE_PREAMP = 0,
PARSE_ID,
PARSE_DATA
} static state = PARSE_PREAMP;
static uint8_t byteCnt = 0;
static uint8_t bitCnt = 0;
static uint8_t totByteCnt = 0;
int8_t byteLength = -1;
void reset() {
byteCnt = 0;
bitCnt = 0;
totByteCnt = 0;
state = PARSE_PREAMP;
byteLength = -1;
}; //end reset
void parseOregonStream(bool level, uint8_t count) {
static uint8_t cnt = 0; //used for counting stuff independent in every state
static uint16_t sensorType = 0;
static int8_t byte;
static uint8_t bytesToParse = 0; //the number of bytes left in the data part to parse
static uint8_t buffer[8];
if (level) {
count+=3;
} else {
count-=3;
}
switch(state) {
case PARSE_PREAMP: //look for 25 big pulses followed by one short in a row
if (BIG_PULSE(count)) {
++cnt;
break;
}
if (SMALL_PULSE(count)) {
if (cnt > 25) {
state=PARSE_ID;
sensorType = 0;
}
cnt = 0;
}
break;
case PARSE_ID: //get the two first Bytes
byte = getByte(level, count);
if (byte == INVALID_DATA) {
reset();
cnt = 0;
break;
} else if (byte == MORE_DATA_NEEDED) {
break;
} else {
if (sensorType == 0) {
sensorType = byte << 8;
} else {
sensorType |= byte;
switch (sensorType) {
case 0xEA4C:
bytesToParse = 5;
byteLength = 63;
break;
case 0x0A4D:
case 0x1A2D: //sensor THGR2228N (channel + sensor_id + battery_level + temp + humidity + checksum)
bytesToParse = 7;
byteLength = 79;
break;
default:
reset();
cnt = 0;
return;
}
state = PARSE_DATA;
cnt = 0;
}
}
break;
case PARSE_DATA: //get the remaining data
byte = getByte(level, count);
if (byte == INVALID_DATA) {
reset();
cnt = 0;
break;
} else if (byte == MORE_DATA_NEEDED) {
break;
}
buffer[cnt] = byte;
++cnt;
if (bytesToParse == 0) {
Serial.print(F("+Wclass:sensor;protocol:oregon;model:0x"));
Serial.print(sensorType, HEX);
Serial.print(F(";data:0x"));
for (int8_t i = 0; i < cnt; ++i) {
Serial.print(buffer[i], HEX);
}
Serial.println(F(";"));
reset();
cnt = 0;
}
--bytesToParse;
break;
}
}; //end parseOregonStream
int8_t getByte(bool level, uint8_t count) {
int8_t bit = getBit(level, count);
static uint8_t byte = 0;
if (bit == INVALID_DATA) {
return INVALID_DATA;
} else if (bit == MORE_DATA_NEEDED) {
return MORE_DATA_NEEDED;
}
byte >>= 1;
if (bit) {
byte |= (1<<7);
}
++totByteCnt;
++byteCnt;
if (byteCnt < 8) {
return MORE_DATA_NEEDED;
}
byteCnt=0;
return byte;
}; //end getByte
int8_t getBit(bool level, uint8_t count) {
static bool bit = 0;
if (bitCnt == 0) {
//First pulse must be small
if (!SMALL_PULSE(count)) {
return INVALID_DATA;
}
bitCnt = 1;
} else if (bitCnt == 1) {
//Second pulse must be long
if (!BIG_PULSE(count) && totByteCnt!=byteLength){ //special check - last byte might have strange values
bitCnt = 0;
return INVALID_DATA;
}
bit = level;
bitCnt = 2;
return bit;
} else if (bitCnt == 2) {
//Prepare for next bit
if (level && SMALL_PULSE(count)) {
//Clean start
bitCnt = 0;
} else if (BIG_PULSE(count)) {
//Combined bit
bitCnt = 1;
} else if (SMALL_PULSE(count)) {
//Clean start
bitCnt = 0;
}
return MORE_DATA_NEEDED;
}
return MORE_DATA_NEEDED;
}; //end getBit

View file

@ -0,0 +1,11 @@
#ifndef OREGONV21_H
#define OREGONV21_H
#include "Arduino.h"
void reset();
void parseOregonStream(bool level, uint8_t sampleCount);
int8_t getByte(bool level, uint8_t count);
int8_t getBit(bool level, uint8_t count);
#endif //OREGONV21_H

View file

@ -0,0 +1,127 @@
#include "rf.h"
#include "buffer.h"
#include "archtech.h"
#include "config.h"
#include "oregonV2.1.h"
#define SILENCE_LENGTH 100 //the number of samples with "low" that represents a silent period between two signals
volatile bool RFRX = false;
void parseRadioRXBuffer() {
static uint8_t* bufferReadP = RF_rxBufferStartP;
static uint8_t* startDataP = 0; //will always point to a "high" buffer address
static uint8_t* endDataP = 0; //will always point to a "low" buffer address
static uint8_t prevValue = 0; //contains the value of the previous buffer index read
bool parse = false;
while (bufferReadP != bufferWriteP) { //stop if the read pointer is pointing to where the writing is currently performed
uint8_t sampleCount = *bufferReadP;
if ( (((uintptr_t)bufferReadP) & 0x1) == 1 ) { //buffer pointer is odd (stores highs)
//Serial.print("high:"); Serial.println(sampleCount);
if (prevValue >= SILENCE_LENGTH) {
startDataP = bufferReadP; //some new data must start here since this is the first "high" after a silent period
}
//stream data to stream parsers
parseOregonStream(HIGH, sampleCount);
} else { //buffer pointer is even (stores lows)
//Serial.print("low:"); Serial.println(sampleCount);
if (sampleCount >= SILENCE_LENGTH) { //evaluate if it is time to parse the curernt data
endDataP = bufferReadP; //this is a silient period and must be the end of a data
if (startDataP != 0){
parse = true;
break;
}
}
//stream data to stream parsers
parseOregonStream(LOW, sampleCount);
}
//step the read pointer one step
uint8_t* nextBufferReadP = getNextBufferPointer(bufferReadP);
if (nextBufferReadP == startDataP) { //next pointer will point to startDataP. Data will overflow. Reset the data pointers.
startDataP = 0;
endDataP = 0;
prevValue = 0;
}
//advance buffer pointer one step
bufferReadP = nextBufferReadP;
prevValue = sampleCount; //update previous value
}
if (!parse) {
return;
}
if (startDataP == 0 || endDataP == 0) {
return;
}
/*
* At this point the startDataP will point to the first high after a silent period
* and the endDataP will point at the first (low) silent period after the data data start.
*/
//Serial.print((uintptr_t)startDataP); Serial.print(" - "); Serial.println((uintptr_t)endDataP);
//Let all available parsers parse the data set now.
parseArctechSelfLearning(startDataP, endDataP);
//TODO: add more parsers here
//reset the data pointers since the data have been parsed at this point
startDataP = 0;
endDataP = 0;
}; //end radioTask
void sendTCodedData(uint8_t* data, uint8_t T_long, uint8_t* timings, uint8_t repeat, uint8_t pause) {
ACTIVATE_RADIO_TRANSMITTER();
for (uint8_t rep = 0; rep < repeat; ++rep) {
bool nextPinState = HIGH;
for (int i = 0; i < T_long; ++i) {
uint8_t timeIndex = (data[i / 4] >> (6 - (2 * (i % 4)))) & 0x03;
if (timings[timeIndex] > 0 || i == T_long - 1) {
if (nextPinState){
TX_PIN_HIGH();
}else{
TX_PIN_LOW();
}
delayMicroseconds(10 * timings[timeIndex]);
}
nextPinState = !nextPinState;
}
TX_PIN_LOW();
if (rep < repeat - 1) {
delay(pause);
}
}
ACTIVATE_RADIO_RECEIVER();
};
void sendSCodedData(uint8_t* data, uint8_t pulseCount, uint8_t repeat, uint8_t pause) {
ACTIVATE_RADIO_TRANSMITTER();
for (uint8_t rep = 0; rep < repeat; ++rep) {
bool nextPinState = HIGH;
for (int i = 0; i < pulseCount; ++i) {
if (data[i] > 0 || i == pulseCount - 1) {
if (nextPinState){
TX_PIN_HIGH();
}else{
TX_PIN_LOW();
}
delayMicroseconds(data[i] * 10);
}
nextPinState = !nextPinState;
}
delay(pause);
}
TX_PIN_LOW();
ACTIVATE_RADIO_RECEIVER();
};

View file

@ -0,0 +1,17 @@
#ifndef RF_H
#define RF_H
#include "Arduino.h"
#define ACTIVATE_RADIO_RECEIVER() (RFRX = true)
#define ACTIVATE_RADIO_TRANSMITTER() (RFRX = false)
#define IS_RADIO_RECIEVER_ON() (RFRX)
#define IS_RADIO_TRANSMITTER_ON() (!RFRX)
extern volatile bool RFRX;
void parseRadioRXBuffer();
void sendTCodedData(uint8_t* data, uint8_t T_long, uint8_t* timings, uint8_t repeat, uint8_t pause);
void sendSCodedData(uint8_t* data, uint8_t pulseCount, uint8_t repeat, uint8_t pause);
#endif //RF_H

View file

@ -0,0 +1,106 @@
#include "usart.h"
#include "rf.h"
uint8_t Serial_rxBuffer[79];
void parseSerialForCommand() {
if (Serial.available() > 0) {
uint8_t rxDataSize = Serial.readBytesUntil('+', &Serial_rxBuffer[0], 79);
if (rxDataSize > 0) {
parseRxBuffer(&Serial_rxBuffer[0], 0, rxDataSize, false, 3, 0);
}
}
}; //end serialTask
bool parseRxBuffer(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause) {
if (startIndex > endIndex) {
return false;
}
char c = buffer[startIndex];
//Serial.print("DEBUG: char:"); Serial.println(c, DEC);
switch (c) {
case 'S':
return handleSCommand(buffer, startIndex + 1, endIndex, debug, repeat, pause);
case 'T':
return handleTCommand(buffer, startIndex + 1, endIndex, debug, repeat, pause);
case 'V':
Serial.println(F("+V2"));
return parseRxBuffer(buffer, startIndex + 1, endIndex, debug, repeat, pause);
case 'D':
return parseRxBuffer(buffer, startIndex + 1, endIndex, !debug, repeat, pause);
case 'P':
if (endIndex - startIndex + 1 < 3) {
return false;
} //at least {'P',[p-value],'+'} must be left in the buffer
return parseRxBuffer(buffer, startIndex + 2, endIndex, debug, repeat, buffer[startIndex + 1]);
case 'R':
if (endIndex - startIndex + 1 < 3) {
return false;
} //at least {'R',[r-value],'+'} must be left in the buffer
return parseRxBuffer(buffer, startIndex + 2, endIndex, debug, buffer[startIndex + 1], pause);
case '+':
return true;
default:
//Serial.print("DEBUG: unknown char: '"); Serial.print(c, BIN); Serial.println("'");
return false;
}
}; //end parseRxBuffer
bool handleSCommand(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause) {
//Parse message received from serial
uint8_t S_data[78]; //78 pulses
uint8_t pulseCount = 0;
for (uint8_t i = startIndex; i <= endIndex; ++i) {
if (buffer[i] == '+') {
break;
} else if (i == endIndex) {
return false;
} else {
S_data[pulseCount++] = buffer[i];
}
}
//Send message
sendSCodedData(&S_data[0], pulseCount, repeat, pause);
//send confirmation over serial
Serial.println(F("+S"));
return true;
}; //end handleS
bool handleTCommand(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause) {
//Parse message received from serial
uint8_t T_data[72]; //0-188 pulses
if (endIndex - startIndex < 5) {
//Serial.println("DEBUG: wrong size!");
return false;
}
uint8_t buff_p = startIndex;
uint8_t T_times[4] = {buffer[buff_p++], buffer[buff_p++], buffer[buff_p++], buffer[buff_p++]};
uint8_t T_long = buffer[buff_p++];
uint8_t T_bytes = 0;
if ( (T_long / 4.0) > (float)(T_long / 4) ) {
T_bytes = T_long / 4 + 1;
} else {
T_bytes = T_long / 4;
}
uint8_t j = 0;
while (j < T_bytes) {
if (buffer[buff_p] == '+') {
break;
} else if (buff_p >= endIndex) {
return false;
} else {
T_data[j++] = buffer[buff_p++];
}
}
if ( j != T_bytes ) {
return false;
}
//Send message
sendTCodedData(&T_data[0], T_long, &T_times[0], repeat, pause);
//send confirmation over serial
Serial.println(F("+T"));
return parseRxBuffer(buffer, buff_p, endIndex, debug, repeat, pause);
}; //end handleT

View file

@ -0,0 +1,13 @@
#ifndef USART_H
#define USART_H
#include "Arduino.h"
void parseSerialForCommand();
bool parseRxBuffer(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause);
bool handleSCommand(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause);
bool handleTCommand(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause);
extern uint8_t Serial_rxBuffer[79];
#endif //USART_H

View file

@ -0,0 +1,31 @@
#ifndef HALCONFIGURATION_H
#define HALCONFIGURATION_H
//#define ENABLE_DEBUG // comment out to disable debug
#define TIMER_MILLISECOND 60000 // poling in minutes
#define INDICATOR_PIN 13 // diode
#define TX_PIN 11
#define DEVICE_BASE_ID 99
// POWER CONSUMPTION SENSOR
//#define POWERCON_ENABLED // comment out to disable sensor
#define POWERCON_SENSOR SensorPhotocell()
#define POWERCON_PROTOCOL ProtocolOregon(TX_PIN, DEVICE_BASE_ID + 0)
#define POWER_TIMER_MULTIPLIER 1
// TEMPERATURE SENSOR
#define TEMPERATURE_ENABLED // comment out to disable sensor
#define TEMPERATURE_SENSOR SensorDHT(DHT11, 10)
#define TEMPERATURE_PROTOCOL ProtocolOregon(TX_PIN, DEVICE_BASE_ID + 1)
#define TEMPERATURE_TIMER_MULTIPLIER 10
// LIGHT SENSOR
//#define LIGHT_ENABLED // comment out to disable sensor
#define LIGHT_SENSOR SensorBH1750()
#define LIGHT_PROTOCOL ProtocolOregon(TX_PIN, DEVICE_BASE_ID + 2)
#define LIGHT_TIMER_MULTIPLIER 10
#endif // HALCONFIGURATION_H

View file

@ -0,0 +1,14 @@
#ifndef HALDEFINITIONS_H
#define HALDEFINITIONS_H
/////// SENSORS
#include "SensorBH1750.h"
#include "SensorDHT.h"
#include "SensorPhotocell.h"
//////// PROTOCOLS
#include "ProtocolNexa.h"
#include "ProtocolOregon.h"
#endif // HALDEFINITIONS_H

View file

@ -0,0 +1,101 @@
#ifndef HALINTERFACES_H
#define HALINTERFACES_H
#include <Arduino.h>
#include "HalConfiguration.h"
// Utility functions
#ifdef ENABLE_DEBUG
#define DEBUG(msg) \
Serial.println(msg); \
Serial.flush();
#define DEBUGF(msg, ...) \
static char buffer[80];\
snprintf(buffer, sizeof(buffer), msg, __VA_ARGS__);\
Serial.println(buffer);\
Serial.flush();
#else
#define DEBUG(msg)
#define DEBUGF(msg, ...)
#endif
inline void pulse(short pin, short count)
{
while (--count >= 0)
{
digitalWrite(INDICATOR_PIN, HIGH);
delay(150);
digitalWrite(INDICATOR_PIN, LOW);
if (count != 0) delay(200);
}
}
///////////////////////////////////////////////////////////////////////////
// INTERFACES
class Sensor
{
public:
virtual void setup() = 0;
};
class Protocol
{
public:
virtual void setup() = 0;
};
struct PowerData
{
unsigned int consumption;
};
class SensorPowerConsumption : public Sensor
{
public:
// returns number of pulses from power meter
virtual void read(PowerData& data) = 0;
};
class ProtocolPowerConsumption : public Protocol
{
public:
virtual void send(const PowerData& data) = 0;
};
struct TemperatureData
{
float temperature;
float humidity;
};
class SensorTemperature : public Sensor
{
public:
virtual void read(TemperatureData& data) = 0;
};
class ProtocolTemperature : public Protocol
{
public:
virtual void send(const TemperatureData& data) = 0;
};
struct LightData
{
unsigned int lumen;
};
class SensorLight : public Sensor
{
public:
virtual void read(LightData& data) = 0;
};
class ProtocolLight : public Protocol
{
public:
virtual void send(const LightData& data) = 0;
};
#endif // HALINTERFACES_H

View file

@ -0,0 +1,132 @@
/*
A interrupt based sensor device that reads multiple sensors and transmits
the data to a central location.
*/
#include <Arduino.h>
#include "HalConfiguration.h"
#include "HalInterfaces.h"
#include "HalInclude.h"
#include "Interrupt.h"
#ifndef POWERCON_ENABLED
#define POWER_TIMER_MULTIPLIER 1
#endif
#ifndef TEMPERATURE_ENABLED
#define TEMPERATURE_TIMER_MULTIPLIER 1
#endif
#ifndef LIGHT_ENABLED
#define LIGHT_TIMER_MULTIPLIER 1
#endif
#define TIMER_MULTIPLIER_MAX \
POWER_TIMER_MULTIPLIER * TEMPERATURE_TIMER_MULTIPLIER * LIGHT_TIMER_MULTIPLIER
unsigned int timerMultiplier = 0;
// Sensors
SensorPowerConsumption* powerSensor;
SensorTemperature* tempSensor;
SensorLight* lightSensor;
// Protocols
ProtocolPowerConsumption* powerProtocol;
ProtocolTemperature* tempProtocol;
ProtocolLight* lightProtocol;
void timerInterruptFunc();
void setup()
{
#ifdef ENABLE_DEBUG
Serial.begin(9600);
#endif
pinMode(INDICATOR_PIN, OUTPUT);
// Setup Sensors and protocols
#ifdef POWERCON_ENABLED
DEBUG("Setup POWERCON_SENSOR");
powerSensor = new POWERCON_SENSOR;
powerSensor->setup();
powerProtocol = new POWERCON_PROTOCOL;
powerProtocol->setup();
#endif
#ifdef TEMPERATURE_ENABLED
DEBUG("Setup TEMPERATURE_SENSOR");
tempSensor = new TEMPERATURE_SENSOR;
tempSensor->setup();
tempProtocol = new TEMPERATURE_PROTOCOL;
tempProtocol->setup();
#endif
#ifdef LIGHT_ENABLED
DEBUG("Setup LIGHT_SENSOR");
lightSensor = new LIGHT_SENSOR;
lightSensor->setup();
lightProtocol = new LIGHT_PROTOCOL;
lightProtocol->setup();
#endif
DEBUG("Setup SLEEP_INTERRUPT");
Interrupt::setWatchDogCallback(timerInterruptFunc);
Interrupt::setupWatchDogInterrupt(TIMER_MILLISECOND); // one minute scheduled interrupt
pulse(INDICATOR_PIN, 3);
DEBUG("Ready");
}
void timerInterruptFunc()
{
++timerMultiplier;
if (timerMultiplier > TIMER_MULTIPLIER_MAX)
timerMultiplier = 1;
}
void loop()
{
digitalWrite(INDICATOR_PIN, HIGH);
// Send power consumption
#ifdef POWERCON_ENABLED
if (timerMultiplier % POWER_TIMER_MULTIPLIER == 0)
{
static PowerData powerData;
powerSensor->read(powerData); // not needed, only here for future use
DEBUGF("Read POWERCON_SENSOR= consumption:%d", powerData.consumption);
powerProtocol->send(powerData);
}
#endif
// Handle temperature sensor
#ifdef TEMPERATURE_ENABLED
if (timerMultiplier % TEMPERATURE_TIMER_MULTIPLIER == 0)
{
static TemperatureData tempData;
tempSensor->read(tempData);
DEBUGF("Read TEMPERATURE_SENSOR= temperature:%d, humidity:%d", (int)tempData.temperature, (int)tempData.humidity);
tempProtocol->send(tempData);
}
#endif
// Handle light sensor
#ifdef LIGHT_ENABLED
if (timerMultiplier % LIGHT_TIMER_MULTIPLIER == 0)
{
static LightData lightData;
lightSensor->read(lightData);
DEBUGF("Read LIGHT_SENSOR= lumen:%d", lightData.lumen);
lightProtocol->send(lightData);
}
#endif
digitalWrite(INDICATOR_PIN, LOW);
DEBUG("Sleeping");
Interrupt::sleep();
DEBUG("Wakeup");
}

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,234 @@
#include "Interrupt.h"
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include "HalInterfaces.h"
void emptyFunc(){}
bool Interrupt::wakeUpNow = false;
InterruptFunction Interrupt::pinCallback = emptyFunc;
InterruptFunction Interrupt::wdtCallback = emptyFunc;
void Interrupt::handlePinInterrupt() // the interrupt is handled here after wakeup
{
(*Interrupt::pinCallback) ();
//Interrupt::wakeUp();
}
void Interrupt::sleep()
{
/*
* The 5 different modes are:
* SLEEP_MODE_IDLE -the least power savings
* SLEEP_MODE_ADC
* SLEEP_MODE_PWR_SAVE
* SLEEP_MODE_STANDBY
* SLEEP_MODE_PWR_DOWN -the most power savings
*
* For now, we want as much power savings as possible, so we
* choose the according
* sleep mode: SLEEP_MODE_PWR_DOWN
*/
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
wakeUpNow = false;
sleep_enable(); // enables the sleep bit in the mcucr register
// so sleep is possible. just a safety pin
//power_adc_disable();
//power_spi_disable();
//power_usart0_disable();
//power_timer0_disable();
//power_timer1_disable();
//power_timer2_disable();
//power_twi_disable();
//power_all_disable();
while( ! Interrupt::wakeUpNow)
{
sleep_mode(); // here the device is actually put to sleep!!
// THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
}
sleep_disable(); // first thing after waking from sleep:
// disable sleep...
//power_adc_enable();
//power_spi_enable();
//power_usart0_enable();
//power_timer0_enable();
//power_timer1_enable();
//power_timer2_enable();
//power_twi_enable();
//power_all_enable(); // during normal running time.
}
void Interrupt::setupPinInterrupt(int pin)
{
noInterrupts(); // disable all interrupts
/* Now it is time to enable an interrupt.
* In the function call attachInterrupt(A, B, C)
* A can be either 0 or 1 for interrupts on pin 2 or 3.
* B Name of a function you want to execute at interrupt for A.
* C Trigger mode of the interrupt pin. can be:
* LOW a low level triggers
* CHANGE a change in level triggers
* RISING a rising edge of a level triggers
* FALLING a falling edge of a level triggers
*
* In all but the IDLE sleep modes only LOW can be used.
*/
attachInterrupt((pin == PIND2 ? 0 : 1), Interrupt::handlePinInterrupt, RISING);
//detachInterrupt(0); // disables interrupt 0 on pin 2 so the
// wakeUpNow code will not be executed
interrupts(); // enable all interrupts
}
//////////////////////////////////////////////////////////////////////////
// Watchdog timer
uint16_t wdtTime;
int32_t wdtTimeLeft;
void Interrupt::handleWatchDogInterrupt()
{
wdt_disable();
if (wdtTime <= 0)
return;
DEBUGF("WDT interrupt, time=%u, timeLeft=%ld", wdtTime, wdtTimeLeft);
if (wdtTimeLeft <= 0)
{
Interrupt::wakeUp();
(*Interrupt::wdtCallback) ();
wdtTimeLeft = wdtTime;
}
setupWatchDogInterrupt();
}
ISR(WDT_vect)
{
Interrupt::handleWatchDogInterrupt();
}
void Interrupt::setupWatchDogInterrupt(int32_t milliseconds)
{
wdtTimeLeft = wdtTime = milliseconds;
setupWatchDogInterrupt();
}
void Interrupt::setupWatchDogInterrupt()
{
if (wdtTime <= 0){
wdt_disable();
return;
}
noInterrupts();
unsigned short duration;
if (8000 <= wdtTimeLeft){
wdtTimeLeft -= 8000;
duration = (1 << WDP3) | (1 << WDP0);
} else if (4000 <= wdtTimeLeft){
wdtTimeLeft -= 4000;
duration = (1 << WDP3);
} else if (2000 <= wdtTimeLeft){
wdtTimeLeft -= 2000;
duration = (1 << WDP2) | (1 << WDP1) | (1 << WDP0);
} else if (1000 <= wdtTimeLeft){
wdtTimeLeft -= 1000;
duration = (1 << WDP2) | (1 << WDP1);
} else if (500 <= wdtTimeLeft){
wdtTimeLeft -= 500;
duration = (1 << WDP2) | (1 << WDP0);
} else if (256 <= wdtTimeLeft){
wdtTimeLeft -= 256;
duration = (1 << WDP2);
} else if (128 <= wdtTimeLeft){
wdtTimeLeft -= 128;
duration = (1 << WDP1) | (1 << WDP0);
} else if (64 <= wdtTimeLeft){
wdtTimeLeft -= 64;
duration = (1 << WDP1);
} else if (32 <= wdtTimeLeft){
wdtTimeLeft -= 32;
duration = (1 << WDP0);
} else { //(16 <= wdtTimeLeft){
wdtTimeLeft -= 16;
duration = 0;
}
wdt_reset();
MCUSR &= ~(1 << WDRF); // reset status flag
/* WDCE = Watchdog Change Enable
*
* WDTON(1) WDE WDIE Mode
* 1 0 0 Stopped
* 1 0 1 Interrupt
* 1 1 0 Reset
* 1 1 1 Interrupt first, reset on second trigger
* 0 x x Reset
*/
WDTCSR = (1 << WDCE) | (1<<WDE); // enable configuration
/* WDP3 WDP2 WDP1 WDP0 Number of cycles Typical Time-out time (VCC = 5.0V)
* 0 0 0 0 2K (2048) 16 ms
* 0 0 0 1 4K (4096) 32 ms
* 0 0 1 0 8K (8192) 64 ms
* 0 0 1 1 16K (16384) 0.125 s
* 0 1 0 0 32K (32768) 0.25 s
* 0 1 0 1 64K (65536) 0.5 s
* 0 1 1 0 128K (131072) 1.0 s
* 0 1 1 1 256K (262144) 2.0 s
* 1 0 0 0 512K (524288) 4.0 s
* 1 0 0 1 1024K (1048576) 8.0 s
*/
WDTCSR = (1 << WDIE) | duration;
//WDTCSR = (1 << WDIE) | (1 << WDP3) | (1 << WDP0);
interrupts();
}
//////////////////////////////////////////////////////////////////////////
// Timer 1
/*
ISR(Timer1_COMPA_vect) // timer compare interrupt service routine
{
//DEBUG("Timer1e Interrupt");
__pinInterruptHandler__();
}
*/
/*
void Interrupt::setupTimerInterrupt(unsigned int milliseconds)
{
noInterrupts(); // disable all interrupts
// initialize Timer1
TCCR1A = 0;
TCCR1B = 0;
/* Clock Select Bit Description
* CS12 CS11 CS10 Description
* 0 0 0 No clock source (Stop timer)
* 0 0 1 clk/1 (No prescaling)
* 0 1 0 clk/8
* 0 1 1 clk/64
* 1 0 0 clk/256
* 1 0 1 clk/1024
* 1 1 0 External clock source on T1 pin. Clock on falling edge.
* 1 1 1 External clock source on T1 pin. Clock on rising edge.
*/
/* TCCR1B |= (1 << CS12); // 256 prescaler
TCNT1 = 34286; // preload timer 65536-16MHz/256/2Hz
//TODO: TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
}
*/

View file

@ -0,0 +1,39 @@
#ifndef INTERRUPT_H
#define INTERRUPT_H
#include <Arduino.h>
typedef void (*InterruptFunction) ();
class Interrupt
{
public:
static void wakeUp() { wakeUpNow = true; };
static void sleep();
static void setupPinInterrupt(int pin);
static void setupWatchDogInterrupt(int32_t milliseconds);
//static void setupTimerInterrupt(unsigned int milliseconds);
static void setPinCallback(InterruptFunction callback){ Interrupt::pinCallback = callback;}
static void setWatchDogCallback(InterruptFunction callback){ Interrupt::wdtCallback = callback;}
/* Should not be called externally, used as triggering functions */
static void handlePinInterrupt();
static void handleWatchDogInterrupt();
private:
static bool wakeUpNow;
static InterruptFunction pinCallback;
static InterruptFunction wdtCallback;
static void setupWatchDogInterrupt();
// Disable constructors and copy operators
Interrupt() {};
Interrupt(Interrupt const&);
void operator=(Interrupt const&);
};
#endif // INTERRUPT_H

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,8 @@
#ifndef PROTOCOLNEXA_H
#define PROTOCOLNEXA_H
#include "HalInterfaces.h"
#endif // PROTOCOLNEXA_H

View file

@ -0,0 +1,215 @@
#include "ProtocolOregon.h"
#define RF_DELAY 512
#define RF_DELAY_LONG RF_DELAY*2
#define RF_SEND_HIGH() digitalWrite(txPin, HIGH)
#define RF_SEND_LOW() digitalWrite(txPin, LOW)
void ProtocolOregon::setup()
{
pinMode(txPin, OUTPUT);
RF_SEND_LOW();
}
void ProtocolOregon::send(const PowerData& data)
{
send(data.consumption, 0);
}
void ProtocolOregon::send(const TemperatureData& data)
{
send(data.temperature, data.humidity);
}
void ProtocolOregon::send(const LightData& data)
{
send(data.lumen, 0);
}
void ProtocolOregon::send(float temperature, short humidity)
{
byte buffer[9];
setType(buffer, 0x1A,0x2D); //temperature/humidity sensor (THGR2228N)
setChannel(buffer, 0x20);
setId(buffer, address); //set id of the sensor, BB=187
setBatteryLevel(buffer, true); // false : low, true : high
setTemperature(buffer, temperature); //org setTemperature(OregonMessageBuffer, 55.5);
setHumidity(buffer, humidity);
calculateAndSetChecksum(buffer);
// Send the Message over RF
rfSend(buffer, sizeof(buffer));
// Send a "pause"
RF_SEND_LOW();
delayMicroseconds(RF_DELAY_LONG * 8);
// Send a copy of the first message. The v2.1 protocol send the message two RF_DELAYs
rfSend(buffer, sizeof(buffer));
RF_SEND_LOW();
}
/**
* \brief Set the sensor type
* \param data Oregon message
* \param type Sensor type
*/
inline void ProtocolOregon::setType(byte data[], byte b1, byte b2)
{
data[0] = b1;
data[1] = b2;
}
/**
* \brief Set the sensor channel
* \param data Oregon message
* \param channel Sensor channel (0x10, 0x20, 0x30)
*/
inline void ProtocolOregon::setChannel(byte data[], byte channel)
{
data[2] = channel;
}
inline void ProtocolOregon::setId(byte data[], byte id)
{
data[3] = id;
}
/**
* \param level false: low, true: high
*/
inline void ProtocolOregon::setBatteryLevel(byte data[], bool level)
{
if (!level) data[4] = 0x0C;
else data[4] = 0x00;
}
inline void ProtocolOregon::setTemperature(byte data[], float temp)
{
// Set temperature sign
if (temp < 0)
{
data[6] = 0x08;
temp *= -1;
}
else
{
data[6] = 0x00;
}
// Determine decimal and float part
int tempInt = (int)temp;
int td = (int)(tempInt / 10);
int tf = (int)round((float)((float)tempInt/10 - (float)td) * 10);
int tempFloat = (int)round((float)(temp - (float)tempInt) * 10);
// Set temperature decimal part
data[5] = (td << 4);
data[5] |= tf;
// Set temperature float part
data[4] |= (tempFloat << 4);
}
inline void ProtocolOregon::setHumidity(byte data[], byte hum)
{
data[7] = (hum/10);
data[6] |= (hum - data[7]*10) << 4;
}
inline void ProtocolOregon::calculateAndSetChecksum(byte data[])
{
int sum = 0;
for(byte i = 0; i<8;i++)
{
sum += (data[i]&0xF0) >> 4;
sum += (data[i]&0x0F);
}
data[8] = ((sum - 0x0A) & 0xFF);
}
//*********************************************************************************************************
/**
* \brief Send logical "0" over RF
* \details a zero bit be represented by an off-to-on transition
* \ of the RF signal at the middle of a clock period.
* \ Remember, the Oregon v2.1 protocol adds an inverted bit first
*/
inline void ProtocolOregon::sendZero(void)
{
RF_SEND_HIGH();
delayMicroseconds(RF_DELAY);
RF_SEND_LOW();
delayMicroseconds(RF_DELAY_LONG);
RF_SEND_HIGH();
delayMicroseconds(RF_DELAY);
}
/**
* \brief Send logical "1" over RF
* \details a one bit be represented by an on-to-off transition
* \ of the RF signal at the middle of a clock period.
* \ Remember, the Oregon v2.1 protocol add an inverted bit first
*/
inline void ProtocolOregon::sendOne(void)
{
RF_SEND_LOW();
delayMicroseconds(RF_DELAY);
RF_SEND_HIGH();
delayMicroseconds(RF_DELAY_LONG);
RF_SEND_LOW();
delayMicroseconds(RF_DELAY);
}
/******************************************************************/
/******************************************************************/
/******************************************************************/
/**
* \brief Send a buffer over RF
* \param data Data to send
* \param length size of data array
*/
void ProtocolOregon::sendData(byte data[], byte length)
{
for (byte i=0; i<length; ++i)
{
(bitRead(data[i], 0)) ? sendOne() : sendZero();
(bitRead(data[i], 1)) ? sendOne() : sendZero();
(bitRead(data[i], 2)) ? sendOne() : sendZero();
(bitRead(data[i], 3)) ? sendOne() : sendZero();
(bitRead(data[i], 4)) ? sendOne() : sendZero();
(bitRead(data[i], 5)) ? sendOne() : sendZero();
(bitRead(data[i], 6)) ? sendOne() : sendZero();
(bitRead(data[i], 7)) ? sendOne() : sendZero();
}
}
/**
* \brief Send an Oregon message
* \param data The Oregon message
*/
void ProtocolOregon::rfSend(byte data[], byte size)
{
// Send preamble
byte preamble[] = { 0xFF,0xFF };
sendData(preamble, 2);
// Send sync nibble
//sendQuarterLSB(0xA); // It is not use in this version since the sync nibble is include in the Oregon message to send.
// Send data
sendData(data, size);
// Send postamble
byte postamble[] = { 0x00 };
sendData(postamble, 1);
}

View file

@ -0,0 +1,37 @@
#ifndef PROTOCOLOREGON_H
#define PROTOCOLOREGON_H
#include <Arduino.h>
#include "HalInterfaces.h"
class ProtocolOregon : public ProtocolTemperature, public ProtocolPowerConsumption, public ProtocolLight
{
public:
ProtocolOregon(short pin, unsigned char address) : txPin(pin), address(address){};
virtual void setup();
virtual void send(const TemperatureData& data);
virtual void send(const PowerData& data);
virtual void send(const LightData& data);
private:
short txPin;
unsigned char address;
void send(float temperature, short humidity);
void setType(byte *data, byte b1, byte b2);
void setChannel(byte *data, byte channel);
void setId(byte *data, byte id);
void setBatteryLevel(byte *data, bool level);
void setTemperature(byte *data, float temp);
void setHumidity(byte* data, byte hum);
void calculateAndSetChecksum(byte* data);
void sendZero(void);
void sendOne(void);
void sendData(byte *data, byte length);
void rfSend(byte *data, byte size);
};
#endif // PROTOCOLOREGON_H

View file

@ -0,0 +1,93 @@
/*
This is a library for the BH1750FVI Digital Light Sensor
breakout board.
The board uses I2C for communication. 2 pins are required to
interface to the device.
based on Christopher Laws, March, 2013 code.
*/
#include "SensorBH1750.h"
#include <util/delay.h>
#define BH1750_I2CADDR 0x23
// No active state
#define BH1750_POWER_DOWN 0x00
// Waiting for measurement command
#define BH1750_POWER_ON 0x01
// Reset data register value - not accepted in POWER_DOWN mode
#define BH1750_RESET 0x07
// Start measurement at 1lx resolution. Measurement time is approx 120ms.
#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10
// Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
#define BH1750_CONTINUOUS_HIGH_RES_MODE_2 0x11
// Start measurement at 4lx resolution. Measurement time is approx 16ms.
#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13
// Start measurement at 1lx resolution. Measurement time is approx 120ms.
// Device is automatically set to Power Down after measurement.
#define BH1750_ONE_TIME_HIGH_RES_MODE 0x20
// Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
// Device is automatically set to Power Down after measurement.
#define BH1750_ONE_TIME_HIGH_RES_MODE_2 0x21
// Start measurement at 1lx resolution. Measurement time is approx 120ms.
// Device is automatically set to Power Down after measurement.
#define BH1750_ONE_TIME_LOW_RES_MODE 0x23
void SensorBH1750::setup() {
Wire.begin();
//configure(BH1750_ONE_TIME_HIGH_RES_MODE);
}
void SensorBH1750::configure(uint8_t mode) {
switch (mode) {
case BH1750_CONTINUOUS_HIGH_RES_MODE:
case BH1750_CONTINUOUS_HIGH_RES_MODE_2:
case BH1750_CONTINUOUS_LOW_RES_MODE:
case BH1750_ONE_TIME_HIGH_RES_MODE:
case BH1750_ONE_TIME_HIGH_RES_MODE_2:
case BH1750_ONE_TIME_LOW_RES_MODE:
// apply a valid mode change
Wire.beginTransmission(BH1750_I2CADDR);
Wire.write(mode);
Wire.endTransmission();
_delay_ms(10);
break;
default:
// Invalid measurement mode
DEBUG("Invalid measurement mode");
break;
}
}
void SensorBH1750::read(LightData& data) {
configure(BH1750_ONE_TIME_HIGH_RES_MODE);
_delay_ms(200); // Wait for measurement
Wire.beginTransmission(BH1750_I2CADDR);
Wire.requestFrom(BH1750_I2CADDR, 2);
uint16_t level = Wire.read();
level <<= 8;
level |= Wire.read();
Wire.endTransmission();
data.lumen = level/1.2; // convert to lux
}

View file

@ -0,0 +1,21 @@
#ifndef SensorBH1750_H
#define SensorBH1750_H
#include <Wire.h>
#include "HalInterfaces.h"
class SensorBH1750 : public SensorLight{
public:
virtual void setup();
virtual void read(LightData& data);
private:
unsigned int pulses;
void configure(uint8_t mode);
};
#endif // SensorBH1750_H

View file

@ -0,0 +1,165 @@
/* DHT library
MIT license
written by Adafruit Industries
*/
// Modified by Ziver Koc
//
#include "SensorDHT.h"
void SensorDHT::setup()
{
// set up the pins!
pinMode(_pin, INPUT_PULLUP);
#ifdef __AVR
_bit = digitalPinToBitMask(_pin);
_port = digitalPinToPort(_pin);
#endif
_maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for
// reading pulses from DHT sensor.
}
// Expect the signal line to be at the specified level for a period of time and
// return a count of loop cycles spent at that level (this cycle count can be
// used to compare the relative time of two pulses). If more than a millisecond
// ellapses without the level changing then the call fails with a 0 response.
// This is adapted from Arduino's pulseInLong function (which is only available
// in the very latest IDE versions):
// https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c
uint32_t SensorDHT::expectPulse(bool level) {
uint32_t count = 0;
// On AVR platforms use direct GPIO port access as it's much faster and better
// for catching pulses that are 10's of microseconds in length:
#ifdef __AVR
uint8_t portState = level ? _bit : 0;
while ((*portInputRegister(_port) & _bit) == portState) {
if (count++ >= _maxcycles) {
return 0; // Exceeded timeout, fail.
}
}
// Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266
// right now, perhaps bugs in direct port access functions?).
#else
while (digitalRead(_pin) == level) {
if (count++ >= _maxcycles) {
return 0; // Exceeded timeout, fail.
}
}
#endif
return count;
}
void SensorDHT::read(TemperatureData& retData)
{
// Reset 40 bits of received data to zero.
static uint8_t data[5];
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
// Send start signal. See DHT datasheet for full signal diagram:
// http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf
// Go into high impedence state to let pull-up raise data line level and
// start the reading process.
digitalWrite(_pin, HIGH);
delay(250);
// First set data line low for 20 milliseconds.
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
delay(20);
uint32_t cycles[80];
{
// Turn off interrupts temporarily because the next sections are timing critical
// and we don't want any interruptions.
noInterrupts();
// End the start signal by setting data line high for 40 microseconds.
digitalWrite(_pin, HIGH);
delayMicroseconds(40);
// Now start reading the data line to get the value from the DHT sensor.
pinMode(_pin, INPUT_PULLUP);
delayMicroseconds(10); // Delay a bit to let sensor pull data line low.
// First expect a low signal for ~80 microseconds followed by a high signal
// for ~80 microseconds again.
if (expectPulse(LOW) == 0) {
DEBUG("DHT:Timeout waiting for start signal low pulse.");
interrupts();
return;
}
if (expectPulse(HIGH) == 0) {
DEBUG("DHT:Timeout waiting for start signal high pulse.");
interrupts();
return;
}
// Now read the 40 bits sent by the sensor. Each bit is sent as a 50
// microsecond low pulse followed by a variable length high pulse. If the
// high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds
// then it's a 1. We measure the cycle count of the initial 50us low pulse
// and use that to compare to the cycle count of the high pulse to determine
// if the bit is a 0 (high state cycle count < low state cycle count), or a
// 1 (high state cycle count > low state cycle count). Note that for speed all
// the pulses are read into a array and then examined in a later step.
for (int i=0; i<80; i+=2) {
cycles[i] = expectPulse(LOW);
cycles[i+1] = expectPulse(HIGH);
}
interrupts();
} // Timing critical code is now complete.
// Inspect pulses and determine which ones are 0 (high state cycle count < low
// state cycle count), or 1 (high state cycle count > low state cycle count).
for (int i=0; i<40; ++i) {
uint32_t lowCycles = cycles[2*i];
uint32_t highCycles = cycles[2*i+1];
if ((lowCycles == 0) || (highCycles == 0)) {
DEBUG("DHT:Timeout waiting for pulse.");
return;
}
data[i/8] <<= 1;
// Now compare the low and high cycle times to see if the bit is a 0 or 1.
if (highCycles > lowCycles) {
// High cycles are greater than 50us low cycle count, must be a 1.
data[i/8] |= 1;
}
// Else high cycles are less than (or equal to, a weird case) the 50us low
// cycle count so this must be a zero. Nothing needs to be changed in the
// stored data.
}
// Check we read 40 bits and that the checksum matches.
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
switch (_type) {
case DHT11:
retData.temperature = data[2];
retData.humidity = data[0];
break;
case DHT22:
case DHT21:
retData.temperature = data[2] & 0x7F;
retData.temperature *= 256;
retData.temperature += data[3];
retData.temperature *= 0.1;
if (data[2] & 0x80) {
retData.temperature *= -1;
}
retData.humidity = data[0];
retData.humidity *= 256;
retData.humidity += data[1];
retData.humidity *= 0.1;
break;
}
}
else {
DEBUG("DHT:Checksum failure!");
}
}

View file

@ -0,0 +1,33 @@
#ifndef SensorDHT_h
#define SensorDHT_h
#include <Arduino.h>
#include "HalInterfaces.h"
// Define types of sensors.
#define DHT11 11
#define DHT22 22
#define DHT21 21
class SensorDHT : public SensorTemperature
{
public:
SensorDHT(uint8_t type, uint8_t pin) : _type(type), _pin(pin) {};
virtual void setup();
virtual void read(TemperatureData& data);
private:
uint8_t _type, _pin;
uint32_t _maxcycles;
#ifdef __AVR
// Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask
// for the digital pin connected to the DHT. Other platforms will use digitalRead.
uint8_t _bit, _port;
#endif
uint32_t expectPulse(bool level);
};
#endif

View file

@ -0,0 +1,25 @@
#include "SensorPhotocell.h"
#include <Arduino.h>
unsigned int SensorPhotocell::pulse = 0;
void SensorPhotocell::interruptHandler()
{
digitalWrite(INDICATOR_PIN, HIGH);
DEBUG("PHCELL: INTERRUPT");
++pulse;
digitalWrite(INDICATOR_PIN, LOW);
}
void SensorPhotocell::setup()
{
Interrupt::setPinCallback(SensorPhotocell::interruptHandler);
Interrupt::setupPinInterrupt(PC2); //PC3
}
void SensorPhotocell::read(PowerData& data)
{
data.consumption = pulse;
pulse = 0;
}

View file

@ -0,0 +1,20 @@
#ifndef SensorPhotocell_H
#define SensorPhotocell_H
#include "HalInterfaces.h"
#include "Interrupt.h"
class SensorPhotocell : public SensorPowerConsumption
{
public:
virtual void setup();
virtual void read(PowerData& data);
private:
static unsigned int pulse;
static void interruptHandler();
};
#endif // SensorPhotocell_H

View file

@ -0,0 +1,155 @@
#include "NexaSelfLearningReceiver.h"
#define TX_PIN 10
#define RX_PIN 4
#define RX_LED 13
//Radio RX
NexaSelfLearningReceiver receiver = NexaSelfLearningReceiver(RX_PIN, RX_LED);
short dim = 0;
uint64_t receivedSignal = 0;
//Serial RX
byte rxBuffer[79];
void setup(){
Serial.begin(9600);
};
void loop(){
//Receive and execute command over serial
if(Serial.available() > 0){
uint8_t rxDataSize = Serial.readBytesUntil('+', &rxBuffer[0], 79);
if(rxDataSize > 0){
if(parseRxBuffer(&rxBuffer[0], 0, rxDataSize, false, 3, 0)){
//Serial.println(F("DEBUG:PARSE OK"));
}else{
//Serial.println(F("DEBUG:PARSE ERROR"));
}
}
}
//Receive signal over air and send it over serial
receivedSignal = receiver.receiveSignal(NULL, NULL, NULL, NULL, &dim, 100);
if(receivedSignal > 0){
Serial.print(F("+Wclass:command;protocol:arctech;model:selflearning;data:0x"));
uint8_t hexToSend = (dim == NULL ? 8 : 9);
for(int8_t i = hexToSend-1; i >= 0; --i){
Serial.print( (byte)((receivedSignal>>(4*i))&0x0F), HEX);
}
Serial.println(F(";"));
}
};
bool parseRxBuffer(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause){
if(startIndex > endIndex){
return false;
}
char c = buffer[startIndex];
//Serial.print("DEBUG: char:"); Serial.println(c, DEC);
switch(c){
case 'S':
return handleS(buffer, startIndex+1, endIndex, debug, repeat, pause);
case 'T':
return handleT(buffer, startIndex+1, endIndex, debug, repeat, pause);
case 'V':
Serial.println(F("+V2"));
return parseRxBuffer(buffer, startIndex+1, endIndex, debug, repeat, pause);
case 'D':
return parseRxBuffer(buffer, startIndex+1, endIndex, !debug, repeat, pause);
case 'P':
if(endIndex-startIndex+1 < 3){return false;} //at least {'P',[p-value],'+'} must be left in the buffer
return parseRxBuffer(buffer, startIndex+2, endIndex, debug, repeat, buffer[startIndex+1]);
case 'R':
if(endIndex-startIndex+1 < 3){return false;} //at least {'R',[r-value],'+'} must be left in the buffer
return parseRxBuffer(buffer, startIndex+2, endIndex, debug, buffer[startIndex+1], pause);
case '+':
return true;
default:
//Serial.print("DEBUG: unknown char: '"); Serial.print(c, BIN); Serial.println("'");
return false;
}
};
bool handleS(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause){
//Parse message received from serial
uint8_t S_data[78]; //78 pulses
uint8_t pulseCount = 0;
for(uint8_t i = startIndex; i <= endIndex; ++i){
if(buffer[i] == '+'){
break;
}else if(i == endIndex){
return false;
}else{
S_data[pulseCount++] = buffer[i];
}
}
//Send message
for(uint8_t rep = 0; rep < repeat; ++rep){
bool nextPinState = HIGH;
for(int i = 0; i < pulseCount; ++i){
if(S_data[i] > 0 || i == pulseCount-1){
digitalWrite(TX_PIN, nextPinState);
delayMicroseconds(S_data[i]*10);
}
nextPinState = !nextPinState;
}
delay(pause);
}
//send confirmation over serial
Serial.println(F("+S"));
return true;
};
bool handleT(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause){
//Parse message received from serial
uint8_t T_data[72]; //0-188 pulses
if(endIndex - startIndex < 5){
//Serial.println("DEBUG: wrong size!");
return false;
}
uint8_t buff_p = startIndex;
uint8_t T_times[4] = {buffer[buff_p++], buffer[buff_p++], buffer[buff_p++], buffer[buff_p++]};
uint8_t T_long = buffer[buff_p++];
uint8_t T_bytes = 0;
if( (T_long/4.0) > (float)(T_long/4) ){
T_bytes = T_long/4 + 1;
}else{
T_bytes = T_long/4;
}
uint8_t j = 0;
while(j < T_bytes){
if(buffer[buff_p] == '+'){
break;
}else if(buff_p >= endIndex){
return false;
}else{
T_data[j++] = buffer[buff_p++];
}
}
if( j != T_bytes ){
return false;
}
//Send message
for(uint8_t rep = 0; rep < repeat; ++rep){
bool nextPinState = HIGH;
for(int i = 0; i < T_long; ++i){
uint8_t timeIndex = (T_data[i/4]>>(6-(2*(i%4))))&0x03;
if(T_times[timeIndex] > 0 || i == T_long-1){
digitalWrite(TX_PIN, nextPinState);
delayMicroseconds(10*T_times[timeIndex]);
}
nextPinState = !nextPinState;
}
digitalWrite(TX_PIN, LOW);
if(rep < repeat-1){
delay(pause);
}
}
//send confirmation over serial
Serial.println(F("+T"));
return parseRxBuffer(buffer, buff_p, endIndex, debug, repeat, pause);
};

@ -0,0 +1 @@
Subproject commit 5fd5429375b3fffbf0bdd041d493d5c6ff0c156a

126
build.gradle Normal file
View file

@ -0,0 +1,126 @@
plugins {
id 'java'
id 'application'
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2025 Ziver Koc
*
* 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.
*/
// ------------------------------------
// Hal common configuration
// ------------------------------------
allprojects {
repositories {
mavenLocal()
mavenCentral()
}
}
subprojects {
apply plugin: 'java-library'
dependencies {
//implementation 'se.koc:zutil:1.0.314'
implementation 'se.koc:zutil:1.0.0-SNAPSHOT'
testImplementation 'junit:junit:4.12'
testImplementation 'org.hamcrest:hamcrest-core:2.2'
}
sourceSets {
main {
java {
srcDirs 'src'
}
// We do not want the resource folder to be included in the jar file
//resources {
// srcDir 'resource'
//}
}
test {
java {
srcDirs 'test'
}
}
}
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:deprecation"
//options.compilerArgs << "-Xlint:unchecked"
}
}
// ------------------------------------
// Hal general configuration
// ------------------------------------
dependencies {
project.subprojects.each { subProject ->
runtimeOnly subProject
}
}
distributions {
main {
contents {
// from root project
from 'hal.conf.example'
from 'logging.properties'
from 'run.sh'
// from subprojects
project.subprojects.each { subProject ->
into('bin') {
from "${subProject.projectDir}/resources/bin"
}
into('web') {
from "${subProject.projectDir}/resources/web"
}
into('resources') {
from ("${subProject.projectDir}/resources") {
exclude 'bin'
exclude 'web'
}
}
}
}
}
}
distTar.enabled = false
distZip.enabled = false
assemble.dependsOn(installDist)
project.gradle.startParameter.taskNames.each { taskName ->
if (taskName == 'distZip') {
distZip.enabled = true
}
}
application {
mainClass = 'se.hal.HalServer'
}
startScripts.enabled = false

View file

@ -1,91 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="Zutil" >
<!-- ________________________ PROPERTIES AND SETTINGS ________________________ -->
<!--common properties-->
<property name="gitRoot" value="." />
<property name="srcDir" value="${gitRoot}/src" />
<property name="testDir" value="${gitRoot}/test" />
<property name="libDir" value="${gitRoot}/lib" />
<property name="buildRoot" value="${gitRoot}/build" />
<property name="buildDir" value="${buildRoot}/production" />
<property name="buildTestDir" value="${buildRoot}/test" />
<property name="releaseDir" value="${buildRoot}/release" />
<property name="reportsDir" value="${buildRoot}/reports" />
<!--define standard arduments for javac-->
<presetdef name="javac">
<javac includeantruntime="false" />
</presetdef>
<!-- ________________________ CLASSPATHS ________________________ -->
<!--classpath included when building-->
<path id="classpath.build">
<fileset dir="${libDir}">
<include name="**/*.jar"/>
</fileset>
<pathelement location="${buildDir}" />
</path>
<path id="classpath.test">
<pathelement location="${buildTestDir}" />
<!--include libraries used for building-->
<path refid="classpath.build"/>
</path>
<!-- ________________________ EXECUTION TARGETS ________________________ -->
<target name="test" depends="build-test">
<mkdir dir="${reportsDir}" />
<junit printsummary="yes" haltonfailure="false" fork="true">
<classpath refid="classpath.test" />
<formatter type="plain" usefile="false" /> <!-- to screen -->
<formatter type="xml" /> <!-- to file -->
<batchtest todir="${reportsDir}" skipNonTests="true">
<fileset dir="${buildTestDir}" includes="**/*Test*.class" />
</batchtest>
</junit>
</target>
<!-- ________________________ BUILD TARGETS ________________________ -->
<!--clean all build paths-->
<target name="clean">
<delete includeemptydirs="true" failonerror="false">
<fileset dir="${buildRoot}" includes="**/*"/>
</delete>
</target>
<!--build product code-->
<target name="release" depends="build">
<jar destfile="${releaseDir}/Zutil.jar" basedir="${buildDir}" />
</target>
<target name="build">
<mkdir dir="${buildDir}" />
<javac srcdir="${srcDir}" destdir="${buildDir}" debug="yes" debugLevel="lines,vars,source">
<classpath refid="classpath.build" />
<include name="**/*.java" />
</javac>
<copy todir="${buildDir}">
<fileset dir="${srcDir}"
excludes="**/*.java" />
</copy>
</target>
<target name="build-test" depends="build">
<mkdir dir="${buildTestDir}" />
<javac srcdir="${testDir}" destdir="${buildTestDir}" debug="yes" debugLevel="lines,vars,source">
<classpath refid="classpath.test" />
<include name="**/*.java" />
</javac>
<copy todir="${buildTestDir}">
<fileset dir="${testDir}"
excludes="**/*.java" />
</copy>
</target>
</project>

BIN
external/Z-Stick_Gen5_Drivers.zip vendored Normal file

Binary file not shown.

7
external/tellstick-core/AUTHORS.txt vendored Normal file
View file

@ -0,0 +1,7 @@
telldus-core has been developed by :
Micke Prag <micke.prag@telldus.se>
Fredrik Jacobsson <fredrik.jacobsson@telldus.se>
Stefan Persson <stefan.persson@telldus.se>
The package is maintained by Micke Prag <micke.prag@telldus.se>

502
external/tellstick-core/LICENSE.txt vendored Normal file
View file

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 2.1 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 Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

267
external/tellstick-core/Protocol.cpp vendored Normal file
View file

@ -0,0 +1,267 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/Protocol.h"
#include <list>
#include <sstream>
#include <string>
#include "client/telldus-core.h"
#include "service/ControllerMessage.h"
#include "service/ProtocolBrateck.h"
#include "service/ProtocolComen.h"
#include "service/ProtocolEverflourish.h"
#include "service/ProtocolFineoffset.h"
#include "service/ProtocolFuhaote.h"
#include "service/ProtocolGroup.h"
#include "service/ProtocolHasta.h"
#include "service/ProtocolIkea.h"
#include "service/ProtocolMandolyn.h"
#include "service/ProtocolNexa.h"
#include "service/ProtocolOregon.h"
#include "service/ProtocolRisingSun.h"
#include "service/ProtocolSartano.h"
#include "service/ProtocolScene.h"
#include "service/ProtocolSilvanChip.h"
#include "service/ProtocolUpm.h"
#include "service/ProtocolWaveman.h"
#include "service/ProtocolX10.h"
#include "service/ProtocolYidong.h"
#include "common/Strings.h"
class Protocol::PrivateData {
public:
ParameterMap parameterList;
std::wstring model;
};
Protocol::Protocol() {
d = new PrivateData;
}
Protocol::~Protocol(void) {
delete d;
}
std::wstring Protocol::model() const {
std::wstring strModel = d->model;
// Strip anything after : if it is found
size_t pos = strModel.find(L":");
if (pos != std::wstring::npos) {
strModel = strModel.substr(0, pos);
}
return strModel;
}
void Protocol::setModel(const std::wstring &model) {
d->model = model;
}
void Protocol::setParameters(const ParameterMap &parameterList) {
d->parameterList = parameterList;
}
std::wstring Protocol::getStringParameter(const std::wstring &name, const std::wstring &defaultValue) const {
ParameterMap::const_iterator it = d->parameterList.find(name);
if (it == d->parameterList.end()) {
return defaultValue;
}
return it->second;
}
int Protocol::getIntParameter(const std::wstring &name, int min, int max) const {
std::wstring value = getStringParameter(name, L"");
if (value == L"") {
return min;
}
std::wstringstream st;
st << value;
int intValue = 0;
st >> intValue;
if (intValue < min) {
return min;
}
if (intValue > max) {
return max;
}
return intValue;
}
bool Protocol::checkBit(int data, int bitno) {
return ((data >> bitno)&0x01);
}
Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname) {
if (TelldusCore::comparei(protocolname, L"arctech")) {
return new ProtocolNexa();
} else if (TelldusCore::comparei(protocolname, L"brateck")) {
return new ProtocolBrateck();
} else if (TelldusCore::comparei(protocolname, L"comen")) {
return new ProtocolComen();
} else if (TelldusCore::comparei(protocolname, L"everflourish")) {
return new ProtocolEverflourish();
} else if (TelldusCore::comparei(protocolname, L"fuhaote")) {
return new ProtocolFuhaote();
} else if (TelldusCore::comparei(protocolname, L"hasta")) {
return new ProtocolHasta();
} else if (TelldusCore::comparei(protocolname, L"ikea")) {
return new ProtocolIkea();
} else if (TelldusCore::comparei(protocolname, L"risingsun")) {
return new ProtocolRisingSun();
} else if (TelldusCore::comparei(protocolname, L"sartano")) {
return new ProtocolSartano();
} else if (TelldusCore::comparei(protocolname, L"silvanchip")) {
return new ProtocolSilvanChip();
} else if (TelldusCore::comparei(protocolname, L"upm")) {
return new ProtocolUpm();
} else if (TelldusCore::comparei(protocolname, L"waveman")) {
return new ProtocolWaveman();
} else if (TelldusCore::comparei(protocolname, L"x10")) {
return new ProtocolX10();
} else if (TelldusCore::comparei(protocolname, L"yidong")) {
return new ProtocolYidong();
} else if (TelldusCore::comparei(protocolname, L"group")) {
return new ProtocolGroup();
} else if (TelldusCore::comparei(protocolname, L"scene")) {
return new ProtocolScene();
}
return 0;
}
std::list<std::string> Protocol::getParametersForProtocol(const std::wstring &protocolName) {
std::list<std::string> parameters;
if (TelldusCore::comparei(protocolName, L"arctech")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"brateck")) {
parameters.push_back("house");
} else if (TelldusCore::comparei(protocolName, L"comen")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"everflourish")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"fuhaote")) {
parameters.push_back("code");
} else if (TelldusCore::comparei(protocolName, L"hasta")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"ikea")) {
parameters.push_back("system");
parameters.push_back("units");
// parameters.push_back("fade");
} else if (TelldusCore::comparei(protocolName, L"risingsun")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"sartano")) {
parameters.push_back("code");
} else if (TelldusCore::comparei(protocolName, L"silvanchip")) {
parameters.push_back("house");
} else if (TelldusCore::comparei(protocolName, L"upm")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"waveman")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"x10")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"yidong")) {
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"group")) {
parameters.push_back("devices");
} else if (TelldusCore::comparei(protocolName, L"scene")) {
parameters.push_back("devices");
}
return parameters;
}
std::list<std::string> Protocol::decodeData(const std::string &fullData) {
std::list<std::string> retval;
std::string decoded = "";
ControllerMessage dataMsg(fullData);
if ( TelldusCore::comparei(dataMsg.protocol(), L"arctech") ) {
decoded = ProtocolNexa::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
decoded = ProtocolWaveman::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
decoded = ProtocolSartano::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if (TelldusCore::comparei(dataMsg.protocol(), L"everflourish") ) {
decoded = ProtocolEverflourish::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if (TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) {
decoded = ProtocolFineoffset::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if (TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) {
decoded = ProtocolMandolyn::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if (TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) {
decoded = ProtocolOregon::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if (TelldusCore::comparei(dataMsg.protocol(), L"x10") ) {
decoded = ProtocolX10::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if (TelldusCore::comparei(dataMsg.protocol(), L"hasta") ) {
decoded = ProtocolHasta::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
}
return retval;
}

46
external/tellstick-core/Protocol.h vendored Normal file
View file

@ -0,0 +1,46 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOL_H_
#define TELLDUS_CORE_SERVICE_PROTOCOL_H_
#include <string>
#include <list>
#include <map>
#include "client/telldus-core.h"
typedef std::map<std::wstring, std::wstring> ParameterMap;
class Controller;
class Protocol {
public:
Protocol();
virtual ~Protocol(void);
static Protocol *getProtocolInstance(const std::wstring &protocolname);
static std::list<std::string> getParametersForProtocol(const std::wstring &protocolName);
static std::list<std::string> decodeData(const std::string &fullData);
virtual int methods() const = 0;
std::wstring model() const;
void setModel(const std::wstring &model);
void setParameters(const ParameterMap &parameterList);
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller) = 0;
protected:
virtual std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const;
virtual int getIntParameter(const std::wstring &name, int min, int max) const;
static bool checkBit(int data, int bit);
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOL_H_

View file

@ -0,0 +1,53 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolBrateck.h"
#include <string>
int ProtocolBrateck::methods() const {
return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP;
}
std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) {
const char S = '!';
const char L = 'V';
const char B1[] = {L, S, L, S, 0};
const char BX[] = {S, L, L, S, 0};
const char B0[] = {S, L, S, L, 0};
const char BUP[] = {L, S, L, S, S, L, S, L, S, L, S, L, S, L, S, L, S, 0};
const char BSTOP[] = {S, L, S, L, L, S, L, S, S, L, S, L, S, L, S, L, S, 0};
const char BDOWN[] = {S, L, S, L, S, L, S, L, S, L, S, L, L, S, L, S, S, 0};
std::string strReturn;
std::wstring strHouse = this->getStringParameter(L"house", L"");
if (strHouse == L"") {
return "";
}
for( size_t i = 0; i < strHouse.length(); ++i ) {
if (strHouse[i] == '1') {
strReturn.insert(0, B1);
} else if (strHouse[i] == '-') {
strReturn.insert(0, BX);
} else if (strHouse[i] == '0') {
strReturn.insert(0, B0);
}
}
strReturn.insert(0, "S");
if (method == TELLSTICK_UP) {
strReturn.append(BUP);
} else if (method == TELLSTICK_DOWN) {
strReturn.append(BDOWN);
} else if (method == TELLSTICK_STOP) {
strReturn.append(BSTOP);
} else {
return "";
}
strReturn.append("+");
return strReturn;
}

View file

@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_
#include <string>
#include "service/Protocol.h"
class ProtocolBrateck : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_

View file

@ -0,0 +1,23 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolComen.h"
#include <string>
int ProtocolComen::methods() const {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN);
}
int ProtocolComen::getIntParameter(const std::wstring &name, int min, int max) const {
if (name.compare(L"house") == 0) {
int intHouse = Protocol::getIntParameter(L"house", 1, 16777215);
// The last two bits must be hardcoded
intHouse <<= 2;
intHouse += 2;
return intHouse;
}
return Protocol::getIntParameter(name, min, max);
}

21
external/tellstick-core/ProtocolComen.h vendored Normal file
View file

@ -0,0 +1,21 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_
#include <string>
#include "service/ProtocolNexa.h"
class ProtocolComen : public ProtocolNexa {
public:
virtual int methods() const;
protected:
virtual int getIntParameter(const std::wstring &name, int min, int max) const;
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_

View file

@ -0,0 +1,133 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolEverflourish.h"
#include <stdio.h>
#include <sstream>
#include <string>
#include "service/ControllerMessage.h"
int ProtocolEverflourish::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN;
}
std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, Controller *) {
unsigned int deviceCode = this->getIntParameter(L"house", 0, 16383);
unsigned int intCode = this->getIntParameter(L"unit", 1, 4)-1;
unsigned char action;
if (method == TELLSTICK_TURNON) {
action = 15;
} else if (method == TELLSTICK_TURNOFF) {
action = 0;
} else if (method == TELLSTICK_LEARN) {
action = 10;
} else {
return "";
}
const char ssss = 85;
const char sssl = 84; // 0
const char slss = 69; // 1
const char bits[2] = {sssl, slss};
int i, check;
std::string strCode;
deviceCode = (deviceCode << 2) | intCode;
check = calculateChecksum(deviceCode);
char preamble[] = {'R', 5, 'T', 114, 60, 1, 1, 105, ssss, ssss, 0};
strCode.append(preamble);
for(i = 15; i >= 0; i--) {
strCode.append(1, bits[(deviceCode >> i)&0x01]);
}
for(i = 3; i >= 0; i--) {
strCode.append(1, bits[(check >> i)&0x01]);
}
for(i = 3; i >= 0; i--) {
strCode.append(1, bits[(action >> i)&0x01]);
}
strCode.append(1, ssss);
strCode.append(1, '+');
return strCode;
}
// The calculation used in this function is provided by Frank Stevenson
unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) {
unsigned int bits[16] = {
0xf, 0xa, 0x7, 0xe,
0xf, 0xd, 0x9, 0x1,
0x1, 0x2, 0x4, 0x8,
0x3, 0x6, 0xc, 0xb
};
unsigned int bit = 1;
unsigned int res = 0x5;
int i;
unsigned int lo, hi;
if ((x & 0x3) == 3) {
lo = x & 0x00ff;
hi = x & 0xff00;
lo += 4;
if (lo>0x100) {
lo = 0x12;
}
x = lo | hi;
}
for(i = 0; i < 16; i++) {
if (x & bit) {
res = res ^ bits[i];
}
bit = bit << 1;
}
return res;
}
std::string ProtocolEverflourish::decodeData(const ControllerMessage &dataMsg) {
uint64_t allData;
unsigned int house = 0;
unsigned int unit = 0;
unsigned int method = 0;
allData = dataMsg.getInt64Parameter("data");
house = allData & 0xFFFC00;
house >>= 10;
unit = allData & 0x300;
unit >>= 8;
unit++; // unit from 1 to 4
method = allData & 0xF;
if(house > 16383 || unit < 1 || unit > 4) {
// not everflourish
return "";
}
std::stringstream retString;
retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:";
if(method == 0) {
retString << "turnoff;";
} else if(method == 15) {
retString << "turnon;";
} else if(method == 10) {
retString << "learn;";
} else {
// not everflourish
return "";
}
return retString.str();
}

View file

@ -0,0 +1,24 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolEverflourish : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
private:
static unsigned int calculateChecksum(unsigned int x);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_

View file

@ -0,0 +1,52 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolFineoffset.h"
#include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <string>
#include "common/Strings.h"
std::string ProtocolFineoffset::decodeData(const ControllerMessage &dataMsg) {
std::string data = dataMsg.getParameter("data");
if (data.length() < 8) {
return "";
}
// Checksum currently not used
// uint8_t checksum = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2));
data = data.substr(0, data.length()-2);
uint8_t humidity = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2));
data = data.substr(0, data.length()-2);
uint16_t value = (uint16_t)TelldusCore::hexTo64l(data.substr(data.length()-3));
double temperature = (value & 0x7FF)/10.0;
value >>= 11;
if (value & 1) {
temperature = -temperature;
}
data = data.substr(0, data.length()-3);
uint16_t id = (uint16_t)TelldusCore::hexTo64l(data) & 0xFF;
std::stringstream retString;
retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:";
if (humidity <= 100) {
retString << "temperaturehumidity;humidity:" << static_cast<int>(humidity) << ";";
} else if (humidity == 0xFF) {
retString << "temperature;";
} else {
return "";
}
retString << "temp:" << std::fixed << std::setprecision(1) << temperature << ";";
return retString.str();
}

View file

@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolFineoffset : public Protocol {
public:
static std::string decodeData(const ControllerMessage &dataMsg);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_

View file

@ -0,0 +1,60 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolFuhaote.h"
#include <string>
int ProtocolFuhaote::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Controller *) {
const char S = 19;
const char L = 58;
const char B0[] = {S, L, L, S, 0};
const char B1[] = {L, S, L, S, 0};
const char OFF[] = {S, L, S, L, S, L, L, S, 0};
const char ON[] = {S, L, L, S, S, L, S, L, 0};
std::string strReturn = "S";
std::wstring strCode = this->getStringParameter(L"code", L"");
if (strCode == L"") {
return "";
}
// House code
for(size_t i = 0; i < 5; ++i) {
if (strCode[i] == '0') {
strReturn.append(B0);
} else if (strCode[i] == '1') {
strReturn.append(B1);
}
}
// Unit code
for(size_t i = 5; i < 10; ++i) {
if (strCode[i] == '0') {
strReturn.append(B0);
} else if (strCode[i] == '1') {
strReturn.append(1, S);
strReturn.append(1, L);
strReturn.append(1, S);
strReturn.append(1, L);
}
}
if (method == TELLSTICK_TURNON) {
strReturn.append(ON);
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append(OFF);
} else {
return "";
}
strReturn.append(1, S);
strReturn.append("+");
return strReturn;
}

View file

@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_
#include <string>
#include "service/Protocol.h"
class ProtocolFuhaote : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_

View file

@ -0,0 +1,16 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolGroup.h"
#include <string>
int ProtocolGroup::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP;
}
std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) {
return "";
}

22
external/tellstick-core/ProtocolGroup.h vendored Normal file
View file

@ -0,0 +1,22 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_
#include <string>
#include "service/Protocol.h"
class ProtocolGroup : public Protocol {
public:
virtual int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_

View file

@ -0,0 +1,201 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolHasta.h"
#include <stdio.h>
#include <sstream>
#include <string>
#include "common/Strings.h"
int ProtocolHasta::methods() const {
return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN;
}
std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Controller *) {
if (TelldusCore::comparei(model(), L"selflearningv2")) {
return getStringForMethodv2(method);
}
return getStringForMethodv1(method);
}
std::string ProtocolHasta::getStringForMethodv1(int method) {
int house = this->getIntParameter(L"house", 1, 65536);
int unit = this->getIntParameter(L"unit", 1, 15);
std::string strReturn;
strReturn.append(1, 164);
strReturn.append(1, 1);
strReturn.append(1, 164);
strReturn.append(1, 1);
strReturn.append(1, 164);
strReturn.append(1, 164);
strReturn.append(convertByte( (house & 0xFF) ));
strReturn.append(convertByte( (house>>8) & 0xFF ));
int byte = unit&0x0F;
if (method == TELLSTICK_UP) {
byte |= 0x00;
} else if (method == TELLSTICK_DOWN) {
byte |= 0x10;
} else if (method == TELLSTICK_STOP) {
byte |= 0x50;
} else if (method == TELLSTICK_LEARN) {
byte |= 0x40;
} else {
return "";
}
strReturn.append(convertByte(byte));
strReturn.append(convertByte(0x0));
strReturn.append(convertByte(0x0));
// Remove the last pulse
strReturn.erase(strReturn.end()-1, strReturn.end());
return strReturn;
}
std::string ProtocolHasta::convertByte(unsigned char byte) {
std::string retval;
for(int i = 0; i < 8; ++i) {
if (byte & 1) {
retval.append(1, 33);
retval.append(1, 17);
} else {
retval.append(1, 17);
retval.append(1, 33);
}
byte >>= 1;
}
return retval;
}
std::string ProtocolHasta::getStringForMethodv2(int method) {
int house = this->getIntParameter(L"house", 1, 65536);
int unit = this->getIntParameter(L"unit", 1, 15);
int sum = 0;
std::string strReturn;
strReturn.append(1, 245);
strReturn.append(1, 1);
strReturn.append(1, 245);
strReturn.append(1, 245);
strReturn.append(1, 63);
strReturn.append(1, 1);
strReturn.append(1, 63);
strReturn.append(1, 1);
strReturn.append(1, 35);
strReturn.append(1, 35);
strReturn.append(convertBytev2( (house>>8) & 0xFF ));
sum = ((house>>8)&0xFF);
strReturn.append(convertBytev2( (house & 0xFF) ));
sum += (house & 0xFF);
int byte = unit&0x0F;
if (method == TELLSTICK_UP) {
byte |= 0xC0;
} else if (method == TELLSTICK_DOWN) {
byte |= 0x10;
} else if (method == TELLSTICK_STOP) {
byte |= 0x50;
} else if (method == TELLSTICK_LEARN) {
byte |= 0x40;
} else {
return "";
}
strReturn.append(convertBytev2(byte));
sum += byte;
strReturn.append(convertBytev2(0x01));
sum += 0x01;
int checksum = ((static_cast<int>(sum/256)+1)*256+1) - sum;
strReturn.append(convertBytev2(checksum));
strReturn.append(1, 63);
strReturn.append(1, 35);
return strReturn;
}
std::string ProtocolHasta::convertBytev2(unsigned char byte) {
std::string retval;
for(int i = 0; i < 8; ++i) {
if (byte & 1) {
retval.append(1, 63);
retval.append(1, 35);
} else {
retval.append(1, 35);
retval.append(1, 63);
}
byte >>= 1;
}
return retval;
}
std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) {
uint64_t allData = dataMsg.getInt64Parameter("data");
unsigned int house = 0;
unsigned int unit = 0;
unsigned int method = 0;
std::string model;
std::string methodstring;
allData >>= 8;
unit = allData & 0xF;
allData >>= 4;
method = allData & 0xF;
allData >>= 4;
if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) {
// version1
house = allData & 0xFFFF;
house = ((house << 8) | (house >> 8)) & 0xFFFF;
model = "selflearning";
if(method == 0) {
methodstring = "up";
} else if(method == 1) {
methodstring = "down";
} else if(method == 5) {
methodstring = "stop";
} else {
return "";
}
} else {
// version2
house = allData & 0xFFFF;
model = "selflearningv2";
if(method == 12) {
methodstring = "up";
} else if(method == 1 || method == 8) { // is method 8 correct?
methodstring = "down";
} else if(method == 5) {
methodstring = "stop";
} else {
return "";
}
}
if(house < 1 || house > 65535 || unit < 1 || unit > 16) {
// not hasta
return "";
}
std::stringstream retString;
retString << "class:command;protocol:hasta;model:" << model << ";house:" << house << ";unit:" << unit << ";method:" << methodstring << ";";
return retString.str();
}

27
external/tellstick-core/ProtocolHasta.h vendored Normal file
View file

@ -0,0 +1,27 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_
#include <string>
#include "service/ControllerMessage.h"
#include "service/Protocol.h"
class ProtocolHasta : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
static std::string convertByte(unsigned char byte);
static std::string convertBytev2(unsigned char byte);
std::string getStringForMethodv1(int method);
std::string getStringForMethodv2(int method);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_

151
external/tellstick-core/ProtocolIkea.cpp vendored Normal file
View file

@ -0,0 +1,151 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolIkea.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "common/Strings.h"
#ifdef _WINDOWS
#define strtok_r(s, d, p) strtok_s(s, d, p)
#endif
int ProtocolIkea::methods() const {
if (TelldusCore::comparei(model(), L"selflearning-switch")) {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM;
}
std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) {
const char B1[] = {84, 84, 0};
const char B0[] = {170, 0};
int intSystem = this->getIntParameter(L"system", 1, 16)-1;
int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true");
std::wstring wstrUnits = this->getStringParameter(L"units", L"");
if (method == TELLSTICK_TURNON) {
level = 255;
} else if (method == TELLSTICK_TURNOFF) {
level = 0;
} else if (method == TELLSTICK_DIM) {
} else {
return "";
}
if (wstrUnits == L"") {
return "";
}
std::string strUnits(TelldusCore::wideToString(wstrUnits));
int intUnits = 0; // Start without any units
char *tempUnits = new char[strUnits.size()+1];
#ifdef _WINDOWS
strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str());
#else
snprintf(tempUnits, strUnits.size()+1, "%s", strUnits.c_str());
#endif
char *saveptr;
char *strToken = strtok_r(tempUnits, ",", &saveptr);
do {
int intUnit = atoi(strToken);
if (intUnit == 10) {
intUnit = 0;
}
intUnits = intUnits | ( 1<<(9-intUnit) );
} while ( (strToken = strtok_r(NULL, ",", &saveptr)) != NULL );
delete[] tempUnits;
std::string strReturn;
strReturn.append(1, 'S');
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 170);
std::string strChannels = "";
int intCode = (intSystem << 10) | intUnits;
int checksum1 = 0;
int checksum2 = 0;
for (int i = 13; i >= 0; --i) {
if ((intCode >> i) & 1) {
strChannels.append(B1);
if (i % 2 == 0)
checksum2++;
else
checksum1++;
} else {
strChannels.append(B0);
}
}
strReturn.append(strChannels); // System + Units
strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum
strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum
int intLevel = 0;
if (level <= 12) {
intLevel = 10; // Level 10 is actually off
} else if (level <= 37) {
intLevel = 1;
} else if (level <= 62) {
intLevel = 2;
} else if (level <= 87) {
intLevel = 3;
} else if (level <= 112) {
intLevel = 4;
} else if (level <= 137) {
intLevel = 5;
} else if (level <= 162) {
intLevel = 6;
} else if (level <= 187) {
intLevel = 7;
} else if (level <= 212) {
intLevel = 8;
} else if (level <= 237) {
intLevel = 9;
} else {
intLevel = 0; // Level 0 is actually full on
}
int intFade = 0;
if (intFadeStyle == 1) {
intFade = 11 << 4; // Smooth
} else {
intFade = 1 << 4; // Instant
}
intCode = intLevel | intFade; // Concat level and fade
checksum1 = 0;
checksum2 = 0;
for (int i = 0; i < 6; ++i) {
if ((intCode >> i) & 1) {
strReturn.append(B1);
if (i % 2 == 0)
checksum1++;
else
checksum2++;
} else {
strReturn.append(B0);
}
}
strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum
strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum
strReturn.append("+");
return strReturn;
}

19
external/tellstick-core/ProtocolIkea.h vendored Normal file
View file

@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_
#include <string>
#include "service/Protocol.h"
class ProtocolIkea : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_

View file

@ -0,0 +1,46 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolMandolyn.h"
#include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <string>
#include "common/Strings.h"
std::string ProtocolMandolyn::decodeData(const ControllerMessage &dataMsg) {
std::string data = dataMsg.getParameter("data");
uint32_t value = (uint32_t)TelldusCore::hexTo64l(data);
// parity not used
// bool parity = value & 0x1;
value >>= 1;
double temp = static_cast<double>(value & 0x7FFF) - static_cast<double>(6400);
temp = temp/128.0;
value >>= 15;
uint8_t humidity = (value & 0x7F);
value >>= 7;
// battOk not used
// bool battOk = value & 0x1;
value >>= 3;
uint8_t channel = (value & 0x3)+1;
value >>= 2;
uint8_t house = value & 0xF;
std::stringstream retString;
retString << "class:sensor;protocol:mandolyn;id:"
<< house*10+channel
<< ";model:temperaturehumidity;"
<< "temp:" << std::fixed << std::setprecision(1) << temp
<< ";humidity:" << static_cast<int>(humidity) << ";";
return retString.str();
}

View file

@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolMandolyn : public Protocol {
public:
static std::string decodeData(const ControllerMessage &dataMsg);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_

279
external/tellstick-core/ProtocolNexa.cpp vendored Normal file
View file

@ -0,0 +1,279 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolNexa.h"
#include <stdio.h>
#include <sstream>
#include <string>
#include "service/TellStick.h"
#include "common/Strings.h"
int ProtocolNexa::lastArctecCodeSwitchWasTurnOff = 0; // TODO(stefan): always removing first turnon now, make more flexible (waveman too)
int ProtocolNexa::methods() const {
if (TelldusCore::comparei(model(), L"codeswitch")) {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF);
} else if (TelldusCore::comparei(model(), L"selflearning-switch")) {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN);
} else if (TelldusCore::comparei(model(), L"selflearning-dimmer")) {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN);
} else if (TelldusCore::comparei(model(), L"bell")) {
return TELLSTICK_BELL;
}
return 0;
}
std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *controller) {
if (TelldusCore::comparei(model(), L"codeswitch")) {
return getStringCodeSwitch(method);
} else if (TelldusCore::comparei(model(), L"bell")) {
return getStringBell();
}
if ((method == TELLSTICK_TURNON) && TelldusCore::comparei(model(), L"selflearning-dimmer")) {
// Workaround for not letting a dimmer do into "dimming mode"
return getStringSelflearning(TELLSTICK_DIM, 255);
}
if (method == TELLSTICK_LEARN) {
std::string str = getStringSelflearning(TELLSTICK_TURNON, data);
// Check to see if we are an old TellStick (fw <= 2, batch <= 8)
TellStick *ts = reinterpret_cast<TellStick *>(controller);
if (!ts) {
return str;
}
if (ts->pid() == 0x0c30 && ts->firmwareVersion() <= 2) {
// Workaround for the bug in early firmwares
// The TellStick have a fixed pause (max) between two packets.
// It is only correct between the first and second packet.
// It seems faster to send two packes at a time and some
// receivers seems picky about this when learning.
// We also return the last packet so Device::doAction() doesn't
// report TELLSTICK_ERROR_METHOD_NOT_SUPPORTED
str.insert(0, 1, 2); // Repeat two times
str.insert(0, 1, 'R');
for (int i = 0; i < 5; ++i) {
controller->send(str);
}
}
return str;
}
return getStringSelflearning(method, data);
}
std::string ProtocolNexa::getStringCodeSwitch(int method) {
std::string strReturn = "S";
std::wstring house = getStringParameter(L"house", L"A");
int intHouse = house[0] - L'A';
strReturn.append(getCodeSwitchTuple(intHouse));
strReturn.append(getCodeSwitchTuple(getIntParameter(L"unit", 1, 16)-1));
if (method == TELLSTICK_TURNON) {
strReturn.append("$k$k$kk$$kk$$kk$$k+");
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append(this->getOffCode());
} else {
return "";
}
return strReturn;
}
std::string ProtocolNexa::getStringBell() {
std::string strReturn = "S";
std::wstring house = getStringParameter(L"house", L"A");
int intHouse = house[0] - L'A';
strReturn.append(getCodeSwitchTuple(intHouse));
strReturn.append("$kk$$kk$$kk$$k$k"); // Unit 7
strReturn.append("$kk$$kk$$kk$$kk$$k+"); // Bell
return strReturn;
}
std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) {
int intHouse = getIntParameter(L"house", 1, 67108863);
int intCode = getIntParameter(L"unit", 1, 16)-1;
return getStringSelflearningForCode(intHouse, intCode, method, level);
}
std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode, int method, unsigned char level) {
const unsigned char START[] = {'T', 127, 255, 24, 1, 0};
// const char START[] = {'T',130,255,26,24,0};
std::string strMessage(reinterpret_cast<const char*>(START));
strMessage.append(1, (method == TELLSTICK_DIM ? 147 : 132)); // Number of pulses
std::string m;
for (int i = 25; i >= 0; --i) {
m.append( intHouse & 1 << i ? "10" : "01" );
}
m.append("01"); // Group
// On/off
if (method == TELLSTICK_DIM) {
m.append("00");
} else if (method == TELLSTICK_TURNOFF) {
m.append("01");
} else if (method == TELLSTICK_TURNON) {
m.append("10");
} else {
return "";
}
for (int i = 3; i >= 0; --i) {
m.append( intCode & 1 << i ? "10" : "01" );
}
if (method == TELLSTICK_DIM) {
unsigned char newLevel = level/16;
for (int i = 3; i >= 0; --i) {
m.append(newLevel & 1 << i ? "10" : "01");
}
}
// The number of data is odd.
// Add this to make it even, otherwise the following loop will not work
m.append("0");
unsigned char code = 9; // b1001, startcode
for (unsigned int i = 0; i < m.length(); ++i) {
code <<= 4;
if (m[i] == '1') {
code |= 8; // b1000
} else {
code |= 10; // b1010
// code |= 11; //b1011
}
if (i % 2 == 0) {
strMessage.append(1, code);
code = 0;
}
}
strMessage.append("+");
// for( int i = 0; i < strMessage.length(); ++i ) {
// printf("%i,", (unsigned char)strMessage[i]);
// }
// printf("\n");
return strMessage;
}
std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) {
uint64_t allData = dataMsg.getInt64Parameter("data");
if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) {
// selflearning
return decodeDataSelfLearning(allData);
} else {
// codeswitch
return decodeDataCodeSwitch(allData);
}
}
std::string ProtocolNexa::decodeDataSelfLearning(uint64_t allData) {
unsigned int house = 0;
unsigned int unit = 0;
unsigned int group = 0;
unsigned int method = 0;
house = allData & 0xFFFFFFC0;
house >>= 6;
group = allData & 0x20;
group >>= 5;
method = allData & 0x10;
method >>= 4;
unit = allData & 0xF;
unit++;
if(house < 1 || house > 67108863 || unit < 1 || unit > 16) {
// not arctech selflearning
return "";
}
std::stringstream retString;
retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:";
if(method == 1) {
retString << "turnon;";
} else if(method == 0) {
retString << "turnoff;";
} else {
// not arctech selflearning
return "";
}
return retString.str();
}
std::string ProtocolNexa::decodeDataCodeSwitch(uint64_t allData) {
unsigned int house = 0;
unsigned int unit = 0;
unsigned int method = 0;
method = allData & 0xF00;
method >>= 8;
unit = allData & 0xF0;
unit >>= 4;
unit++;
house = allData & 0xF;
if(house > 16 || unit < 1 || unit > 16) {
// not arctech codeswitch
return "";
}
house = house + 'A'; // house from A to P
if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) {
lastArctecCodeSwitchWasTurnOff = 0;
return ""; // probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose
// one turnon/bell, but it's better than the alternative...
}
if(method == 6) {
lastArctecCodeSwitchWasTurnOff = 1;
}
std::stringstream retString;
retString << "class:command;protocol:arctech;model:codeswitch;house:" << static_cast<char>(house);
if(method == 6) {
retString << ";unit:" << unit << ";method:turnoff;";
} else if(method == 14) {
retString << ";unit:" << unit << ";method:turnon;";
} else if(method == 15) {
retString << ";method:bell;";
} else {
// not arctech codeswitch
return "";
}
return retString.str();
}
std::string ProtocolNexa::getCodeSwitchTuple(int intCode) {
std::string strReturn = "";
for( int i = 0; i < 4; ++i ) {
if (intCode & 1) { // Convert 1
strReturn.append("$kk$");
} else { // Convert 0
strReturn.append("$k$k");
}
intCode >>= 1;
}
return strReturn;
}
std::string ProtocolNexa::getOffCode() const {
return "$k$k$kk$$kk$$k$k$k+";
}

39
external/tellstick-core/ProtocolNexa.h vendored Normal file
View file

@ -0,0 +1,39 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_
#ifdef _MSC_VER
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#include <string>
#include "service/ControllerMessage.h"
#include "service/Device.h"
class ProtocolNexa : public Protocol {
public:
virtual int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
std::string getStringSelflearning(int method, unsigned char data);
std::string getStringCodeSwitch(int method);
std::string getStringBell();
virtual std::string getOffCode() const;
static std::string getCodeSwitchTuple(int code);
static std::string getStringSelflearningForCode(int house, int unit, int method, unsigned char data);
private:
static int lastArctecCodeSwitchWasTurnOff;
static std::string decodeDataCodeSwitch(uint64_t allData);
static std::string decodeDataSelfLearning(uint64_t allData);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_

View file

@ -0,0 +1,347 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolOregon.h"
#include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <string>
#include "common/Strings.h"
std::string ProtocolOregon::decodeData(const ControllerMessage &dataMsg) {
std::string data = dataMsg.getParameter("data");
std::wstring model = dataMsg.model();
if (model.compare(L"0xEA4C") == 0) {
return decodeEA4C(data);
} else if (model.compare(L"0x1A2D") == 0) {
return decode1A2D(data);
} else if (model.compare(L"0xF824") == 0) {
return decodeF824(data);
} else if (model.compare(L"0x1984") == 0 || model.compare(L"0x1994") == 0) {
return decode1984(data, model);
} else if (model.compare(L"0x2914") == 0) {
return decode2914(data);
} else if (model.compare(L"0xC844") == 0 || model.compare(L"0xEC40") == 0) {
// C844 - pool thermometer
return decodeC844(data, model);
}
return "";
}
std::string ProtocolOregon::decodeEA4C(const std::string &data) {
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t checksum = 0xE + 0xA + 0x4 + 0xC;
checksum -= (value & 0xF) * 0x10;
checksum -= 0xA;
value >>= 8;
uint8_t checksumw = (value >> 4) & 0xF;
bool neg = value & (1 << 3);
int hundred = value & 3;
checksum += (value & 0xF);
value >>= 8;
uint8_t temp2 = value & 0xF;
uint8_t temp1 = (value >> 4) & 0xF;
checksum += temp2 + temp1;
value >>= 8;
uint8_t temp3 = (value >> 4) & 0xF;
checksum += (value & 0xF) + temp3;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t address = value & 0xFF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
// channel not used
// uint8_t channel = (value >> 4) & 0x7;
if (checksum != checksumw) {
return "";
}
double temperature = ((hundred * 1000) + (temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (neg) {
temperature = -temperature;
}
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:EA4C;id:" << static_cast<int>(address)
<< ";temp:" << std::fixed << std::setprecision(1) << temperature << ";";
return retString.str();
}
std::string ProtocolOregon::decode1984(const std::string &data, const std::wstring &model) {
// wind
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t crcCheck = value & 0xF; // PROBABLY crc
value >>= 4;
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t avg1 = value & 0xF;
value >>= 4;
uint8_t avg2 = value & 0xF;
value >>= 4;
uint8_t avg3 = value & 0xF;
value >>= 4;
uint8_t gust1 = value & 0xF;
value >>= 4;
uint8_t gust2 = value & 0xF;
value >>= 4;
uint8_t gust3 = value & 0xF;
value >>= 4;
uint8_t unknown1 = value & 0xF;
value >>= 4;
uint8_t unknown2 = value & 0xF;
value >>= 4;
uint8_t direction = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; // PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += unknown1 + unknown2 + avg1 + avg2 + avg3 + gust1 + gust2 + gust3 + direction + battery + channel;
if (model.compare(L"0x1984") == 0) {
checksum += 0x1 + 0x9 + 0x8 + 0x4;
} else {
checksum += 0x1 + 0x9 + 0x9 + 0x4;
}
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) {
// checksum error
return "";
}
double avg = ((avg1 * 100) + (avg2 * 10) + avg3)/10.0;
double gust = ((gust1 * 100) + (gust2 * 10) + gust3)/10.0;
float directiondegree = 22.5 * direction;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:1984;id:" << static_cast<int>(rollingcode)
<< ";winddirection:" << directiondegree
<< ";windaverage:" << std::fixed << std::setprecision(1) << avg
<< ";windgust:" << std::fixed << std::setprecision(1) << gust << ";";
return retString.str();
}
std::string ProtocolOregon::decode1A2D(const std::string &data) {
uint64_t value = TelldusCore::hexTo64l(data);
// checksum2 not used yet
// uint8_t checksum2 = value & 0xFF;
value >>= 8;
uint8_t checksum1 = value & 0xFF;
value >>= 8;
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t hum1 = value & 0xF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t neg = value & (1 << 3);
uint8_t hum2 = (value >> 4) & 0xF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t temp2 = value & 0xF;
uint8_t temp1 = (value >> 4) & 0xF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t temp3 = (value >> 4) & 0xF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t address = value & 0xFF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
// channel not used
// uint8_t channel = (value >> 4) & 0x7;
checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA;
// TODO(micke): Find out how checksum2 works
if (checksum != checksum1) {
return "";
}
double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (neg) {
temperature = -temperature;
}
int humidity = (hum1 * 10.0) + hum2;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:1A2D;id:" << static_cast<int>(address)
<< ";temp:" << std::fixed << std::setprecision(1) << temperature
<< ";humidity:" << humidity << ";";
return retString.str();
}
std::string ProtocolOregon::decode2914(const std::string &data) {
// rain
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t totRain1 = value & 0xF;
value >>= 4;
uint8_t totRain2 = value & 0xF;
value >>= 4;
uint8_t totRain3 = value & 0xF;
value >>= 4;
uint8_t totRain4 = value & 0xF;
value >>= 4;
uint8_t totRain5 = value & 0xF;
value >>= 4;
uint8_t totRain6 = value & 0xF;
value >>= 4;
uint8_t rainRate1 = value & 0xF;
value >>= 4;
uint8_t rainRate2 = value & 0xF;
value >>= 4;
uint8_t rainRate3 = value & 0xF;
value >>= 4;
uint8_t rainRate4 = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; // PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += totRain1 + totRain2 + totRain3 + totRain4 + totRain5 + totRain6 + rainRate1 + rainRate2 + rainRate3 + rainRate4 + battery + channel + 0x2 + 0x9 + 0x1 + 0x4;
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) {
// checksum error
return "";
}
double totRain = ((totRain1 * 100000) + (totRain2 * 10000) + (totRain3 * 1000) + (totRain4 * 100) + (totRain5 * 10) + totRain6)/1000.0*25.4;
double rainRate = ((rainRate1 * 1000) + (rainRate2 * 100) + (rainRate3 * 10) + rainRate4)/100.0*25.4;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:2914;id:" << static_cast<int>(rollingcode)
<< ";raintotal:" << std::fixed << std::setprecision(1) << totRain
<< ";rainrate:" << std::fixed << std::setprecision(1) << rainRate << ";";
return retString.str();
}
std::string ProtocolOregon::decodeF824(const std::string &data) {
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t crcCheck = value & 0xF; // PROBABLY crc
value >>= 4;
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t unknown = value & 0xF;
value >>= 4;
uint8_t hum1 = value & 0xF;
value >>= 4;
uint8_t hum2 = value & 0xF;
value >>= 4;
uint8_t neg = value & 0xF;
value >>= 4;
uint8_t temp1 = value & 0xF;
value >>= 4;
uint8_t temp2 = value & 0xF;
value >>= 4;
uint8_t temp3 = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; // PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += unknown + hum1 + hum2 + neg + temp1 + temp2 + temp3 + battery + channel + 0xF + 0x8 + 0x2 + 0x4;
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) {
// checksum error
return "";
}
double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (neg) {
temperature = -temperature;
}
int humidity = (hum1 * 10.0) + hum2;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:F824;id:" << static_cast<int>(rollingcode)
<< ";temp:" << std::fixed << std::setprecision(1) << temperature
<< ";humidity:" << humidity << ";";
return retString.str();
}
std::string ProtocolOregon::decodeC844(const std::string &data, const std::wstring &model) {
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t neg = value & 0xF;
value >>= 4;
uint8_t temp1 = value & 0xF;
value >>= 4;
uint8_t temp2 = value & 0xF;
value >>= 4;
uint8_t temp3 = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; // PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += neg + temp1 + temp2 + temp3 + battery + channel;
if (model.compare(L"0xC844") == 0) {
checksum += 0xC + 0x8 + 0x4 + 0x4;
} else {
checksum += 0xE + 0xC + 0x4 + 0x0;
}
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) {
// checksum error
return "";
}
double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (neg) {
temperature = -temperature;
}
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:C844;id:" << static_cast<int>(rollingcode)
<< ";temp:" << std::fixed << std::setprecision(1) << temperature << ";";
return retString.str();
}

View file

@ -0,0 +1,27 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolOregon : public Protocol {
public:
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
static std::string decodeEA4C(const std::string &data);
static std::string decode1A2D(const std::string &data);
static std::string decodeF824(const std::string &data);
static std::string decode1984(const std::string &data, const std::wstring &model);
static std::string decode2914(const std::string &data);
static std::string decodeC844(const std::string &data, const std::wstring &model);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_

View file

@ -0,0 +1,115 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolRisingSun.h"
#include <string>
#include "common/Strings.h"
int ProtocolRisingSun::methods() const {
if (TelldusCore::comparei(model(), L"selflearning")) {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN);
}
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data, Controller *controller) {
if (TelldusCore::comparei(model(), L"selflearning")) {
return getStringSelflearning(method);
}
return getStringCodeSwitch(method);
}
std::string ProtocolRisingSun::getStringSelflearning(int method) {
int intHouse = this->getIntParameter(L"house", 1, 33554432)-1;
int intCode = this->getIntParameter(L"code", 1, 16)-1;
const char code_on[][7] = {
"110110", "001110", "100110", "010110",
"111001", "000101", "101001", "011001",
"110000", "001000", "100000", "010000",
"111100", "000010", "101100", "011100"
};
const char code_off[][7] = {
"111110", "000001", "101110", "011110",
"110101", "001101", "100101", "010101",
"111000", "000100", "101000", "011000",
"110010", "001010", "100010", "010010"
};
const char l = 120;
const char s = 51;
std::string strCode = "10";
int code = intCode;
code = (code < 0 ? 0 : code);
code = (code > 15 ? 15 : code);
if (method == TELLSTICK_TURNON) {
strCode.append(code_on[code]);
} else if (method == TELLSTICK_TURNOFF) {
strCode.append(code_off[code]);
} else if (method == TELLSTICK_LEARN) {
strCode.append(code_on[code]);
} else {
return "";
}
int house = intHouse;
for(int i = 0; i < 25; ++i) {
if (house & 1) {
strCode.append(1, '1');
} else {
strCode.append(1, '0');
}
house >>= 1;
}
std::string strReturn;
for(unsigned int i = 0; i < strCode.length(); ++i) {
if (strCode[i] == '1') {
strReturn.append(1, l);
strReturn.append(1, s);
} else {
strReturn.append(1, s);
strReturn.append(1, l);
}
}
std::string prefix = "P";
prefix.append(1, 5);
if (method == TELLSTICK_LEARN) {
prefix.append("R");
prefix.append( 1, 50 );
}
prefix.append("S");
strReturn.insert(0, prefix);
strReturn.append(1, '+');
return strReturn;
}
std::string ProtocolRisingSun::getStringCodeSwitch(int method) {
std::string strReturn = "S.e";
strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"house", 1, 4)-1));
strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"unit", 1, 4)-1));
if (method == TELLSTICK_TURNON) {
strReturn.append("e..ee..ee..ee..e+");
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append("e..ee..ee..e.e.e+");
} else {
return "";
}
return strReturn;
}
std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) {
std::string strReturn = "";
for(int i = 0; i < 4; ++i) {
if (i == intToConvert) {
strReturn.append( ".e.e" );
} else {
strReturn.append( "e..e" );
}
}
return strReturn;
}

View file

@ -0,0 +1,24 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_
#include <string>
#include "service/Protocol.h"
class ProtocolRisingSun : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
protected:
std::string getStringSelflearning(int method);
std::string getStringCodeSwitch(int method);
static std::string getCodeSwitchTuple(int code);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_

View file

@ -0,0 +1,108 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolSartano.h"
#ifdef _MSC_VER
typedef unsigned __int16 uint16_t;
#else
#include <stdint.h>
#endif
#include <stdio.h>
#include <sstream>
#include <string>
int ProtocolSartano::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Controller *) {
std::wstring strCode = this->getStringParameter(L"code", L"");
return getStringForCode(strCode, method);
}
std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int method) {
std::string strReturn("S");
for (size_t i = 0; i < strCode.length(); ++i) {
if (strCode[i] == L'1') {
strReturn.append("$k$k");
} else {
strReturn.append("$kk$");
}
}
if (method == TELLSTICK_TURNON) {
strReturn.append("$k$k$kk$$k+");
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append("$kk$$k$k$k+");
} else {
return "";
}
return strReturn;
}
std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) {
uint64_t allDataIn;
uint16_t allData = 0;
unsigned int code = 0;
unsigned int method1 = 0;
unsigned int method2 = 0;
unsigned int method = 0;
allDataIn = dataMsg.getInt64Parameter("data");
uint16_t mask = (1<<11);
for(int i = 0; i < 12; ++i) {
allData >>= 1;
if((allDataIn & mask) == 0) {
allData |= (1<<11);
}
mask >>= 1;
}
code = allData & 0xFFC;
code >>= 2;
method1 = allData & 0x2;
method1 >>= 1;
method2 = allData & 0x1;
if(method1 == 0 && method2 == 1) {
method = 0; // off
} else if(method1 == 1 && method2 == 0) {
method = 1; // on
} else {
return "";
}
if(code > 1023) {
// not sartano
return "";
}
std::stringstream retString;
retString << "class:command;protocol:sartano;model:codeswitch;code:";
mask = (1<<9);
for(int i = 0; i < 10; i++) {
if((code & mask) != 0) {
retString << 1;
} else {
retString << 0;
}
mask >>= 1;
}
retString << ";method:";
if(method == 0) {
retString << "turnoff;";
} else {
retString << "turnon;";
}
return retString.str();
}

View file

@ -0,0 +1,24 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolSartano : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
std::string getStringForCode(const std::wstring &code, int method);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_

View file

@ -0,0 +1,16 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolScene.h"
#include <string>
int ProtocolScene::methods() const {
return TELLSTICK_EXECUTE;
}
std::string ProtocolScene::getStringForMethod(int method, unsigned char data, Controller *) {
return "";
}

22
external/tellstick-core/ProtocolScene.h vendored Normal file
View file

@ -0,0 +1,22 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_
#include <string>
#include "service/Protocol.h"
class ProtocolScene : public Protocol {
public:
virtual int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_

View file

@ -0,0 +1,146 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolSilvanChip.h"
#include <string>
#include "common/Strings.h"
int ProtocolSilvanChip::methods() const {
if (TelldusCore::comparei(model(), L"kp100")) {
return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN;
} else if (TelldusCore::comparei(model(), L"ecosavers")) {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN;
} else if (TelldusCore::comparei(model(), L"displaymatic")) {
return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP;
}
return 0;
}
std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) {
if (TelldusCore::comparei(model(), L"kp100")) {
std::string preamble;
preamble.append(1, 100);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 100);
const std::string one = "\xFF\x1\x2E\x2E";
const std::string zero = "\x2E\xFF\x1\x2E";
int button = 0;
if (method == TELLSTICK_UP) {
button = 2;
} else if (method == TELLSTICK_DOWN) {
button = 8;
} else if (method == TELLSTICK_STOP) {
button = 4;
} else if (method == TELLSTICK_LEARN) {
button = 1;
} else {
return "";
}
return this->getString(preamble, one, zero, button);
} else if (TelldusCore::comparei(model(), L"displaymatic")) {
std::string preamble;
preamble.append(1, 0x25);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 0x25);
const std::string one = "\x69\25";
const std::string zero = "\x25\x69";
int button = 0;
if (method == TELLSTICK_UP) {
button = 1;
} else if (method == TELLSTICK_DOWN) {
button = 4;
} else if (method == TELLSTICK_STOP) {
button = 2;
}
return this->getString(preamble, one, zero, button);
} else if (TelldusCore::comparei(model(), L"ecosavers")) {
std::string preamble;
preamble.append(1, 0x25);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 0x25);
const std::string one = "\x69\25";
const std::string zero = "\x25\x69";
int intUnit = this->getIntParameter(L"unit", 1, 4);
int button = 0;
if (intUnit == 1) {
button = 7;
} else if (intUnit == 2) {
button = 3;
} else if (intUnit == 3) {
button = 5;
} else if (intUnit == 4) {
button = 6;
}
if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) {
button |= 8;
}
return this->getString(preamble, one, zero, button);
}
return "";
}
std::string ProtocolSilvanChip::getString(const std::string &preamble, const std::string &one, const std::string &zero, int button) {
int intHouse = this->getIntParameter(L"house", 1, 1048575);
std::string strReturn = preamble;
for( int i = 19; i >= 0; --i ) {
if (intHouse & (1 << i)) {
strReturn.append(one);
} else {
strReturn.append(zero);
}
}
for( int i = 3; i >= 0; --i) {
if (button & (1 << i)) {
strReturn.append(one);
} else {
strReturn.append(zero);
}
}
strReturn.append(zero);
return strReturn;
}

View file

@ -0,0 +1,22 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_
#include <string>
#include "service/Protocol.h"
class ProtocolSilvanChip : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
protected:
virtual std::string getString(const std::string &preamble, const std::string &one, const std::string &zero, int button);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_

78
external/tellstick-core/ProtocolUpm.cpp vendored Normal file
View file

@ -0,0 +1,78 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolUpm.h"
#include <string>
int ProtocolUpm::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN;
}
std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) {
const char S = ';';
const char L = '~';
const char START[] = {S, 0};
const char B1[] = {L, S, 0};
const char B0[] = {S, L, 0};
// const char BON[] = {S,L,L,S,0};
// const char BOFF[] = {S,L,S,L,0};
int intUnit = this->getIntParameter(L"unit", 1, 4)-1;
std::string strReturn;
int code = this->getIntParameter(L"house", 0, 4095);
for( size_t i = 0; i < 12; ++i ) {
if (code & 1) {
strReturn.insert(0, B1);
} else {
strReturn.insert(0, B0);
}
code >>= 1;
}
strReturn.insert(0, START); // Startcode, first
code = 0;
if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) {
code += 2;
} else if (method != TELLSTICK_TURNOFF) {
return "";
}
code <<= 2;
code += intUnit;
int check1 = 0, check2 = 0;
for( size_t i = 0; i < 6; ++i ) {
if (code & 1) {
if (i % 2 == 0) {
check1++;
} else {
check2++;
}
}
if (code & 1) {
strReturn.append(B1);
} else {
strReturn.append(B0);
}
code >>= 1;
}
if (check1 % 2 == 0) {
strReturn.append(B0);
} else {
strReturn.append(B1);
}
if (check2 % 2 == 0) {
strReturn.append(B0);
} else {
strReturn.append(B1);
}
strReturn.insert(0, "S");
strReturn.append("+");
return strReturn;
}

19
external/tellstick-core/ProtocolUpm.h vendored Normal file
View file

@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_
#include <string>
#include "service/Protocol.h"
class ProtocolUpm : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_

View file

@ -0,0 +1,77 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolWaveman.h"
#ifdef _MSC_VER
#else
#include <stdint.h>
#endif
#include <stdio.h>
#include <sstream>
#include <string>
int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff = 0;
int ProtocolWaveman::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolWaveman::getStringForMethod(int method, unsigned char, Controller *) {
return getStringCodeSwitch(method);
}
std::string ProtocolWaveman::getOffCode() const {
return "$k$k$k$k$k$k$k$k$k+";
}
std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) {
uint64_t allData = 0;
unsigned int house = 0;
unsigned int unit = 0;
unsigned int method = 0;
allData = dataMsg.getInt64Parameter("data");
method = allData & 0xF00;
method >>= 8;
unit = allData & 0xF0;
unit >>= 4;
unit++;
house = allData & 0xF;
if(house > 16 || unit < 1 || unit > 16) {
// not waveman
return "";
}
house = house + 'A'; // house from A to P
if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) {
lastArctecCodeSwitchWasTurnOff = 0;
return ""; // probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose
// one turnon/bell, but it's better than the alternative...
}
if(method == 6) {
lastArctecCodeSwitchWasTurnOff = 1;
}
std::stringstream retString;
retString << "class:command;protocol:waveman;model:codeswitch;house:" << static_cast<char>(house);
if(method == 0) {
retString << ";unit:" << unit << ";method:turnoff;";
} else if(method == 14) {
retString << ";unit:" << unit << ";method:turnon;";
} else {
// not waveman
return "";
}
return retString.str();
}

View file

@ -0,0 +1,26 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_
#include <string>
#include "service/ProtocolNexa.h"
class ProtocolWaveman : public ProtocolNexa {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
virtual std::string getOffCode() const;
private:
static int lastArctecCodeSwitchWasTurnOff;
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_

185
external/tellstick-core/ProtocolX10.cpp vendored Normal file
View file

@ -0,0 +1,185 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolX10.h"
#ifdef _MSC_VER
#else
#include <stdint.h>
#endif
#include <stdio.h>
#include <sstream>
#include <string>
const unsigned char HOUSES[] = {6, 0xE, 2, 0xA, 1, 9, 5, 0xD, 7, 0xF, 3, 0xB, 0, 8, 4, 0xC};
int ProtocolX10::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) {
const unsigned char S = 59, L = 169;
const char B0[] = {S, S, 0};
const char B1[] = {S, L, 0};
const unsigned char START_CODE[] = {'S', 255, 1, 255, 1, 255, 1, 100, 255, 1, 180, 0};
const unsigned char STOP_CODE[] = {S, 0};
std::string strReturn = reinterpret_cast<const char*>(START_CODE);
std::string strComplement = "";
std::wstring strHouse = getStringParameter(L"house", L"A");
int intHouse = strHouse[0] - L'A';
if (intHouse < 0) {
intHouse = 0;
} else if (intHouse > 15) {
intHouse = 15;
}
// Translate it
intHouse = HOUSES[intHouse];
int intCode = getIntParameter(L"unit", 1, 16)-1;
for( int i = 0; i < 4; ++i ) {
if (intHouse & 1) {
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
intHouse >>= 1;
}
strReturn.append( B0 );
strComplement.append( B1 );
if (intCode >= 8) {
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
strReturn.append( B0 );
strComplement.append( B1 );
strReturn.append( B0 );
strComplement.append( B1 );
strReturn.append( strComplement );
strComplement = "";
strReturn.append( B0 );
strComplement.append( B1 );
if (intCode >> 2 & 1) { // Bit 2 of intCode
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
if (method == TELLSTICK_TURNON) {
strReturn.append(B0);
strComplement.append(B1);
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append(B1);
strComplement.append(B0);
} else {
return "";
}
if (intCode & 1) { // Bit 0 of intCode
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
if (intCode >> 1 & 1) { // Bit 1 of intCode
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
for( int i = 0; i < 3; ++i ) {
strReturn.append( B0 );
strComplement.append( B1 );
}
strReturn.append( strComplement );
strReturn.append( reinterpret_cast<const char*>(STOP_CODE) );
strReturn.append("+");
return strReturn;
}
std::string ProtocolX10::decodeData(const ControllerMessage& dataMsg) {
uint64_t intData = 0, currentBit = 31;
bool method = 0;
intData = dataMsg.getInt64Parameter("data");
int unit = 0;
int rawHouse = 0;
for(int i = 0; i < 4; ++i) {
rawHouse >>= 1;
if (checkBit(intData, currentBit--)) {
rawHouse |= 0x8;
}
}
if (checkBit(intData, currentBit--) != 0) {
return "";
}
if (checkBit(intData, currentBit--)) {
unit |= (1<<3);
}
if (checkBit(intData, currentBit--)) {
return "";
}
if (checkBit(intData, currentBit--)) {
return "";
}
currentBit = 14;
if (checkBit(intData, currentBit--)) {
unit |= (1<<2);
}
if (checkBit(intData, currentBit--)) {
method = 1;
}
if (checkBit(intData, currentBit--)) {
unit |= (1<<0);
}
if (checkBit(intData, currentBit--)) {
unit |= (1<<1);
}
int intHouse = 0;
for(int i = 0; i < 16; ++i) {
if (HOUSES[i] == rawHouse) {
intHouse = i;
break;
}
}
std::stringstream retString;
retString << "class:command;protocol:x10;model:codeswitch;";
retString << "house:" << static_cast<char>('A' + intHouse);
retString << ";unit:" << unit+1;
retString << ";method:";
if (method == 0) {
retString << "turnon;";
} else {
retString << "turnoff;";
}
return retString.str();
}

22
external/tellstick-core/ProtocolX10.h vendored Normal file
View file

@ -0,0 +1,22 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLX10_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLX10_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolX10 : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLX10_H_

View file

@ -0,0 +1,31 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <string>
#include "service/ProtocolYidong.h"
std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) {
int intCode = this->getIntParameter(L"unit", 1, 4);
std::wstring strCode = L"111";
switch(intCode) {
case 1:
strCode.append(L"0010");
break;
case 2:
strCode.append(L"0001");
break;
case 3:
strCode.append(L"0100");
break;
case 4:
strCode.append(L"1000");
break;
}
strCode.append(L"110");
return getStringForCode(strCode, method);
}

View file

@ -0,0 +1,18 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_
#include <string>
#include "service/ProtocolSartano.h"
class ProtocolYidong : public ProtocolSartano {
public:
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_

30
external/tellstick-core/README.txt vendored Normal file
View file

@ -0,0 +1,30 @@
This is Telldus Core version {version}
Telldus Core is the driver and tools for controlling a Telldus Technologies
TellStick. It does not containing any GUI tools which makes it suitable for
server use.
INSTALLING Telldus Core
On Windows, if you want to install the precompiles binary packages, simply
launch the package and follow the instructions in the installation wizard.
If you have a source package (a .tar.gz file), follow the instruction in the
INSTALL file.
CONFIGURATION AND TOOLS
Once Telldus Core is installed, we suggest that you start by adding the devices
you want to control.
On Windows, this is done by installing TelldusCenter. On Linux it's done by
editing the file /etc/tellstick.conf directly, or in TelldusCenter.
Telldus Core installs the tool tdtool for controlling devices with TellStick.
Have a look in the man page for a description how to use it:
man tdtool
TellStick is a trademark of Telldus Technologies AB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more