Note: The instructions in this post have been substantially revised and can now be found here. The new instructions include:
- installing mosquitto and Z2M in a separate jail,
- a symlink from the
/dev/cuaXX
to/zigbee
, and- allowing mosquitto to receive connections from outside the jail.
In a previous post, we got Home Assistant Core and it’s dependencies installed into a Bastille jail. We were able to start HA were greeted by the initial landing page. Now it’s time to make HA more useful by pulling in Zigbee data.
Why Zigbee? It’s what I have
Now there are two ways to let HA use Zigbee, Zigbee Home Automation and Zigbee2MQTT. I am going to use Zigbee2MQTT because I prefer to keep services separate where possible.
Software Link to heading
- Home Assistant Core 2023.12 (installed in a previous post)
- Zigbee2MQTT 1.34.0 (installed from Github)
- Mosquitto 2.0.15 (installed from FreeBSD ports)
Getting the Zigbee USB dongle ready Link to heading
I know that the Zigbee dongle is recognised by the FreeBSD kernel because I get this output from dmesg
when I pull it out and plug it back in:
ugen2.3: <ITead Sonoff Zigbee 3.0 USB Dongle Plus> at usbus2 (disconnected)
uslcom0: at uhub1, port 2, addr 2 (disconnected)
uslcom0: detached
ugen0.4: <ITead Sonoff Zigbee 3.0 USB Dongle Plus> at usbus0
uslcom0 on uhub2
uslcom0: <ITead Sonoff Zigbee 3.0 USB Dongle Plus, class 0/0, rev 2.00/1.00, addr 3> on usbus0
On my system, the dongle is accessible at
/dev/cuaU0
. So far, I haven’t worked out how to rename this to something unique to this dongle, for example/dev/zigbee
. I can use adevd
rule to create a symlink from/dev/zibgee
to/dev/cuaU0
, but this symlink does not show up in the jail. So for now, we will have to persist with/dev/cuaU0
Passing this new device to the jail Link to heading
By default, the /dev/cuaU0
device is not visible within the jail:
root@home-assistant:~ # ls -lah /dev/
dr-xr-xr-x 9 root wheel 512B Dec 24 18:15 .
drwxr-xr-x 14 root wheel 24B Dec 10 16:33 ..
crw------- 1 root wheel 0x27 Dec 24 18:15 bpf
lrwxr-xr-x 1 root wheel 3B Dec 24 18:15 bpf0 -> bpf
crw-rw-rw- 1 root wheel 0x42 Dec 13 11:55 crypto
dr-xr-xr-x 2 root wheel 512B Dec 24 18:15 fd
crw-rw-rw- 1 root wheel 0x14 Dec 24 19:11 null
crw------- 1 root wheel 0xab Dec 13 11:56 pf
dr-xr-xr-x 2 root wheel 512B Dec 24 18:15 pts
crw-r--r-- 1 root wheel 0x4 Dec 13 11:56 random
lrwxr-xr-x 1 root wheel 4B Dec 24 18:15 stderr -> fd/2
lrwxr-xr-x 1 root wheel 4B Dec 24 18:15 stdin -> fd/0
lrwxr-xr-x 1 root wheel 4B Dec 24 18:15 stdout -> fd/1
lrwxr-xr-x 1 root wheel 6B Dec 24 18:15 urandom -> random
crw-rw-rw- 1 root wheel 0x15 Dec 13 11:55 zero
crw-rw-rw- 1 root operator 0x3f Dec 13 11:55 zfs
To make it visible, we need to allow the jail running home-assistant to see cuaXX
devices.
First, we create a new ruleset within /etc/devfs.rules
:
root@freebsd-server:~ # cat /etc/devfs.rules
[bastille_vnet=13] <---- This is what you will have if you are using VNET jails
#add path 'bpf*' unhide
#add include $devfsrules_jail
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_jail
add include $devfsrules_jail_vnet
add path 'bpf*' unhide
[bastille_homeassistant=14] <---- This is what you need to create
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_jail
add include $devfsrules_jail_vnet
add include $bastille_vnet
add path 'cua*' unhide <---- The important part
bastille_vnet
is what you would have created when you were setting up the jails.
bastille_homeassistant
is what we’ve created specially for home assistant.
It includes all of the rules used by the bastille_vnet
ruleset, plus another rule that allows cuaXX
devices to be visible.
Next, you need to restart the devfs
service:
root@freebsd-server:~ # service devfs restart
Then, we change the ruleset used by the home-assistant jail:
root@freebsd-server:~ # cat /usr/local/bastille/jails/home-assistant/jail.conf
home-assistant {
devfs_ruleset = 14; <----- Set this to the number of the ruleset you just created
enforce_statfs = 2;
exec.clean;
exec.consolelog = /var/log/bastille/home-assistant_console.log;
exec.start = '/bin/sh /etc/rc';
exec.stop = '/bin/sh /etc/rc.shutdown';
host.hostname = home-assistant;
mount.devfs;
mount.fstab = /usr/local/bastille/jails/home-assistant/fstab;
path = /usr/local/bastille/jails/home-assistant/root;
securelevel = 2;
vnet;
vnet.interface = e0b_bastille4;
exec.prestart += "jib addm bastille4 igb0";
exec.prestart += "ifconfig e0a_bastille4 ether 02:77:49:b9:d8:0a";
exec.prestart += "ifconfig e0b_bastille4 ether 02:77:49:b9:d8:0b";
exec.prestart += "ifconfig e0a_bastille4 description \"vnet host interface for Bastille jail home-assistant\"";
exec.poststop += "jib destroy bastille4";
}
Finally, restart the jail.
Now, from inside the jail you can see the newly unhidden devices:
root@home-assistant:~ # ls -lah /dev/
dr-xr-xr-x 9 root wheel 512B Dec 24 18:15 .
drwxr-xr-x 14 root wheel 24B Dec 10 16:33 ..
crw------- 1 root wheel 0x27 Dec 24 18:15 bpf
lrwxr-xr-x 1 root wheel 3B Dec 24 18:15 bpf0 -> bpf
crw-rw-rw- 1 root wheel 0x42 Dec 13 11:55 crypto
crw-rw---- 1 uucp dialer 0xe1 Dec 24 13:22 cuaU0 <----- Here,
crw-rw---- 1 uucp dialer 0xee Dec 24 13:22 cuaU0.init <----- here,
crw-rw---- 1 uucp dialer 0xf2 Dec 24 13:22 cuaU0.lock <----- and here!
dr-xr-xr-x 2 root wheel 512B Dec 24 18:15 fd
crw-rw-rw- 1 root wheel 0x14 Dec 24 19:11 null
crw------- 1 root wheel 0xab Dec 13 11:56 pf
dr-xr-xr-x 2 root wheel 512B Dec 24 18:15 pts
crw-r--r-- 1 root wheel 0x4 Dec 13 11:56 random
lrwxr-xr-x 1 root wheel 4B Dec 24 18:15 stderr -> fd/2
lrwxr-xr-x 1 root wheel 4B Dec 24 18:15 stdin -> fd/0
lrwxr-xr-x 1 root wheel 4B Dec 24 18:15 stdout -> fd/1
lrwxr-xr-x 1 root wheel 6B Dec 24 18:15 urandom -> random
crw-rw-rw- 1 root wheel 0x15 Dec 13 11:55 zero
crw-rw-rw- 1 root operator 0x3f Dec 13 11:55 zfs
We only need access to the cuaU0
device, the others were automatically created when the dongle is plugged in.
Mosquitto MQTT Link to heading
As I mentioned earlier, I will be using Zigbee2MQTT. This requires a MQTT server. Luckily, Mosquitto is available in the FreeBSD ports and it works out of the box.
root@home-assistant:~ # pkg install mosquitto
root@home-assistant:~ # service mosquitto enable
mosquitto enabled in /etc/rc.conf
root@home-assistant:~ # service mosquitto start
Starting mosquitto.
1703409712: mosquitto version 2.0.15 starting
1703409712: Config loaded from /usr/local/etc/mosquitto/mosquitto.conf.
1703409712: Starting in local only mode. Connections will only be possible from clients running on this machine.
1703409712: Create a configuration file which defines a listener to allow remote access.
1703409712: For more details see https://mosquitto.org/documentation/authentication-methods/
1703409712: Opening ipv4 listen socket on port 1883.
1703409712: Opening ipv6 listen socket on port 1883.
1703409712: mosquitto version 2.0.15 running
root@home-assistant:~ # sockstat -4
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
nobody mosquitto 45787 3 tcp4 *:* *:*
nobody mosquitto 45787 4 tcp4 127.0.0.1:1883 *:*
Zigbee2MQTT Link to heading
Unfortunately, Zigbee2MQTT is not available in the ports, but it is very easy to get up and running.
Requirements Link to heading
- You will need a working MQTT broker to get Z2M running.
- You will also need to install
node npm git gmake gcc
if you haven’t already done so.
Installation Link to heading
Clone the git repository, install the node dependencies, update the configuration to point to your zigbee controller, and start.
[homeassistant@home-assistant ~]$ git clone --depth 1 https://github.com/Koenkk/zigbee2mqtt.git
[homeassistant@home-assistant ~]$ cd zigbee2mqtt
[homeassistant@home-assistant ~/zigbee2mqtt]$ npm ci
added 813 packages, and audited 814 packages in 7s
90 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
[homeassistant@home-assistant ~/zigbee2mqtt]$ cat data/configuration.yaml
homeassistant: true
permit_join: true
mqtt:
base_topic: zigbee2mqtt
server: mqtt://127.0.0.1:1883
serial:
port: /dev/cuaU0
adapter: zstack
frontend: true
advanced:
log_output:
- console
log_level: info <----- debug will give a lot of output
timestamp_format: YYYY-MM-DD HH:mm:ss
channel: 25
[homeassistant@home-assistant ~/zigbee2mqtt]$ npm start
zigbee2mqtt@1.34.0 start
node index.js
<I've cut down the output here to show you the main things to look for>
Zigbee2MQTT:info 2023-12-24 20:30:26: Starting Zigbee2MQTT version 1.34.0 (commit #56589dc)
Zigbee2MQTT:info 2023-12-24 20:30:26: Starting zigbee-herdsman (0.25.0)
Zigbee2MQTT:info 2023-12-24 20:30:31: Coordinator firmware version: '{"meta":{"maintrel":1,"majorrel":2,"minorrel":7,"product":1,"revision":20210708,"transportrev":2},"type":"zStack3x0"}'
Zigbee2MQTT:warn 2023-12-24 20:30:31: `permit_join` set to `true` in configuration.yaml.
Zigbee2MQTT:warn 2023-12-24 20:30:31: Allowing new devices to join.
Zigbee2MQTT:warn 2023-12-24 20:30:31: Set `permit_join` to `false` once you joined all devices.
Zigbee2MQTT:info 2023-12-24 20:30:31: Zigbee: allowing new devices to join.
Zigbee2MQTT:info 2023-12-24 20:30:31: Connecting to MQTT server at mqtt://127.0.0.1:1883
Zigbee2MQTT:debug 2023-12-24 20:30:31: Using MQTT anonymous login
Zigbee2MQTT:info 2023-12-24 20:30:31: Connected to MQTT server
Zigbee2MQTT:info 2023-12-24 20:30:31: MQTT publish: topic 'zigbee2mqtt/bridge/state', payload '{"state":"online"}'
Zigbee2MQTT:info 2023-12-24 20:30:31: Started frontend on port 8080
Zigbee2MQTT:info 2023-12-24 20:30:31: Zigbee2MQTT started!
You will see of output here as you add devices to the network, especially if you set the logging to debug
.
We can set this up to run as a daemonised service with logging:
root@home-assistant:~ # cat /usr/local/etc/rc.d/zigbee2mqtt
#!/bin/sh
# PROVIDE: zigbee2mqtt
# REQUIRE: DAEMON NETWORKING
# BEFORE: LOGIN
# KEYWORD: shutdown
. /etc/rc.subr
name="zigbee2mqtt"
rcvar=zigbee2mqtt_enable
: ${zigbee2mqtt_enable:="NO"}
# daemon
pidfile="/var/run/${name}.pid"
node="/usr/local/bin/node"
script_js="/home/homeassistant/zigbee2mqtt/index.js"
command=/usr/sbin/daemon
#procname="daemon"
command_args="-S -l local0 -s info -P ${pidfile} -r ${node} ${script_js}"
load_rc_config $name
run_rc_command "$1"
root@home-assistant:~ # cat /etc/syslog.conf
#
# Spaces ARE valid field separators in this file. However,
# other *nix-like systems still insist on using tabs as field
# separators. If you are sharing this file between systems, you
# may want to use only tabs as field separators here.
# Consult the syslog.conf(5) manpage.
*.err;kern.warning;auth.notice;mail.crit /dev/console
*.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err /var/log/messages
security.* /var/log/security
auth.info;authpriv.info /var/log/auth.log
mail.info /var/log/maillog
cron.* /var/log/cron
!-devd
*.=debug /var/log/debug.log
*.emerg *
daemon.info /var/log/daemon.log
local0.info /var/log/zigbee2mqtt.log <------ Add this line here
<Later lines removed>
After you restart the syslogd
service, enable and then start the zigbee2mqtt
service, you can head to jail-ip-address:8080 to see the Zigbee2MQTT dashboard.
If this is not working, check the log files for any misconfigurations.
Configuring devices Link to heading
In the Z2M dashboard, you can give custom names to devices as you add them. These names will be passed through to Home Assistant as device names.
Getting Zigbee into Home Assistant Link to heading
All that is needed now is to install and configure the MQTT integration into Home Assistant.
Go to Settings
-> Devices & services
-> + ADD INTEGRATION
.
Search for and add MQTT
.
Set the broker to 127.0.0.1
and the port to 1883
.
Wait a few minutes and your added Zigbee devices should be discovered by Home Assistant.