Configure a FRITZ!Box in openHAB, using Ansible

Posted by ads' corner on Wednesday, 2018-12-12
Posted in [Ansible][Linux][Openhab]

A while ago I posted about adding a Fritz!Box to openHAB, using Ansible. Now I had to use the Playbook to install another Raspberry, and found that some parts are missing in my posting. Mostly at the end, when it comes to configuring the Fritz!Box.

Therefore let’s run over all the steps again, and make sure that everything is covered.

First things first, the required packages:

1
2
3
4
5
6
- name: Install required packages
  apt: name={{ item }} state=present
  with_items:
    - openhab2-addons
    - openhab2-addons-legacy
    - libhttpclient-java

TheĀ fritzboxtr0641 binding needs special configuration. Also legacy bindings need to be activated in order for this binding to show up.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
- name: Update extensions configuration
  lineinfile:
    dest: /etc/openhab2/services/addons.cfg
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
    state: "{{ item.state }}"
    create: yes
  with_items:
    - { regexp: '^#? *package', line: 'package = expert', state: present }
    - { regexp: '^#? *remote', line: 'remote = true', state: present }
    - { regexp: '^#? *legacy', line: 'legacy = true', state: present }

Install the extension:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
- name: Get list of available and installed extensions
  uri:
    url: "http://{{ ansible_host }}:8080/rest/extensions"
  register: oh2_extensions
  changed_when: false

- name: Install extensions
  uri:
    url: "http://{{ ansible_host }}:8080/rest/extensions/{{ item }}/install"
    method: POST
  when: "not (oh2_extensions.json|byattr('id', item))[0].installed"
  with_items:
    - binding-fritzboxtr0641
  register: oh2_install_extensions

The extension comes with a configuration file, which holds access credentials to access the Fritz!Box. It is strongly recommended to create a separate account on the Fritz!Box, and not use the admin account here.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
- name: Read openhab user
  set_fact:
    fritzbox_user: "{{ item }}"
  with_file:
    - "{{ playbook_dir }}/credentials/fritzbox-openhab-user.txt"

- name: Update fritzboxtr064.cfg
  lineinfile:
    dest: /etc/openhab2/services/fritzboxtr064.cfg
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
    state: "{{ item.state }}"
    create: yes
  with_items:
    - { regexp: '^#? *url', line: 'url=http://{{ fritzbox_ip }}:49000', state: present }
    - { regexp: '^#? *user', line: 'user={{ fritzbox_user }}', state: present }
    - { regexp: '^#? *pass', line: 'pass={{ lookup('password', playbook_dir + '/credentials/fritzbox-openhab-pass.txt') }}', state: present }

At some point the extension shows up in the openHAB Inbox. From there it must be approved:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- name: Get inbox
  uri:
    url: "http://{{ ansible_host }}:8080/rest/inbox"
  register: oh2_inbox
  changed_when: false

- name: Auto-approve certain inbox items
  uri:
    url: "{{ oh2_inbox.url }}/{{ item.thingUID }}/approve"
    method: POST
  when: item.flag == "NEW" and item.thingTypeUID == "avmfritz:fritzbox"
  loop: "{{ oh2_inbox.json }}"

The Fritz!Box can not yet be used, the openHAB configuration is missing. That is a bit ugly, because a JSON object must be send to the server, and plenty of escaping is required. Also the credentials are read from two files (can also come from a Vault) in order not to store them directly in the Playbook.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- name: Read openhab user
  set_fact:
    fritzbox_user: "{{ item }}"
  with_file:
    - "{{ playbook_dir }}/credentials/fritzbox-openhab-user.txt"

- name: Initialize FRITZ!Box configuration
  uri:
    url: "{{ o2_things.url }}/{{ item.UID | urlencode }}/config"
    body: "{ \"syncTimeout\"{{':'}} \"{{ item.configuration.syncTimeout }}\", \"protocol\"{{':'}} \"http\", \"password\"{{':'}} \"{{ lookup('password', playbook_dir + '/credentials/fritzbox-openhab-pass.txt') }}\", \"asyncTimeout\"{{':'}} \"{{ item.configuration.asyncTimeout }}\", \"ipAddress\"{{':'}} \"{{ item.configuration.ipAddress }}\", \"pollingInterval\"{{':'}} \"{{ item.configuration.pollingInterval }}\", \"user\"{{':'}} \"{{ fritzbox_user }}\" }"
    body_format: json
    method: PUT
  when: item.thingTypeUID == "avmfritz:fritzbox" and item.statusInfo.status == "UNINITIALIZED"
  loop: "{{ o2_things.json }}"
  loop_control:
    label: "{{ item.thingTypeUID }} - {{ item.UID }}"

- name: Update FRITZ!Box configuration
  uri:
    url: "{{ o2_things.url }}/{{ item.UID | urlencode }}/config"
    body: "{ \"syncTimeout\"{{':'}} \"{{ item.configuration.syncTimeout }}\", \"protocol\"{{':'}} \"http\", \"password\"{{':'}} \"{{ lookup('password', playbook_dir + '/credentials/fritzbox-openhab-pass.txt') }}\", \"asyncTimeout\"{{':'}} \"{{ item.configuration.asyncTimeout }}\", \"ipAddress\"{{':'}} \"{{ item.configuration.ipAddress }}\", \"pollingInterval\"{{':'}} \"{{ item.configuration.pollingInterval }}\", \"user\"{{':'}} \"{{ fritzbox_user }}\" }"
    body_format: json
    method: PUT
  when: item.thingTypeUID == "avmfritz:fritzbox" and item.statusInfo.status == "ONLINE" and item.configuration.user != fritzbox_user
  loop: "{{ o2_things.json }}"
  loop_control:
    label: "{{ item.thingTypeUID }} - {{ item.UID }}"

The first “Initialize” step is only run the first time. It will configure the Fritz!Box extension. The second “Update” step is run every time the credentials change.

After a few seconds all the Fritz!Box adapters will show up in openHAB.


Categories: [Ansible] [Linux] [Openhab]