Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Sofia start/stop through MQTT #19

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 101 additions & 64 deletions include/bin/listener_mqtt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ WIFISTATS_CRON_MIN=2
STATUS_ONLINE=""
LAST_OPEN=0

log(){ echo "$*" | tee /dev/kmsg; }
get_code(){ echo -e $(grep "^$1 " ${CODES_FILE} | cut -d' ' -f2-); }
reverse_code(){
CODE=$(od -t x1 < ${INPUT_FILE} | head -n1 | cut -d' ' -f2- | tr [:lower:] [:upper:] | sed 's/^/\\\\x/' | sed 's/ /\\\\x/g')
log() { echo "$*" | tee /dev/kmsg; }
get_code() { echo -e $(grep "^$1 " ${CODES_FILE} | cut -d' ' -f2-); }
reverse_code() {
CODE=$(od -t x1 <"${INPUT_FILE}" | head -n1 | cut -d' ' -f2- | tr [:lower:] [:upper:] | sed 's/^/\\\\x/' | sed 's/ /\\\\x/g')
CODEGET=$(grep " ${CODE}" ${CODES_FILE} | cut -d' ' -f1)
[ -z "${CODEGET}" ] && CODEGET="unknown - ${CODE}"
echo ${CODEGET}
echo "${CODEGET}"
}

# Check running once
if [ -f "${PIDFILE}" ]; then
if [ -e "/proc/`cat ${PIDFILE}`" ]; then
if [ -e "/proc/$(cat ${PIDFILE})" ]; then
log "Listener is already running! Closing."
exit 0
else
Expand All @@ -29,81 +29,118 @@ if [ -f "${PIDFILE}" ]; then
done
fi
fi
echo "$$" > ${PIDFILE}
echo "$$" >${PIDFILE}

source ./mqtt_functions.sh
log "Starting MQTT listener"

TOPIC=`mqtt_base_topic`
TOPIC=$(mqtt_base_topic)

# clear previous status before running
mosquitto_pub ${MQTT_OPTS} -t "${TOPIC}" -r -n
mosquitto_pub "${MQTT_OPTS}" -t "${TOPIC}" -r -n

mosquitto_sub -v -k 300 --will-topic ${TOPIC} --will-payload offline --will-retain ${MQTT_OPTS} -t "${TOPIC}" -t "${TOPIC}/#" | while read -r line; do
mosquitto_sub -v -k 300 --will-topic "${TOPIC}" --will-payload offline --will-retain "${MQTT_OPTS}" -t "${TOPIC}" -t "${TOPIC}/#" | while read -r line; do
val=$(echo "$line" | awk '{print $2}' | tr '[:lower:]' '[:upper:]')
case $line in
"${TOPIC}/door/set"*)
if [ "$val" = "ON" ] || [ "$val" = "PRESS" ]; then
log "MQTT Open door"
get_code TRANSFER_CMD_UNLOCK_DOOR > ${INTERCOM_DEVICE}
(sleep 1 && mosquitto_pub ${MQTT_OPTS} -t "${TOPIC}/door/set" -m OFF) &
"${TOPIC}/sofia"*)
# Activate sofia
if [ "$val" = "ON" ] || [ "$val" = "START" ]; then
if [ ! -r /mnt/mtd/post.sh ]; then
touch /mnt/mtd/factory
cat <<'EOF' >/mnt/mtd/post.sh
#!/bin/sh

for NAME in listener listener_mqtt; do
if [ -e "/tmp/${NAME}.pid" ]; then
kill `cat /tmp/${NAME}.pid`
fi
done

# Commented because we want to still run mqtt listener to be able to turn off Sofia
# for NAME in head mosquitto_sub listener_mqtt.sh; do
# killall ${NAME}
# done

# run factory program
/usr/run-orig.sh

EOF
fi
;;
"${TOPIC}/door"*)
log "MQTT Door $val"
if [ "$val" = "ON" ] || [ "$val" = "ONLINE" ]; then
if [ "$((`date +%s` - ${LAST_OPEN}))" -ge 3 ] && [ ! -f "/tmp/intercom_opened" ]; then
get_code START_CALL > ${INTERCOM_DEVICE}
LAST_OPEN=`date +%s`
fi
elif [ "$val" = "OFF" ] || [ "$val" = "OFFLINE" ]; then
get_code STOP_CALL > ${INTERCOM_DEVICE}
[ -f "/tmp/intercom_opened" ] && rm -f /tmp/intercom_opened

if [ ! -x /mnt/mtd/post.sh ]; then
chmod +x /mnt/mtd/post.sh
fi
fi

# Turn off sofia and use patched software
if [ "$val" = "OFF" ] || [ "$val" = "STOP" ]; then
rm -f /mnt/mtd/factory
chmod -x /mnt/mtd/post.sh
fi

;;
"${TOPIC}/door/set"*)
if [ "$val" = "ON" ] || [ "$val" = "PRESS" ]; then
log "MQTT Open door"
get_code TRANSFER_CMD_UNLOCK_DOOR >${INTERCOM_DEVICE}
(sleep 1 && mosquitto_pub "${MQTT_OPTS}" -t "${TOPIC}/door/set" -m OFF) &
fi
;;
"${TOPIC}/forward"*)
if [ "$((`date +%s` - ${LAST_OPEN}))" -ge 2 ]; then
log "MQTT Forward status $val"
if [ "$val" = "ON" ] || [ "$val" = "ONLINE" ]; then
get_code PUSH_STATE_1 > ${INTERCOM_DEVICE}
elif [ "$val" = "OFF" ] || [ "$val" = "OFFLINE" ]; then
get_code PUSH_STATE_0 > ${INTERCOM_DEVICE}
fi
LAST_OPEN=`date +%s`
else
log "MQTT Forward status $val - skipping"
"${TOPIC}/door"*)
log "MQTT Door $val"
if [ "$val" = "ON" ] || [ "$val" = "ONLINE" ]; then
if [ "$(($(date +%s) - ${LAST_OPEN}))" -ge 3 ] && [ ! -f "/tmp/intercom_opened" ]; then
get_code START_CALL >${INTERCOM_DEVICE}
LAST_OPEN=$(date +%s)
fi
elif [ "$val" = "OFF" ] || [ "$val" = "OFFLINE" ]; then
get_code STOP_CALL >${INTERCOM_DEVICE}
[ -f "/tmp/intercom_opened" ] && rm -f /tmp/intercom_opened
fi
;;
"${TOPIC}/f1"*)
log "MQTT F1 Button $val"
if [ "$val" = "ON" ]; then
get_code START_F1 > ${INTERCOM_DEVICE}
elif [ "$val" = "OFF" ]; then
get_code STOP_F1 > ${INTERCOM_DEVICE}
elif [ "$val" = "PRESS" ]; then
get_code START_F1 > ${INTERCOM_DEVICE}
sleep 3
get_code STOP_F1 > ${INTERCOM_DEVICE}
"${TOPIC}/forward"*)
if [ "$(($(date +%s) - ${LAST_OPEN}))" -ge 2 ]; then
log "MQTT Forward status $val"
if [ "$val" = "ON" ] || [ "$val" = "ONLINE" ]; then
get_code PUSH_STATE_1 >${INTERCOM_DEVICE}
elif [ "$val" = "OFF" ] || [ "$val" = "OFFLINE" ]; then
get_code PUSH_STATE_0 >${INTERCOM_DEVICE}
fi
LAST_OPEN=$(date +%s)
else
log "MQTT Forward status $val - skipping"
fi
;;
"${TOPIC} "*)
if [ "$val" = "CONFIG" ]; then
STATUS_ONLINE=1
log "Connected successfully, configuring Home Assistant MQTT device"
./mqtt_config_homeassistant.sh && mosquitto_pub ${MQTT_OPTS} -t "${TOPIC}" -m online
if ! grep -q "mqtt_wifi_stats.sh" ${CRONFILE}; then
log "Configuring wifi stats reporter and restarting cron"
echo "*/${WIFISTATS_CRON_MIN} * * * * /usr/bin/mqtt_wifi_stats.sh" >> ${CRONFILE}
echo "*/10 * * * * /usr/bin/heartbeat_mqtt.sh" >> ${CRONFILE}
killall crond
crond -b
fi

elif [ "$val" = "OFFLINE" ] && [ -n "${STATUS_ONLINE}" ]; then
log "Disconnected from MQTT. Rebooting in 60 seconds."
sleep 60
reboot
"${TOPIC}/f1"*)
log "MQTT F1 Button $val"
if [ "$val" = "ON" ]; then
get_code START_F1 >${INTERCOM_DEVICE}
elif [ "$val" = "OFF" ]; then
get_code STOP_F1 >${INTERCOM_DEVICE}
elif [ "$val" = "PRESS" ]; then
get_code START_F1 >${INTERCOM_DEVICE}
sleep 3
get_code STOP_F1 >${INTERCOM_DEVICE}
fi
;;
"${TOPIC} "*)
if [ "$val" = "CONFIG" ]; then
STATUS_ONLINE=1
log "Connected successfully, configuring Home Assistant MQTT device"
./mqtt_config_homeassistant.sh && mosquitto_pub "${MQTT_OPTS}" -t "${TOPIC}" -m online
if ! grep -q "mqtt_wifi_stats.sh" ${CRONFILE}; then
log "Configuring wifi stats reporter and restarting cron"
echo "*/${WIFISTATS_CRON_MIN} * * * * /usr/bin/mqtt_wifi_stats.sh" >>${CRONFILE}
echo "*/10 * * * * /usr/bin/heartbeat_mqtt.sh" >>${CRONFILE}
killall crond
crond -b
fi

elif [ "$val" = "OFFLINE" ] && [ -n "${STATUS_ONLINE}" ]; then
log "Disconnected from MQTT. Rebooting in 60 seconds."
sleep 60
reboot
fi
;;
esac
done
Expand Down
116 changes: 60 additions & 56 deletions include/bin/mqtt_config_homeassistant.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,97 +2,101 @@

source ./mqtt_functions.sh

setup_topic(){
# object type, topic name
[ -n "${MQTT_HOMEASSISTANT}" ] && BASETOPIC="${MQTT_HOMEASSISTANT}"
echo -n "${BASETOPIC:-homeassistant}/$1/`mqtt_base_uniqueid $2`/config"
setup_topic() {
# object type, topic name
[ -n "${MQTT_HOMEASSISTANT}" ] && BASETOPIC="${MQTT_HOMEASSISTANT}"
echo -n "${BASETOPIC:-homeassistant}/$1/$(mqtt_base_uniqueid $2)/config"
}

IFACE=wlan0
IFACE_IP=`ip -4 addr show ${IFACE} | grep "inet " | awk '{print $2}' | cut -d '/' -f1`
IFACE_MAC=`cat /sys/class/net/${IFACE}/address`
IFACE_IP=$(ip -4 addr show ${IFACE} | grep "inet " | awk '{print $2}' | cut -d '/' -f1)
IFACE_MAC=$(cat /sys/class/net/${IFACE}/address)

setup_device_base(){
echo -n {\""identifiers\"":[\""wibox_${MODEL}\""],\""connections\"":[[\""mac\"",\""${IFACE_MAC}\""]],\""name\"":\""${MODEL}\"",\""model\"":\""WiBox 7938\"",\""manufacturer\"":\""Fermax\"",\""suggested_area\"":\""Entrance\"",\""configuration_url\"":\""http://${IFACE_IP}\""}
setup_device_base() {
echo -n {\""identifiers\"":[\""wibox_${MODEL}\""],\""connections\"":[[\""mac\"",\""${IFACE_MAC}\""]],\""name\"":\""${MODEL}\"",\""model\"":\""WiBox 7938\"",\""manufacturer\"":\""Fermax\"",\""suggested_area\"":\""Entrance\"",\""configuration_url\"":\""http://${IFACE_IP}\""}
}

setup_switch_message(){
# topic, name, icon, availabilty_topic_root (false)
TOPIC="`mqtt_base_topic`/$1"
AVTOPIC="${TOPIC}"
[ -n "$4" ] && AVTOPIC="`mqtt_base_topic`/$4"
[ -n "$4" ] && [ "$4" = "true" ] && AVTOPIC="`mqtt_base_topic`"
echo -n {\""command_topic\"": \""${TOPIC}\"", \""state_topic\"": \""${TOPIC}\"", \""availability_topic\"": \""${AVTOPIC}\"", \""icon\"": \""mdi:$3\"", \""name\"": \""`mqtt_base_name "$2"`\"", \""unique_id\"": \""`mqtt_base_uniqueid $1`\"", \""device\"": `setup_device_base`}
setup_switch_message() {
# topic, name, icon, availabilty_topic_root (false)
TOPIC="$(mqtt_base_topic)/$1"
AVTOPIC="${TOPIC}"
[ -n "$4" ] && AVTOPIC="$(mqtt_base_topic)/$4"
[ -n "$4" ] && [ "$4" = "true" ] && AVTOPIC="$(mqtt_base_topic)"
echo -n {\""command_topic\"": \""${TOPIC}\"", \""state_topic\"": \""${TOPIC}\"", \""availability_topic\"": \""${AVTOPIC}\"", \""icon\"": \""mdi:$3\"", \""name\"": \""$(mqtt_base_name "$2")\"", \""unique_id\"": \""$(mqtt_base_uniqueid $1)\"", \""device\"": $(setup_device_base)}
}

setup_switch_opener_message(){
# unique_id, name, icon
TOPIC="`mqtt_base_topic`/door"
AVTOPIC="`mqtt_base_topic`"
echo -n {\""command_topic\"": \""${TOPIC}\"", \""state_topic\"": \""${TOPIC}\"", \""payload_on\"": \""online\"", \""payload_off\"": \""offline\"", \""availability_topic\"": \""${AVTOPIC}\"", \""icon\"": \""mdi:$3\"", \""name\"": \""`mqtt_base_name "$2"`\"", \""unique_id\"": \""`mqtt_base_uniqueid $1`\"", \""device\"": `setup_device_base`}
setup_switch_opener_message() {
# unique_id, name, icon
TOPIC="$(mqtt_base_topic)/door"
AVTOPIC="$(mqtt_base_topic)"
echo -n {\""command_topic\"": \""${TOPIC}\"", \""state_topic\"": \""${TOPIC}\"", \""payload_on\"": \""online\"", \""payload_off\"": \""offline\"", \""availability_topic\"": \""${AVTOPIC}\"", \""icon\"": \""mdi:$3\"", \""name\"": \""$(mqtt_base_name "$2")\"", \""unique_id\"": \""$(mqtt_base_uniqueid $1)\"", \""device\"": $(setup_device_base)}
}

setup_device_automation_message(){
# type, subtype, payload
TOPIC="`mqtt_base_topic`/action"
echo -n {\""automation_type\"":\""trigger\"", \""type\"":\""button_${1}_press\"", \""subtype\"":\""button_$2\"", \""payload\"":\""$3\"", \""topic\"":\""${TOPIC}\"", \""device\"": `setup_device_base`}
setup_device_automation_message() {
# type, subtype, payload
TOPIC="$(mqtt_base_topic)/action"
echo -n {\""automation_type\"":\""trigger\"", \""type\"":\""button_${1}_press\"", \""subtype\"":\""button_$2\"", \""payload\"":\""$3\"", \""topic\"":\""${TOPIC}\"", \""device\"": $(setup_device_base)}
}

setup_binary_sensor_message(){
# topic, name, device_class, off_delay
TOPIC="`mqtt_base_topic`/$1"
AVTOPIC="`mqtt_base_topic`"
echo -n {\""state_topic\"": \""${TOPIC}\"", \""availability_topic\"": \""${AVTOPIC}\"", \""device_class\"": \""$3\"", \""off_delay\"": $4, \""name\"": \""`mqtt_base_name "$2"`\"", \""unique_id\"": \""`mqtt_base_uniqueid $1`\"", \""device\"": `setup_device_base`}
setup_binary_sensor_message() {
# topic, name, device_class, off_delay
TOPIC="$(mqtt_base_topic)/$1"
AVTOPIC="$(mqtt_base_topic)"
echo -n {\""state_topic\"": \""${TOPIC}\"", \""availability_topic\"": \""${AVTOPIC}\"", \""device_class\"": \""$3\"", \""off_delay\"": $4, \""name\"": \""$(mqtt_base_name "$2")\"", \""unique_id\"": \""$(mqtt_base_uniqueid $1)\"", \""device\"": $(setup_device_base)}
}

setup_sensor_message(){
# topic, name, device_class, icon
TOPIC="`mqtt_base_topic`/$1"
AVTOPIC="`mqtt_base_topic`"
echo -n {\""state_topic\"": \""${TOPIC}\"", \""availability_topic\"": \""${AVTOPIC}\"", \""device_class\"": \""$3\"", \""icon\"": \""mdi:$4\"", \""name\"": \""`mqtt_base_name "$2"`\"", \""unique_id\"": \""`mqtt_base_uniqueid $1`\"", \""device\"": `setup_device_base`}
setup_sensor_message() {
# topic, name, device_class, icon
TOPIC="$(mqtt_base_topic)/$1"
AVTOPIC="$(mqtt_base_topic)"
echo -n {\""state_topic\"": \""${TOPIC}\"", \""availability_topic\"": \""${AVTOPIC}\"", \""device_class\"": \""$3\"", \""icon\"": \""mdi:$4\"", \""name\"": \""$(mqtt_base_name "$2")\"", \""unique_id\"": \""$(mqtt_base_uniqueid $1)\"", \""device\"": $(setup_device_base)}
}

setup_sensor_advanced_message(){
# topic, name, device_class, icon, value_template, unit_of_measurement, json_attributes_topic
TOPIC="`mqtt_base_topic`/$1"
AVTOPIC="`mqtt_base_topic`"
echo -n {\""state_topic\"": \""${TOPIC}\"", \""availability_topic\"": \""${AVTOPIC}\"", \""device_class\"": \""$3\"", \""icon\"": \""mdi:$4\"", \""name\"": \""`mqtt_base_name "$2"`\"", \""unique_id\"": \""`mqtt_base_uniqueid $1`\"", \""value_template\"": \""$5\"", \""unit_of_measurement\"": \""$6\"", \""json_attributes_topic\"": \""`mqtt_base_topic`/$7\"", \""device\"": `setup_device_base`}
setup_sensor_advanced_message() {
# topic, name, device_class, icon, value_template, unit_of_measurement, json_attributes_topic
TOPIC="$(mqtt_base_topic)/$1"
AVTOPIC="$(mqtt_base_topic)"
echo -n {\""state_topic\"": \""${TOPIC}\"", \""availability_topic\"": \""${AVTOPIC}\"", \""device_class\"": \""$3\"", \""icon\"": \""mdi:$4\"", \""name\"": \""$(mqtt_base_name "$2")\"", \""unique_id\"": \""$(mqtt_base_uniqueid $1)\"", \""value_template\"": \""$5\"", \""unit_of_measurement\"": \""$6\"", \""json_attributes_topic\"": \""$(mqtt_base_topic)/$7\"", \""device\"": $(setup_device_base)}
}

mqtt_send(){ mosquitto_pub ${MQTT_OPTS} -t "${MTOPIC}" -m "${MDATA}"; }
mqtt_send() { mosquitto_pub ${MQTT_OPTS} -t "${MTOPIC}" -m "${MDATA}"; }

for BTN in 1 2; do
for CLK in short long quintuple; do
MTOPIC=`setup_topic device_automation pb${BTN}_${CLK}`
MDATA=`setup_device_automation_message ${CLK} ${BTN} pb${BTN}_${CLK}`
MTOPIC=$(setup_topic device_automation pb${BTN}_${CLK})
MDATA=$(setup_device_automation_message ${CLK} ${BTN} pb${BTN}_${CLK})
mqtt_send
done
done

MTOPIC=`setup_topic button door`
MDATA=`setup_switch_message door/set "Door Relay" door door`
MTOPIC=$(setup_topic button door)
MDATA=$(setup_switch_message door/set "Door Relay" door door)
mqtt_send

MTOPIC=`setup_topic button f1`
MDATA=`setup_switch_message f1 "F1 Button" keyboard-f1 true`
MTOPIC=$(setup_topic button f1)
MDATA=$(setup_switch_message f1 "F1 Button" keyboard-f1 true)
mqtt_send

MTOPIC=`setup_topic switch opener`
MDATA=`setup_switch_opener_message opener "Open Caller" phone`
MTOPIC=$(setup_topic switch opener)
MDATA=$(setup_switch_opener_message opener "Open Caller" phone)
mqtt_send

MTOPIC=`setup_topic switch forward`
MDATA=`setup_switch_message forward "Forward Status" phone-forward true`
MTOPIC=$(setup_topic switch forward)
MDATA=$(setup_switch_message forward "Forward Status" phone-forward true)
mqtt_send

MTOPIC=`setup_topic binary_sensor ding`
MDATA=`setup_binary_sensor_message ding "Ding" occupancy 30`
MTOPIC=$(setup_topic switch sofia)
MDATA=$(setup_switch_message sofia "Sofia software status" disc switch)
mqtt_send

MTOPIC=`setup_topic sensor last_ding`
MDATA=`setup_sensor_message ding/last "Last Ding" timestamp history`
MTOPIC=$(setup_topic binary_sensor ding)
MDATA=$(setup_binary_sensor_message ding "Ding" occupancy 30)
mqtt_send

MTOPIC=`setup_topic sensor linkquality`
MDATA=`setup_sensor_advanced_message wifi/stats "RSSI" signal_strength wifi "{{ value_json.RSSI }}" dBm wifi/stats`
MTOPIC=$(setup_topic sensor last_ding)
MDATA=$(setup_sensor_message ding/last "Last Ding" timestamp history)
mqtt_send

MTOPIC=$(setup_topic sensor linkquality)
MDATA=$(setup_sensor_advanced_message wifi/stats "RSSI" signal_strength wifi "{{ value_json.RSSI }}" dBm wifi/stats)
mqtt_send
2 changes: 1 addition & 1 deletion include/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ echo "IDS7938${UDID:8:4}" > /proc/sys/kernel/hostname

/usr/bin/listener.sh &

[ -f "/mnt/mtd/post.sh" ] && /mnt/mtd/post.sh
[ -x "/mnt/mtd/post.sh" ] && /mnt/mtd/post.sh

# remove lock if present
rm -f /tmp/heartbeat.lock
Expand Down