Skip to content

Commit

Permalink
Merge pull request #18 from Snuffy2/Get-JuiceBox-ID-and-Save-Config
Browse files Browse the repository at this point in the history
Get JuiceBox ID and Save Config
  • Loading branch information
snicker authored Nov 14, 2023
2 parents f8b7ecc + 2151cae commit 10dd4ed
Show file tree
Hide file tree
Showing 6 changed files with 379 additions and 163 deletions.
15 changes: 7 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@ ENV MQTT_HOST="127.0.0.1"
ENV MQTT_PORT=1883
ENV MQTT_DISCOVERY_PREFIX="homeassistant"
ENV DEVICE_NAME="JuiceBox"
ENV ENELX_PORT=8047
ENV ENELX_SERVER="juicenet-udp-prod3-usa.enelx.com"
ENV SRC_DEFAULT="127.0.0.1"
ENV DST_DEFAULT="54.161.147.91"
ENV DEBUG=false

RUN pip install --upgrade pip
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y git curl dnsutils net-tools telnet expect
# RUN apt-get install -y iputils-ping netcat-traditional nano # Used for debugging
RUN apt-get update && apt-get install -y gnupg curl
RUN echo "deb https://ppa.launchpadcontent.net/rmescandon/yq/ubuntu jammy main" > /etc/apt/sources.list.d/yq.list
RUN echo "deb-src https://ppa.launchpadcontent.net/rmescandon/yq/ubuntu jammy main" >> /etc/apt/sources.list.d/yq.list
RUN curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x9a2d61f6bb03ced7522b8e7d6657dbe0cc86bb64' | gpg --dearmor | tee /etc/apt/trusted.gpg.d/yq.gpg
RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y git dnsutils net-tools telnet expect yq
RUN git clone https://github.com/snicker/juicepassproxy.git /juicepassproxy
RUN pip install --no-cache-dir -r /juicepassproxy/requirements.txt
RUN chmod +x /juicepassproxy/*.sh /juicepassproxy/*.expect

ENTRYPOINT /juicepassproxy/docker_entrypoint.sh
6 changes: 5 additions & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ _Hopefully we won't need this if EnelX fixes their API!_
## Docker Compose Installation

### Features
* If JuiceBox Local IP is defined, it will run a telnet script to get the EnelX Server and Port.
* If JuiceBox Local IP is defined, it will run a telnet script to get the EnelX Server and Port as well as the JuiceBox ID.

* If DST is not defined, it will use `dig` with the CloudFlare DNS (1.1.1.1) to get the IP address of the EnelX Server and avoid a DNS lookup loop.

Expand All @@ -27,6 +27,8 @@ _Hopefully we won't need this if EnelX fixes their API!_

B. Define the applicable environment variables _(see [Docker Environment Variables](#docker-environment-variables))_.

C. Specify the location for the config folder

1. Start the Docker container.

### Example Docker Compose
Expand Down Expand Up @@ -58,6 +60,7 @@ services:
- MQTT_PASS=***
volumes:
- /etc/localtime:/etc/localtime:ro
- ./config:/config
```
### Docker Environment Variables
Expand All @@ -67,6 +70,7 @@ Variable | Required | Description & Default |
**JUICEBOX_LOCAL_IP** | **Recommended** | If defined, it will attempt to get the EnelX Server and Port using Telnet. If unsuccessful, it will default to the EnelX Server and Port below.
**SRC** | No | If not defined, it will attempt to get the Local Docker IP. If unsuccessful, it will default to 127.0.0.1.
**DST** | No | If not defined, it will attempt to get the IP of the EnelX Server. If unsuccessful, it will default to 54.161.185.130. If manually defined, you should only use the IP address of the EnelX Server and not the fully qualified domain name to avoid DNS lookup loops.
**JUICEBOX_ID** | No | If not defined, it will attempt to get the JuiceBox ID using Telnet.
**ENELX_SERVER** | No | juicenet-udp-prod3-usa.enelx.com
**ENELX_PORT** | No | 8047
**MQTT_HOST** | No | 127.0.0.1
Expand Down
206 changes: 169 additions & 37 deletions docker_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,66 +1,198 @@
#!/bin/bash

NOW=$(date +'%x %X')
CONFIG_FILE="/config/juicepassproxy.yaml"
JUICEPASSPROXY="/juicepassproxy/juicepassproxy.py"
TELNET_GET_SERVER="/juicepassproxy/telnet_get_server.expect"
TELNET_GET_JUICEBOX_ID="/juicepassproxy/telnet_get_juicebox_id.expect"

ENELX_PORT_DEFAULT="8047"
ENELX_SERVER_DEFAULT="juicenet-udp-prod3-usa.enelx.com"
SRC_DEFAULT="127.0.0.1"
DST_DEFAULT="54.161.147.91"

RED='\033[1;31m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

function logger() {
if [ "${1^^}" != "DEBUG" ] || ($DEBUG && [ "${1^^}" = "DEBUG" ]); then
if [ "${1^^}" = "ERROR" ]; then
printf "%-15s ${RED}%-10s %s${NC}\n" "$(date +'%Y-%m-%d %H:%M:%S')" "${1^^}" "${2}"
elif [ "${1^^}" = "WARNING" ]; then
printf "%-15s ${YELLOW}%-10s %s${NC}\n" "$(date +'%Y-%m-%d %H:%M:%S')" "${1^^}" "${2}"
else
printf "%-15s %-10s %s\n" "$(date +'%Y-%m-%d %H:%M:%S')" "${1^^}" "${2}"
fi
fi
}

function valid_ip() {
local ip=$1
local stat=1

if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
return $stat
}

echo "--------------------------------"
echo "${NOW}: Starting JuicePassProxy"
logger info "Starting JuicePass Proxy"
echo ""
logger INFO "DEBUG: ${DEBUG}"

if test -f ${CONFIG_FILE}; then
logger DEBUG "Importing Config File"
JUICEBOX_ID_CONFIG="$(yq e '.JUICEBOX_ID' ${CONFIG_FILE})"
if [[ "${JUICEBOX_ID_CONFIG}" = "null" ]]; then
unset JUICEBOX_ID_CONFIG
fi
ENELX_SERVER_CONFIG="$(yq e '.ENELX_SERVER' ${CONFIG_FILE})"
if [[ "${ENELX_SERVER_CONFIG}" = "null" ]]; then
unset ENELX_SERVER_CONFIG
fi
ENELX_PORT_CONFIG="$(yq e '.ENELX_PORT' ${CONFIG_FILE})"
if [[ "${ENELX_PORT_CONFIG}" = "null" ]]; then
unset ENELX_PORT_CONFIG
fi
SRC_CONFIG="$(yq e '.SRC' ${CONFIG_FILE})"
if [[ "${SRC_CONFIG}" = "null" ]]; then
unset SRC_CONFIG
fi
DST_CONFIG="$(yq e '.DST' ${CONFIG_FILE})"
if [[ "${DST_CONFIG}" = "null" ]]; then
unset DST_CONFIG
fi
else
logger DEBUG "No Config File Found."
fi

if [ ! -z "${JUICEBOX_LOCAL_IP+x}" ]; then
echo "${NOW}: JUICEBOX_LOCAL_IP: ${JUICEBOX_LOCAL_IP}"
TELNET_STRING=$(/juicepassproxy/telnet_get_server.expect ${JUICEBOX_LOCAL_IP} | grep "UDPC")
retval=$?
if [ ${retval} -eq 0 ]; then
#echo "${NOW}: TELNET_STRING: ${TELNET_STRING}"
ENELX_SERVER=$(echo ${TELNET_STRING} | sed -E 's/(^.*[0-9]+.*UDPC[ ]+)(.*)(:.*)/\2/g')
#echo "${NOW}: ENELX_SERVER: ${ENELX_SERVER}"
ENELX_PORT=$(echo ${TELNET_STRING} | sed -E 's/(^.*:)(.*)([ ]+.*)/\2/g')
#echo "${NOW}: ENELX_PORT: ${ENELX_PORT}"
if [[ ! -z "${JUICEBOX_LOCAL_IP}" ]]; then
if [[ -z "${JUICEBOX_ID}" ]]; then
JUICEBOX_ID=$(${TELNET_GET_JUICEBOX_ID} ${JUICEBOX_LOCAL_IP} | sed -n 8p)
if [[ ! -z "${JUICEBOX_ID}" ]]; then
logger DEBUG "Sucessfully obtained JuiceBox ID."
JUICEBOX_ID=${JUICEBOX_ID%?}
elif [[ ! -z "${JUICEBOX_ID_CONFIG}" ]]; then
logger WARNING "Cannot get JuiceBox ID. Using config."
JUICEBOX_ID=${JUICEBOX_ID_CONFIG}
else
echo -e "\n${RED}******************************************************************************${NC}"
logger ERROR "Cannot get JuiceBox ID from Telnet. If a JuiceBox ID is later set or is obtained via Telnet, it will likely create a new JuiceBox Device with new Entities in Home Assistant."
echo -e "${RED}******************************************************************************${NC}\n"
unset JUICEBOX_ID
fi
fi

TELNET_SERVER_STRING=$(${TELNET_GET_SERVER} ${JUICEBOX_LOCAL_IP} | grep "UDPC")
if [[ ! -z "${TELNET_SERVER_STRING}" ]]; then
logger DEBUG "Sucessfully obtained EnelX Server and Port."
#logger debug "TELNET_SERVER_STRING: ${TELNET_SERVER_STRING}"
ENELX_SERVER=$(echo ${TELNET_SERVER_STRING} | sed -E 's/(# 2 UDPC[ ]+)(.*)(:.*)/\2/g')
ENELX_PORT=$(echo ${TELNET_SERVER_STRING} | sed -E 's/(.*:)(.*)([ ]+.*)/\2/g')
else
echo "ERROR getting EnelX Server from Telnet. Using defaults."
if [[ ! -z "${ENELX_SERVER_CONFIG}" ]]; then
logger WARNING "Cannot get EnelX Server from Telnet. Using config."
ENELX_SERVER=${ENELX_SERVER_CONFIG}
else
logger ERROR "Cannot get EnelX Server from Telnet. Not set in config. Using default."
ENELX_SERVER=${ENELX_SERVER_DEFAULT}
fi
if [[ ! -z "${ENELX_PORT_CONFIG}" ]]; then
logger WARNING "Cannot get EnelX Port from Telnet. Using config."
ENELX_PORT=${ENELX_PORT_CONFIG}
else
logger ERROR "Cannot get EnelX Port from Telnet. Not set in config. Using default."
ENELX_PORT=${ENELX_PORT_DEFAULT}
fi
fi
else
logger DEBUG "JuiceBox Local IP not defined."
fi
if [ -z "${SRC+x}" ]; then

if [[ -z "${SRC}" ]]; then
SRC=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p')
retval=$?
if [ ${retval} -ne 0 ]; then
echo "ERROR getting Docker Local IP. Using default."
if valid_ip ${SRC}; then
logger DEBUG "Sucessfully obtained Docker Local IP."
elif [[ ! -z "${SRC_CONFIG}" ]]; then
logger WARNING "Cannot get Docker Local IP. Using config."
SRC=${SRC_CONFIG}
else
logger ERROR "Cannot get Docker Local IP. Not set in config. Using default."
SRC=${SRC_DEFAULT}
fi
fi

if [ -z "${DST+x}" ]; then
if [[ -z "${DST}" ]]; then
DST=$(dig +short @1.1.1.1 ${ENELX_SERVER} | awk '{ getline ; print $1 ; exit }')
retval=$?
if [ ${retval} -ne 0 ]; then
echo "ERROR getting EnelX Server IP. Using default."
if valid_ip ${DST}; then
logger DEBUG "Sucessfully obtained EnelX Server IP."
elif [[ ! -z "${DST_CONFIG}" ]]; then
logger WARNING "Cannot get EnelX Server IP. Using config."
DST=${DST_CONFIG}
else
logger ERROR "Cannot get EnelX Server IP. Not set in config. Using default."
DST=${DST_DEFAULT}
fi
fi

JPP_STRING="python /juicepassproxy/juicepassproxy.py --src ${SRC}:${ENELX_PORT} --dst ${DST}:${ENELX_PORT} --host ${MQTT_HOST} --port ${MQTT_PORT} --discovery-prefix ${MQTT_DISCOVERY_PREFIX} --name ${DEVICE_NAME}"
JPP_STRING="python3 ${JUICEPASSPROXY} --src ${SRC}:${ENELX_PORT} --dst ${DST}:${ENELX_PORT} --host ${MQTT_HOST} --port ${MQTT_PORT} --discovery-prefix ${MQTT_DISCOVERY_PREFIX} --name ${DEVICE_NAME}"
echo ""
logger INFO "DEVICE_NAME: ${DEVICE_NAME}"
logger INFO "JUICEBOX_LOCAL_IP: ${JUICEBOX_LOCAL_IP}"
if [[ ! -z "${JUICEBOX_ID}" ]]; then
logger INFO "JUICEBOX_ID: ${JUICEBOX_ID}"
JPP_STRING+=" --juicebox-id ${JUICEBOX_ID}"
fi

echo "${NOW}: SRC: ${SRC}"
echo "${NOW}: DST: ${DST}"
echo "${NOW}: ENELX_SERVER: ${ENELX_SERVER}"
echo "${NOW}: ENELX_PORT: ${ENELX_PORT}"
echo "${NOW}: MQTT_HOST: ${MQTT_HOST}"
echo "${NOW}: MQTT_PORT: ${MQTT_PORT}"
if [ ! -z "${MQTT_USER+x}" ]; then
echo "${NOW}: MQTT_USER: ${MQTT_USER}"
logger INFO "SRC: ${SRC}"
logger INFO "DST: ${DST}"
logger INFO "ENELX_SERVER: ${ENELX_SERVER}"
logger INFO "ENELX_PORT: ${ENELX_PORT}"
logger INFO "MQTT_HOST: ${MQTT_HOST}"
logger INFO "MQTT_PORT: ${MQTT_PORT}"
if [[ ! -z "${MQTT_USER}" ]]; then
logger INFO "MQTT_USER: ${MQTT_USER}"
JPP_STRING+=" --user ${MQTT_USER}"
fi
if [ ! -z "${MQTT_PASS+x}" ]; then
echo "${NOW}: MQTT_PASS: $(echo ${MQTT_PASS} | sed -E 's/./*/g')"
if [[ ! -z "${MQTT_PASS}" ]]; then
logger INFO "MQTT_PASS: $(echo ${MQTT_PASS} | sed -E 's/./*/g')"
JPP_STRING+=" --password ${MQTT_PASS}"
fi
echo "${NOW}: MQTT_DISCOVERY_PREFIX: ${MQTT_DISCOVERY_PREFIX}"
echo "${NOW}: DEVICE_NAME: ${DEVICE_NAME}"
echo "${NOW}: DEBUG: ${DEBUG}"

if [ "${DEBUG}" = true ] ; then
logger INFO "MQTT_DISCOVERY_PREFIX: ${MQTT_DISCOVERY_PREFIX}"

if $DEBUG; then
JPP_STRING+=" --debug"
fi

echo "${NOW}: COMMAND: $(echo ${JPP_STRING} | sed -E 's/(--password )(\<.*\>)(.*)/\1*****\3/')"
touch ${CONFIG_FILE}
if [[ ! -z "${JUICEBOX_ID}" ]]; then
eval "yq e -i '.JUICEBOX_ID = \"${JUICEBOX_ID}\"' ${CONFIG_FILE}"
fi
if [[ ! -z "${ENELX_SERVER}" ]]; then
eval "yq e -i '.ENELX_SERVER = \"${ENELX_SERVER}\"' ${CONFIG_FILE}"
fi
if [[ ! -z "${ENELX_PORT}" ]]; then
eval "yq e -i '.ENELX_PORT = \"${ENELX_PORT}\"' ${CONFIG_FILE}"
fi
if [[ ! -z "${SRC}" ]]; then
eval "yq e -i '.SRC = \"${SRC}\"' ${CONFIG_FILE}"
fi
if [[ ! -z "${DST}" ]]; then
eval "yq e -i '.DST = \"${DST}\"' ${CONFIG_FILE}"
fi
if $DEBUG; then
echo -e "\n${CYAN}${CONFIG_FILE}:${NC}"
yq e /config/juicepassproxy.yaml
echo ""
fi
logger INFO "COMMAND: $(echo ${JPP_STRING} | sed -E 's/(--password )(\<.*\>)(.*)/\1*****\3/')"
eval ${JPP_STRING}
Loading

0 comments on commit 10dd4ed

Please sign in to comment.