From 4f386ee3ed25ffb564b855ab5071ad785017cc71 Mon Sep 17 00:00:00 2001 From: Thuan Bui Date: Mon, 11 May 2026 04:17:54 +0000 Subject: [PATCH] Initialize sinric-n8n-bridge with Docker setup, environment configuration, and core functionality --- .env.example | 6 ++++++ .gitignore | 2 ++ Dockerfile | 10 +++++++++ README | 1 + compose.yml | 7 +++++++ index.js | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 8 +++++++ 7 files changed, 93 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README create mode 100644 compose.yml create mode 100644 index.js create mode 100644 package.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a20be52 --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +APP_KEY= +APP_SECRET= +DEVICE_ID= + +N8N_WEBHOOK_URL= +N8N_TOKEN= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6ed48a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +node_modules diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6e1d8ff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM node:22-alpine + +WORKDIR /app + +COPY package.json . +RUN npm install + +COPY index.js . + +CMD ["node", "index.js"] diff --git a/README b/README new file mode 100644 index 0000000..133c015 --- /dev/null +++ b/README @@ -0,0 +1 @@ +A lightweight Dockerized bridge that listens to Sinric Pro switch events and forwards them to n8n webhooks for home automation workflows. diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..ae38a75 --- /dev/null +++ b/compose.yml @@ -0,0 +1,7 @@ +services: + sinric-bridge: + build: . + container_name: sinric-bridge + restart: always + env_file: + - .env diff --git a/index.js b/index.js new file mode 100644 index 0000000..b15ba80 --- /dev/null +++ b/index.js @@ -0,0 +1,59 @@ +const axios = require("axios"); +const { SinricPro, SinricProSwitch } = require("sinricpro"); + +const APP_KEY = process.env.APP_KEY; +const APP_SECRET = process.env.APP_SECRET; +const DEVICE_ID = process.env.DEVICE_ID; + +const N8N_WEBHOOK_URL = process.env.N8N_WEBHOOK_URL; +const N8N_TOKEN = process.env.N8N_TOKEN; + +async function callN8n(action) { + try { + const res = await axios.post( + N8N_WEBHOOK_URL, + { action }, + { + headers: { + "X-Token": N8N_TOKEN, + "Content-Type": "application/json" + } + } + ); + + console.log(`[n8n] ${action} -> ${res.status}`); + } catch (err) { + console.error("[n8n error]", err.message); + } +} + +const device = new SinricProSwitch(DEVICE_ID); + +device.onPowerState(async (state) => { + const action = state ? "on" : "off"; + + console.log(`[sinric] ${action.toUpperCase()}`); + + await callN8n(action); + + return true; +}); + +const sinric = new SinricPro(); + +sinric.add(device); + +sinric.onConnected(() => { + console.log("[bridge] Connected"); +}); + +sinric.onDisconnected(() => { + console.log("[bridge] Disconnected"); +}); + +sinric.begin({ + appKey: APP_KEY, + appSecret: APP_SECRET, + server: "ws.sinric.pro", + port: 443 +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..de1466c --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "name": "sinric-bridge", + "version": "1.0.0", + "dependencies": { + "axios": "^1.7.0", + "sinricpro": "^5.1.0" + } +}