Skip to content
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
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM node:trixie

# Create app directory
WORKDIR /rethink

# Copy project
COPY ./rethink /rethink

# Install dependencies
RUN npm install
RUN npm run build
# perhaps removing all unneeded files after building to clean up?
# Copy Bridge Service Script
COPY start-bridge-services.sh /start-bridge-services.sh
RUN chmod +x /start-bridge-services.sh

# Copy Entrypoint Script
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Expose ports
EXPOSE 443
EXPOSE 4433
EXPOSE 8884
EXPOSE 1884

ENTRYPOINT ["/entrypoint.sh"]
58 changes: 58 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

services:
rethink:
build:
context: .
dockerfile: Dockerfile
image: rethink:local
container_name: rethink
restart: unless-stopped
ports:
- "443:443"
- "8884:8884"
- "1884:1884"
environment:
# Hostname (cannot be an IP)
RETHINK_HOSTNAME: "common.lgthinq.com" # Create a DNS record to redirect this domain to your Rethink server's IP

# Local MQTT server settings
RETHINK_MQTT_URL: "mqtt://mqtt5:1883"
RETHINK_DISCOVERY_PREFIX: "homeassistant"
RETHINK_PREFIX: "rethink"
RETHINK_MQTT_USER: "user"
RETHINK_MQTT_PASS: "pass"

# Certificate files
RETHINK_CA_KEY_FILE: "ca.key" # Mounting key and cert files to another folder (for example /cert/ca.key) caused connectivity issues
RETHINK_CA_CERT_FILE: "ca.cert"

# Internal Server Ports
RETHINK_HTTPS_PORT: "443"
RETHINK_MQTTS_PORT: "8884"
RETHINK_MQTT_PORT: "1884"

# Server Mode
RETHINK_SERVER_MODE: "both" # Accepted values: "cloud", "bridge" or "both".

# Use if you are running CLOUD Service in a diffrent container and you want to spin up a Bridge for one Device only
RETHINK_COUNTRY_CODE: "PL"
RETHINK_DEVICE_TYPE: "401"
RETHINK_MODEL_NAME: "RAC_056905_WW"
RETHINK_DEVICE_ID: "68b5784e-3ae6-40ce-86d6-111fec8838e8"

# Persist of certificates and BRIDGE configuration for devices
volumes:
- ./config:/config

# Keep logs in RAM to avoid disk writes
tmpfs:
- /var/log/rethink:rw,mode=1777

# Healthcheck is not yet implimented. at the moment it simply checks if CLOUD Service is running
# mayby looking for errors in LOGS for Container Health?
healthcheck:
test: ps aux | grep "dist/rethink-cloud.js" | grep -v grep >/dev/null || exit 1
interval: 900s
timeout: 30s
retries: 3
start_period: 60s
141 changes: 141 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#!/bin/bash
set -e

# -------------------------
# Load environment variables
# -------------------------
RETHINK_HOSTNAME="${RETHINK_HOSTNAME:-rethink.lan}"
RETHINK_MQTT_URL="${RETHINK_MQTT_URL:-mqtt://localhost:1883}"
RETHINK_DISCOVERY_PREFIX="${RETHINK_DISCOVERY_PREFIX:-homeassistant}"
RETHINK_PREFIX="${RETHINK_PREFIX:-rethink}"
RETHINK_MQTT_USER="${RETHINK_MQTT_USER:-user}"
RETHINK_MQTT_PASS="${RETHINK_MQTT_PASS:-pass}"
RETHINK_CA_KEY_FILE="${RETHINK_CA_KEY_FILE:-ca.key}"
RETHINK_CA_CERT_FILE="${RETHINK_CA_CERT_FILE:-ca.cert}"
RETHINK_HTTPS_PORT="${RETHINK_HTTPS_PORT:-4433}"
RETHINK_MQTTS_PORT="${RETHINK_MQTTS_PORT:-8884}"
RETHINK_MQTT_PORT="${RETHINK_MQTT_PORT:-1884}"
RETHINK_SERVER_MODE="${RETHINK_SERVER_MODE:-both}"
RETHINK_DEVICE_ID="${RETHINK_DEVICE_ID:-68b5784e-3ae6-40ce-86d6-111fec8838e8}"
RETHINK_COUNTRY_CODE="${RETHINK_COUNTRY_CODE:-PL}"
RETHINK_MODEL_NAME="${RETHINK_MODEL_NAME:-RAC_056905_WW}"
RETHINK_DEVICE_TYPE="${RETHINK_DEVICE_TYPE:-401}"
RETHINK_LOG="${RETHINK_LOG:-[\"status\",\"incoming\"]}"

# Rewrite config.json
cat <<EOF >/rethink/config.json
{
"hostname": "$RETHINK_HOSTNAME",

"homeassistant": {
"mqtt_url": "$RETHINK_MQTT_URL",
"discovery_prefix": "$RETHINK_DISCOVERY_PREFIX",
"rethink_prefix": "$RETHINK_PREFIX",
"mqtt_user": "$RETHINK_MQTT_USER",
"mqtt_pass": "$RETHINK_MQTT_PASS"
},

"ca_key_file": "$RETHINK_CA_KEY_FILE",
"ca_cert_file": "$RETHINK_CA_CERT_FILE",
"https_port": $RETHINK_HTTPS_PORT,
"mqtts_port": $RETHINK_MQTTS_PORT,
"mqtt_port": $RETHINK_MQTT_PORT,

"log": $RETHINK_LOG
}
EOF

echo "[INFO] Generated /rethink/config.json:"
#cat /rethink/config.json

echo "[INFO] Syncing /config into /rethink as symbolic links..."
mkdir -p /config
# Iterate over all items including hidden files (but excluding . and ..)
shopt -s dotglob

for item in /config/*; do
name=$(basename "$item")
target="/rethink/$name"

echo "[INFO] Processing: $name"

# Remove existing file or directory at destination
if [ -e "$target" ] || [ -L "$target" ]; then
echo "[INFO] Removing existing $target"
rm -rf "$target" || echo "[WARN] Failed to remove $target"
fi

# Create symbolic link
ln -s "$item" "$target"
if [ $? -eq 0 ]; then
echo "[INFO] Linked $item → $target"
else
echo "[ERROR] Failed to link $item → $target"
fi
done

shopt -u dotglob

echo "[INFO] Finished syncing /config → /rethink"


# -------------------------
# Start services depending on mode
# -------------------------

echo "[INFO] Running in mode: $RETHINK_SERVER_MODE"
mkdir -p /var/log/rethink

# Start CLOUD mode

if [ "$RETHINK_SERVER_MODE" = "cloud" ] || [ "$RETHINK_SERVER_MODE" = "both" ]; then
echo "[INFO] Starting CLOUD service..."
npm run start > /var/log/rethink/cloud.log 2>&1 &
fi
sleep 5
echo "[INFO] Ensuring /config contains CA certificate and key"

for f in ca.cert ca.key; do
src="/rethink/$f"
dst="/config/$f"

if [ -f "$dst" ]; then
echo "[INFO] $dst already exists — not overwriting"
continue
fi

if [ ! -f "$src" ]; then
echo "[WARN] $src does not exist — cannot copy"
continue
fi

cp "$src" "$dst"
if [ $? -eq 0 ]; then
echo "[INFO] Copied $src → $dst"
else
echo "[ERROR] Failed to copy $src → $dst"
fi
done

# Start BRIDGE mode

if [ "$RETHINK_SERVER_MODE" = "both" ]; then
echo "[INFO] Starting BRIDGE services..."
/start-bridge-services.sh > /var/log/rethink/bridge.log 2>&1 &
fi

if [ "$RETHINK_SERVER_MODE" = "bridge" ]; then
echo "[INFO] Starting BRIDGE service for Device ID ${RETHINK_DEVICE_ID}..."
node dist/experimental/bridge/bridge.js \
mqtt://${RETHINK_HOSTNAME}:${RETHINK_MQTT_PORT}/ \
"$RETHINK_COUNTRY_CODE" \
"$RETHINK_DEVICE_TYPE" \
"$RETHINK_MODEL_NAME" \
"$RETHINK_DEVICE_ID" \
> /var/log/rethink/bridge.${RETHINK_DEVICE_ID}.log 2>&1 &
fi

# -------------------------
# Keep container alive
# -------------------------
exec tail -F /var/log/rethink/*.log
82 changes: 82 additions & 0 deletions start-bridge-services.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/bin/bash

CLOUD_LOG="/var/log/rethink/cloud.log"

echo "[INFO] Bridge watcher started"
echo "[INFO] Monitoring: $CLOUD_LOG"

# Ensure log file exists before tailing
if [ ! -f "$CLOUD_LOG" ]; then
echo "[WARN] Cloud log does not exist yet. Waiting..."
touch "$CLOUD_LOG"
fi

# Tail the log and process each line once
tail -Fn0 "$CLOUD_LOG" | while read -r line; do
# Skip empty or invalid lines
if [ -z "$line" ]; then
continue
fi

#echo "[INFO] Processing line: $line"

# Only process lines containing `"type":0`
# this is to process only lines that contain all the keys for Bridge mode
if ! echo "$line" | grep -q "\"type\":0"; then
#echo "[DEBUG] Line does not contain type 0. Skipping."
continue
fi

echo "[INFO] device connected to CLOUD Server."

# ------------------------------
# Extract values using sed
# ------------------------------

did=$(echo "$line" | sed -n 's/.*"did":"\([^"]*\)".*/\1/p')
country=$(echo "$line" | sed -n 's/.*"subCountryCode":"\([^"]*\)".*/\1/p')
model=$(echo "$line" | sed -n 's/.*"modelName":"\([^"]*\)".*/\1/p')
dtype=$(echo "$line" | sed -n 's/.*"DeviceType":"\([^"]*\)".*/\1/p')

# Check if values extracted
if [ -z "$did" ] || [ -z "$country" ] || [ -z "$model" ] || [ -z "$dtype" ]; then
echo "[ERROR] Failed to extract one or more required Key Values: did=$did country=$country model=$model dtype=$dtype"
continue
fi

echo "[INFO] Extracted Key DID: $did"
echo "[INFO] Extracted Key Country: $country"
echo "[INFO] Extracted Key Model: $model"
echo "[INFO] Extracted Key DeviceType: $dtype"

# ------------------------------
# Check if this bridge is already running
# ------------------------------

if ps aux | grep -v grep | grep -q "$did"; then
echo "[INFO] BRIDGE Service for Device ID $did already running. Skipping."
continue
fi

echo "[INFO] No running BRIDGE Services for Device ID $did. Starting new bridge instance..."

# ------------------------------
# Start the bridge service
# ------------------------------

LOGFILE="/var/log/rethink/bridge.${did}.log"
#echo "[INFO] Starting BRIDGE Server → logging to: $LOGFILE"

(
echo "[INFO] BRIDGE Service start for Device ID $did"
node dist/experimental/bridge/bridge.js \
"mqtt://${RETHINK_HOSTNAME}:${RETHINK_MQTT_PORT}/" \
"$country" \
"$dtype" \
"$model" \
"$did"
echo "[ERROR] BRIDGE Service for Device ID $did exited unexpectedly!"
) >"$LOGFILE" 2>&1 &

echo "[INFO] BRIDGE Service instance for Device ID $did started successfully."
done