I have a Pico W running a python script publishing sensor readings from a BME280 to MQTT. I am running both homeassistant and moquitto in docker containers on my raspberry pi.
I have confirmed that the MQTT connection is working and that data is being received, as when I go to settings > devices and services > MQTT > entities, the topics are displayed as follows:
This “entity is unavailable” error message is always showing. This is also causing (I think) neither of these ‘states’ to show up in the developer tools > states list, and when I add these entities to a dashboard, they only show the same error message (I cannot post another image as I am a new user).
I am at a complete loss as I have been troubleshooting this for countless hours to no avail…
My python file is as follows:
from machine import Pin, I2C
from time import sleep
import network
from umqtt.simple import MQTTClient
import config
import BME280
import json # Import json to format the configuration messages
# Constants for MQTT Topics
MQTT_TOPIC_TEMPERATURE_CONFIG = 'homeassistant/sensor/pico_temperature/config'
MQTT_TOPIC_PRESSURE_CONFIG = 'homeassistant/sensor/pico_pressure/config'
# State topics for sensor readings
MQTT_TOPIC_TEMPERATURE_STATE = 'homeassistant/sensor/pico_temperature/state'
MQTT_TOPIC_PRESSURE_STATE = 'homeassistant/sensor/pico_pressure/state'
# MQTT Parameters
MQTT_SERVER = config.mqtt_server
MQTT_PORT = 1883 # Set to your MQTT port, usually 1883
MQTT_USER = config.mqtt_username
MQTT_PASSWORD = config.mqtt_password
MQTT_CLIENT_ID = b"raspberrypi_picow"
MQTT_KEEPALIVE = 100
MQTT_SSL = False # set to False if using local Mosquitto MQTT broker
# Initialize I2C communication
i2c = I2C(id=1, scl=Pin(19), sda=Pin(18), freq=10000)
# Initialize BME280 sensor
bme = BME280.BME280(i2c=i2c, addr=0x76)
def get_sensor_readings():
temp = float(bme.temperature[:-1]) # Get temperature and convert to float
pres = float(bme.pressure[:-3]) # Get pressure and convert to float
return temp, pres
def initialize_wifi(ssid, password):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Connect to the network
wlan.connect(ssid, password)
# Wait for Wi-Fi connection
connection_timeout = 10
while connection_timeout > 0:
if wlan.status() >= 3:
break
connection_timeout -= 1
print('Waiting for Wi-Fi connection...')
sleep(1)
# Check if connection is successful
if wlan.status() != 3:
return False
else:
print('Connection successful!')
network_info = wlan.ifconfig()
print('IP address:', network_info[0])
return True
def connect_mqtt():
try:
client = MQTTClient(client_id=MQTT_CLIENT_ID,
server=MQTT_SERVER,
port=MQTT_PORT,
user=MQTT_USER,
password=MQTT_PASSWORD,
keepalive=MQTT_KEEPALIVE,
ssl=MQTT_SSL)
client.connect()
return client
except Exception as e:
print('Error connecting to MQTT:', e)
raise # Re-raise the exception to see the full traceback
def publish_sensor_config(client):
# Device information
device_info = {
"identifiers": ["pico_w_sensor"],
"name": "Raspberry Pi Pico W",
"manufacturer": "Raspberry Pi",
"model": "Pico W"
}
# Configuration for temperature sensor
temperature_config = {
"name": "Pico Temperature",
"state_topic": MQTT_TOPIC_TEMPERATURE_STATE,
"unit_of_measurement": "°C",
"device_class": "temperature",
"unique_id": "pico_temperature_1",
"device": device_info
}
client.publish(MQTT_TOPIC_TEMPERATURE_CONFIG, json.dumps(temperature_config).encode('utf-8'), retain=True)
# Configuration for pressure sensor
pressure_config = {
"name": "Pico Pressure",
"state_topic": MQTT_TOPIC_PRESSURE_STATE,
"unit_of_measurement": "hPa",
"device_class": "pressure",
"unique_id": "pico_pressure_1",
"device": device_info
}
client.publish(MQTT_TOPIC_PRESSURE_CONFIG, json.dumps(pressure_config).encode('utf-8'), retain=True)
def publish_sensor_readings(client, temperature, pressure):
client.publish(MQTT_TOPIC_TEMPERATURE_STATE, str(temperature), retain=True)
client.publish(MQTT_TOPIC_PRESSURE_STATE, str(pressure), retain=True)
try:
if not initialize_wifi(config.wifi_ssid, config.wifi_password):
print('Error connecting to the network... exiting program')
else:
client = connect_mqtt()
if client:
# Publish sensor configurations
publish_sensor_config(client)
while True:
# Read sensor data
temperature, pressure = get_sensor_readings()
# Publish sensor readings
publish_sensor_readings(client, temperature, pressure)
# Delay 10 seconds
sleep(10)
else:
print("Failed to connect to MQTT broker.")
except Exception as e:
print('Error:', e)
My docker-compose.yaml file contains:
version: '3.0'
services:
portainer:
container_name: portainer
image: portainer/portainer-ce
restart: always
ports:
- "9000:9000/tcp"
environment:
- TZ=Europe/London
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/portainer:/data
homeassistant:
container_name: homeassistant
image: "ghcr.io/home-assistant/home-assistant:stable"
volumes:
- /opt/homeassistant/config:/config
- /etc/localtime:/etc/localtime:ro
restart: unless-stopped
privileged: true
network_mode: host
mosquitto:
image: eclipse-mosquitto
container_name: mosquitto
volumes:
- /opt/mosquitto:/mosquitto
- /opt/mosquitto/data:/mosquitto/data
- /opt/mosquitto/log:/mosquitto/log
ports:
- 1883:1883
- 9001:9001
My home assistant is using the discovery prefix homeassistant and configuration.yaml contains:
# Loads default set of integrations. Do not remove.
default_config:
# Load frontend themes from the themes folder
frontend:
themes: !include_dir_merge_named themes
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
mqtt:
sensor:
- name: "Pico Temperature"
state_topic: "homeassistant/sensor/pico_temperature/state"
value_template: "{{ value | float }}"
unit_of_measurement: "°C"
device_class: "temperature"
state_class: "measurement" # This indicates the sensor is a numeric value
- name: "Pico Pressure"
state_topic: "homeassistant/sensor/pico_pressure/state"
value_template: "{{ value | float }}"
unit_of_measurement: "hPa"
device_class: "pressure"
state_class: "measurement" # Same as above
Any help would be greatly appreciated, please let me know if anymore information is required!