dyndns


2018-09-16

I promised an article to address the dynamic DNS issue for external access to my home network. Sadly, most of the solutions involve an amount of work and configuration that was way too much to handle. My preferred solution would have been a combination of PowerDNS (SQL backend) and some updating via REST, together with my current domain hoster, domainfactory, where all xxx.dyndns.tld requests would be forwarded to PowerDNS.

Since this setup is way too complex for my small setup, I setteled for following solution:

  • router updates no-ip.com address
  • domainfactory has CNAME entry, pointing to no-ip.com Address

Pros:

  • simple setup, no additional components need to be installed/configured
  • unlimited (sub) domains, pointing to just one no-ip.com address, simple config
  • since the CNAME target does not change, I don't need to keep an eye on the TTL, but can rely on the TTL no-ip.com uses

Cons:

  • less flexible than a SQL-based solution
  • no-ip.com needs to be verified every month or it will be deactivated
  • there's no way to mask the service behind the CNAME

All in all, the compromise with a dyndns service is a bearable one. Also There's the possibility to use SSL certificates with LetsEncrypt for the specific dyndns domains and also refresh them easily. The alternative is a partial custom solution: Use a provider like e.g. inwx.de that offers an integrated DynDNS service for domains hosted there, which I will try in the future.

Tags: tinkering

Building temp/hum sensor rev1 and rev2


2018-09-03

Both sensors are based on the modified MySensors.org sketch. The pro mini has modified hardware to cut energy consumption as suggested by Björns technik blog (German) by removing status LED and voltage converter.

Rev1 temp/hum sensor

Baseline-Sensor to test the whole setup. After first using the FTDI adapter to monitor the serial data generated in debug mode, the sketch is used "as is", so every 60 seconds a touple of temp/hum values is pushed into the influxdb via MQTT. I did this to test if the reach of the nRF24 is enough for my purposes and also to get a rough idea how long two AA batteries could last.

To remind you: A pro mini operates on 3.3V and a single AA battery has 1.5V - used in serial and together, we're just at 3V which is quite close to the BOD threshold of ~2.7V. The actual calculated value is 3.2V with two AA type batteries;

Note: I did not change the brown out detection fuse.

According to the spec the min Voltage at 8 MHz should be:
(( 2.7-1.8 )/2)+1.8 = 2.25 V

This is a nice value, but DHT22 and nRF24 need some more juice available, so brown out at the default 2.7V threshold should be fine. Therefore, in Rev2 there will be battery voltage detection.

Every measurement cycle lasts roughly 62 seconds, 60s cycle + 2s wait for the sensor to measure. This means:

24 * 60 * 60 = 86400 seconds a day 86400 / 62s intervals = ~1393 measurements a day

Based on these numbers, the sensor is running for 6 days straight, now. I'm planning to change the intervals to very 30 minutes. So we (again, roughly) get:

24*2 with half-hourly measurements = 48 measurements a day 1393 / 48 = ~29 days

Every day the sensor runs at the current (fast) measurement cycle gives us roughly 29 days of 30 minute timed measurements. Considering our current uptime of 6 days, we're in for at least 174 days or half a year worth of measurements. Quite satisfactory, isn't it?

Excerpt from the logfile:

2018-09-03 14:07:08.459 [vent.ItemStateChangedEvent] - DHT22_101_01_cellar_temp changed from 19.3 to 19.2
2018-09-03 14:09:11.974 [vent.ItemStateChangedEvent] - DHT22_101_02_cellar_hum changed from 77.9 to 77.8
2018-09-03 14:09:11.980 [GroupItemStateChangedEvent] - gHumidity changed from 68.0 to 67.9 through DHT22_101_02_cellar_hum
2018-09-03 14:10:07.490 [vent.ItemStateChangedEvent] - DHT22_102_02_pantry_hum changed from 58.0 to 57.9
2018-09-03 14:10:13.757 [vent.ItemStateChangedEvent] - DHT22_101_02_cellar_hum changed from 77.8 to 77.9
2018-09-03 14:11:15.526 [vent.ItemStateChangedEvent] - DHT22_101_02_cellar_hum changed from 77.9 to 78.3
2018-09-03 14:11:15.535 [GroupItemStateChangedEvent] - gHumidity changed from 67.9 to 68.1 through DHT22_101_02_cellar_hum
2018-09-03 14:12:17.328 [vent.ItemStateChangedEvent] - DHT22_101_02_cellar_hum changed from 78.3 to 78.2
2018-09-03 14:13:19.082 [vent.ItemStateChangedEvent] - DHT22_101_02_cellar_hum changed from 78.2 to 78.0
2018-09-03 14:13:19.087 [GroupItemStateChangedEvent] - gHumidity changed from 68.1 to 68.0 through DHT22_101_02_cellar_hum

Designing the actual sensor

As a first prototype, I used a breadboard with a directly soldered-on pro mini. To be able to program the arduino with my ISP programmer, I added a few pin-headers to connect the cable. I also soldered the nRF4 to the board. As casing, I used some ABS box where most of the stuff fits in without problems. One challenge is placing the two AAs somewhere. Four small holes for the DHT22 allow for measuring outside the box.

sensor rev1 open casing

sensor rev1 closed casing

Problems/learnings from this design

I had massive problems with the signal strengh while placing the sensor inside the vaulted cellar. That's around one meter of sandstone and concrete between sender and receiver. The next iteration in design will be another case, placed outside the cellar and a few cables connecting the sensor from within. I think, around one meter of length should suffice. My learnings from this design are:

  • Having soldered on the arduino saves me some socket strips but having to provide a programming interface instead is more trouble, since you'll have to look up the pin maps twice ;-)
  • Using socket strips saves some breadboard space, too.
  • Overall this allows for smaller casings, in the long run, too.

Rev2 temp/hum sensor

Next iteration for my sensor design: Socket strips, no capacitor for the nRF24 (had none left) and an improved sketch design. I'm still using the same ABS casing and external battery case. The sensor will be placed in the pantry: So I'll able to tell when temperature levels are high enough for my bread rolls to be moved into the fridge.

Big thanks go out to @hggh for the battery measurement routine, based on the internal 1.1V reference.

Sketch is incremented to v2.0, since the refactoring into subroutines, adding battery level and a new message type are breaking changes.

// ...

#define CHILD_ID_VGE 2
int V_VGE;
// for later checking the battery status
byte ADCSRA_status;
const float InternalReferenceVoltage = 1.1;
short battery_status = 0;

// ...
MyMessage msgVoltage(CHILD_ID_VGE, V_VGE);

// ...

void presentation()  
{ 
  // Send the sketch version information to the gateway
  sendSketchInfo("TemperatureAndHumidity", "2.0");

  // Register all sensors to gw (they will be created as child devices)
  present(CHILD_ID_HUM, S_HUM);
  present(CHILD_ID_TEMP, S_TEMP);
  present(CHILD_ID_VGE, V_VGE);

  metric = getControllerConfig().isMetric;
}

void setup()
{
  ADCSRA_status = ADCSRA;
  ADCSRA &= ~(1 << 7);
  power_adc_disable();

  // ...
}

void loop()      
{  
  // Force reading sensor, so it works also after sleep()
  dht.readSensor(true);

  handle_temperature();
  handle_humidity();
  read_battery_voltage();

  // Sleep for a while to save energy
  sleep(UPDATE_INTERVAL); 
}

void read_battery_voltage()
{
  power_adc_enable();
  ADCSRA = ADCSRA_status;
  ADCSRA |= bit (ADPS0) |  bit (ADPS1) | bit (ADPS2);  // Prescaler of 128
  ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);

  delay(10);
  bitSet (ADCSRA, ADSC);
  while (bit_is_set(ADCSRA, ADSC)) {
  }
  float battery_voltage = InternalReferenceVoltage / float (ADC + 0.5) * 1024.0;

  ADCSRA &= ~(1 << 7);
  power_adc_disable();

  if (isnan(battery_voltage)) {
    Serial.println("Failed reading battery_voltage");
  } else {
    #ifdef MY_DEBUG
    Serial.print("V: ");
    Serial.println(battery_voltage);
    #endif

    send(msgVoltage.set(battery_voltage, 1));
  }
}

void handle_temperature()
{
  // ...
}

void handle_humidity()
{
  // ...
}

This sketch will introduce a third subnode ID in concert with a new message type (derived from the default message), based on MySensors framework. With this third message type, the current calculated voltage is transmitted to openhab2.

sensor rev2 detail view

sensor rev2 complete

Tags: tinkering, IoT, smart home, arduino, mysensors

OpenHAB2, Mosquitto and MySensors Gateway


2018-08-27

my first sensor is a DHT22 (temperature/humidity, very good accuracy), attached to a 3.3V pro mini (ATMEGA 328p), connected via a NRF24 l 01+ (2.4GHz) which is capable of low-power transmission. This enables the arduino to later work on battery power only. My goal is to build three of these sensors. The assembly is straight forward:

pro mini with sensor and transceiver attached

I had many setbacks, connecting the sensor to the Raspberry Pi, though. This forced me to understand how a basic MQTT infrastructure has to interact with its data sources and OpenHAB2:

infrastructure with DHT22 attached

Steps to connect:

  • add node ID and parent ID to sketch
  • define lower baud rate for later running the board at a lowered clock speed
  • get MySensors Gateway working on RPi
  • Connect GateWay to Mosquitto
  • Connect Mosquitto to the OpenHAB MQTT binding

Step by step

Following the basic steps in more detail. Keep in mind that starting with OpenHAB2, the "old" bindings like MQTT are not shown in PaperUI, even when installed. So you'd have to configure all items manually (which took me a few hours to find out)!

Sensor IDs and baud settings in sketch

#define MY_NODE_ID 101
#define MY_PARENT_NODE_ID 0

// Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
#if F_CPU == 8000000L
#define MY_BAUD_RATE 9600
#endif

I've set up my sensor node IDs in "namespaces" like that:

  • 1xx environmental sensor nodes
  • 2xx extra nodes like elecrity IR reader

Attaching the NRF24 is relatively straight forward, as is connecting the DHT22.

Install and configure mosquitto

The current version, provided by apt is 1.4.x - I only managed to get it running in a stable manner when using 1.5.

- name: Add mosquitto repository
  apt_key:
    url: http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
    state: present

- apt_repository:
    repo: "deb https://repo.mosquitto.org/debian stretch main"
    update_cache: True
    state: present 

- name: install packages
  apt: pkg= state=latest
  with_items:
    - mosquitto
    - mosquitto-clients

Install MySensors gateway

In hindsight this is quite easy. Most of the time I needed, went into a reproducable ansible script ;-) You can find instructions here. Since I won't be exposing my OpenHAB instance to the internet - only available via VPN - I will not introduce authentication.

So, follow the instructions and install/compile the gateway. Keep in mind, that you will need mosquitto installed, too. I'd also opt for the MQTT binding for OpenHAB, since it's working fine with mosquitto. You can use the defaults @ mosquitto.

Some ansible help:

- name: get mysensors mqtt repo
  git:
    repo: https://github.com/mysensors/MySensors.git
    dest: /home/pi/MySensors
    accept_hostkey: yes
    version: master

- name: configure
  command: "./configure --my-transport=nrf24 --my-gateway=mqtt --my-controller-ip-address=127.0.0.1 --my-mqtt-publish-topic-prefix=mysensors-out --my-mqtt-subscribe-topic-prefix=mysensors-in --my-mqtt-client-id=mysensors-gateway"
  args:
    chdir: /home/pi/MySensors

- name: copy mysensors config
  template: src=./mysensors.conf.j2 dest=/etc/mysensors.conf owner=root group=root mode=755

- name: make
  command: "make"
  args:
    chdir: /home/pi/MySensors

- name: install
  command: "make install"
  args:
    chdir: /home/pi/MySensors
  notify:
    - start mysqw

It's that easy, since all components reside within the RPi. Don't forget to attach a NRF24 to your RPi aswell!

Install the MQTT binding and influxdb

Two parts: Install influxdb and client and manually install the bindings in OpenHAB.

- name: Add influxdb apt key
  apt_key:
    url: https://repos.influxdata.com/influxdb.key
    state: present

- apt_repository:
    repo: "deb https://repos.influxdata.com/debian stretch stable"
    update_cache: True
    state: present

 - name: install base packages
  apt: pkg= state=latest
  with_items:
    - influxdb
    - influxdb-client
  notify:
    - start influxdb

For influxdb, use the defaults provided here. Don't forget to configure persistence for OpenHAB (influxdb.persist)!

Strategies { default = everyChange }
Items { * : strategy = everyUpdate, restoreOnStartup }

Configure OpenHAB

I installed OpenHAB as a package, so no OpenHABbian. This means: All configuration resides in /etc/openhab2 I strongly(!!!) suggest you to pack the whole directory into a separate git repository! You will configure a lot via config files and since PaperUI persists only in json files, which most of the times are generated from the config files, the latter are the safer bet.

services/mqtt.cfg:

mosquitto.url=tcp://localhost:1883
mosquitto.clientId=openhab
mosquitto.qos=1
mosquitto.retain=true
mosquitto.async=false

services/mqtt-eventbus.cfg:

broker=mosquitto
stateSubscribeTopic=mosquitto/stateUpdates/${item}/state
commandSubscribeTopic=mosquitto/commandUpdates/${item}/command

items/dht22.items:

Group    Home                    "home"                   <house>

Group    GF                      "Ground Floor"           <groundfloor>   (Home)
Group    FF                      "First Floor"            <firstfloor>    (Home)
Group    F2                      "Second Floor"           <attic>         (Home)
Group    F3                      "Third Floor"            <attic>         (Home)

Group    GF_Cellar               "Cellar"                 <cellar>        (Home, GF)
Group    FF_LivingDining         "Living & Dining Room"   <sofa>          (Home, FF)
Group    F2_Bedroom              "Bedroom"                <bedroom>       (Home, F2)
Group    F2_KidsRoom             "Kids Room"              <girl_3>        (Home, F2)
Group    F3_GuestRoom            "Guest Room"             <parents_4_3>   (Home, F3)

Number DHT22_101_01_cellar_temp  "temperature [%.1f °C]" <temperature> (gTemperature, GF_Cellar) {mqtt="<[mosquitto:mysensors-out/101/1/1/0/0:state:default]"}
Number DHT22_101_02_cellar_hum  "humidity [%.1f %%]" <humidity> (gHumidity, GF_Cellar) {mqtt="<[mosquitto:mysensors-out/101/0/1/0/1:state:default]"}

Group:Number:AVG   gTemperature   "Temperature"   <temperature>   (Home)
Group:Number:AVG   gHumidity      "Humidity"      <humidity>      (Home)

That's a lot in the items but mostly it's auto-generated grouping. The really interesting lines are the ones starting with "Number". They actually handle the processing of incoming sensor values for the temp/hum DHT22 sensor. Addotional sensor definitions (for DHT22s) would be located in here, too.

If you've followed this guide, you should have a working sensor with MySensors framework communicating with a RPi, having a MQTT gateway, broker and binding, pushing data into an influxdb.

Tags: tinkering, IoT, smart home, arduino, mysensors