commit 52234251b9bf5323a3d58b3c2d3a0619c52dee3f Author: Izan Gil <66965250+SrIzan10@users.noreply.github.com> Date: Sun Dec 15 13:24:48 2024 +0100 init diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..857d244 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,39 @@ +name: Publish Docker image + +on: + push: + branches: + - main + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: srizan10/dlink + tags: latest + + - name: Build and push Docker image + uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b1ee42 --- /dev/null +++ b/.gitignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..6725f25 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "useTabs": false, + "printWidth": 100, + "tabWidth": 2, + "singleQuote": true, + "trailingComma": "es5", + "semi": true +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e09af67 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM node:alpine AS builder + +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install + +COPY . . + +FROM node:alpine + +WORKDIR /app + +COPY --from=builder /app/package.json ./ +COPY --from=builder /app/yarn.lock ./ +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/index.js ./ + +ENV NODE_ENV=production + +EXPOSE 4000 + +CMD ["node", "index.js"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb47e17 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# dlink + +A really simple proxy for the TP-Link DSP-W115 and DSP-W245 smart plugs. Created with Home Assistant in mind, though setup has to be done manually. + +## Installation + +A Docker image is available on Docker Hub, so you can run the app with the following command: + +```bash +docker run -d -p 4000:4000 --name dlink -e IP=ip -e PIN=123456 --restart unless-stopped srizan10/dlink +``` +Or with docker-compose: +```yaml +services: + dlink: + image: srizan10/dlink + container_name: dlink + environment: + - IP=ip + - PIN=123456 + ports: + - 4000:4000 + restart: unless-stopped +``` + +## API routes +The routes require absolutely no authentication, so make sure to run the app in a secure environment. + +### GET /status +Returns the status of the plug. + +### POST /on +Turns the plug on. + +### POST /off +Turns the plug off. \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..b954305 --- /dev/null +++ b/index.js @@ -0,0 +1,33 @@ +import WebSocketClient from 'dlink_websocketclient'; +import { serve } from '@hono/node-server'; +import { Hono } from 'hono'; + +const client = new WebSocketClient({ + ip: process.env.IP, + pin: process.env.PIN, +}); + +const app = new Hono(); +app.get('/status', async (c) => { + const status = await client.state(); + return c.text(status ? 'on' : 'off'); +}); +app.post('/on', async (c) => { + await client.switch(true); + return c.text('cool'); +}); +app.post('/off', async (c) => { + await client.switch(false); + return c.text('cool'); +}); + +await client.login().then(() => console.log('Logged onto device')); +serve( + { + fetch: app.fetch, + port: 4000, + }, + (i) => { + console.log(`Server started on port ${i.port}`); + } +); diff --git a/package.json b/package.json new file mode 100644 index 0000000..ffb014e --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "dlink", + "scripts": { + "start": "node --env-file=.env index.js" + }, + "type": "module", + "dependencies": { + "@hono/node-server": "^1.13.7", + "dlink_websocketclient": "^0.5.5", + "hono": "^4.6.14" + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..cf57e43 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,25 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@hono/node-server@^1.13.7": + version "1.13.7" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.13.7.tgz#af95cf97bd24ddffc97e72851738cbde0a98c791" + integrity sha512-kTfUMsoloVKtRA2fLiGSd9qBddmru9KadNyhJCwgKBxTiNkaAJEwkVN9KV/rS4HtmmNRtUh6P+YpmjRMl0d9vQ== + +dlink_websocketclient@^0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/dlink_websocketclient/-/dlink_websocketclient-0.5.5.tgz#173638d875aa74020480477c625e3de54cc27971" + integrity sha512-pMpJSxoMCZRsglGlNR36mLjOdtLt9szQVqyOlRKquL5lzGdPs+no0nPGaxXuyqmaEMcAo7mL2VIUsUyeN4x05w== + dependencies: + ws "^8.13.0" + +hono@^4.6.14: + version "4.6.14" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.6.14.tgz#f83f51e81b8ae5611dab459570990bf4c977d20c" + integrity sha512-j4VkyUp2xazGJ8eCCLN1Vm/bxdvm/j5ZuU9AIjLu9vapn2M44p9L3Ktr9Vnb2RN2QtcR/wVjZVMlT5k7GJQgPw== + +ws@^8.13.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==