I haven't used Zigbee before but I need local control of TRV's - my broadband has been poor over the last few months and relying on the Tuya cloud anymore isn't an option for me.
I've installed and run zigbee2mqtt on my RPI5. I use the same Pi for Node Red and MQTT broker, but I don't run Docker. I can run zigbee2mqtt manually by typing
sudo pnpm start
from the /opt/zigbee2mqtt folder. However if I try running zigbee2mqtt as a service, I get the following response to
sudo systemctl status zigbee2mqtt.service
Ă— zigbee2mqtt.service - zigbee2mqtt
Loaded: loaded (/etc/systemd/system/zigbee2mqtt.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Fri 2026-02-27 12:00:03 GMT; 34s ago
Duration: 5ms
Invocation: 9e7d3815f2fd4e6ebb7542f85c9c7825
Process: 1055 ExecStart=/opt/zigbee2mqtt/pnpm start (code=exited, status=217/USER)
Main PID: 1055 (code=exited, status=217/USER)
Feb 27 12:00:03 RPI5Node-Red systemd[1]: zigbee2mqtt.service: Scheduled restart job, restart counter is at 5.
Feb 27 12:00:03 RPI5Node-Red systemd[1]: zigbee2mqtt.service: Start request repeated too quickly.
Feb 27 12:00:03 RPI5Node-Red systemd[1]: zigbee2mqtt.service: Failed with result 'exit-code'.
Feb 27 12:00:03 RPI5Node-Red systemd[1]: Failed to start zigbee2mqtt.service - zigbee2mqtt.
I'm also struggling to get my head around writing a device specific descriptor for the TRV602z.
I can see and control the TRV from the zigbee2mqtt dashboard and NR reports the TRV as connected and recognises its 'friendly name' but I can't get it to report status or issue any dp commands.
I've put a suggested file called trv602z.js in /opt/zigbee2mqtt (also in /data sub folder) which looks like this...
Oh, I have just noticed that you are using sudo when you run it manually. You should not need to do that. You should be able to run it without sudo from the user that you used when you installed it. what does this command show? ls -l /opt/zigbee2mqtt/data
I assume you used sudo when running the install script, hence all the files are owned by root, which is why it is now failing. I wouldn't use a user called pi as that is the default on the pi and any hacker will try and attack that user. If you want to run it as your normal user, which appears to be chrissaich, then change all the files to be owned by yourself
cd /opt
sudo chown -R chrissaich:chrissaich zigbee2mqtt
then change the user in the service file to match that, and don't use sudo when starting it manually (or it will set any files that it writes back to root again).
According to this it should be recognised by the standard software, though it seems that there are some issues. It should basically function, I think, without the workaround there (is that the one you have tried to use), so I would first get it going without the workaround. It should report its status without the workaround. Have you tried using MQTTExplorer, which is invaluable in such cases, as it will easily show you exactly what it is publishing.
current_heating_setpoint: Temperature setpoint. To control publish a message to topic
zigbee2mqtt/FRIENDLY_NAME/set with payload {"current_heating_setpoint": VALUE}
where VALUE is the °C between 5 and 35. Reading (/get) this attribute is not possible
Note; You cannot 'get' or 'set' either battery or local_temperature they can only be read when a TRV update occurs. (as shown in your Definitely getting closer post and dynamicdave's example)
current_heating_setpoint can only be 'set', again it can only be read when the TRV updates