{"version":3,"sources":["jsdelivr-header.js","/npm/iobroker.fenecon@0.7.0/main.js"],"names":[],"mappings":"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","file":"/npm/iobroker.fenecon@0.7.0/main.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/iobroker.fenecon@0.7.0/main.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","\"use strict\";\n\n/*\n * Created with @iobroker/create-adapter v2.6.3\n */\n\n// The adapter-core module gives you access to the core ioBroker functions\n// you need to create an adapter\nconst utils = require(\"@iobroker/adapter-core\");\n\n// Load your modules here, e.g.:\nconst axios = require(\"axios\");\nconst States = require(\"./lib/states\")\n\nlet createdChannel = [];\nlet createdState = [];\n\nclass Fenecon extends utils.Adapter {\n\t/**\n\t * @param {Partial<utils.AdapterOptions>} [options={}]\n\t */\n\tconstructor(options) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\tname: \"fenecon\",\n\t\t});\n\n\t\tthis.on(\"ready\", this.onReady.bind(this));\n\t\tthis.on(\"unload\", this.onUnload.bind(this));\n\t}\n\n\t/**\n\t * Is called when databases are connected and adapter received configuration.\n\t */\n\tasync onReady() {\n\t\t// Initialize your adapter here\n\n\t\ttry {\n\n\t\t\t// The adapters config (in the instance object everything under the attribute \"native\") is accessible via\n\t\t\tif (!this.config.ipAddress) {\n\t\t\t\tthis.log.error(`[onReady] FEMS IP address is empty - please check configuration of ${this.namespace}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!this.config.ipAddress.match(\"^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}\")) {\n\t\t\t\tthis.log.error(`[onReady] IP address has wrong format - please check configuration of ${this.namespace}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.config.refreshIntervall < 5 || this.config.refreshIntervall > 3600) {\n\t\t\t\tthis.log.error(`[onReady] Refresh interval only allows a range from 5s to 3600s - please check configuration of ${this.namespace}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// http://x:user@<ipAddress>/rest/channel/\n\t\t\tthis.log.debug(\"[onReady] Adapter successful started.\");\n\t\t\tthis.apiClient = axios.create({\n\t\t\t\tbaseURL: `http://x:owner@${this.config.ipAddress}/rest/channel/`,\n\t\t\t\ttimeout: 5000,\n\t\t\t\tresponseType: \"json\",\n\t\t\t\tresponseEncoding: \"utf8\"\n\t\t\t});\n\t\t\tthis.log.debug(\"[onReady] axios instance successful created.\");\n\n\t\t\tawait this.loadData();\n\t\t}\n\t\tcatch (err) {\n\t\t\tthis.log.error(`[onReady] Error during startup with message: ${err.message}`);\n\t\t}\n\t}\n\n\tasync loadData() {\n\t\ttry {\n\t\t\tthis.log.debug(\"[loadData] Load data from FEMS.\");\n\t\t\tif (!this.apiClient) {\n\t\t\t\tthis.log.error(\"[loadData] Apiclient not instanced.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/** @type {{ data: any[] }} */\n\t\t\tlet response = { data: [] };\n\t\t\tif (!this.config.useCustomEndpoints) {\n\t\t\t\tconst apiResponse = await this.apiClient.get(\".*/.*\");\n\t\t\t\tif (apiResponse.status === 200) {\n\t\t\t\t\tresponse.data.push(...apiResponse.data);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst endpoints = this.config.endpoints;\n\t\t\t\tconst endpointRequests = [];\n\t\t\t\tendpoints.forEach(endpoint => {\n\t\t\t\t\tconst channelIds = (endpoint.channelId || \"\").split(\";\").map(id => id.trim()).filter(Boolean);\n\t\t\t\t\tchannelIds.forEach(channelId => {\n\t\t\t\t\t\tconst getEndpoint = `${endpoint.componentId}/${channelId}`;\n\t\t\t\t\t\tthis.log.silly(`[loadData] Endpoint:  ${getEndpoint}`);\n\t\t\t\t\t\tendpointRequests.push(\n\t\t\t\t\t\t\tthis.apiClient\n\t\t\t\t\t\t\t\t? this.apiClient.get(getEndpoint).catch(err => {\n\t\t\t\t\t\t\t\t\tthis.log.error(`[loadData] Error for endpoint ${getEndpoint}: ${err.message}`);\n\t\t\t\t\t\t\t\t\treturn null; // Fehlerhafte Antwort als null markieren\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: Promise.reject(new Error(\"[loadData] API client is not defined\"))\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tconst endpointResponses = await Promise.all(endpointRequests);\n\n\t\t\t\tendpointResponses.forEach(endpointResponse => {\n\t\t\t\t\tif (endpointResponse && endpointResponse.status === 200) {\n\t\t\t\t\t\tlet data = endpointResponse.data;\n\t\t\t\t\t\tif (!Array.isArray(data)) data = [data];\n\t\t\t\t\t\tresponse.data.push(...data);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tthis.log.silly(`[loadData] combined response: ${JSON.stringify(response.data)}`);\n\n\t\t\tif (response.data.length > 0) {\n\t\t\t\tawait this.createUpdateState(response.data);\n\t\t\t\tawait this.calculateAutarchy();\n\t\t\t\tawait this.calculateSelfConsumption();\n\t\t\t}\n\t\t\tthis.log.debug(\"[loadData] REST request done and states updated.\");\n\t\t}\n\t\tcatch (err) {\n\t\t\tthis.log.error(`[loadData] Error during loading data: ${err.message}`);\n\t\t}\n\t\tfinally {\n\t\t\t// Restart request load Data!\n\t\t\tthis.timer = this.setTimeout(async () => {\n\t\t\t\tthis.log.debug(\"[loadData] Start next request.\");\n\t\t\t\tthis.timer = null;\n\t\t\t\tawait this.loadData();\n\t\t\t}, this.config.refreshIntervall * 1000);\n\t\t}\n\t}\n\n\t/**\n\t * Updates state.\n\t * @param {object} data AXIOS Response Object Data\n\t */\n\tasync createUpdateState(data) {\n\t\ttry {\n\t\t\tfor (const item of data) {\n\t\t\t\tconst [channel, state] = item.address.split(\"/\");\n\t\t\t\tif (!channel || !state) continue;\n\n\t\t\t\tconst channelName = this.name2id(channel);\n\t\t\t\tconst stateName = this.name2id(state);\n\t\t\t\tconst id = `${channel}.${state}`;\n\n\t\t\t\tconst type = this.typeTranslation(item.type);\n\n\t\t\t\tif (type === \"boolean\") {\n\t\t\t\t\titem.value = !!item.value;\n\t\t\t\t}\n\n\t\t\t\tawait this.createFolderObject(channelName);\n\t\t\t\tawait this.createStateObject(id, item, stateName);\n\n\t\t\t\tthis.log.debug(`[createUpdateState] StateId ${id} setState.`);\n\t\t\t\tawait this.setState(id, { val: item.value, ack: true });\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthis.log.error(\"[createUpdateState] Exception. \" + err.message);\n\t\t}\n\t}\n\n\t/**\n\t * @param {string} channelName\n\t */\n\tasync createFolderObject(channelName) {\n\t\tif (!createdChannel.includes(channelName)) {\n\t\t\tthis.log.debug(`[createFolderObject] Channel ${channelName} not exists. Extend Object.`);\n\t\t\tawait this.extendObject(channelName, {\n\t\t\t\t_id: channelName,\n\t\t\t\ttype: \"channel\",\n\t\t\t\tcommon: {\n\t\t\t\t\tname: channelName\n\t\t\t\t},\n\t\t\t\tnative: {}\n\t\t\t});\n\t\t\tcreatedChannel.push(channelName);\n\t\t}\n\t}\n\n\t/**\n\t * @param {string} id\n\t * @param {{ address: string; text: any; accessMode: string; type: any; unit: any; }} item\n\t * @param {any} stateName\n\t */\n\tasync createStateObject(id, item, stateName) {\n\t\tif (!createdState.includes(id)) {\n\t\t\tthis.log.debug(`[createStateObject] StateId ${id} not exists. Extend state.`);\n\t\t\tconst existingState = States.find(f => f.address === item.address);\n\t\t\tawait this.extendObject(id, {\n\t\t\t\tcommon: {\n\t\t\t\t\tname: stateName,\n\t\t\t\t\tdesc: item.text,\n\t\t\t\t\trole: existingState?.role ?? \"state\",\n\t\t\t\t\twrite: false,\n\t\t\t\t\tread: item.accessMode === \"RO\" || item.accessMode === \"RW\",\n\t\t\t\t\ttype: this.typeTranslation(item.type),\n\t\t\t\t\tunit: item.unit\n\t\t\t\t},\n\t\t\t\ttype: \"state\",\n\t\t\t\tnative: {}\n\t\t\t});\n\t\t\tcreatedState.push(id);\n\t\t}\n\t}\n\n\tname2id(pName) {\n\t\treturn (pName || '').replace(this.FORBIDDEN_CHARS, '_');\n\t}\n\n\ttypeTranslation(inType) {\n\t\tconst types = {\n\t\t\tINTEGER: \"number\",\n\t\t\tLONG: \"number\",\n\t\t\tDOUBLE: \"number\",\n\t\t\tFLOAT: \"number\",\n\t\t\tBOOLEAN: \"boolean\",\n\t\t\tSTRING: \"string\"\n\t\t};\n\t\treturn types[inType];\n\t}\n\t/**\n\t * Is called when adapter shuts down - callback has to be called under any circumstances!\n\t * @param {() => void} callback\n\t */\n\tonUnload(callback) {\n\t\ttry {\n\t\t\tif (this.timer) {\n\t\t\t\tthis.clearTimeout(this.timer);\n\t\t\t\tthis.timer = null;\n\t\t\t}\n\t\t\tcallback();\n\t\t} catch (e) {\n\t\t\tcallback();\n\t\t}\n\t}\n\n\tasync calculateAutarchy() {\n\t\tconst gridActivePowerId = \"_sum.GridActivePower\";\n\t\tconst consumptionActivePowerId = \"_sum.ConsumptionActivePower\";\n\n\t\tif (!createdState.includes(gridActivePowerId) || !createdState.includes(consumptionActivePowerId)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst [gridActivePowerState, consumptionActivePowerState] = await Promise.all([\n\t\t\tthis.getStateAsync(gridActivePowerId),\n\t\t\tthis.getStateAsync(consumptionActivePowerId)\n\t\t]);\n\n\t\tconst gridActivePower = gridActivePowerState?.val;\n\t\tconst consumptionActivePower = consumptionActivePowerState?.val;\n\t\tlet autarchy = 0;\n\t\tif (gridActivePower != null && consumptionActivePower != null && Number.isInteger(gridActivePower) && Number.isInteger(consumptionActivePower)) {\n\t\t\tif (+consumptionActivePower <= 0)\n\t\t\t\tautarchy = 100;\n\t\t\telse\n\t\t\t\tautarchy = Math.round(Math.max(0, Math.min(100, (1 - +gridActivePower / +consumptionActivePower) * 100)));\n\n\t\t}\n\t\tawait this.createFolderObject(\"_sum\");\n\t\tawait this.createStateObject(\n\t\t\t\"_sum.Autarchy\",\n\t\t\t{\n\t\t\t\taddress: \"_sum/Autarchy\",\n\t\t\t\ttext: \"Autarchy\",\n\t\t\t\taccessMode: \"RO\",\n\t\t\t\ttype: \"INTEGER\",\n\t\t\t\tunit: \"%\"\n\t\t\t},\n\t\t\t\"Autarchy\");\n\t\tawait this.setState(\"_sum.Autarchy\", { val: autarchy, ack: true });\n\t}\n\n\tasync calculateSelfConsumption() {\n\t\tconst gridActivePowerId = \"_sum.GridActivePower\";\n\t\tconst productionActivePowerId = \"_sum.ProductionActivePower\";\n\n\t\tif (!createdState.includes(gridActivePowerId) || !createdState.includes(productionActivePowerId)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst [gridActivePowerState, productionActivePowerState] = await Promise.all([\n\t\t\tthis.getStateAsync(gridActivePowerId),\n\t\t\tthis.getStateAsync(productionActivePowerId)\n\t\t]);\n\n\t\tlet sellToGrid = gridActivePowerState?.val;\n\t\tconst productionActivePower = productionActivePowerState?.val;\n\n\t\tlet selfConsumption = 0;\n\n\t\tif (sellToGrid != null && productionActivePower != null && Number.isInteger(sellToGrid) && Number.isInteger(productionActivePower)) {\n\t\t\tif (+sellToGrid <= 0)\n\t\t\t\tsellToGrid = +sellToGrid * -1\n\t\t\tif (+productionActivePower > 0) {\n\t\t\t\tselfConsumption = (1 - (+sellToGrid / +productionActivePower)) * 100;\n\t\t\t\tselfConsumption = Math.max(0, Math.min(100, Math.floor(selfConsumption)));\n\t\t\t\t// // At least 0 %\n\t\t\t\t// selfConsumption = Math.max(selfConsumption, 0);\n\n\t\t\t\t// // At most 100 %\n\t\t\t\t// selfConsumption = Math.min(selfConsumption, 100);\n\t\t\t\t// selfConsumption = Math.floor(selfConsumption);\n\t\t\t}\n\t\t}\n\t\tawait this.createFolderObject(\"_sum\");\n\t\tawait this.createStateObject(\n\t\t\t\"_sum.SelfConsumption\",\n\t\t\t{\n\t\t\t\taddress: \"_sum/SelfConsumption\",\n\t\t\t\ttext: \"SelfConsumption\",\n\t\t\t\taccessMode: \"RO\",\n\t\t\t\ttype: \"INTEGER\",\n\t\t\t\tunit: \"%\"\n\t\t\t},\n\t\t\t\"SelfConsumption\");\n\t\tawait this.setState(\"_sum.SelfConsumption\", { val: selfConsumption, ack: true });\n\t}\n}\n\nif (require.main !== module) {\n\t// Export the constructor in compact mode\n\t/**\n\t * @param {Partial<utils.AdapterOptions>} [options={}]\n\t */\n\tmodule.exports = (options) => new Fenecon(options);\n} else {\n\t// otherwise start the instance directly\n\tnew Fenecon();\n}\n"]}