Connected Home

How to build and “open blueIOT interface” to your smart home? – Part 1 Hardware

Qivicon™ is supporting the HomeMatic standard, which is using an 868MHz transceiver and paired with the “Home Base” for further encryption. As we are not going to hack into this secure communication, we simply connect and Arduino to the off the shelf „Funk-Wandtaster“ allowing us to interact with the home control. Pressing the button can activate a home profile. Now the Arduino should take over this control! As we are using also a Bluetooth™ Smart (BLE) transceiver we can detect Beacons close by or we can simulate an Beacon. Leaving the home will now switch automatically to „Abwesend“ when our Smartphone is out of a defined distance to the „Funk-Wandtaster“ and vise versa.

Parts you will need:

– „Funk-Wandtaster“
– blueIOT (combines Arduino with the power of Bluetoot™ Smart)

How to wire up things:

First pair the “Funk-Wandtaster” with your Home Base, it should now look like this:

The „Funk-Wandtaster“ runs on 3V (2xAAA batteries) – so no level converters are required, we can directly connect the blueIOT module to the MCU of the „Funk-Wandtaster“ – it is the same as on the Arduino side: an Atmel ATmega328P. The wiring is very simple:
black – GND
Red – Supply Voltage (3V)
Green – Button TA1, connected to digital Pin 5
Blue – Button TA2, connected to digital Pin 8

The final intergration looks like this:

How to build and “open blueIOT interface” to your smart home? – Part 2 Software

We do now have our open hardware interface to Qivicon up and running but of course we do need some code on the Arduino to interact with its environment. Here are two code examples – first without using BLE, so you can use any Ardruino running on 3V (like the Adruino mini Pro 3.3V/8MHz) and a second using the BGlib (credits to Jeff Rowberg) for more complex interaction with Smartphones and Beacons to detect even proxmitity.

Code sample (without BLE):

int TA1 = 5;
int TA2 = 8;

// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(TA1, OUTPUT);
pinMode(TA2, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
digitalWrite(TA1, LOW); // turn the TA1 on (active: LOW)
delay(500); // wait for 500ms
digitalWrite(TA1, HIGH); // turn the TA1
delay(5000); // wait for 5 seconds
digitalWrite(TA2, LOW); // turn the TA2 on (active: LOW)
delay(500); // wait for 500ms
digitalWrite(TA2, HIGH); // turn the TA2 off
delay(5000); // wait for 5 seconds
}

Code sample (with BLE):

** Frist flash bglib-Profile to BLE112 module **

#include
#include „BGLib.h“

SoftwareSerial bleSerialPort(6, 9); // RX, TX
BGLib ble112((HardwareSerial *)&bleSerialPort, 0, 1);

uint8_t isScanActive = 0;

#define BLE_WAKEUP_PIN 7 // digital pin 7 is connected to BLE wake-up pin

int flag = 0;

void setup() {
pinMode(5, OUTPUT);
pinMode(8, OUTPUT);

// initialize BLE wake-up pin to allow (not force) sleep mode
pinMode(BLE_WAKEUP_PIN, OUTPUT);
digitalWrite(BLE_WAKEUP_PIN, LOW);

// open Arduino USB serial
Serial.begin(9600);

ble112.onBusy = onBusy;
ble112.onIdle = onIdle;
ble112.onTimeout = onTimeout;

ble112.onBeforeTXCommand = onBeforeTXCommand;
ble112.onTXCommandComplete = onTXCommandComplete;

ble112.ble_rsp_system_hello = my_rsp_system_hello;
ble112.ble_rsp_gap_set_scan_parameters = my_rsp_gap_set_scan_parameters;
ble112.ble_rsp_gap_discover = my_rsp_gap_discover;
ble112.ble_rsp_gap_end_procedure = my_rsp_gap_end_procedure;

// set up BGLib event handlers (called at unknown times)
ble112.ble_evt_system_boot = my_evt_system_boot;
ble112.ble_evt_gap_scan_response = my_evt_gap_scan_response;

// set the data rate for the SoftwareSerial port
bleSerialPort.begin(38400);
}

void loop() {
ble112.checkActivity();
uint8_t status;
// Toggle scanning for advertising BLE devices
if (isScanActive) {
isScanActive = 0;
Serial.println(„–>\tgap_end_procedure“);
ble112.ble_cmd_gap_end_procedure();
while ((status = ble112.checkActivity(1000)));
// response should come back within milliseconds
} else {
isScanActive = 1;
Serial.println(„–>\tgap_set_scan_parameters: { scan_interval: 0xC8, scan_window: 0xC8, active: 1 }“);
ble112.ble_cmd_gap_set_scan_parameters(0xC8, 0xC8, 1);
while ((status = ble112.checkActivity(1000)));
// response should come back within milliseconds
Serial.println(„–>\tgap_discover: { mode: 2 (GENERIC) }“);
ble112.ble_cmd_gap_discover(BGLIB_GAP_DISCOVER_GENERIC);
while ((status = ble112.checkActivity(1000)));
// response should come back within milliseconds
// scan response events may happen at any time after this
}

}

// ================================================================
// INTERNAL BGLIB CLASS CALLBACK FUNCTIONS
// ================================================================

void onBusy() {
// turn LED on when we’re busy
//digitalWrite(LED_PIN, HIGH);
}

void onIdle() {
// turn LED off when we’re no longer busy
//digitalWrite(LED_PIN, LOW);
}

void onTimeout() {
Serial.println(„!!!\tTimeout occurred!“);
}

void onBeforeTXCommand() {
// wake module up (assuming here that digital pin 5 is connected to the BLE wake-up pin)
digitalWrite(BLE_WAKEUP_PIN, HIGH);

// wait for „hardware_io_port_status“ event to come through, and parse it (and otherwise ignore it)
uint8_t *last;
while (1) {
ble112.checkActivity();
last = ble112.getLastEvent();
if (last[0] == 0x07 && last[1] == 0x00) break;
}

// give a bit of a gap between parsing the wake-up event and allowing the command to go out
delayMicroseconds(1000);
}

void onTXCommandComplete() {
// allow module to return to sleep (assuming here that digital pin 5 is connected to the BLE wake-up pin)
digitalWrite(BLE_WAKEUP_PIN, LOW);
}

// ================================================================
// USER-DEFINED BGLIB RESPONSE CALLBACKS
// ================================================================

void my_rsp_system_hello(const ble_msg_system_hello_rsp_t *msg) {
Serial.println(„<--\tsystem_hello"); } void my_rsp_gap_set_scan_parameters(const ble_msg_gap_set_scan_parameters_rsp_t *msg) { Serial.print("<--\tgap_set_scan_parameters: { "); Serial.print("result: "); Serial.print((uint16_t)msg -> result, HEX);
Serial.println(“ }“);
}

void my_rsp_gap_discover(const ble_msg_gap_discover_rsp_t *msg) {
Serial.print(„<--\tgap_discover: { "); Serial.print("result: "); Serial.print((uint16_t)msg -> result, HEX);
Serial.println(“ }“);
}

void my_rsp_gap_end_procedure(const ble_msg_gap_end_procedure_rsp_t *msg) {
Serial.print(„<--\tgap_end_procedure: { "); Serial.print("result: "); Serial.print((uint16_t)msg -> result, HEX);
Serial.println(“ }“);
}

// ================================================================
// USER-DEFINED BGLIB EVENT CALLBACKS
// ================================================================

void my_evt_system_boot(const ble_msg_system_boot_evt_t *msg) {
Serial.print(„###\tsystem_boot: { „);
Serial.print(„major: „); Serial.print(msg -> major, HEX);
Serial.print(„, minor: „); Serial.print(msg -> minor, HEX);
Serial.print(„, patch: „); Serial.print(msg -> patch, HEX);
Serial.print(„, build: „); Serial.print(msg -> build, HEX);
Serial.print(„, ll_version: „); Serial.print(msg -> ll_version, HEX);
Serial.print(„, protocol_version: „); Serial.print(msg -> protocol_version, HEX);
Serial.print(„, hw: „); Serial.print(msg -> hw, HEX);
Serial.println(“ }“);
}

void my_evt_gap_scan_response(const ble_msg_gap_scan_response_evt_t *msg) {
Serial.print(„###\tgap_scan_response: { „);
Serial.print(„rssi: „); Serial.print((-1)*(msg->rssi));

if (((msg -> rssi) > -40) && (flag == 0))

{
digitalWrite(5, LOW);
Serial.print („**ON**“);
delay (500);
digitalWrite(5, HIGH);
delay (2000);
flag = 1;

}
if (((msg -> rssi) < -60) && (flag == 1)) { digitalWrite(8, LOW); Serial.print ("**OFF**"); delay (500); digitalWrite(8, HIGH); delay (2000); flag = 0; } Serial.println(" }"); }

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*