Hello there,
I have a bunch of old Ubiquiti MFI devices in my house still. I’m not using the mfi component because it requires both a dedicated pc/mac to be always on running the mfi controller, and secondly the HASS mfi component only controls outlets, and not lights. I borrowed a script i found and have made some massive adjustments to get all the sensor data out. It works great to turn on the switches/outlets and I’m making a seperate command line sensor call to get the power usage from it. I was looking at the script and modified the output to get back some additional values in the command line. Is there anyway I can update a bunch of different sensors with these values without making individual calls? Below is an example of what the script is out puting, below that is an example of a switch, and sensor from my configuration.yaml, and finally at the bottom is the entire script.
- platform: command_line
switches:
garage_light:
command_on: '/home/pi/mfi_lights/mfictrl.sh -l 192.168.0.51 ON'
command_off: '/home/pi/mfi_lights/mfictrl.sh -l 192.168.0.51 OFF'
command_state: '/home/pi/mfi_lights/mfictrl.sh -l 192.168.0.51 STATUS'
friendly_name: Garage Light
sensor
- platform: command_line
name: Garage Light
command: '/home/pi/mfi_lights/mfictrl.sh -l 192.168.0.51 STATUS'
value_template: '{{ value | round(0)}}'
unit_of_measurement: "W"
Example of what i’d like to see in hass all tied to one switch instead of making individual script calls:
Command Line Response:
homeassistant@raspberrypi:/home/pi/mfi_lights$ /home/pi/mfi_lights/mfimulti.sh -l 192.168.0.51 STATUS sensor.voltage:118.823003053, sensor.power:261.650984644, sensor.current:2.205826342, sensor.enabled:1, sensor.lock:0, sensor.output:1, sensor.powerfactor:0.99827577, sensor.prevmonth:34481, sensor.relay:1, sensor.thismonth:1029
Bash Script:
#!/bin/bash
###############################################################################
#
# mfictrl - Control Ubiquiti mFi devices
#
# Description: This script allows for the control of Ubiquiti mFi devices.
# Given the IP address (or DNS name) of a device, the script will control
# the device (turn it on [with dim level], off) or return the current status
# of the device.
#
###############################################################################
MFICTRL_SCRIPT_VERSION="1.0a"
base=$(/usr/bin/basename $0)
# Default variables
USERNAME="YOURUSERNAME"
PASSWORD="YOURPASSWORD"
PORT="1"
MFI_SESSION_ID=""
#------------------------------------------------------------------------------
#
# Functions used by the script
#
#------------------------------------------------------------------------------
#
# This function prints usage information for this script
#
mfictrl_usage()
{
help_message=$(/bin/cat <<EOF
NAME
${base} - Control a Ubiquiti mFi device
VERSION
${MFICTRL_SCRIPT_VERSION}
SYNOPSIS
${base} [-h] [-p PORT] [-v] [-l] <device_ip> ON [<dim%>] | OFF | STATUS
DESCRIPTION
${base} is used to control a Ubiquiti mFi device. The device can be
turned on, turned off, or the current status of the device can be
returned.
OPTIONS
-h Help. Displays this message
-p PORT Uses the specified PORT on the device. If not supplied the
default of port 1 will be used.
-v Verbose. Print debugging output
-l Print a message after command completion.
-u USERNAME The user name to login to the mFi device
-a PASSWORD The password to login to the mFi device
<device_ip>
The IP address of the device which is being controlled. This
can also be a DNS name if one has been defined.
ON [<dim>] | OFF | STATUS
The command to execute. ON turns the device on at the specified
dim level (or 100% if not specified). OFF turns the device off,
and STATUS retrieves the current state of the device.
EOF
)
echo "${help_message}\n" >&2
}
#
# This function prints its parameters if the verbose flag is set.
#
verbose_log()
{
if [ -n "${VERBOSE}" ]
then
echo -e $@ >&2
fi
}
#
# This function sets the global MFI_SESSION_ID variable to a random value. The
# session ID must be 32 decimal digits.
#
get_random_session_id()
{
# Loop 8 times, getting 4 random digits each time.
MFI_SESSION_ID=""
for quad in {1..8}
do
MFI_SESSION_ID+=$(printf %04d $(( $RANDOM % 10000 )) )
done
}
#
# This function logs into the mFi device
#
# Usage: mfi_login USERNAME PASSWORD SESSION_ID IP_ADDR
#
mfi_login()
{
local USERNAME=${1}
local PASSWORD=${2}
local SESSION_ID=${3}
local IP_ADDR=${4}
verbose_log "Calling mfi_login with USERNAME=${USERNAME} PASSWORD=${PASSWORD} SESSION_ID=${SESSION_ID} IP_ADDR=${IP_ADDR}"
# Login to the device
/usr/bin/curl \
-X POST \
-s \
-d 'username='${USERNAME}'&password='${PASSWORD} \
-b 'AIROS_SESSIONID='${SESSION_ID} \
${IP_ADDR}/login.cgi
# Everything OK? Check the curl return code.
local STATUS=$?
if [ ${STATUS} -ne 0 ]
then
echo "Login to ${IP_ADDR} ${USERNAME}:${PASSWORD} session ${SESSION_ID} failed with code ${STATUS}"
exit ${STATUS}
fi
}
#
# This function logs out of the mFi device
#
# Usage: mfi_logout SESSION_ID IP_ADDR
#
mfi_logout()
{
local SESSION_ID=${1}
local IP_ADDR=${2}
verbose_log "Calling mfi_logout with SESSION_ID=${SESSION_ID} IP_ADDR=${IP_ADDR}"
# Log out of the device
/usr/bin/curl \
-s \
-b 'AIROS_SESSIONID='${SESSION_ID} \
${IP_ADDR}/logout.cgi
# Everything OK? Check the curl return code.
local STATUS=$?
if [ ${STATUS} -ne 0 ]
then
echo "Logout from ${IP_ADDR} ${SESSION_ID} failed with code ${STATUS}"
exit ${STATUS}
fi
}
# This function gets the status of a device. The status is returned in the
# MFI_OUTPUT (0 or 1), MFI_DIM_LEVEL (0-100), and MFI_SWITCH_MODE ("switch" or
# "dimmer") global variables.
#
# Usage: mfi_get_status SESSION_ID IP_ADDR PORT
#
# Typical JSON output from the switch has a format similar to this. The 'jq'
# command is used to parse this information:
#
# {
# "sensors": [
# {
# "current": 0.0,
# "dimmer_level": 50,
# "dimmer_mode": "dimmer",
# "enabled": 0,
# "lock": 0,
# "output": 0,
# "port": 1,
# "power": 0.0,
# "powerfactor": 0.0,
# "prevmonth": 174253,
# "relay": 0,
# "thismonth": 44846,
# "voltage": 122.882881164
# }
# ],
# "status": "success"
# }
mfi_get_status()
{
local SESSION_ID=${1}
local IP_ADDR=${2}
local PORT=${3}
verbose_log "Calling mfi_get_status with SESSION_ID=${SESSION_ID} IP_ADDR=${IP_ADDR} PORT=${PORT}"
# Get the status from the device
local STATUS_JSON=$(/usr/bin/curl \
-s \
-b 'AIROS_SESSIONID='${SESSION_ID} \
${IP_ADDR}/sensors)
# Everything OK? Check both curl return code and JSON output
local STATUS=$?
if [ ${STATUS} -ne 0 ]
then
echo "Status retrieval from ${IP_ADDR} ${SESSION_ID} failed with code ${STATUS}"
mfi_logout ${SESSION_ID} ${IP_ADDR}
exit ${STATUS}
fi
local JSON_STATUS=$(/usr/bin/jq '.status' <<< ${STATUS_JSON})
if [ ${JSON_STATUS} != "\"success\"" ]
then
echo "Status in JSON output was not success: ${JSON_STATUS}. Retrieval from ${IP_ADDR} ${SESSION_ID} failed."
mfi_logout ${SESSION_ID} ${IP_ADDR}
exit -1
fi
# Get the output value for the selected port
MFI_OUTPUT=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.output
else empty end' <<< ${STATUS_JSON})
# Get the dimmer_level value for the selected port
MFI_DIM_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.dimmer_level
else empty end' <<< ${STATUS_JSON})
# Get the dimmer_mode value for the selected port
MFI_SWITCH_MODE=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.dimmer_mode
else empty end' <<< ${STATUS_JSON})
# Get the power value for the selected port
MFI_POWER_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.power
else empty end' <<< ${STATUS_JSON})
MFI_VOLTAGE_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.voltage
else empty end' <<< ${STATUS_JSON})
MFI_CURRENT_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.current
else empty end' <<< ${STATUS_JSON})
MFI_ENABLED_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.enabled
else empty end' <<< ${STATUS_JSON})
MFI_LOCK_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.lock
else empty end' <<< ${STATUS_JSON})
# MFI_OUTPUT_LEVEL=$(/usr/bin/jq \
# '.sensors[]? as $sensor |
# if $sensor.port == '"${PORT}"' then $sensor.output
# else empty end' <<< ${STATUS_JSON})
MFI_POWERFACTOR_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.powerfactor
else empty end' <<< ${STATUS_JSON})
MFI_PREVMONTH_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.prevmonth
else empty end' <<< ${STATUS_JSON})
MFI_RELAY_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.relay
else empty end' <<< ${STATUS_JSON})
MFI_THISMONTH_LEVEL=$(/usr/bin/jq \
'.sensors[]? as $sensor |
if $sensor.port == '"${PORT}"' then $sensor.thismonth
else empty end' <<< ${STATUS_JSON})
# If the dimmer_mode is "switch" then displayed DIM_LEVEL is 100%
local DISPLAYED_DIM_LEVEL=${MFI_DIM_LEVEL}
[ ${MFI_SWITCH_MODE} == "\"switch\"" ] && DISPLAYED_DIM_LEVEL=100
# If the dimmer_mode is not "switch" then lights are only mostly off
local DISPLAYED_EXTRA_INFO
[ ${MFI_SWITCH_MODE} != "\"switch\"" ] && DISPLAYED_EXTRA_INFO=" (mostly)"
# Print out a message about the current status
if [ ${MFI_OUTPUT} -ne 0 ]
then
echo "sensor.voltage:${MFI_VOLTAGE_LEVEL}, sensor.power:${MFI_POWER_LEVEL}, sensor.current:${MFI_CURRENT_LEVEL}, sensor.enabled:${MFI_ENABLED_LEVEL}, sensor.lock:${MFI_LOCK_LEVEL}, sensor.output:${MFI_OUTPUT}, sensor.powerfactor:${MFI_POWERFACTOR_LEVEL}, sensor.prevmonth:${MFI_PREVMONTH_LEVEL}, sensor.relay:${MFI_RELAY_LEVEL}, sensor.thismonth:${MFI_THISMONTH_LEVEL}"
#echo 0
exit 0
else
echo "sensor.voltage:${MFI_VOLTAGE_LEVEL}, sensor.power:${MFI_POWER_LEVEL}, sensor.current:${MFI_CURRENT_LEVEL}, sensor.enabled:${MFI_ENABLED_LEVEL}, sensor.lock:${MFI_LOCK_LEVEL}, sensor.output:${MFI_OUTPUT_LEVEL}, sensor.powerfactor:${MFI_POWERFACTOR_LEVEL}, sensor.prevmonth:${MFI_PREVMONTH_LEVEL}, sensor.relay:${MFI_RELAY_LEVEL}, sensor.thismonth:${MFI_THISMONTH_LEVEL}"
#echo 1
exit -1
fi
}
#
# This function turns on a device
#
# Usage: mfi_turn_on SESSION_ID IP_ADDR PORT DIMMER_LEVEL
#
mfi_turn_on()
{
local SESSION_ID=${1}
local IP_ADDR=${2}
local PORT=${3}
local DIMMER_LEVEL=${4}
verbose_log "Calling mfi_turn_on with SESSION_ID=${SESSION_ID} IP_ADDR=${IP_ADDR} PORT=${PORT} DIMMER_LEVEL=${DIMMER_LEVEL}"
# Turn the device on by enabling dimmer mode, output, and setting the dimmer level
# local PUT_JSON=$(/usr/bin/curl \
# -X PUT \
# -s \
# -d 'dimmer_mode=dimmer' \
# -b 'AIROS_SESSIONID='${SESSION_ID} \
# ${IP_ADDR}/sensors/${PORT})
local PUT_JSON=$(/usr/bin/curl \
-X PUT \
-s \
-d 'output=1' \
-b 'AIROS_SESSIONID='${SESSION_ID} \
${IP_ADDR}/sensors/${PORT})
# Everything OK? Check both curl return code and JSON output
local STATUS=$?
if [ ${STATUS} -ne 0 ]
then
echo "Turning on ${IP_ADDR} with session ${SESSION_ID} failed with code ${STATUS}"
mfi_logout ${SESSION_ID} ${IP_ADDR}
exit ${STATUS}
fi
local JSON_STATUS=$(/usr/bin/jq '.status' <<< ${PUT_JSON})
if [ ${JSON_STATUS} != "\"success\"" ]
then
echo "Status in JSON output was not success: ${JSON_STATUS}. Turning on ${IP_ADDR} ${SESSION_ID} failed."
mfi_logout ${SESSION_ID} ${IP_ADDR}
exit -1
fi
}
#
# This function turns off a device
#
# Usage: mfi_turn_off SESSION_ID IP_ADDR PORT
#
mfi_turn_off()
{
local SESSION_ID=${1}
local IP_ADDR=${2}
local PORT=${3}
verbose_log "Calling mfi_turn_off with SESSION_ID=${SESSION_ID} IP_ADDR=${IP_ADDR} PORT=${PORT}"
# Turn the device off by enabling switch mode, and turning off output and the relay
local PUT_JSON=$(/usr/bin/curl \
-X PUT \
-s \
-d 'dimmer_mode=switch' \
-b 'AIROS_SESSIONID='${SESSION_ID} \
${IP_ADDR}/sensors/${PORT})
local PUT_JSON=$(/usr/bin/curl \
-X PUT \
-s \
-d 'output=0&relay=0' \
-b 'AIROS_SESSIONID='${SESSION_ID} \
${IP_ADDR}/sensors/${PORT})
# Everything OK? Check both curl return code and JSON output
local STATUS=$?
if [ ${STATUS} -ne 0 ]
then
echo "Turning off ${IP_ADDR} with session ${SESSION_ID} failed with code ${STATUS}"
mfi_logout ${SESSION_ID} ${IP_ADDR}
exit ${STATUS}
fi
verbose_log "The JSON output is: ${PUT_JSON}"
local JSON_STATUS=$(/usr/bin/jq '.status' <<< ${PUT_JSON})
if [ ${JSON_STATUS} != "\"success\"" ]
then
echo "Status in JSON output was not success: ${JSON_STATUS}. Turning off ${IP_ADDR} ${SESSION_ID} failed."
mfi_logout ${SESSION_ID} ${IP_ADDR}
exit -1
fi
}
#------------------------------------------------------------------------------
#
# Script execution begins here
#
#------------------------------------------------------------------------------
#
# Parse command line options
#
cl_args="hvlp:u:a:"
while getopts "${cl_args}" a ; do
case $a in
h) mfictrl_usage
exit 0
;;
v) VERBOSE=1
;;
l) LOGMSG=1
;;
p) PORT=${OPTARG}
;;
u) USERNAME=${OPTARG}
;;
a) PASSWORD=${OPTARG}
;;
\?) mfictrl_usage
echo "*** The command line option -${OPTARG} is not recognized and will be ignored" >&2
;;
:) mfictrl_usage
echo "*** The command line option ${OPTARG} requires an argument" >&2
exit 1
;;
esac
done
shift $(($OPTIND-1))
#
# Get the IP address and operation
#
DEV_IP=${1}
shift 1
if [ -z "${DEV_IP}" ]
then
mfictrl_usage
echo "*** An IP address or DNS name of the mFi device is required." >&2
exit 1
fi
OPERATION=${1}
shift 1
if [ -z "${OPERATION}" ]
then
mfictrl_usage
echo "*** An operation to perform (ON, OFF, STATUS) is required." >&2
exit 1
fi
#
# Perform the requested operation
#
get_random_session_id
mfi_login ${USERNAME} ${PASSWORD} ${MFI_SESSION_ID} ${DEV_IP}
case ${OPERATION} in
STATUS|status)
verbose_log "Executing STATUS command"
mfi_get_status ${MFI_SESSION_ID} ${DEV_IP} ${PORT}
;;
ON|on)
DIM_LEVEL=$1
shift 1
if [ -z "${DIM_LEVEL}" ]
then
DIM_LEVEL=100
fi
verbose_log "Executing ON ${DIM_LEVEL} command"
mfi_turn_on ${MFI_SESSION_ID} ${DEV_IP} ${PORT} ${DIM_LEVEL}
if [ -n "${LOGMSG}" ]
then
mfi_get_status ${MFI_SESSION_ID} ${DEV_IP} ${PORT}
fi
;;
OFF|off)
verbose_log "Executing OFF command"
mfi_turn_off ${MFI_SESSION_ID} ${DEV_IP} ${PORT}
if [ -n "${LOGMSG}" ]
then
mfi_get_status ${MFI_SESSION_ID} ${DEV_IP} ${PORT}
fi
;;
*)
echo "Unsupported operation: ${OPERATION}" >&2
mfi_logout ${MFI_SESSION_ID} ${DEV_IP}
exit 1
;;
esac
mfi_logout ${MFI_SESSION_ID} ${DEV_IP}