iobroker.smartfriends 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +34 -0
- package/README.md +67 -0
- package/admin/i18n/de/translations.json +19 -0
- package/admin/i18n/en/translations.json +19 -0
- package/admin/i18n/es/translations.json +19 -0
- package/admin/i18n/fr/translations.json +19 -0
- package/admin/i18n/it/translations.json +19 -0
- package/admin/i18n/nl/translations.json +19 -0
- package/admin/i18n/pl/translations.json +19 -0
- package/admin/i18n/pt/translations.json +19 -0
- package/admin/i18n/ru/translations.json +19 -0
- package/admin/i18n/uk/translations.json +19 -0
- package/admin/i18n/zh-cn/translations.json +19 -0
- package/admin/jsonConfig.json +99 -0
- package/admin/smartfriends.png +0 -0
- package/admin/words.js +207 -0
- package/io-package.json +92 -0
- package/lib/DeviceManager.js +121 -0
- package/lib/SchellenbergBridge.js +315 -0
- package/lib/SchellenbergDevice.js +218 -0
- package/lib/adapter-config.d.ts +19 -0
- package/lib/comunication/CA.pem +22 -0
- package/lib/comunication/CommandFactory.js +123 -0
- package/lib/comunication/DataDelegateInterface.js +7 -0
- package/lib/comunication/HashHelper.js +41 -0
- package/lib/comunication/SmartSocket.js +189 -0
- package/lib/comunication/SmartSocketFactory.js +119 -0
- package/lib/comunication/comModel/JSONCommand.js +21 -0
- package/lib/comunication/comModel/JSONHelper.js +43 -0
- package/lib/comunication/comModel/JSONResponse.js +43 -0
- package/lib/comunication/comModel/responseBody/AllNewDeviceInfos.js +38 -0
- package/lib/comunication/comModel/responseBody/DeviceInfo.js +41 -0
- package/lib/comunication/comModel/responseBody/DeviceValue.js +24 -0
- package/lib/comunication/comModel/responseBody/HeloResponse.js +17 -0
- package/lib/comunication/comModel/responseBody/LanguageTranslation.js +17 -0
- package/lib/comunication/comModel/responseBody/LoginResponse.js +26 -0
- package/lib/comunication/comModel/responseBody/NewCompatibilityConfiguration.js +16 -0
- package/lib/comunication/comModel/responseBody/NewDeviceInfos.js +20 -0
- package/lib/comunication/comModel/responseBody/NewDeviceValues.js +20 -0
- package/lib/comunication/comModel/responseBody/NewLanguageTranslation.js +23 -0
- package/lib/helpers/CommonDefines.js +40 -0
- package/lib/helpers/Deffered.js +41 -0
- package/main.js +239 -0
- package/package.json +71 -0
package/main.js
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Created with @iobroker/create-adapter v1.30.1
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// The adapter-core module gives you access to the core ioBroker functions you need to create an adapter
|
|
8
|
+
const utils = require("@iobroker/adapter-core");
|
|
9
|
+
const schellenbergBridge = require("./lib/SchellenbergBridge");
|
|
10
|
+
const commonDefines = require("./lib/helpers/CommonDefines");
|
|
11
|
+
const DeviceManager = require("./lib/DeviceManager");
|
|
12
|
+
|
|
13
|
+
let SchellenbergBridge = null;
|
|
14
|
+
|
|
15
|
+
// Default gateway parameters
|
|
16
|
+
const defaultPort = 4900;
|
|
17
|
+
const defaultShcVersion = "3.7.4";
|
|
18
|
+
const defaultShcApiVersion = "3.4";
|
|
19
|
+
const defaultCSymbol = "D19033i";
|
|
20
|
+
|
|
21
|
+
class ConfigValidator {
|
|
22
|
+
static validate(config) {
|
|
23
|
+
// Add input type validation
|
|
24
|
+
const validations = {
|
|
25
|
+
smartFriendsIP: ip => typeof ip === "string" && ip.length > 0,
|
|
26
|
+
smartFriendsPort: port => typeof port === "number" && port > 0,
|
|
27
|
+
smartFriendsUsername: user => typeof user === "string" && user.length > 0,
|
|
28
|
+
smartFriendsPassword: pwd => typeof pwd === "string" && pwd.length > 0,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const errors = Object.entries(validations)
|
|
32
|
+
.filter(([key, validator]) => !validator(config[key]))
|
|
33
|
+
.map(([key]) => `Invalid ${key}`);
|
|
34
|
+
|
|
35
|
+
if (errors.length) {
|
|
36
|
+
throw new Error(errors.join(", "));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const defaults = {
|
|
40
|
+
port: defaultPort,
|
|
41
|
+
cSymbol: defaultCSymbol,
|
|
42
|
+
shcVersion: defaultShcVersion,
|
|
43
|
+
shApiVersion: defaultShcApiVersion,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Set defaults
|
|
47
|
+
config.smartFriendsPort = config.smartFriendsPort || defaults.port;
|
|
48
|
+
config.smartFriendsCSymbol = config.smartFriendsCSymbol || defaults.cSymbol;
|
|
49
|
+
config.smartFriendsShcVersion = config.smartFriendsShcVersion || defaults.shcVersion;
|
|
50
|
+
config.smartFriendsShApiVersion = config.smartFriendsShApiVersion || defaults.shApiVersion;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
class Smartfriends extends utils.Adapter {
|
|
55
|
+
/**
|
|
56
|
+
* @param {Partial<utils.AdapterOptions>} [options]
|
|
57
|
+
*/
|
|
58
|
+
constructor(options) {
|
|
59
|
+
super({
|
|
60
|
+
...options,
|
|
61
|
+
name: "smartfriends",
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
this.on("ready", this.onReady.bind(this));
|
|
65
|
+
this.on("stateChange", this.onStateChange.bind(this));
|
|
66
|
+
this.on("unload", this.onUnload.bind(this));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async checkSettings() {
|
|
70
|
+
this.log.debug("Checking adapter settings...");
|
|
71
|
+
|
|
72
|
+
if (this.config.ignoreSslErrors) {
|
|
73
|
+
this.log.warn("SSL errors are ignored when communicating with the gateway. This is potentially insecure!");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ConfigValidator.validate(this.config);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async initObjects() {
|
|
80
|
+
this.log.debug("Initializing objects...");
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// Initialize DeviceManager here when adapter is ready
|
|
84
|
+
this.deviceManager = new DeviceManager(this);
|
|
85
|
+
|
|
86
|
+
// info
|
|
87
|
+
let infoPrefix = commonDefines.AdapterDatapointIDs.Info;
|
|
88
|
+
await this.setObjectNotExistsAsync(infoPrefix, {
|
|
89
|
+
type: "channel",
|
|
90
|
+
common: {
|
|
91
|
+
name: "Adapter information",
|
|
92
|
+
},
|
|
93
|
+
native: {},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
infoPrefix += ".";
|
|
97
|
+
|
|
98
|
+
await this.setObjectNotExistsAsync(infoPrefix + commonDefines.AdapterStateIDs.Connection, {
|
|
99
|
+
type: "state",
|
|
100
|
+
common: {
|
|
101
|
+
name: "Connection to gateway",
|
|
102
|
+
type: "boolean",
|
|
103
|
+
role: "indicator.connected",
|
|
104
|
+
read: true,
|
|
105
|
+
write: false,
|
|
106
|
+
desc: "Indicates if connection to SmartFriendsBox was successful or not",
|
|
107
|
+
},
|
|
108
|
+
native: {},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// gateway
|
|
112
|
+
let gatewayPrefix = commonDefines.AdapterDatapointIDs.Gateway;
|
|
113
|
+
await this.setObjectNotExistsAsync(gatewayPrefix, {
|
|
114
|
+
type: "channel",
|
|
115
|
+
common: {
|
|
116
|
+
name: "Gateway information",
|
|
117
|
+
},
|
|
118
|
+
native: {},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
gatewayPrefix += ".";
|
|
122
|
+
|
|
123
|
+
await this.setObjectNotExistsAsync(gatewayPrefix + commonDefines.AdapterStateIDs.HardwareName, {
|
|
124
|
+
type: "state",
|
|
125
|
+
common: {
|
|
126
|
+
name: "Hardware name",
|
|
127
|
+
type: "string",
|
|
128
|
+
role: "text",
|
|
129
|
+
read: true,
|
|
130
|
+
write: false,
|
|
131
|
+
desc: "Actual Hardware name",
|
|
132
|
+
},
|
|
133
|
+
native: {},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
await this.setObjectNotExistsAsync(gatewayPrefix + commonDefines.AdapterStateIDs.MacAddress, {
|
|
137
|
+
type: "state",
|
|
138
|
+
common: {
|
|
139
|
+
name: "Hardware MAC address",
|
|
140
|
+
type: "string",
|
|
141
|
+
role: "info.mac",
|
|
142
|
+
read: true,
|
|
143
|
+
write: false,
|
|
144
|
+
desc: "Hardware MAC address",
|
|
145
|
+
},
|
|
146
|
+
native: {},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
this.setAdapterConnectionState(false);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
this.log.error(`Failed to initialize objects: ${error.message}`);
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async connectToGateway() {
|
|
157
|
+
this.log.info("Connecting to gateway and retrieving data...");
|
|
158
|
+
this.log.debug(
|
|
159
|
+
`IP: ${this.config.smartFriendsIP} - Port: ${this.config.smartFriendsPort} - CSymbol: ${this.config.smartFriendsCSymbol} - SHCVersion: ${this.config.smartFriendsShcVersion} - SHAPIVersion: ${this.config.smartFriendsShApiVersion}`,
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
SchellenbergBridge = new schellenbergBridge.SchellenbergBridge(this);
|
|
163
|
+
|
|
164
|
+
if (this.deviceManager != null) {
|
|
165
|
+
this.deviceManager.setBridge(SchellenbergBridge);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
SchellenbergBridge.Connect();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async setAdapterConnectionState(isConnected) {
|
|
172
|
+
await this.setStateChangedAsync(
|
|
173
|
+
`${commonDefines.AdapterDatapointIDs.Info}.${commonDefines.AdapterStateIDs.Connection}`,
|
|
174
|
+
isConnected,
|
|
175
|
+
true,
|
|
176
|
+
);
|
|
177
|
+
await this.setForeignState(`system.adapter.${this.namespace}.connected`, isConnected, true);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Is called when databases are connected and adapter received configuration.
|
|
182
|
+
*/
|
|
183
|
+
async onReady() {
|
|
184
|
+
this.initObjects()
|
|
185
|
+
.then(() => this.checkSettings())
|
|
186
|
+
.then(() => {
|
|
187
|
+
this.connectToGateway();
|
|
188
|
+
this.subscribeStates("devices.*.control.*"); // only subsribe to states changes under "devices.X.control."
|
|
189
|
+
})
|
|
190
|
+
.catch(err => this.log.error(err));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Is called when adapter shuts down - callback has to be called under any circumstances!
|
|
195
|
+
* @param {() => void} callback
|
|
196
|
+
*/
|
|
197
|
+
onUnload(callback) {
|
|
198
|
+
try {
|
|
199
|
+
if (SchellenbergBridge != null) {
|
|
200
|
+
SchellenbergBridge.handleDisconnect();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
this.setAdapterConnectionState(false);
|
|
204
|
+
this.log.info("onUnload(): Cleaned everything up...");
|
|
205
|
+
|
|
206
|
+
callback();
|
|
207
|
+
} catch {
|
|
208
|
+
callback();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Is called if a subscribed state changes
|
|
214
|
+
* @param {string} id
|
|
215
|
+
* @param {ioBroker.State | null | undefined} state
|
|
216
|
+
*/
|
|
217
|
+
async onStateChange(id, state) {
|
|
218
|
+
if (state) {
|
|
219
|
+
this.log.silly(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
|
|
220
|
+
if (this.deviceManager != null) {
|
|
221
|
+
await this.deviceManager.handleStateChange(id, state);
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
this.log.silly(`state ${id} deleted`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// @ts-expect-error parent is a valid property on module
|
|
230
|
+
if (module.parent) {
|
|
231
|
+
// Export the constructor in compact mode
|
|
232
|
+
/**
|
|
233
|
+
* @param {Partial<utils.AdapterOptions>} [options]
|
|
234
|
+
*/
|
|
235
|
+
module.exports = options => new Smartfriends(options);
|
|
236
|
+
} else {
|
|
237
|
+
// otherwise start the instance directly
|
|
238
|
+
new Smartfriends();
|
|
239
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iobroker.smartfriends",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "smartfriends",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Black-Thunder",
|
|
7
|
+
"email": "glwars@aol.de"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/Black-Thunder/ioBroker.smartfriends",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"ioBroker",
|
|
13
|
+
"Smart Home",
|
|
14
|
+
"home automation",
|
|
15
|
+
"smartfriends",
|
|
16
|
+
"schellenberg"
|
|
17
|
+
],
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/Black-Thunder/ioBroker.smartfriends.git"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">= 20"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@iobroker/adapter-core": "^3.3.2",
|
|
27
|
+
"base-64": "^1.0.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@alcalzone/release-script": "^5.0.0",
|
|
31
|
+
"@alcalzone/release-script-plugin-iobroker": "^4.0.0",
|
|
32
|
+
"@alcalzone/release-script-plugin-license": "^4.0.0",
|
|
33
|
+
"@alcalzone/release-script-plugin-manual-review": "^4.0.0",
|
|
34
|
+
"@iobroker/adapter-dev": "^1.5.0",
|
|
35
|
+
"@iobroker/dev-server": "^0.8.0",
|
|
36
|
+
"@iobroker/eslint-config": "^2.2.0",
|
|
37
|
+
"@iobroker/testing": "^5.2.2",
|
|
38
|
+
"@tsconfig/node20": "^20.1.8",
|
|
39
|
+
"@types/gulp": "^4.0.18",
|
|
40
|
+
"@types/node": "^25.0.2",
|
|
41
|
+
"@types/proxyquire": "^1.3.31",
|
|
42
|
+
"globals": "^16.5.0",
|
|
43
|
+
"proxyquire": "^2.1.3"
|
|
44
|
+
},
|
|
45
|
+
"main": "main.js",
|
|
46
|
+
"files": [
|
|
47
|
+
"admin{,/!(src)/**}/!(tsconfig|tsconfig.*|.eslintrc).{json,json5}",
|
|
48
|
+
"admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js}",
|
|
49
|
+
"lib/",
|
|
50
|
+
"www/",
|
|
51
|
+
"io-package.json",
|
|
52
|
+
"LICENSE",
|
|
53
|
+
"main.js"
|
|
54
|
+
],
|
|
55
|
+
"scripts": {
|
|
56
|
+
"test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"",
|
|
57
|
+
"test:package": "mocha test/package --exit",
|
|
58
|
+
"test:integration": "mocha test/integration --exit",
|
|
59
|
+
"test": "npm run test:js && npm run test:package",
|
|
60
|
+
"check": "tsc --noEmit -p tsconfig.check.json",
|
|
61
|
+
"lint": "eslint -c eslint.config.mjs .",
|
|
62
|
+
"lint:fix": "eslint -c eslint.config.mjs . --fix",
|
|
63
|
+
"translate": "translate-adapter",
|
|
64
|
+
"release": "release-script",
|
|
65
|
+
"dev-server": "dev-server"
|
|
66
|
+
},
|
|
67
|
+
"bugs": {
|
|
68
|
+
"url": "https://github.com/Black-Thunder/ioBroker.smartfriends/issues"
|
|
69
|
+
},
|
|
70
|
+
"readmeFilename": "README.md"
|
|
71
|
+
}
|