├── .eslintignore
├── admin
├── favicon.ico
├── homekit-controller.png
├── manifest.json
├── static
│ ├── media
│ │ ├── Upstairs.441813e54e0daca0882d.svg
│ │ ├── Outdoor Blinds.37b85a9c060a4af48da9.svg
│ │ ├── Garage Doors.0c2a1cfca7ad1ea59625.svg
│ │ ├── Doors.d59bf859f582d3488a04.svg
│ │ ├── Window.421664f57c35e5109aa2.svg
│ │ ├── Bedroom.2a16d8d98fafe965fd1b.svg
│ │ ├── Floor Lamps.471e0bcf308d94963504.svg
│ │ ├── Sockets.8320e1a99be9de004629.svg
│ │ ├── Handle.3de1d1320fc3ce2f9712.svg
│ │ ├── Hanging Lamps.0bd452fc843edd645c30.svg
│ │ ├── Tv.4e9745a548e57bfac0c7.svg
│ │ ├── Water Consumption.68891649591cc2434c5b.svg
│ │ ├── Stairwell.0914feea948153a8637a.svg
│ │ ├── Basement.fe636968eec9556bfd1f.svg
│ │ ├── Shed.491a2ad372036118002c.svg
│ │ ├── Shading.0577383dc227cd043b3d.svg
│ │ ├── Printer.146d983be964b95745d2.svg
│ │ ├── Carport.8337662544b9e95f4b27.svg
│ │ ├── Water Heater.7e4bb4d99a5213f24d08.svg
│ │ ├── Hall.9c2fa95419cb84ecda68.svg
│ │ ├── Storeroom.7de4e6f3364554459b8a.svg
│ │ ├── Power Consumption.4faab614c3c788f2d338.svg
│ │ ├── Ceiling Spotlights.485822441b5df3b3384a.svg
│ │ ├── Lock.2cbfe17ea8923e0f4e9e.svg
│ │ ├── Swimming Pool.190b378cb0707edb9461.svg
│ │ ├── Garage.f7fc0a9b326d582afee6.svg
│ │ ├── Outdoors.da42e64a4b6ec2dd1e1c.svg
│ │ ├── People.12a7e9127e72f3259186.svg
│ │ ├── Laundry Room.58da550dff0173676e02.svg
│ │ ├── Fan.8a29f85d6ca99c584603.svg
│ │ ├── Awnings.78480df8796f09859b6a.svg
│ │ ├── Washroom.bfb54196f381f36de9d6.svg
│ │ ├── Computer.9558f6ee3941dba4e3c5.svg
│ │ ├── Coffee Makers.9fb4d82f957a06f30dae.svg
│ │ ├── Attic.bb5d690a160bb1d4edb2.svg
│ │ ├── Table Lamps.bd92de33bf86b6cbaec9.svg
│ │ ├── Nursery.9cecc0544bdb5c28500c.svg
│ │ ├── Terrace.d71d07d9290674f2ca20.svg
│ │ ├── Guest Bathroom.d07a9f1cf32a82d03267.svg
│ │ ├── Receiver.26b5ae166395a6dcb83f.svg
│ │ ├── Sleeping Area.828017602bfcc2dd7dce.svg
│ │ ├── Dryer.5ea89bd6dc20a00fb442.svg
│ │ ├── Consumption.fecd7a10a13fe4e5f69b.svg
│ │ ├── Hairdryer.5960b514dac1f04f3c4d.svg
│ │ ├── Weather.e91dae647698d48365e3.svg
│ │ ├── Mowing Machine.9ead5b039f36cdc800e6.svg
│ │ ├── Playroom.e64c9de43030c28d2f96.svg
│ │ ├── Kitchen.deb7f976c1f43f9039a2.svg
│ │ ├── Wc.83604dd2daafb67067dd.svg
│ │ ├── Toilet.83604dd2daafb67067dd.svg
│ │ ├── Temperature Sensors.75d805988a6b77b231d8.svg
│ │ ├── Hoods.c177ddfec9fa9a6335db.svg
│ │ ├── Ventilation.c31761d86d67e245ac92.svg
│ │ ├── Led Strip.5cf2de461e29ffbaa5f0.svg
│ │ ├── Amplifier.6f5d18048328386033f8.svg
│ │ ├── Office.7e6a38218390b655e270.svg
│ │ ├── Boiler Room.548e785e2f92b45f72b3.svg
│ │ ├── Summer House.541a9fec69f01105e244.svg
│ │ ├── SmokeDetector.8222f77cb07030a409ee.svg
│ │ ├── Cold Water.937aad5fa21b0c20a856.svg
│ │ ├── Hot Water.5c0a9e01741562e1fbab.svg
│ │ ├── Stairway.9b007e08605296110003.svg
│ │ ├── Living Room.3c380ab767be35f904e1.svg
│ │ ├── Doorstep.10630b759b4867a10776.svg
│ │ ├── Iron.b8a65a48503b6f3e0dc8.svg
│ │ ├── Gates.5a8baf2c3d4832ca57e8.svg
│ │ ├── Speaker.db548379676317470c4f.svg
│ │ ├── Chamber.71daaa4d14262dae029b.svg
│ │ ├── Guest Room.41c7cfa38806f5009f82.svg
│ │ ├── Rear Wall.38843c33f1ea1f575500.svg
│ │ ├── Battery Status.5951e2078ae1e573510e.svg
│ │ ├── Barn.5d839e84c80918ce2ef0.svg
│ │ ├── Workshop.7856e59fe4f164c90609.svg
│ │ ├── Security.1ec78971bd34efa950f8.svg
│ │ ├── Chandelier.8b9fbdbc73bc2e955ef7.svg
│ │ └── Workspace.97d73e419d966bfb6428.svg
│ └── css
│ │ ├── main.96b3c861.css
│ │ └── main.96b3c861.css.map
└── index_m.html
├── .github
├── FUNDING.yml
├── dependabot.yml
├── auto-merge.yml
├── ISSUE_TEMPLATE
│ └── bug_report.md
├── workflows
│ └── dependabot-auto-merge.yml
└── stale.yml
├── srcAdmin
├── public
│ ├── favicon.ico
│ ├── homekit-controller.png
│ ├── manifest.json
│ └── index.html
├── src
│ ├── App.test.js
│ ├── index.css
│ ├── i18n
│ │ ├── zh-cn.json
│ │ ├── en.json
│ │ ├── uk.json
│ │ ├── it.json
│ │ ├── es.json
│ │ ├── de.json
│ │ ├── pl.json
│ │ ├── nl.json
│ │ ├── ru.json
│ │ ├── pt.json
│ │ └── fr.json
│ └── index.js
└── package.json
├── .releaseconfig.json
├── test
├── package.js
├── tsconfig.json
├── mocharc.custom.json
├── unit.js
├── integration.js
└── mocha.setup.js
├── src
├── lib
│ ├── converter
│ │ ├── base64.ts
│ │ ├── number-to-boolean.ts
│ │ ├── number-to-boolean-invert.ts
│ │ └── index.ts
│ ├── adapter-config.d.ts
│ └── tools.ts
└── main.test.ts
├── .babelrc
├── tsconfig.build.json
├── .gitignore
├── .npmignore
├── LICENSE
├── .create-adapter.json
├── tsconfig.json
├── .eslintrc.js
└── package.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/.eslintrc.js
2 | **/build
3 |
--------------------------------------------------------------------------------
/admin/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apollon77/ioBroker.homekit-controller/HEAD/admin/favicon.ico
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: Apollon77
4 | patreon: Apollon77
5 |
--------------------------------------------------------------------------------
/srcAdmin/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apollon77/ioBroker.homekit-controller/HEAD/srcAdmin/public/favicon.ico
--------------------------------------------------------------------------------
/admin/homekit-controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apollon77/ioBroker.homekit-controller/HEAD/admin/homekit-controller.png
--------------------------------------------------------------------------------
/.releaseconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["iobroker", "license"],
3 | "exec": {
4 | "before_commit": "npm run build"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/srcAdmin/public/homekit-controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apollon77/ioBroker.homekit-controller/HEAD/srcAdmin/public/homekit-controller.png
--------------------------------------------------------------------------------
/test/package.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { tests } = require('@iobroker/testing');
3 |
4 | // Validate the package files
5 | tests.packageFiles(path.join(__dirname, '..'));
6 |
--------------------------------------------------------------------------------
/test/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "noImplicitAny": false
5 | },
6 | "include": [
7 | "./**/*.js"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/test/mocharc.custom.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": [
3 | "test/mocha.setup.js",
4 | "ts-node/register",
5 | "source-map-support/register"
6 | ],
7 | "watch-files": [
8 | "src/**/*.test.ts"
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/unit.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { tests } = require('@iobroker/testing');
3 |
4 | // Run unit tests - See https://github.com/ioBroker/testing for a detailed explanation and further options
5 | tests.unit(path.join(__dirname, '..'));
6 |
--------------------------------------------------------------------------------
/test/integration.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { tests } = require('@iobroker/testing');
3 |
4 | // Run integration tests - See https://github.com/ioBroker/testing for a detailed explanation and further options
5 | tests.integration(path.join(__dirname, '..'));
6 |
--------------------------------------------------------------------------------
/srcAdmin/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/src/lib/converter/base64.ts:
--------------------------------------------------------------------------------
1 | import { ConverterType } from './index';
2 |
3 | export default {
4 | read: (value: ioBroker.StateValue): ioBroker.StateValue => {
5 | return value;
6 | },
7 | write: (value: ioBroker.StateValue): ioBroker.StateValue => {
8 | return value;
9 | }
10 | } as ConverterType;
11 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-typescript",
4 | ["@babel/preset-env", { "targets": { "node": "current" } }]
5 | ],
6 | "plugins": [
7 | ["@babel/plugin-transform-typescript", { "allowDeclareFields": true }],
8 | ["@babel/plugin-proposal-decorators", { "legacy": true }]
9 | ]
10 | }
--------------------------------------------------------------------------------
/src/lib/converter/number-to-boolean.ts:
--------------------------------------------------------------------------------
1 | import { ConverterType } from './index';
2 |
3 | export default {
4 | read: (value: ioBroker.StateValue): ioBroker.StateValue => {
5 | return !!value;
6 | },
7 | write: (value: ioBroker.StateValue): ioBroker.StateValue => {
8 | return value ? 1 : 0;
9 | }
10 | } as ConverterType;
11 |
--------------------------------------------------------------------------------
/src/lib/converter/number-to-boolean-invert.ts:
--------------------------------------------------------------------------------
1 | import { ConverterType } from './index';
2 |
3 | export default {
4 | read: (value: ioBroker.StateValue): ioBroker.StateValue => {
5 | return !value;
6 | },
7 | write: (value: ioBroker.StateValue): ioBroker.StateValue => {
8 | return value ? 0 : 1;
9 | }
10 | } as ConverterType;
11 |
--------------------------------------------------------------------------------
/admin/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Homekit-Controller",
3 | "name": "ioBroker Homekit-Controller Settings",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/srcAdmin/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Homekit-Controller",
3 | "name": "ioBroker Homekit-Controller Settings",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | // Specialized tsconfig to only compile .ts-files in the src dir
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "allowJs": false,
6 | "checkJs": false,
7 | "noEmit": false,
8 | "declaration": false
9 | },
10 | "include": [
11 | "src/**/*.ts"
12 | ],
13 | "exclude": [
14 | "src/**/*.test.ts"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .git
2 | .idea
3 | *.code-workspace
4 | node_modules
5 | nbproject
6 | .cache
7 |
8 | # Sourcemaps
9 | maps/
10 |
11 | # npm package files
12 | iobroker.*.tgz
13 |
14 | Thumbs.db
15 |
16 | # i18n intermediate files
17 | admin/i18n/flat.txt
18 | admin/i18n/*/flat.txt
19 |
20 | .dev-server
21 | /admin/src/package-lock.json
22 | /srcAdmin/package-lock.json
23 | /srcAdmin/build
24 |
25 | #ignore .commitinfo created by ioBroker release script
26 | .commitinfo
27 |
--------------------------------------------------------------------------------
/admin/static/media/Upstairs.441813e54e0daca0882d.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .*
2 | node_modules/
3 | nbproject/
4 | *.code-workspace
5 | Thumbs.db
6 | gulpfile.js
7 |
8 | # CI test files
9 | test/
10 | travis/
11 | appveyor.yaml
12 |
13 | # React sources for the Admin UI
14 | srcAdmin/
15 |
16 | # TypeScript sources and project configuration
17 | src/
18 | tsconfig.json
19 | tsconfig.*.json
20 |
21 | # Sourcemaps
22 | *.map
23 |
24 | # npm package files
25 | iobroker.*.tgz
26 | package-lock.json
27 |
28 | # maintenance scripts
29 | maintenance/**
30 |
31 | .dev-server
32 |
--------------------------------------------------------------------------------
/admin/static/css/main.96b3c861.css:
--------------------------------------------------------------------------------
1 | body,html{height:100%}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0;overflow:hidden;padding:0;width:100%}::-webkit-scrollbar,::-webkit-scrollbar-track{background-color:#ccc}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-thumb{background-color:#575757}#root,.App{height:100%}
2 | /*# sourceMappingURL=main.96b3c861.css.map*/
--------------------------------------------------------------------------------
/src/lib/converter/index.ts:
--------------------------------------------------------------------------------
1 | import Base64Converter from './base64';
2 | import NumberToBooleanConverter from './number-to-boolean';
3 | import NumberToBooleanInvertConverter from './number-to-boolean-invert';
4 |
5 | export interface ConverterType {
6 | read: (value: ioBroker.StateValue) => ioBroker.StateValue,
7 | write: (value: ioBroker.StateValue) => ioBroker.StateValue,
8 | }
9 |
10 | export default {
11 | 'base64': Base64Converter,
12 | 'number-to-boolean': NumberToBooleanConverter,
13 | 'number-to-boolean-invert': NumberToBooleanInvertConverter
14 | };
15 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Dependabot will run on day 20 of each month at 01:31 (Europe/Berlin timezone)
2 | version: 2
3 | updates:
4 |
5 | - package-ecosystem: "github-actions"
6 | directory: "/"
7 | schedule:
8 | interval: "cron"
9 | timezone: "Europe/Berlin"
10 | cronjob: "31 1 20 * *"
11 | open-pull-requests-limit: 15
12 |
13 | - package-ecosystem: "npm"
14 | schedule:
15 | interval: "cron"
16 | timezone: "Europe/Berlin"
17 | cronjob: "31 1 20 * *"
18 | open-pull-requests-limit: 20
19 | versioning-strategy: "increase"
20 | directories:
21 | - "**/*"
22 |
--------------------------------------------------------------------------------
/admin/index_m.html:
--------------------------------------------------------------------------------
1 |
Homekit-Controller Settings
--------------------------------------------------------------------------------
/src/lib/adapter-config.d.ts:
--------------------------------------------------------------------------------
1 | // This file extends the AdapterConfig type from "@types/iobroker"
2 |
3 | // Augment the globally declared type ioBroker.AdapterConfig
4 | declare global {
5 | namespace ioBroker {
6 | interface AdapterConfig {
7 | discoverIp: boolean;
8 | discoverBle: boolean;
9 | dataPollingIntervalIp: number;
10 | dataPollingIntervalBle: number;
11 | bleInterface: string;
12 | updateOnlyChangedValues: boolean;
13 | }
14 | }
15 | }
16 |
17 | // this is required so the above AdapterConfig is found by TypeScript / type checking
18 | export {};
19 |
--------------------------------------------------------------------------------
/admin/static/media/Outdoor Blinds.37b85a9c060a4af48da9.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/auto-merge.yml:
--------------------------------------------------------------------------------
1 | # Configure here which dependency updates should be merged automatically.
2 | # The recommended configuration is the following:
3 | - match:
4 | # Only merge patches for production dependencies
5 | dependency_type: production
6 | update_type: "semver:patch"
7 | - match:
8 | # Except for security fixes, here we allow minor patches
9 | dependency_type: production
10 | update_type: "security:minor"
11 | - match:
12 | # and development dependencies can have a minor update, too
13 | dependency_type: development
14 | update_type: "semver:minor"
15 |
16 | # The syntax is based on the legacy dependabot v1 automerged_updates syntax, see:
17 | # https://dependabot.com/docs/config-file/#automerged_updates
18 |
--------------------------------------------------------------------------------
/srcAdmin/src/index.css:
--------------------------------------------------------------------------------
1 | html {
2 | height: 100%;
3 | }
4 | body {
5 | margin: 0;
6 | padding: 0;
7 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
8 | -webkit-font-smoothing: antialiased;
9 | -moz-osx-font-smoothing: grayscale;
10 | width: 100%;
11 | height: 100%;
12 | overflow: hidden;
13 | }
14 | /* scrollbar */
15 | *::-webkit-scrollbar-track {
16 | background-color: #ccc;
17 | }
18 | *::-webkit-scrollbar {
19 | width: 6px;
20 | background-color: #ccc;
21 | }
22 | *::-webkit-scrollbar-thumb {
23 | background-color: #575757;
24 | }
25 |
26 |
27 | #root {
28 | height: 100%;
29 | }
30 | .App {
31 | height: 100%;
32 | }
--------------------------------------------------------------------------------
/admin/static/media/Garage Doors.0c2a1cfca7ad1ea59625.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/admin/static/media/Doors.d59bf859f582d3488a04.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/mocha.setup.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Makes ts-node ignore warnings, so mocha --watch does work
4 | process.env.TS_NODE_IGNORE_WARNINGS = 'TRUE';
5 | // Sets the correct tsconfig for testing
6 | process.env.TS_NODE_PROJECT = 'tsconfig.json';
7 | // Make ts-node respect the "include" key in tsconfig.json
8 | process.env.TS_NODE_FILES = 'TRUE';
9 |
10 | // Don't silently swallow unhandled rejections
11 | process.on('unhandledRejection', (e) => {
12 | throw e;
13 | });
14 |
15 | // enable the should interface with sinon
16 | // and load chai-as-promised and sinon-chai by default
17 | const sinonChai = require('sinon-chai');
18 | const chaiAsPromised = require('chai-as-promised');
19 | const { should, use } = require('chai');
20 |
21 | should();
22 | use(sinonChai);
23 | use(chaiAsPromised);
--------------------------------------------------------------------------------
/admin/static/media/Window.421664f57c35e5109aa2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/main.test.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This is a dummy TypeScript test file using chai and mocha
3 | *
4 | * It's automatically excluded from npm and its build output is excluded from both git and npm.
5 | * It is advised to test all your modules with accompanying *.test.ts-files
6 | */
7 |
8 | import { expect } from 'chai';
9 | // import { functionToTest } from "./moduleToTest";
10 |
11 | describe('module to test => function to test', () => {
12 | // initializing logic
13 | const expected = 5;
14 |
15 | it(`should return ${expected}`, () => {
16 | const result = 5;
17 | // assign result a value from functionToTest
18 | expect(result).to.equal(expected);
19 | // or using the should() syntax
20 | result.should.equal(expected);
21 | });
22 | // ... more tests => it
23 |
24 | });
25 |
26 | // ... more test suites => describe
27 |
--------------------------------------------------------------------------------
/admin/static/css/main.96b3c861.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"static/css/main.96b3c861.css","mappings":"AAGA,UAFE,WAWF,CATA,KAIE,kCAAmC,CACnC,iCAAkC,CAFlC,mIAA8J,CAF9J,QAAS,CAOT,eAAgB,CANhB,SAAU,CAIV,UAGF,CAKA,8CAFE,qBAKF,CAHA,oBACE,SAEF,CACA,0BACE,wBACF,CAMA,WACE,WACF","sources":["index.css"],"sourcesContent":["html {\n height: 100%;\n}\nbody {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\", \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n/* scrollbar */\n*::-webkit-scrollbar-track {\n background-color: #ccc;\n}\n*::-webkit-scrollbar {\n width: 6px;\n background-color: #ccc;\n}\n*::-webkit-scrollbar-thumb {\n background-color: #575757;\n}\n\n\n#root {\n height: 100%;\n}\n.App {\n height: 100%;\n}"],"names":[],"sourceRoot":""}
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/zh-cn.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "错误",
3 | "Paired": "配对",
4 | "Unpaired": "未配对",
5 | "Identified": "已鉴定",
6 | "Connected": "连接的",
7 | "Discovered": "发现",
8 | "Identify": "确认",
9 | "Pair": "一对",
10 | "Unpair": "取消配对",
11 | "Refresh devices list": "刷新设备列表",
12 | "ID": "ID",
13 | "Type": "类型",
14 | "Name": "名称",
15 | "Category": "类别",
16 | "Please enter PIN": "请输入密码",
17 | "PIN": "别针",
18 | "Close": "关闭",
19 | "Instance must be started to set up the devices": "必须启动实例才能设置设备",
20 | "Start?": "开始?",
21 | "Discover over IP": "通过 IP 发现",
22 | "Discover over Bluetooth": "通过蓝牙发现",
23 | "Data polling interval for IP": "IP 的数据轮询间隔",
24 | "Data polling interval for Bluetooth": "蓝牙数据轮询间隔",
25 | "Update only changed values": "仅更新更改的值",
26 | "Options": "选项",
27 | "Devices": "设备",
28 | "seconds": "秒",
29 | "Are you sure?": "你确定吗?",
30 | "Please confirm": "请确认",
31 | "Cancel": "取消"
32 | }
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Something is not working as it should
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 | **Describe the bug**
10 | A clear and concise description of what the bug is.
11 |
12 | **To Reproduce**
13 | Steps to reproduce the behavior:
14 | 1. Go to '...'
15 | 2. Click on '...'
16 | 3. Scroll down to '....'
17 | 4. See error
18 |
19 | **Expected behavior**
20 | A clear and concise description of what you expected to happen.
21 |
22 | **Screenshots & Logfiles**
23 | If applicable, add screenshots and logfiles to help explain your problem.
24 |
25 | **Versions:**
26 | - Adapter version:
27 | - JS-Controller version:
28 | - Node version:
29 | - Operating system:
30 |
31 | **Additional context**
32 | Add any other context about the problem here.
33 |
--------------------------------------------------------------------------------
/admin/static/media/Bedroom.2a16d8d98fafe965fd1b.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/admin/static/media/Floor Lamps.471e0bcf308d94963504.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/srcAdmin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "homekit-controller-admin",
3 | "version": "0.5.11",
4 | "private": true,
5 | "dependencies": {
6 | "@iobroker/adapter-react-v5": "^4.9.5",
7 | "@mui/material": "5.14.14",
8 | "@mui/styles": "5.14.14",
9 | "@mui/icons-material": "^5.15.6",
10 | "@sentry/browser": "^7.98.0",
11 | "@sentry/integrations": "^7.98.0",
12 | "babel-eslint": "^10.1.0",
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "react-icons": "^5.0.1",
16 | "react-scripts": "^5.0.1"
17 | },
18 | "scripts": {
19 | "start": "react-scripts start",
20 | "build": "react-scripts build",
21 | "test": "react-scripts test",
22 | "eject": "react-scripts eject"
23 | },
24 | "eslintConfig": {
25 | "extends": "react-app"
26 | },
27 | "homepage": ".",
28 | "browserslist": [
29 | ">0.2%",
30 | "not dead",
31 | "not ie <= 11",
32 | "not op_mini all"
33 | ]
34 | }
--------------------------------------------------------------------------------
/.github/workflows/dependabot-auto-merge.yml:
--------------------------------------------------------------------------------
1 | # Automatically merge Dependabot PRs when version comparison is within the range
2 | # that is configured in .github/auto-merge.yml
3 |
4 | name: Auto-Merge Dependabot PRs
5 |
6 | on:
7 | # WARNING: This needs to be run in the PR base, DO NOT build untrusted code in this action
8 | # details under https://github.blog/changelog/2021-02-19-github-actions-workflows-triggered-by-dependabot-prs-will-run-with-read-only-permissions/
9 | pull_request_target:
10 |
11 | jobs:
12 | auto-merge:
13 | if: github.actor == 'dependabot[bot]'
14 | runs-on: ubuntu-latest
15 | steps:
16 | - name: Checkout code
17 | uses: actions/checkout@v4
18 |
19 | - name: Check if PR should be auto-merged
20 | uses: ahmadnassri/action-dependabot-auto-merge@v2
21 | with:
22 | # This must be a personal access token with push access
23 | github-token: ${{ secrets.AUTO_MERGE_TOKEN }}
24 | # By default, squash and merge, so Github chooses nice commit messages
25 | command: squash and merge
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021-2024 Ingo Fischer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/admin/static/media/Sockets.8320e1a99be9de004629.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/admin/static/media/Handle.3de1d1320fc3ce2f9712.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Error",
3 | "Paired": "Paired",
4 | "Unpaired": "Unpaired",
5 | "Identified": "Identified",
6 | "Connected": "Connected",
7 | "Discovered": "Discovered",
8 | "Identify": "Identify",
9 | "Pair": "Pair",
10 | "Unpair": "Unpair",
11 | "Refresh devices list": "Refresh the device list",
12 | "ID": "ID",
13 | "Type": "Type",
14 | "Name": "Name",
15 | "Category": "Category",
16 | "Please enter PIN": "Please enter PIN",
17 | "PIN": "PIN",
18 | "Close": "Close",
19 | "Instance must be started to set up the devices": "Instance must be started to set up the devices",
20 | "Start?": "Start?",
21 | "Discover over IP": "Discover over IP",
22 | "Discover over Bluetooth": "Discover over Bluetooth",
23 | "Data polling interval for IP": "Data polling interval for IP",
24 | "Data polling interval for Bluetooth": "Data polling interval for Bluetooth",
25 | "Update only changed values": "Update only changed values",
26 | "Options": "Options",
27 | "Devices": "Devices",
28 | "seconds": "seconds",
29 | "Are you sure?": "Are you sure?",
30 | "Please confirm": "Please confirm",
31 | "Cancel": "Cancel"
32 | }
33 |
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/uk.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure?": "Ти впевнений?",
3 | "Cancel": "Скасувати",
4 | "Category": "Категорія",
5 | "Close": "Закрити",
6 | "Connected": "Підключено",
7 | "Data polling interval for Bluetooth": "Інтервал опитування даних для Bluetooth",
8 | "Data polling interval for IP": "Інтервал опитування даних для IP",
9 | "Devices": "Пристрої",
10 | "Discover over Bluetooth": "Відкривайте через Bluetooth",
11 | "Discover over IP": "Відкривайте через IP",
12 | "Discovered": "Виявлено",
13 | "Error": "Помилка",
14 | "ID": "ID",
15 | "Identified": "Ідентифікований",
16 | "Identify": "Ідентифікувати",
17 | "Instance must be started to set up the devices": "Для налаштування пристроїв необхідно запустити екземпляр",
18 | "Name": "Ім'я",
19 | "Options": "Опції",
20 | "PIN": "PIN-код",
21 | "Pair": "Пара",
22 | "Paired": "Парні",
23 | "Please confirm": "Будь-ласка підтвердіть",
24 | "Please enter PIN": "Введіть PIN-код",
25 | "Refresh devices list": "Оновіть список пристроїв",
26 | "Start?": "почати?",
27 | "Type": "Тип",
28 | "Unpair": "Розірвати пару",
29 | "Unpaired": "Без пари",
30 | "Update only changed values": "Оновлювати лише змінені значення",
31 | "seconds": "секунд"
32 | }
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/it.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Errore",
3 | "Paired": "accoppiato",
4 | "Unpaired": "non abbinato",
5 | "Identified": "Identificato",
6 | "Connected": "Collegato",
7 | "Discovered": "Scoperto",
8 | "Identify": "Identificare",
9 | "Pair": "Coppia",
10 | "Unpair": "Disaccoppia",
11 | "Refresh devices list": "Aggiorna l'elenco dei dispositivi",
12 | "ID": "ID",
13 | "Type": "Tipo",
14 | "Name": "Nome",
15 | "Category": "Categoria",
16 | "Please enter PIN": "Si prega di inserire il PIN",
17 | "PIN": "SPILLO",
18 | "Close": "Chiudere",
19 | "Instance must be started to set up the devices": "L'istanza deve essere avviata per configurare i dispositivi",
20 | "Start?": "Cominciare?",
21 | "Discover over IP": "Scopri su IP",
22 | "Discover over Bluetooth": "Scopri tramite Bluetooth",
23 | "Data polling interval for IP": "Intervallo di polling dati per IP",
24 | "Data polling interval for Bluetooth": "Intervallo di polling dati per Bluetooth",
25 | "Update only changed values": "Aggiorna solo i valori modificati",
26 | "Options": "Opzioni",
27 | "Devices": "Dispositivi",
28 | "seconds": "secondi",
29 | "Are you sure?": "Sei sicuro?",
30 | "Please confirm": "Si prega di confermare",
31 | "Cancel": "Annulla"
32 | }
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/es.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Error",
3 | "Paired": "Emparejado",
4 | "Unpaired": "Desemparejado",
5 | "Identified": "Identificado",
6 | "Connected": "Conectado",
7 | "Discovered": "Descubierto",
8 | "Identify": "Identificar",
9 | "Pair": "Par",
10 | "Unpair": "Desemparejar",
11 | "Refresh devices list": "Actualizar la lista de dispositivos",
12 | "ID": "ID",
13 | "Type": "Escribe",
14 | "Name": "Nombre",
15 | "Category": "Categoría",
16 | "Please enter PIN": "Por favor ingrese su PIN",
17 | "PIN": "ALFILER",
18 | "Close": "Cerrar",
19 | "Instance must be started to set up the devices": "Se debe iniciar la instancia para configurar los dispositivos",
20 | "Start?": "¿Comienzo?",
21 | "Discover over IP": "Descubrir sobre IP",
22 | "Discover over Bluetooth": "Descubrir por Bluetooth",
23 | "Data polling interval for IP": "Intervalo de sondeo de datos para IP",
24 | "Data polling interval for Bluetooth": "Intervalo de sondeo de datos para Bluetooth",
25 | "Update only changed values": "Actualizar solo los valores modificados",
26 | "Options": "Opciones",
27 | "Devices": "Dispositivos",
28 | "seconds": "segundos",
29 | "Are you sure?": "¿Está seguro?",
30 | "Please confirm": "Por favor confirmar",
31 | "Cancel": "Cancelar"
32 | }
--------------------------------------------------------------------------------
/admin/static/media/Hanging Lamps.0bd452fc843edd645c30.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Tv.4e9745a548e57bfac0c7.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Fehler",
3 | "Paired": "Gepaart",
4 | "Unpaired": "Nicht gekoppelt",
5 | "Identified": "Identifiziert",
6 | "Connected": "Verbunden",
7 | "Discovered": "Entdeckt",
8 | "Identify": "Identifizieren",
9 | "Pair": "Paaren",
10 | "Unpair": "Entkoppeln",
11 | "Refresh devices list": "Aktualisieren Sie die Geräteliste",
12 | "ID": "ID",
13 | "Type": "Typ",
14 | "Name": "Name",
15 | "Category": "Kategorie",
16 | "Please enter PIN": "Bitte PIN eingeben",
17 | "PIN": "PIN",
18 | "Close": "Schließen",
19 | "Instance must be started to set up the devices": "Instanz muss zum Einrichten der Geräte gestartet werden",
20 | "Start?": "Starten?",
21 | "Discover over IP": "Über IP entdecken",
22 | "Discover over Bluetooth": "Über Bluetooth entdecken",
23 | "Data polling interval for IP": "Datenabfrageintervall für IP",
24 | "Data polling interval for Bluetooth": "Datenabfrageintervall für Bluetooth",
25 | "Update only changed values": "Nur geänderte Werte aktualisieren",
26 | "Options": "Optionen",
27 | "Devices": "Geräte",
28 | "seconds": "Sekunden",
29 | "Are you sure?": "Wirklich sicher?",
30 | "Please confirm": "Bitte bestätigen",
31 | "Cancel": "Abbrechen"
32 | }
33 |
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/pl.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Błąd",
3 | "Paired": "Sparowane",
4 | "Unpaired": "Nieparzysty",
5 | "Identified": "Zidentyfikowane",
6 | "Connected": "Połączony",
7 | "Discovered": "Odkryty",
8 | "Identify": "Zidentyfikować",
9 | "Pair": "Para",
10 | "Unpair": "Usuń sparowanie",
11 | "Refresh devices list": "Odśwież listę urządzeń",
12 | "ID": "ID",
13 | "Type": "Typ",
14 | "Name": "Nazwa",
15 | "Category": "Kategoria",
16 | "Please enter PIN": "Wprowadź kod PIN",
17 | "PIN": "SZPILKA",
18 | "Close": "Zamknij",
19 | "Instance must be started to set up the devices": "Aby skonfigurować urządzenia, należy uruchomić instancję",
20 | "Start?": "Początek?",
21 | "Discover over IP": "Odkryj przez IP",
22 | "Discover over Bluetooth": "Odkryj przez Bluetooth",
23 | "Data polling interval for IP": "Interwał odpytywania danych dla IP",
24 | "Data polling interval for Bluetooth": "Interwał odpytywania danych dla Bluetooth",
25 | "Update only changed values": "Aktualizuj tylko zmienione wartości",
26 | "Options": "Opcje",
27 | "Devices": "Urządzenia",
28 | "seconds": "sekund",
29 | "Are you sure?": "Jesteś pewny?",
30 | "Please confirm": "Proszę potwierdzić",
31 | "Cancel": "Odwołaj"
32 | }
33 |
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/nl.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Fout",
3 | "Paired": "Gekoppeld",
4 | "Unpaired": "ongepaarde",
5 | "Identified": "geïdentificeerd",
6 | "Connected": "Verbonden",
7 | "Discovered": "ontdekt",
8 | "Identify": "Identificeren",
9 | "Pair": "Paar",
10 | "Unpair": "Ontkoppelen",
11 | "Refresh devices list": "Vernieuw de apparatenlijst",
12 | "ID": "ID",
13 | "Type": "Type",
14 | "Name": "Naam",
15 | "Category": "Categorie",
16 | "Please enter PIN": "Voer pincode in",
17 | "PIN": "PIN",
18 | "Close": "Dichtbij",
19 | "Instance must be started to set up the devices": "Instantie moet worden gestart om de apparaten in te stellen",
20 | "Start?": "Begin?",
21 | "Discover over IP": "Ontdek via IP",
22 | "Discover over Bluetooth": "Ontdek via Bluetooth",
23 | "Data polling interval for IP": "Interval voor gegevenspolling voor IP",
24 | "Data polling interval for Bluetooth": "Interval voor gegevenspolling voor Bluetooth",
25 | "Update only changed values": "Alleen gewijzigde waarden bijwerken",
26 | "Options": "Opties",
27 | "Devices": "Apparaten",
28 | "seconds": "seconden",
29 | "Are you sure?": "Weet je zeker dat?",
30 | "Please confirm": "Bevestig alstublieft",
31 | "Cancel": "Annuleren"
32 | }
33 |
--------------------------------------------------------------------------------
/admin/static/media/Water Consumption.68891649591cc2434c5b.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Ошибка",
3 | "Paired": "Связанный",
4 | "Unpaired": "Неспаренный",
5 | "Identified": "Выявлено",
6 | "Connected": "Связан",
7 | "Discovered": "Обнаруженный",
8 | "Identify": "Идентифицировать",
9 | "Pair": "Привязать",
10 | "Unpair": "Разорвать связь",
11 | "Refresh devices list": "Обновите список устройств",
12 | "ID": "ID",
13 | "Type": "Тип",
14 | "Name": "Имя",
15 | "Category": "Категория",
16 | "Please enter PIN": "Пожалуйста, введите PIN-код",
17 | "PIN": "PIN",
18 | "Close": "Закрыть",
19 | "Instance must be started to set up the devices": "Экземпляр должен быть запущен для настройки устройств",
20 | "Start?": "Начинать?",
21 | "Discover over IP": "Искать устройства через IP",
22 | "Discover over Bluetooth": "Искать устройства через Bluetooth",
23 | "Data polling interval for IP": "Интервал опроса данных по IP",
24 | "Data polling interval for Bluetooth": "Интервал опроса данных по Bluetooth",
25 | "Update only changed values": "Обновлять только измененные значения",
26 | "Options": "Параметры",
27 | "Devices": "Устройства",
28 | "seconds": "секунды",
29 | "Are you sure?": "Вы уверены?",
30 | "Please confirm": "Пожалуйста подтвердите",
31 | "Cancel": "Отмена"
32 | }
33 |
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/pt.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Erro",
3 | "Paired": "Emparelhados",
4 | "Unpaired": "Não emparelhado",
5 | "Identified": "Identificado",
6 | "Connected": "Conectado",
7 | "Discovered": "Descoberto",
8 | "Identify": "Identificar",
9 | "Pair": "Par",
10 | "Unpair": "Desemparelhar",
11 | "Refresh devices list": "Atualize a lista de dispositivos",
12 | "ID": "ID",
13 | "Type": "Tipo",
14 | "Name": "Nome",
15 | "Category": "Categoria",
16 | "Please enter PIN": "Por favor insira o PIN",
17 | "PIN": "ALFINETE",
18 | "Close": "Fechar",
19 | "Instance must be started to set up the devices": "A instância deve ser iniciada para configurar os dispositivos",
20 | "Start?": "Começar?",
21 | "Discover over IP": "Descubra por IP",
22 | "Discover over Bluetooth": "Descubra por Bluetooth",
23 | "Data polling interval for IP": "Intervalo de sondagem de dados para IP",
24 | "Data polling interval for Bluetooth": "Intervalo de sondagem de dados para Bluetooth",
25 | "Update only changed values": "Atualizar apenas os valores alterados",
26 | "Options": "Opções",
27 | "Devices": "Dispositivos",
28 | "seconds": "segundos",
29 | "Are you sure?": "Tem certeza?",
30 | "Please confirm": "Por favor confirme",
31 | "Cancel": "Cancelar"
32 | }
33 |
--------------------------------------------------------------------------------
/srcAdmin/src/i18n/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "Error": "Erreur",
3 | "Paired": "Jumelé",
4 | "Unpaired": "Non apparié",
5 | "Identified": "Identifié",
6 | "Connected": "Connecté",
7 | "Discovered": "Découvert",
8 | "Identify": "Identifier",
9 | "Pair": "Paire",
10 | "Unpair": "Dissocier",
11 | "Refresh devices list": "Actualiser la liste des appareils",
12 | "ID": "ID",
13 | "Type": "Taper",
14 | "Name": "Nom",
15 | "Category": "Catégorie",
16 | "Please enter PIN": "Veuillez saisir le code PIN",
17 | "PIN": "ÉPINGLER",
18 | "Close": "proche",
19 | "Instance must be started to set up the devices": "L'instance doit être démarrée pour configurer les appareils",
20 | "Start?": "Début?",
21 | "Discover over IP": "Découvrir sur IP",
22 | "Discover over Bluetooth": "Découvrir via Bluetooth",
23 | "Data polling interval for IP": "Intervalle d'interrogation des données pour IP",
24 | "Data polling interval for Bluetooth": "Intervalle d'interrogation des données pour Bluetooth",
25 | "Update only changed values": "Mettre à jour uniquement les valeurs modifiées",
26 | "Options": "Options",
27 | "Devices": "Dispositifs",
28 | "seconds": "secondes",
29 | "Are you sure?": "Es-tu sûr?",
30 | "Please confirm": "Veuillez confirmer",
31 | "Cancel": "Annuler"
32 | }
33 |
--------------------------------------------------------------------------------
/admin/static/media/Stairwell.0914feea948153a8637a.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/admin/static/media/Basement.fe636968eec9556bfd1f.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Shed.491a2ad372036118002c.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/.create-adapter.json:
--------------------------------------------------------------------------------
1 | {
2 | "expert": "yes",
3 | "cli": false,
4 | "adapterName": "homekit-controller",
5 | "title": "HomeKit Controller",
6 | "description": "Pair and control HomeKit devices directly",
7 | "keywords": [
8 | "homekit",
9 | "hap"
10 | ],
11 | "authorName": "Ingo Fischer",
12 | "authorGithub": "Apollon77",
13 | "authorEmail": "github@fischer-ka.de",
14 | "features": [
15 | "adapter"
16 | ],
17 | "adminFeatures": [],
18 | "type": "iot-systems",
19 | "startMode": "daemon",
20 | "connectionType": "local",
21 | "dataSource": "poll",
22 | "connectionIndicator": "yes",
23 | "adapterSettings": [
24 | {
25 | "key": "discoverIp",
26 | "label": "Discover IP Devices",
27 | "inputType": "checkbox",
28 | "defaultValue": true
29 | },
30 | {
31 | "key": "discoverBle",
32 | "label": "Discover Bluetooth Devices",
33 | "inputType": "checkbox",
34 | "defaultValue": false
35 | }
36 | ],
37 | "language": "TypeScript",
38 | "adminReact": "yes",
39 | "indentation": "Space (4)",
40 | "quotes": "single",
41 | "es6class": "yes",
42 | "tools": [
43 | "ESLint"
44 | ],
45 | "gitRemoteProtocol": "HTTPS",
46 | "license": "MIT License",
47 | "ci": "gh-actions",
48 | "dependabot": "yes",
49 | "creatorVersion": "1.33.0"
50 | }
--------------------------------------------------------------------------------
/admin/static/media/Shading.0577383dc227cd043b3d.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Printer.146d983be964b95745d2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Carport.8337662544b9e95f4b27.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/admin/static/media/Water Heater.7e4bb4d99a5213f24d08.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/admin/static/media/Hall.9c2fa95419cb84ecda68.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/admin/static/media/Storeroom.7de4e6f3364554459b8a.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Power Consumption.4faab614c3c788f2d338.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Ceiling Spotlights.485822441b5df3b3384a.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | // Root tsconfig to set the settings and power editor support for all TS files
2 | {
3 | "compileOnSave": true,
4 | "compilerOptions": {
5 | // do not compile anything, this file is just to configure type checking
6 | // the compilation is configured in tsconfig.build.json
7 | "noEmit": true,
8 |
9 | // check JS files, but do not compile them => tsconfig.build.json
10 | "allowJs": true,
11 | "checkJs": true,
12 |
13 | "skipLibCheck": true, // Don't report errors in 3rd party definitions
14 | "noEmitOnError": true,
15 | "outDir": "./build/",
16 | "removeComments": false,
17 | "module": "commonjs",
18 | "moduleResolution": "node",
19 | "esModuleInterop": true,
20 | // this is necessary for the automatic typing of the adapter config
21 | "resolveJsonModule": true,
22 |
23 | // Set this to false if you want to disable the very strict rules (not recommended)
24 | "strict": true,
25 | // Or enable some of those features for more fine-grained control
26 | // "strictNullChecks": true,
27 | // "strictPropertyInitialization": true,
28 | // "strictBindCallApply": true,
29 | // "noImplicitAny": true,
30 | // "noUnusedLocals": true,
31 | // "noUnusedParameters": true,
32 |
33 | // Consider targetting es2019 or higher if you only support Node.js 12+
34 | "target": "es2019",
35 |
36 | "sourceMap": true,
37 | "inlineSourceMap": false,
38 | "useUnknownInCatchVariables": false,
39 | },
40 | "include": [
41 | "src/**/*.ts",
42 | "admin/**/*.ts",
43 | "admin/**/*.tsx"
44 | ],
45 | "exclude": [
46 | "build/**",
47 | "node_modules/**"
48 | ]
49 | }
50 |
--------------------------------------------------------------------------------
/admin/static/media/Lock.2cbfe17ea8923e0f4e9e.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/srcAdmin/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 | import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';
4 | import { StylesProvider, createGenerateClassName } from '@mui/styles';
5 | import './index.css';
6 | import App from './App';
7 | import * as serviceWorker from './serviceWorker';
8 | import pack from '../package.json';
9 | import theme from '@iobroker/adapter-react-v5/Theme';
10 | import Utils from '@iobroker/adapter-react-v5/Components/Utils';
11 |
12 | window.adapterName = 'homekit-controller';
13 | // window.sentryDSN = 'https://5ad729dbed504d15aa8bde423cae9a8e@sentry.iobroker.net/57';
14 |
15 | let themeName = Utils.getThemeName();
16 |
17 | console.log(`iobroker.${window.adapterName}@${pack.version} using theme "${themeName}"`);
18 | const generateClassName = createGenerateClassName({
19 | productionPrefix: 'iob',
20 | });
21 |
22 | function build() {
23 | const container = document.getElementById('root');
24 | const root = createRoot(container);
25 | return root.render(
26 |
27 |
28 | {
30 | themeName = _theme;
31 | build();
32 | }}
33 | />
34 |
35 |
36 |
37 | );
38 | }
39 |
40 | build();
41 |
42 | // If you want your app to work offline and load faster, you can change
43 | // unregister() to register() below. Note this comes with some pitfalls.
44 | // Learn more about service workers: http://bit.ly/CRA-PWA
45 | serviceWorker.unregister();
46 |
--------------------------------------------------------------------------------
/admin/static/media/Swimming Pool.190b378cb0707edb9461.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/admin/static/media/Garage.f7fc0a9b326d582afee6.svg:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/admin/static/media/Outdoors.da42e64a4b6ec2dd1e1c.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/admin/static/media/People.12a7e9127e72f3259186.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/admin/static/media/Laundry Room.58da550dff0173676e02.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Fan.8a29f85d6ca99c584603.svg:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/admin/static/media/Awnings.78480df8796f09859b6a.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Washroom.bfb54196f381f36de9d6.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Computer.9558f6ee3941dba4e3c5.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/admin/static/media/Coffee Makers.9fb4d82f957a06f30dae.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Attic.bb5d690a160bb1d4edb2.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/admin/static/media/Table Lamps.bd92de33bf86b6cbaec9.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Nursery.9cecc0544bdb5c28500c.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Terrace.d71d07d9290674f2ca20.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Guest Bathroom.d07a9f1cf32a82d03267.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Receiver.26b5ae166395a6dcb83f.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Sleeping Area.828017602bfcc2dd7dce.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/admin/static/media/Dryer.5ea89bd6dc20a00fb442.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Consumption.fecd7a10a13fe4e5f69b.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Hairdryer.5960b514dac1f04f3c4d.svg:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/admin/static/media/Weather.e91dae647698d48365e3.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/admin/static/media/Mowing Machine.9ead5b039f36cdc800e6.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Playroom.e64c9de43030c28d2f96.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Kitchen.deb7f976c1f43f9039a2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Wc.83604dd2daafb67067dd.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/admin/static/media/Toilet.83604dd2daafb67067dd.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/srcAdmin/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
15 |
16 |
28 |
29 |
38 | Homekit-Controller Settings
39 |
40 |
41 |
42 |
43 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true, // Don't look outside this project for inherited configs
3 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser
4 | parserOptions: {
5 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
6 | sourceType: 'module', // Allows for the use of imports
7 | project: './tsconfig.json',
8 | ecmaFeatures: {
9 | jsx: true,
10 | },
11 | },
12 | extends: [
13 | 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
14 | ],
15 | rules: {
16 | 'indent': 'off',
17 | '@typescript-eslint/indent': [
18 | 'error',
19 | 4,
20 | {
21 | 'SwitchCase': 1
22 | }
23 | ],
24 | 'quotes': [
25 | 'error',
26 | 'single',
27 | {
28 | 'avoidEscape': true,
29 | 'allowTemplateLiterals': true
30 | }
31 | ],
32 | '@typescript-eslint/no-parameter-properties': 'off',
33 | '@typescript-eslint/no-explicit-any': 'off',
34 | '@typescript-eslint/no-use-before-define': [
35 | 'error',
36 | {
37 | functions: false,
38 | typedefs: false,
39 | classes: false,
40 | },
41 | ],
42 | '@typescript-eslint/no-unused-vars': [
43 | 'error',
44 | {
45 | ignoreRestSiblings: true,
46 | argsIgnorePattern: '^_',
47 | },
48 | ],
49 | '@typescript-eslint/explicit-function-return-type': [
50 | 'warn',
51 | {
52 | allowExpressions: true,
53 | allowTypedFunctionExpressions: true,
54 | },
55 | ],
56 | '@typescript-eslint/no-object-literal-type-assertion': 'off',
57 | '@typescript-eslint/interface-name-prefix': 'off',
58 | '@typescript-eslint/no-non-null-assertion': 'off', // This is necessary for Map.has()/get()!
59 | 'no-var': 'error',
60 | 'prefer-const': 'error',
61 | 'no-trailing-spaces': 'error',
62 | },
63 | overrides: [
64 | {
65 | files: ['*.test.ts', '*.tsx'],
66 | rules: {
67 | '@typescript-eslint/explicit-function-return-type': 'off',
68 | },
69 | },
70 | ],
71 | };
72 |
--------------------------------------------------------------------------------
/admin/static/media/Temperature Sensors.75d805988a6b77b231d8.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/admin/static/media/Hoods.c177ddfec9fa9a6335db.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Ventilation.c31761d86d67e245ac92.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/admin/static/media/Led Strip.5cf2de461e29ffbaa5f0.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Amplifier.6f5d18048328386033f8.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Office.7e6a38218390b655e270.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/admin/static/media/Boiler Room.548e785e2f92b45f72b3.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Summer House.541a9fec69f01105e244.svg:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/admin/static/media/SmokeDetector.8222f77cb07030a409ee.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Cold Water.937aad5fa21b0c20a856.svg:
--------------------------------------------------------------------------------
1 |
32 |
--------------------------------------------------------------------------------
/admin/static/media/Hot Water.5c0a9e01741562e1fbab.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iobroker.homekit-controller",
3 | "version": "0.5.11",
4 | "description": "Pair and control HomeKit devices directly",
5 | "author": {
6 | "name": "Ingo Fischer",
7 | "email": "github@fischer-ka.de"
8 | },
9 | "homepage": "https://github.com/Apollon77/ioBroker.homekit-controller",
10 | "license": "MIT",
11 | "keywords": [
12 | "homekit",
13 | "hap"
14 | ],
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/Apollon77/ioBroker.homekit-controller"
18 | },
19 | "dependencies": {
20 | "@iobroker/adapter-core": "^3.2.2",
21 | "bignumber.js": "^9.1.2",
22 | "debug": "^4.3.7",
23 | "hap-controller": "^0.10.2",
24 | "@esm2cjs/p-queue": "^7.3.0"
25 | },
26 | "devDependencies": {
27 | "@alcalzone/release-script": "^3.8.0",
28 | "@alcalzone/release-script-plugin-iobroker": "^3.7.2",
29 | "@alcalzone/release-script-plugin-license": "^3.7.0",
30 | "@babel/cli": "^7.25.9",
31 | "@babel/core": "^7.26.0",
32 | "@babel/plugin-proposal-decorators": "^7.25.9",
33 | "@babel/preset-env": "^7.26.0",
34 | "@babel/preset-typescript": "^7.26.0",
35 | "@iobroker/adapter-dev": "^1.3.0",
36 | "@iobroker/dev-server": "^0.7.8",
37 | "@iobroker/testing": "^5.0.0",
38 | "@types/chai": "^4.3.20",
39 | "@types/chai-as-promised": "^7.1.8",
40 | "@types/debug": "^4.1.12",
41 | "@types/gulp": "^4.0.17",
42 | "@types/mocha": "^10.0.9",
43 | "@types/node": "^22.8.5",
44 | "@types/proxyquire": "^1.3.31",
45 | "@types/sinon": "^17.0.3",
46 | "@types/sinon-chai": "^3.2.12",
47 | "@typescript-eslint/eslint-plugin": "^7.18.0",
48 | "@typescript-eslint/parser": "^7.18.0",
49 | "chai": "^4.5.0",
50 | "chai-as-promised": "^7.1.2",
51 | "eslint": "^8.57.1",
52 | "gulp": "^4.0.2",
53 | "mocha": "^10.8.2",
54 | "parcel-bundler": "^1.12.5",
55 | "proxyquire": "^2.1.3",
56 | "rimraf": "^5.0.10",
57 | "sinon": "^17.0.2",
58 | "sinon-chai": "^3.7.0",
59 | "source-map-support": "^0.5.21",
60 | "ts-node": "^10.9.2",
61 | "typescript": "^5.6.3"
62 | },
63 | "main": "build/main.js",
64 | "scripts": {
65 | "prebuild": "rimraf ./build",
66 | "build:ts": "tsc -p tsconfig.build.json",
67 | "build": "npm run build:ts && npm run buildGui",
68 | "buildGui": "gulp",
69 | "watch:ts": "tsc -p tsconfig.build.json --watch",
70 | "watch": "npm run watch:ts",
71 | "test:ts": "mocha --config test/mocharc.custom.json src/**/*.test.ts",
72 | "test:package": "mocha test/package --exit",
73 | "test:unit": "mocha test/unit --exit",
74 | "test:integration": "mocha test/integration --exit",
75 | "test": "npm run test:ts && npm run test:package",
76 | "check": "tsc --noEmit",
77 | "lint": "eslint --ext .ts,.tsx src/",
78 | "release": "release-script",
79 | "translate": "translate-adapter"
80 | },
81 | "bugs": {
82 | "url": "https://github.com/Apollon77/ioBroker.homekit-controller/issues"
83 | },
84 | "readmeFilename": "README.md"
85 | }
86 |
--------------------------------------------------------------------------------
/admin/static/media/Stairway.9b007e08605296110003.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Living Room.3c380ab767be35f904e1.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/admin/static/media/Doorstep.10630b759b4867a10776.svg:
--------------------------------------------------------------------------------
1 |
36 |
--------------------------------------------------------------------------------
/admin/static/media/Iron.b8a65a48503b6f3e0dc8.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Gates.5a8baf2c3d4832ca57e8.svg:
--------------------------------------------------------------------------------
1 |
33 |
--------------------------------------------------------------------------------
/admin/static/media/Speaker.db548379676317470c4f.svg:
--------------------------------------------------------------------------------
1 |
36 |
--------------------------------------------------------------------------------
/admin/static/media/Chamber.71daaa4d14262dae029b.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/admin/static/media/Guest Room.41c7cfa38806f5009f82.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/admin/static/media/Rear Wall.38843c33f1ea1f575500.svg:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/admin/static/media/Battery Status.5951e2078ae1e573510e.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Barn.5d839e84c80918ce2ef0.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-stale - https://github.com/probot/stale
2 |
3 | # Number of days of inactivity before an Issue or Pull Request becomes stale
4 | daysUntilStale: 90
5 |
6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
8 | daysUntilClose: 7
9 |
10 | # Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
11 | onlyLabels: []
12 |
13 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
14 | exemptLabels:
15 | - enhancement
16 | - security
17 |
18 | # Set to true to ignore issues in a project (defaults to false)
19 | exemptProjects: true
20 |
21 | # Set to true to ignore issues in a milestone (defaults to false)
22 | exemptMilestones: true
23 |
24 | # Set to true to ignore issues with an assignee (defaults to false)
25 | exemptAssignees: false
26 |
27 | # Label to use when marking as stale
28 | staleLabel: wontfix
29 |
30 | # Comment to post when marking as stale. Set to `false` to disable
31 | markComment: >
32 | This issue has been automatically marked as stale because it has not had
33 | recent activity. It will be closed if no further activity occurs within the next 7 days.
34 | Please check if the issue is still relevant in the most current version of the adapter
35 | and tell us. Also check that all relevant details, logs and reproduction steps
36 | are included and update them if needed.
37 | Thank you for your contributions.
38 |
39 | Dieses Problem wurde automatisch als veraltet markiert, da es in letzter Zeit keine Aktivitäten gab.
40 | Es wird geschlossen, wenn nicht innerhalb der nächsten 7 Tage weitere Aktivitäten stattfinden.
41 | Bitte überprüft, ob das Problem auch in der aktuellsten Version des Adapters noch relevant ist,
42 | und teilt uns dies mit. Überprüft auch, ob alle relevanten Details, Logs und Reproduktionsschritte
43 | enthalten sind bzw. aktualisiert diese.
44 | Vielen Dank für Eure Unterstützung.
45 |
46 | # Comment to post when removing the stale label.
47 | # unmarkComment: >
48 | # Your comment here.
49 |
50 | # Comment to post when closing a stale Issue or Pull Request.
51 | closeComment: >
52 | This issue has been automatically closed because of inactivity. Please open a new
53 | issue if still relevant and make sure to include all relevant details, logs and
54 | reproduction steps.
55 | Thank you for your contributions.
56 |
57 | Dieses Problem wurde aufgrund von Inaktivität automatisch geschlossen. Bitte öffnet ein
58 | neues Issue, falls dies noch relevant ist und stellt sicher das alle relevanten Details,
59 | Logs und Reproduktionsschritte enthalten sind.
60 | Vielen Dank für Eure Unterstützung.
61 |
62 | # Limit the number of actions per hour, from 1-30. Default is 30
63 | limitPerRun: 30
64 |
65 | # Limit to only `issues` or `pulls`
66 | only: issues
67 |
68 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
69 | # pulls:
70 | # daysUntilStale: 30
71 | # markComment: >
72 | # This pull request has been automatically marked as stale because it has not had
73 | # recent activity. It will be closed if no further activity occurs. Thank you
74 | # for your contributions.
75 |
76 | # issues:
77 | # exemptLabels:
78 | # - confirmed
--------------------------------------------------------------------------------
/admin/static/media/Workshop.7856e59fe4f164c90609.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/lib/tools.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | /**
4 | * Tests whether the given variable is a real object and not an Array
5 | * @param it The variable to test
6 | */
7 | export function isObject(it: unknown): it is Record {
8 | // This is necessary because:
9 | // typeof null === 'object'
10 | // typeof [] === 'object'
11 | // [] instanceof Object === true
12 | return Object.prototype.toString.call(it) === '[object Object]';
13 | }
14 |
15 | /**
16 | * Tests whether the given variable is really an Array
17 | * @param it The variable to test
18 | */
19 | export function isArray(it: unknown): it is any[] {
20 | if (Array.isArray != null) return Array.isArray(it);
21 | return Object.prototype.toString.call(it) === '[object Array]';
22 | }
23 |
24 | /**
25 | * Translates text using the Google Translate API
26 | * @param text The text to translate
27 | * @param targetLang The target languate
28 | * @param yandexApiKey The yandex API key. You can create one for free at https://translate.yandex.com/developers
29 | */
30 | export async function translateText(text: string, targetLang: string, yandexApiKey?: string): Promise {
31 | if (targetLang === 'en') {
32 | return text;
33 | } else if (!text) {
34 | return '';
35 | }
36 | if (yandexApiKey) {
37 | return translateYandex(text, targetLang, yandexApiKey);
38 | } else {
39 | return translateGoogle(text, targetLang);
40 | }
41 | }
42 |
43 | /**
44 | * Translates text with Yandex API
45 | * @param text The text to translate
46 | * @param targetLang The target languate
47 | * @param apiKey The yandex API key. You can create one for free at https://translate.yandex.com/developers
48 | */
49 | async function translateYandex(text: string, targetLang: string, apiKey: string): Promise {
50 | if (targetLang === 'zh-cn') {
51 | targetLang = 'zh';
52 | }
53 | try {
54 | const url = `https://translate.yandex.net/api/v1.5/tr.json/translate?key=${apiKey}&text=${encodeURIComponent(text)}&lang=en-${targetLang}`;
55 | const response = await axios.request({url, timeout: 15000});
56 | if (isArray(response.data?.text)) {
57 | return response.data.text[0];
58 | }
59 | throw new Error('Invalid response for translate request');
60 | } catch (e) {
61 | throw new Error(`Could not translate to "${targetLang}": ${e}`);
62 | }
63 | }
64 |
65 | /**
66 | * Translates text with Google API
67 | * @param text The text to translate
68 | * @param targetLang The target languate
69 | */
70 | async function translateGoogle(text: string, targetLang: string): Promise {
71 | try {
72 | const url = `http://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}&ie=UTF-8&oe=UTF-8`;
73 | const response = await axios.request({url, timeout: 15000});
74 | if (isArray(response.data)) {
75 | // we got a valid response
76 | return response.data[0][0][0];
77 | }
78 | throw new Error('Invalid response for translate request');
79 | } catch (e) {
80 | if (e.response?.status === 429) {
81 | throw new Error(
82 | `Could not translate to "${targetLang}": Rate-limited by Google Translate`
83 | );
84 | } else {
85 | throw new Error(`Could not translate to "${targetLang}": ${e}`);
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/admin/static/media/Security.1ec78971bd34efa950f8.svg:
--------------------------------------------------------------------------------
1 |
35 |
--------------------------------------------------------------------------------
/admin/static/media/Chandelier.8b9fbdbc73bc2e955ef7.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/static/media/Workspace.97d73e419d966bfb6428.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------